![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
ProgGuy
Joined: 08 Oct 2003 Posts: 4
|
Echoing characters with interrupts via rs232 on pic18f452 |
Posted: Thu Oct 09, 2003 8:41 am |
|
|
I'm sending some data (123456789\r) repeatedly from my pc at 38400, data bits=8, stop bits 1 parity=none. When the PIC sees a CR it echoes the entire contents of the buffer to the pc. What I don't understand is that every second transmission echoes garbage back to my pc (ex: 123456789 then 1#$*@! then 123456789 back again). Is there something wrong with my interrupt routine? When typing in the data from hyperterm everything is fine but it fails when it's being streamed. I tried every other baud rate and I still get sporadic garbage. Just in case any of you want to know, I'm using a max232.
Thanks,
Here's my example code.
#if defined(__PCH__)
#include <18F452.h>
#use delay(clock=19660800)
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#endif
#define BUFFER_SIZE 128
BYTE buffer[BUFFER_SIZE];
BYTE tail = 0;
BYTE receivedFrame = 0;
#INT_RDA
void serial_isr()
{
buffer[tail] = getc();
if(buffer[tail] == '\r' || tail == (BUFFER_SIZE - 1))
{
receivedFrame = 1;
disable_interrupts(GLOBAL);
}
else
{
tail++;
}
}
void main()
{
BYTE head = 0;
enable_interrupts(global);
enable_interrupts(int_rda);
do
{
if(receivedFrame == 1)
{
while(head <= tail)
putc(buffer[head++]);
head = tail = 0;
receivedFrame = 0;
enable_interrupts(global);
}
}
while (TRUE);
} |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 09, 2003 8:56 am |
|
|
Try disabling the rda int. The global int will be restored by hardware on the return from int instruction.
Code: |
#if defined(__PCH__)
#include <18F452.h>
#use delay(clock=19660800)
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#endif
#define BUFFER_SIZE 128
BYTE buffer[BUFFER_SIZE];
BYTE tail = 0;
BYTE receivedFrame = 0;
#INT_RDA
void serial_isr()
{
buffer[tail] = getc();
if(buffer[tail] == '\r' || tail == (BUFFER_SIZE - 1))
{
receivedFrame = 1;
disable_interrupts(int_rda);
}
else
{
tail++;
}
}
void main()
{
BYTE head = 0;
enable_interrupts(global);
enable_interrupts(int_rda);
while (TRUE)
{
if(receivedFrame == 1)
{
while(head <= tail)
putc(buffer[head++]);
head = tail = 0;
receivedFrame = 0;
enable_interrupts(int_rda);
}
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
ProgGuy
Joined: 08 Oct 2003 Posts: 4
|
|
Posted: Thu Oct 09, 2003 11:25 am |
|
|
I still have the same problem after changing the GLOBAL to INT_RDA. Thanks for the quick reponse though. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Thu Oct 09, 2003 12:08 pm |
|
|
ProgGuy wrote: | I still have the same problem after changing the GLOBAL to INT_RDA. Thanks for the quick reponse though. |
There are a series of things that might/will cause some problems, but I cannot see what is immediately causing the 'every second time' problem.
The first is that since you disable interupts, you should really 'flush' the receive buffer in the chip, before re-enabling, or some garbage may result from this.
The second, is that because you are using the hardware UART, you should really check for the output buffer having emptied, before re-enabling the interrupts (there may be a couple of characters still 'in transmission', when you start looking for the incoming characters).
It will be quicker in the interrupt code, to use a 'temporary' character, and code as:
buffer[tail++]=temp=getc();
if (temp=='\r' || tail>=BUFFER_SIZE)
This is because 'array accesses', are relatively slow, involving the addition of the offset, and then access through the indirect register I/O, while a simple variable is directly accessed.
I would test for tail, being >= to BUFFER_SIZE-1, since it is always safer in case the value is 'unexpected' at some point.
I would also clear the RDIF bit, before re-enabling the interrupt, since otherwise if any reception has occured, there will be an immediate interrupt on re-enabling the interrupt, and possible garbage reception from this.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 09, 2003 12:19 pm |
|
|
Quote: |
I would also clear the RDIF bit, before re-enabling the interrupt, since otherwise if any reception has occured, there will be an immediate interrupt on re-enabling the interrupt, and possible garbage reception from this.
|
The RDIF bit is read only and is cleared when the RCREG is read. To clear the int you probably have to do something like:
Code: |
if (kbhit())
(void)getc();
|
Quote: |
When typing in the data from hyperterm everything is fine but it fails when it's being streamed.
|
Are you sure that the program that you are using to stream the data is working correctly? Can you feed this output of this program back through Hyperterminal and see it correctly? What happens if you cut and paste with Hyperterminal? Does it fail also?
Mark |
|
![](templates/subSilver/images/spacer.gif) |
ProgGuy
Joined: 08 Oct 2003 Posts: 4
|
|
Posted: Thu Oct 09, 2003 12:39 pm |
|
|
Mark,
The driving program works fine. I get the same result if I paste blocks of text in hyperterm. I'm still working on some previous response and will post my results shortly.
Thanks,
ProgGuy |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|