|
|
View previous topic :: View next topic |
Author |
Message |
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
What do you think this packet handler? |
Posted: Wed Feb 03, 2010 8:49 pm |
|
|
Dear programmers,
I'm working on a PIC to PIC communication (5 packets / sec)
I'm pretty new with Serial comms with interrupts is that short enough or i can improve something?
I figured out that safest way is to need an external «flowcontrol» such a pin rise when packet start. In software only the problem even with a fixed width packet and 2 delimiters you can have an offset if data goes corrupt or contain values that are the same as delimiters
dspic receiver code:
Code: |
//---PACKET RS232 RX-------
//PACKET = [83,SPEED,WHEEL_0,WHEEL_1,WHEEL_2,WHEEL_3,RPM_0,RPM_1,CHECKSUM]
//BUFFER[0] start with speed and end with CHECKSUM
#INT_RDA
void analyzepacket_isr(){
byte inputchar;
if ((charcount > 7)&&(buffer[7] == buffer[0]+buffer[1]+buffer[2]+buffer[3]+buffer[4]+buffer[5]+buffer[6])) {bufferready = 1;startbuffering =0;} //set the ready flag if checksum pass and buffering done!
inputchar = getc();
//capture the 8 bytes wide data packet
if ((charcount < 7) && (startbuffering == 1)) {buffer[charcount] = inputchar;charcount++;}
//verify if FlowControl is high and the packet is 83 then start buffering data
if ((inputchar == 83) && (input(FlowControl)) && (bufferready == 0)) {charcount = 0;startbuffering =1;}
}
//---------------------
|
the emitter code 18f2550
Code: |
#int_timer3
void timer3_isr(void)
{
byte checksum;
byte wheel_0,wheel_1,wheel_2,wheel_3;
byte rpm_0,rpm_1;
if (timercount < 4){timercount++} //software postscaler
else {
wheel_0 = make8(wheelcount, 0);
wheel_1 = make8(wheelcount, 1);
wheel_2 = make8(wheelcount, 2);
wheel_3 = make8(wheelcount, 3);
rpm_0 = make8(rpm, 0);
rpm_1 = make8(rpm, 1);
checksum = speed + wheel_0 + wheel_1 + wheel_2 + wheel_3 + rpm_0 + rpm_1;
output_high(pin_a0);
putc(83); //PACKET START
output_low(pin_a0);
putc(speed);
putc(wheel_0);
putc(wheel_1);
putc(wheel_2);
putc(wheel_3);
putc(rpm_0);
putc(rpm_1);
putc(checksum);
timercount = 0;
};
} |
Thank you! _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Wed Feb 03, 2010 11:31 pm |
|
|
The timer interrupt handler is a problem. The timer interrupt handler will not exit until it has sent all the serial characters out of the interface.
Instead of doing this, use the timer interrupt handler to acquire the data into the respective volatile variables. The set a "data_ready" flag;
In the mainline look for data_ready. If set then, disable the timer interrupt, copy to data the another set of variables (shadow copies if you like) not shared with the timer interrupt handler, reenable the timer interrupt and then printout the contents of these shadow variable. This approach will have minimal impact on the interrupt handler and the data printed will alway be from a complete read of all the variables (i.e. they will not change mid stream as a result of another timer interrupt ocuring). _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Thu Feb 04, 2010 4:52 pm |
|
|
Thank you for you reply
If i understood you .... you mean this ?
PIC emitter code
TIMER3:
Code: |
#int_timer3
void timer3_isr(void)
{
if (timercount < 3)&&(dataready==0)){timercount++;}
else {
wheel_0 = make8(wheelcount, 0);
wheel_1 = make8(wheelcount, 1);
wheel_2 = make8(wheelcount, 2);
wheel_3 = make8(wheelcount, 3);
rpm_0 = make8(rpm, 0);
rpm_1 = make8(rpm, 1);
checksum = speed + wheel_0 + wheel_1 + wheel_2 + wheel_3 + rpm_0 + rpm_1;
dataready = 1;
timercount = 0;}
}
|
and now in the main loop:
Code: |
// *** PACKET TRANSMIT ***
if (dataready){
disable_interrupts(INT_TIMER3);
buffer[0] = speed;
buffer[1] = wheel_0;
buffer[2] = wheel_1;
buffer[3] = wheel_2;
buffer[4] = wheel_3;
buffer[5] = rpm_0;
buffer[6] = rpm_1;
buffer[7] = checksum;
dataready = 0;
enable_interrupts(INT_TIMER3);
output_high(PIN_A0);
putc(83);
output_low(PIN_A0);
putc(buffer[0]);
putc(buffer[1]);
putc(buffer[2]);
putc(buffer[3]);
putc(buffer[4]);
putc(buffer[5]);
putc(buffer[6]);
putc(buffer[7]);
}
//========================
|
Code could be shorter but I didn't use any loops for the sake of code performance.
Is that what you mean ?
Have a nice day! _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Fri Feb 05, 2010 7:48 am |
|
|
asmallri wrote: | The timer interrupt handler is a problem. The timer interrupt handler will not exit until it has sent all the serial characters out of the interface.
Instead of doing this, use the timer interrupt handler to acquire the data into the respective volatile variables. The set a "data_ready" flag;
|
I agree with Andrew. Your timer3 is unneeded and potentially troublesome.
I do it a little different than he suggests (just a little though).
my INT_RDA is a state machine that:
1:Looks for start of packet
2:collects data to end of packet or buffer (DON'T OVERRUN!)
3:Sets have_packet flag
4:waits for have_packet to be reset by main() routine.
In main:
if have_packet == true, then process it:
1. Copy the packet to a temp buffer
2. clear have_packet (now the INT_RDA can run again)
3. Process packet
The reason I don't DISABLE the interrupt is to allow the flow of inbound chars to keep coming. This way there isn't a buffer overflow.
Yes, I might miss packets, but if I overflow, I miss packets anyway. the ISR is written to ALWAYS getc(); -- but the state machine controls whether that received char is actually saved or discarded.
Cheers,
- Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Feb 05, 2010 10:41 am |
|
|
ELCouz wrote: | Thank you for you reply
If i understood you .... you mean this ?
PIC emitter code
TIMER3:
Code: |
#int_timer3
void timer3_isr(void)
{
if (timercount < 3)&&(dataready==0)){timercount++;}
else {
wheel_0 = make8(wheelcount, 0);
wheel_1 = make8(wheelcount, 1);
wheel_2 = make8(wheelcount, 2);
wheel_3 = make8(wheelcount, 3);
rpm_0 = make8(rpm, 0);
rpm_1 = make8(rpm, 1);
checksum = speed + wheel_0 + wheel_1 + wheel_2 + wheel_3 + rpm_0 + rpm_1;
dataready = 1;
timercount = 0;}
}
|
and now in the main loop:
Code: |
// *** PACKET TRANSMIT ***
if (dataready){
disable_interrupts(INT_TIMER3);
buffer[0] = speed;
buffer[1] = wheel_0;
buffer[2] = wheel_1;
buffer[3] = wheel_2;
buffer[4] = wheel_3;
buffer[5] = rpm_0;
buffer[6] = rpm_1;
buffer[7] = checksum;
dataready = 0;
enable_interrupts(INT_TIMER3);
output_high(PIN_A0);
putc(83);
output_low(PIN_A0);
putc(buffer[0]);
putc(buffer[1]);
putc(buffer[2]);
putc(buffer[3]);
putc(buffer[4]);
putc(buffer[5]);
putc(buffer[6]);
putc(buffer[7]);
}
//========================
|
Code could be shorter but I didn't use any loops for the sake of code performance.
Is that what you mean ?
Have a nice day! |
Yes. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Fri Feb 05, 2010 3:51 pm |
|
|
Quote: | I agree with Andrew. Your timer3 is unneeded and potentially troublesome. |
Actually i only use timer to regulate the quantity of data packets that is sent throught the link on the pic that send data (it's a one way communication) and with a timer interrupt i know that packet will not be missed , always on time and priority over the main program.
Quote: | The reason I don't DISABLE the interrupt is to allow the flow of inbound chars to keep coming. This way there isn't a buffer overflow.
Yes, I might miss packets, but if I overflow, I miss packets anyway. the ISR is written to ALWAYS getc(); -- but the state machine controls whether that received char is actually saved or discarded. |
I also do this anyway you need to getc in the RDA interrupt to clear it (unless you clear it manually) and you may get into trouble if the buffer overflow. Better play safe
Thank you guys for your guidelines
Have a nice week-end _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
|
|
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
|