|
|
View previous topic :: View next topic |
Author |
Message |
JDBoyd
Joined: 11 Aug 2010 Posts: 4
|
Help with using 2 UART RX interrupts with 18F46J50 |
Posted: Wed Aug 11, 2010 1:13 pm |
|
|
I am trying to use both hardware UARTS on a PIC18F46J50 with CCS PCH 4.109, and I want to use RX interupts (INT_RDA and INT_RDA2) with each.
What I'm finding is that INT_RDA works, but INT_RDA2 never fires. I say it never fires both on the variable in the interrupt handler never being incremented and also on the basis that setting a breakpoint in the interrupt never gets hit.
In the main function, the for(;;) loop, the fprintf is to send a message to the device on the other end of the 485 to cause it to send a reply (that should trigger the interrupt). I can see from a line sniffer that the device on the other end replies, and if I turn off the interrupt and use fgetc, I can see the reply, so it isn't that nothing is being sent to the second serial port.
Here is sample program that recreates my problem. Sorry for the length, I tried to trim it as much as I could without removing something that might be important.
Code: | #include <18F46J50.h>
#use delay(clock=48Mhz)
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES PRIMARY //Primary clock is system clock when scs=00
#FUSES HSPLL //High Speed Crystal/Resonator with PLL enabled not
#FUSES PLLDIV3
#FUSES NOCPUDIV
// #FUSES DEBUG //Debug mode for use with ICD
// #FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOPROTECT //Code not protected from reading
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES IOL1WAY //Allows only one reconfiguration of peripheral pins
#FUSES NOWPCFG
#FUSES WPEND
#FUSES WPDIS
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES T1DIG
#FUSES MSSPMSK7
#FUSES DSWDT2147483648
#FUSES DSWDT
#FUSES DSBOR
#FUSES RTCOSC_T1
#FUSES DSWDTOSC_INT
#FUSES WPFP
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=remote_232)
#use rs232(baud=19200,parity=N,xmit=PIN_C1,rcv=PIN_C0,enable=PIN_C2,bits=8, stream=cp_485)
/*
Uart handler code with interrupts
*/
#define RX_SIZE 0x3f // must be in modulo value for
int RxBuf_485[RX_SIZE+1]; // 64 byte rcv ring buffer for comms485
int RxH_485= 0; // buffer first in idx
int RxT_485= 0; // buffer last in idx
int RxBuf_232[RX_SIZE+1]; // 64 byte rcv ring buffer for comms232
int RxH_232= 0;
int RxT_232= 0;
#INT_RDA2
void RDA2_isr(void)
{
RxBuf_485[RxH_485++] = fgetc(cp_485); // capture the incomming char and bump the idx
if (RxH_485 > RX_SIZE)
RxH_485 =0; // reset the idx if wrap point
//if (RxT_485 == RxH_485) printf("ERROR! Rx_485 Full\n\r"); // does not stop just wraps over tail ?????
}
// Dequeue the Rx_485 buffer returns a 0xff if no data available
int Getc_485(void)
{
int bufdat;
if (RxT_485 != RxH_485)
{
bufdat = RxBuf_485[RxT_485++];
if (RxT_485 > RX_SIZE)
RxT_485 =0; // reset the idx if wrap point
return bufdat;
}
return -1;
}
// see if anything in Rxbuf ret = number of elements available
int Poll_485RxB(void)
{
int temp_T;
temp_T = RX_SIZE-RxT_485;
if( RxH_485 >= RxT_485) return (RxH_485 - RxT_485);
else return (RxH_485 + temp_T);
}
#INT_RDA
void RDA_isr(void)
{
RxBuf_232[RxH_232++] = fgetc(remote_232); // capture the incomming char and bump the idx
if (RxH_232 > RX_SIZE) RxH_232 = 0; // reset the idx if wrap point
//if (RxT_232 == RxH_232) printf("ERROR! Rx_232 Full\n\r"); // does not stop just wraps over tail ?????
}
// Dequeue the Rx_485 buffer returns a 0xff if no data available
int Getc_232(void)
{
int bufdat;
if (RxT_232 != RxH_232)
{
// printf("Rx_232 Tail %d\n\r" RxT_232);
bufdat = RxBuf_232[RxT_232++];
if (RxT_232 > RX_SIZE) RxT_232 =0x00; // reset the idx if wrap point
return bufdat;
}
return -1;
}
// see if anything in Rxbuf ret = number of elements available
int Poll_232RxB(void)
{
int temp_T;
temp_T = RX_SIZE-RxT_232;
if( RxH_232 >= RxT_232) return (RxH_232 - RxT_232);
else return (RxH_232 + temp_T);
}
void main( void )
{
//TODO: Read a switch and set speed based on that.
setup_oscillator(OSC_PLL_ON);
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_EXT_L_TO_H);
setup_timer_1(T1_FOSC | T1_DIV_BY_1);
enable_interrupts(INT_RDA); // remote Rx 232 port
enable_interrupts(INT_RDA2); // remote Rx 485 port
enable_interrupts(GLOBAL);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
fprintf(remote_232, "Starting\r\n");
for(;;)
{
fprintf(cp_485, "\xbf\x04\x8d");
fprintf(remote_232, "485: %d\r\n", RxH_485);
fprintf(remote_232, "232: %d\r\n", RxH_232);
delay_ms(100);
}
}
|
|
|
|
Jeff King
Joined: 20 Oct 2003 Posts: 43 Location: Hillsdale, Michigan USA
|
|
Posted: Wed Aug 11, 2010 1:30 pm |
|
|
I'm doing something with the PIC18F25J50, which is in the same family as your part, and I do have TX interrupts working on the second serial port. I'm about to implement RX interrupts but one thing I noticed is you didn't define the pins for the second uart with the pin_select command. This family allows mapping of some of the peripherals, the 2nd UART being one. Here is my setup code, and as I said, I do know for a fact transmit works on the 2nd serial port
Code: |
#define XB_DI PIN_B2
#define XB_DO PIN_B3
#pragma pin_select U2TX=XB_DI
#pragma pin_select U2RX=XB_DO
#pragma use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7, ERRORS, STREAM=GPS)
#pragma use rs232(uart2, baud=9600, ERRORS, STREAM=XBRADIO)
|
I'll let you know how the RX for the 2nd port works for me later today. I'm using 4.109 as well. |
|
|
Jeff King
Joined: 20 Oct 2003 Posts: 43 Location: Hillsdale, Michigan USA
|
|
Posted: Sat Aug 14, 2010 1:23 am |
|
|
My RX ISR worked fine.
Any luck after you tried the pin select command? |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
Re: Help with using 2 UART RX interrupts with 18F46J50 |
Posted: Sat Aug 14, 2010 8:50 am |
|
|
JDBoyd wrote: |
Code: | #include <18F46J50.h>
.....snip....
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=remote_232)
#use rs232(baud=19200,parity=N,xmit=PIN_C1,rcv=PIN_C0,enable=PIN_C2,bits=8, stream=cp_485)
....snip....
|
|
I would also include UART1 and UART2 here just for clarity. You're missing uart2 at a minimum.
having both will make your code more self-explanatory.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Jeff King
Joined: 20 Oct 2003 Posts: 43 Location: Hillsdale, Michigan USA
|
|
Posted: Sat Aug 14, 2010 10:34 am |
|
|
Agreed, here are my new defines and works like a champ for me:
Code: | #define XB_DI PIN_B2
#define XB_DO PIN_B3
#pragma pin_select U2TX=XB_DI
#pragma pin_select U2RX=XB_DO
#pragma use rs232(uart1, baud=9600, ERRORS, STREAM=GPS)
#pragma use rs232(uart2, baud=9600, ERRORS, STREAM=XBRADIO) |
uart1 pins being part of the part spec and uart2 being selected with the pin_select command
What I think is happening with the gents code, is since he is not using Pin Select, the compiler is defining the UART as a software one, and hence he has no hardware IRQ to fire. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sat Aug 14, 2010 10:43 am |
|
|
Jeff King wrote: | Agreed, here are my new defines and works like a champ for me:
Code: | #define XB_DI PIN_B2
#define XB_DO PIN_B3
#pragma pin_select U2TX=XB_DI
#pragma pin_select U2RX=XB_DO
#pragma use rs232(uart1, baud=9600, ERRORS, STREAM=GPS)
#pragma use rs232(uart2, baud=9600, ERRORS, STREAM=XBRADIO) |
uart1 pins being part of the part spec and uart2 being selected with the pin_select command
What I think is happening with the gents code, is since he is not using Pin Select, the compiler is defining the UART as a software one, and hence he has no hardware IRQ to fire. |
That's probably exactly what's happening. Software UART --hence no IRQ.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
JDBoyd
Joined: 11 Aug 2010 Posts: 4
|
|
Posted: Tue Aug 17, 2010 8:03 am |
|
|
Jeff King wrote: | I'm doing something with the PIC18F25J50, which is in the same family as your part, and I do have TX interrupts working on the second serial port. I'm about to implement RX interrupts but one thing I noticed is you didn't define the pins for the second uart with the pin_select command. This family allows mapping of some of the peripherals, the 2nd UART being one. Here is my setup code, and as I said, I do know for a fact transmit works on the 2nd serial port
Code: |
#define XB_DI PIN_B2
#define XB_DO PIN_B3
#pragma pin_select U2TX=XB_DI
#pragma pin_select U2RX=XB_DO
#pragma use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7, ERRORS, STREAM=GPS)
#pragma use rs232(uart2, baud=9600, ERRORS, STREAM=XBRADIO)
|
I'll let you know how the RX for the 2nd port works for me later today. I'm using 4.109 as well. |
OK, I updated to 4.110, made the changes required by the new update (PLLDIV3 -> PLL3, remove the #fuse PRIMARY), and added #pin_select lines, and now the second is working.
Thanks. |
|
|
fbtech
Joined: 25 Mar 2015 Posts: 7
|
|
Posted: Fri Mar 27, 2015 11:20 am |
|
|
Hello,
I have the problem of the 2 UART with 18f25j50.
I use the code posted in this discussion.
Here is my header file generated by PIC c wizard:
Code: |
#include <18F25J50.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#use delay(clock=48MHz,crystal=8MHz,USB_FULL)
#byte PORTA = 0xf80
#byte PORTB = 0xf81
#byte PORTC = 0xf82
#byte TRISA = 0xf92
#byte TRISB = 0xf93
#byte TRISC = 0xf94
#define XB_DI PIN_B2
#define XB_DO PIN_B3
#pragma pin_select U2TX=XB_DI
#pragma pin_select U2RX=XB_DO
#pragma use rs232(uart1,baud=9600, ERRORS, STREAM=DATA1)
#pragma use rs232(uart2, baud=9600, ERRORS, STREAM=DATA2)
//#use rs232(UART1,baud=2400,ERRORS,stream=UART1)
//#use rs232(UART2,baud=9600,ERRORS,stream=UART2)
#define USB_CONFIG_VID 0x2405
#define USB_CONFIG_PID 0x000B
#define USB_CONFIG_BUS_POWER 500
#define USB_STRINGS_OVERWRITTEN
char USB_STRING_DESC_OFFSET[]={0,4,18};
char const USB_STRING_DESC[]={
//string 0 - language
4, //length of string index
0x03, //descriptor type (STRING)
0x09,0x04, //Microsoft Defined for US-English
//string 1 - manufacturer
14, //length of string index
0x03, //descriptor type (STRING)
'F',0,
'B',0,
'T',0,
'e',0,
'C',0,
'H',0,
//string 2 - product
14, //length of string index
0x03, //descriptor type (STRING)
'F',0,
'B',0,
'T',0,
'e',0,
'C',0,
'H',0
};
#include <usb_cdc.h>
|
here my main.c
Code: |
#include <main.h>
#include <string.h>
//RTCC
rtc_time_t wizardTempTime;
#INT_RDA
void RDA_isr(void)
{
}
#INT_RDA2
void RDA2_isr(void)
{
}
void initialisation(void)
{
}
/* TODO: Use usb_cdc_putc() to transmit data to the USB
virtual COM port. Use usb_cdc_kbhit() and usb_cdc_getc() to
receive data from the USB virtual COM port. usb_enumerated()
can be used to see if connected to a host and ready to
communicate. */
void main()
{
char f,gfilename[12];
char msg[64];
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
TRISA = 0xDF;
TRISB = 0x08;
TRISC = 0x8C;
//setup_adc_ports(sAN0);
//setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_0);
//set_adc_channel( 0 );
// value = read_adc();
// setup_adc( ADC_OFF );
//RTCC
setup_rtc(RTC_ENABLE | RTC_OUTPUT_SOURCE, 0);
wizardTempTime.tm_year = 15;
wizardTempTime.tm_mon = 3;
wizardTempTime.tm_mday = 26;
wizardTempTime.tm_wday = 4;
wizardTempTime.tm_hour = 15;
wizardTempTime.tm_min = 30;
wizardTempTime.tm_sec = 37;
rtc_write(&wizardTempTime);
// enable_interrupts(INT_RDA);
// enable_interrupts(INT_RDA2);
// enable_interrupts(GLOBAL);
// usb_init();
fprintf(DATA1,"\r\n UART1 TEST \r\n");
fprintf(DATA2,"\r\n UART2 TEST \r\n");
while(true);
} //Main
|
The result that I have with Proteus 8.1 is as follows:
http://www.4shared.com/download/NMmJ1sUBba/UART_ERROR.jpg?lgfp=3000
I'm using 5.036 compiler.
Thanks |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
|
fbtech
Joined: 25 Mar 2015 Posts: 7
|
|
Posted: Fri Mar 27, 2015 12:53 pm |
|
|
The question is about the c program and I try to give the maximum information to get the answer.
thanks |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sat Mar 28, 2015 12:04 am |
|
|
Are you running the code in proteus or on actual hardware? _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Sat Mar 28, 2015 5:09 am |
|
|
Seriously repeat 15 times the first rule of debugging. Simplify.
Then repeat the second. Proteus Isis, does not work well with PIC's.
Then repeat "pragma is pointless in CCS" (read what it says about it in the manual).
With those repeated, your test code becomes:
Code: |
#include <18F25J50.h>
#device ADC=10
#FUSES HSPLL, PLL2, NOXINST, NOCPUDIV, NOFCMEN, NOIESO, NOIOL1WAY, NOWDT
#use delay(clock=48MHz)
#pin_select U2TX=PIN_B2
#pin_select U2RX=PIN_B3
#use rs232(uart1,baud=9600, ERRORS, STREAM=DATA1)
#use rs232(uart2, baud=9600, ERRORS, STREAM=DATA2)
void main()
{
setup_adc_ports(NO_ANALOGS);
output_drive(PIN_B2); //This may be needed depending on compiler version
delay_ms(100);
//most RS232 level generator chips _need_ a few mSec after power on
fprintf(DATA1,"\r\n UART1 TEST \r\n");
fprintf(DATA2,"\r\n UART2 TEST \r\n");
while(true)
;
} //Main
|
This correctly prints the two strings to the two UART's on a properly working board. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|