|
|
View previous topic :: View next topic |
Author |
Message |
new guy Guest
|
help with int_rda |
Posted: Sat Dec 16, 2006 2:46 am |
|
|
Hi forum
I need some help regarding the serial interrupt int_rda. I am using 18f452 and compiler version is 3.249.
I want to receive 20 characters on through serial interrupt, but i dont want the normal code to run during the receival of these 20 characters. But i still need to use interrupts because the data might come at any time. The problem is that i keep missing characters when the normal code is running and serial interrupt begin generated. I am using a 20mhz crystal and baud rate is 19200.
best Regards |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
Re: help with int_rda |
Posted: Sat Dec 16, 2006 2:56 am |
|
|
new guy wrote: | The problem is that i keep missing characters when the normal code is running and serial interrupt begin generated. |
Generally, this shouldn't be happening, because the ISR runs independently of the main() loop. Does you main() disable interrupts? The problem could lie in the ISR itself: if the ISR is lond and it can't service the receipt of a character before the next character arrives, you will eventually start loosing characters. If you post your ISR, may be we can spot the problem.
Last edited by kender on Sat Dec 16, 2006 5:46 pm; edited 1 time in total |
|
|
new guy Guest
|
|
Posted: Sat Dec 16, 2006 3:12 am |
|
|
here is the ISR:
Code: |
void rstprocess()
{
do
{
write_ext_eeprom(writeadd,buffer[qindex]); //overwrites memory with the new string
qindex++;
writeadd++;
}while(buffer[qindex] != '!');
write_ext_eeprom(writeadd,buffer[qindex]); //overwrites memory with the new string
fprintf(pc,"\n\rRESETTING SYSTEM !!\n\r");
glcd_fillScreen(OFF);
glcd_text57(8, 28, textmsg3, 2, ON);
fputc('R',con1); //send reset signal to UC1
do
{
despo = fgetc(con1); //wait for lrf to reach 0 degrees
fprintf(pc,"\n\rGOT SIGNAL:%c",despo);
}while(despo != 'R');
windex = 0;
despo = 0;
reset_cpu(); //reset the cpu after writing string into EEPROM
}
#int_rda
void serial_isr()
{
despo = fgetc(special);
buffer[windex] = despo;
windex++;
if(despo == '!') //so configuration string received completely
{
rstprocess();
}
}
|
|
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Sat Dec 16, 2006 5:19 pm |
|
|
You're obviously trying to do too much in the ISR. Probably, what gets you the most is the serial writes inside ISR. ISR should store the received character in the buffer, set some flags, increment some counters and exit immediately. Processing of and reaction to the incoming data should be left to the main(), with the exception for the cases, when the fast reaction to the interrupt is of paramount importance.
Sorry, I've been looking at your code for only about 20 sec. Will write more later. |
|
|
Andreas
Joined: 25 Oct 2004 Posts: 136
|
ISR |
Posted: Sun Dec 17, 2006 3:20 am |
|
|
Hi,
As the last post already said, keep the ISR as short as possible !!
Usually I am doing a simple state machine in the main for reacting and having only some flags set in the isr, so you will never miss one character !
best regards
Andreas |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Dec 17, 2006 9:06 am |
|
|
I agree that an ISR should be as short as possible, but that's the case here except for one special condition where reception of a '!' character marks the end of message. This special case takes extreme long but then resets the processor, so no need to care about the long processing. I don't think this is a very elegant implementation and it might introduce other problems but it is not related to the missing of characters.
Most likely there is something in your main loop disabling the interrupts, either some code written by you or a compiler internal library function. For example, are you using a software RS232 driver with the DISABLE_INTS function? |
|
|
Ttelmah Guest
|
|
Posted: Sun Dec 17, 2006 10:34 am |
|
|
I'd suspect the problem relates to how many functions exist in 'rstprocess'. All functions used here, will result in the interrupts being disabled in the main code if they are used outside the interrupt. Since this includes things like LCD I/O, and serial I/O, soem quite long periods with the interrupt disabled are likely. Some GLCD functions (like clearing the screen), can take a significant time, so having the interrupts enabled outside, could easily result in characters being missed.
Best Wishes |
|
|
new guy Guest
|
|
Posted: Mon Dec 18, 2006 6:08 am |
|
|
Hi all
Thank you for all your replies. but the problem still remains.after much trouble i have been able to identify exactly where the problem lies. First of all my hardware configuration:
PIC18f452
20Mhz crystal
Compiler version 3.249
I am using serial interrupt INT_RDA. PIN C7 is pulled up. I am sending serial data through my computer and i want the serial interrupt subroutine to store that data into an array. The problem is that e.g if i enter '$ROTOS' from the hyperterminal then only $R is registered. If i sent '$' and wait for about one second and then sent 'ROTOS' then all the data is registered satisfactorily. I got to know that by getting data in serial interrupt and then printing it back on the computer immediately. Once the data appears i send the next character. After this occurance of controller getting lost somewhere after getting '$' then the int_rda works fine no matter how quickly i enter the data. So only intially the controller gets stuck somewhere. Here is my ISR
Code: |
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,ERRORS,stream=special)
#int_rda
void serial_isr()
{
do
{
cra = fgetc(special);
fputc(cra,pc);
}while(cra != 13);
}
|
Just to recap: once i enter the first character, it is printed back on pc after 1 second, but all subsequent characters (after this delay) are echoed back immediated. During this delay of 1second any charactes entered are lost some where. What i want to know is that what is causing this delay.
Kind regards |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Mon Dec 18, 2006 7:45 am |
|
|
Many have a lot of grieve when it comes to #int rda. Read all that has been written on this board about int #RDA.
The interrupt is called each and every time a single char is received. You do violence to this by putting a do while in the interrupt. By doing this you completely defeat the purpose of the interrupt forcing it to wait in the interrupt until the final char is received. The first char is triggers your interrupt then no other incoming char is allowed to use the interrupt because your do loop doesn't allow the interrupt to exit after one char is received.
Read all you can about the interrupt and start over with your isr design. |
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 18, 2006 7:50 am |
|
|
First, echoing back like this, is a pretty sure way of losing characters. The reason is that you are echoing on another stream, and since there is only one hardware UART, this will involve the code in being unable to respond to the serial interrupt for a character time. Second though, the main fault is almost certainly in the code outside the interrupt. If (for instance), there is any output to the same stream as is now being used in the interrupt for output, this will result in the interrupts being disabled, and further problems.
Now, let me post a larger program than is 'normal' for me, but this shows the sort of code needed to do what you want:
Code: |
#include <18F452.h>
#FUSES NOWDT, WDT128, HS, NOPROTECT, NOOSCSEN, BROWNOUT, BORV42, PUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
//Buffer tests and handling
#define isempty(buff,in,out,size) (in==out)
#define hasdata(buff,in,out,size) (in!=out)
#define isfull(buff,in,out,size) (((in+1)&(size-1))==out)
#define tobuff(buff,in,out,size,chr) { buff[in]=chr;\
in=((in+1) & (size-1));\
if (in==out) out=((out+1) & (size-1));\
}
#define frombuff(buff,in,out,size) (btemp=buff[out],\
out=(out+1) & (size-1), \
btemp)
#define ifrombuff(buff,in,out,size) (ibtemp=buff[out],\
out=(out+1) & (size-1), \
ibtemp)
#define clrbuff(buff,in,out,size) {in=0;\
out=0;}
//buffer size - must be a binary size for the code as posted
#define SRBUFF (16)
int8 RSRbuff[SRBUFF],RSRin,RSRout;
#INT_RDA /* RS232 'receive' interrupt */
void RXINT(void)
{
tobuff(RSRbuff,RSRin,RSRout,SRBUFF,getc());
}
void main(void) {
int8 input_message[20], ctr=0, temp;
setup_counters(RTCC_INTERNAL,WDT_OFF);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_adc(ADC_OFF);
clrbuff(RSRbuff,RSRin,RSRout,SRBUFF);
CLEAR_INTERRUPTS(INT_RDA);
ENABLE_INTERRUPTS(INT_RDA); /* Rx data */
ENABLE_INTERRUPTS(GLOBAL);
while (TRUE) {
while (isempty(RSRbuff,RSRin,RSRout,SRBUFF)) {
//Here do stuff while waiting for the serial
}
//Here a character is ready.
temp=frombuff(RSRbuff,RSRin,RSRout,SRBUFF);
if (temp=='$') {
//Here have first character
ctr=0;
}
input_message[ctr++]=temp;
if (ctr==19 || temp==13) {
//Here either a line feed, or buffer is full
input_message[ctr]=0; //null terminate string
printf("%s",input_message); //send to whatever output you want
ctr=0; //prevent buffer overrun
}
}
}
|
This will send back the entire received string, when it is completed (either buffer is full, or linefeed is seen). The input will be stored in the array 'input_message', starting with the $ character.
Best Wishes |
|
|
|
|
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
|