View previous topic :: View next topic |
Author |
Message |
Lincad
Joined: 24 Feb 2012 Posts: 2
|
PIC24 INT_RDA does not work |
Posted: Fri Feb 24, 2012 8:48 am |
|
|
Code: |
#use rs232(UART1, baud=9600, xmit=PIN_G6, rcv=PIN_C1, BRGH1OK, PARITY=E,BITS =8, STOP=1, RESTART_WDT, ERRORS )
// Globals used for serial interrupt routine.
unsigned int8 buffer[80];
unsigned int8 next_in = 0;
unsigned int8 next_out = 0;
enable_interrupts(INTR_GLOBAL);
enable_interrupts(INT_RDA);
#INT_RDA
void serial_isr(void)
{
int8 t;
// Globals
// 'next-in' is the next available slot in the buffer for the arriving char.
// 'next_out' is the last read out slot in the buffer.
// Store incomming byte
buffer[next_in]=getc();
t=next_in;
// 'next_out' chases the tail of next_in. At some point the buffer slot nears its
// max value rolls over.
next_in=(next_in+1) % sizeof(buffer);
// Prevent buffer overflow
if(next_in==next_out)
{
next_in=t;
}
}
|
On receiving bytes the interrupt never gets triggered. I know I am receiving bytes as the following code works, if only for three bytes.
Code: |
/*
while((count < 4) && (++timeout<50000) )
{
delay_us(10);
if(kbhit())
{
result = getc();
uart_rcv_data[count] = result;
count++;
}
}
// fourth byte usually wrong.
*/
|
Any help appreciated. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Fri Feb 24, 2012 7:02 pm |
|
|
Your interrupt enable logic is shown in the wrong place. Is it really there or is in inside main() ?
In order to minimize the interrupt handler execution time, it is more efficient to compare with a maximum value than to use the modulus operator.
I personally would not reset the WDT in a hardware based interrupt driven serial receive handler. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Fri Feb 24, 2012 7:28 pm |
|
|
Hi,
I don't have the data sheet handy, but your Tx/Rx pins look suspicious. If you don't specify the correct hardware UART pins, the compiler will create a software serial implementation, and the serial interrupt won't work.
John |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Feb 25, 2012 3:18 am |
|
|
For a meaningful answer, we need to know the PIC24 type and CCS C version. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Sat Feb 25, 2012 8:38 am |
|
|
Kind of an offshoot question based on the code he submitted. He used both UART1 and set his xmit and rcv in the #use rs232() statement. Is that valid. I know I typically do #pin_select to set U1TX and U1RX and then use UART1 in the #use rs232() statement.
Is that setup valid (maybe a software UART???).
I'm only asking because if it isn't valid, then maybe it is causing a conflict. |
|
|
Rogier
Joined: 25 Feb 2012 Posts: 12 Location: NL
|
|
Posted: Sun Feb 26, 2012 4:22 am |
|
|
I have the same problems with a PIC24 with a CCS version 4.104. I think there is a bug in the kbhit command when using hardware UART. When I set FORCE_SW it works.
I found out in the disassembly listing that the kbhit command produces no code.
NowI do the kbhit manually:
Below a simple RS232 code that echoes back any character.
This code DOES NOT work with H/W UART:
Code: |
#include <24FJ64GB106.H>
#rom 0xABFA = {0xFFFF} // fuses
#rom 0xABFC = {0x93DD}
#rom 0xABFE = {0x3E7F}
#use delay(clock=32M, oscillator=8M, restart_wdt)
#pin_select U1TX = PIN_D3
#pin_select U1RX = PIN_D0
#use rs232(UART1, STREAM=1, baud=115200, BITS=8, PARITY=N, STOP=1, ERRORS )
char RX_BYTE;
void main()
{
while (TRUE)
{
restart_wdt();
if (kbhit(1) == TRUE)
{
RX_BYTE = getc(1);
fputc(RX_BYTE, 1);
}
}
}
|
Remove kbhit (see PIC24 datasheet for SFR's) and this will work:
Code: |
#include <24FJ64GB106.H>
#rom 0xABFA = {0xFFFF} // fuses
#rom 0xABFC = {0x93DD}
#rom 0xABFE = {0x3E7F}
#use delay(clock=32M, oscillator=8M, restart_wdt)
#pin_select U1TX = PIN_D3
#pin_select U1RX = PIN_D0
#use rs232(UART1, STREAM=1, baud=115200, BITS=8, PARITY=N, STOP=1, ERRORS )
#word U1STA = 0x0222 // SFR
#define URXDA 0
#bit KBHIT_UART1 = U1STA.URXDA // = 1 if data is available
char RX_BYTE;
void main()
{
while (TRUE)
{
restart_wdt();
if (KBHIT_UART1 == TRUE)
{
RX_BYTE = getc(1);
fputc(RX_BYTE, 1);
}
}
}
|
|
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun Feb 26, 2012 6:39 am |
|
|
Where in the manual does it say this form of kbhit is supported?
Quote: | if (kbhit(1) == TRUE) |
The only form I can find is where the actual stream name is
specified...maybe that's why it doesn't work? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
Rogier
Joined: 25 Feb 2012 Posts: 12 Location: NL
|
|
Posted: Sun Feb 26, 2012 12:06 pm |
|
|
Even when fill in another stream name it still doesn't work. I do it manually now and it works ok!
Here the SFR for the other UARTS of the PIC24FJ64GB106:
Code: |
#word U1STA = 0x0222 // SFR
#word U2STA = 0x0232 // SFR
#word U3STA = 0x0252 // SFR
#word U4STA = 0x02B2 // SFR
#define URXDA 0
#bit KBHIT_UART1 = U1STA.URXDA // = TRUE if data is available
#bit KBHIT_UART2 = U2STA.URXDA // = TRUE if data is available
#bit KBHIT_UART3 = U3STA.URXDA // = TRUE if data is available
#bit KBHIT_UART4 = U4STA.URXDA // = TRUE if data is available
|
|
|
|
Lincad
Joined: 24 Feb 2012 Posts: 2
|
|
Posted: Mon Feb 27, 2012 5:23 am |
|
|
Thanks for all your responses.
With help from CCS support I have a solution
One thing to note the two #pin_select lines for setting the UART1 pins must be
before the #use rs232() line.
Code: |
#pin_select U1RX=PIN_C1
#pin_select U1TX=PIN_G6
#use rs232(UART1, baud=9600, BRGH1OK ,PARITY=E,BITS =8, STOP=1, RESTART_WDT, ERRORS)
|
I had also mistakenly reconfigured the TX pin as an input with set_tris_() function. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Mon Feb 27, 2012 1:55 pm |
|
|
It is often better to not use tris the upside to tris is specific but the downside can waste hours if a direction is missed. Most let the compiler do the work.
The select pin before the use rs232 is necessary since the compile needs to know the pins ( unless you are using defaults ) before setting up the UART logic. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Feb 27, 2012 2:24 pm |
|
|
Quote: | I had also mistakenly reconfigured the TX pin as an input with set_tris_() function. |
That's just meaningless, because tristate is commanded by the dedicated port module when a PPS output function is assigned to the pin.
As a side remark, you still didn't mention your PIC24 chip. Noone can guess if it has PPS or not. That's the way to create truely helpless cases. |
|
|
|