CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

What do you think this packet handler?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ELCouz



Joined: 18 Jul 2007
Posts: 427
Location: Montreal,Quebec

View user's profile Send private message

What do you think this packet handler?
PostPosted: Wed Feb 03, 2010 8:49 pm     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Feb 03, 2010 11:31 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 04, 2010 4:52 pm     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Fri Feb 05, 2010 7:48 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Feb 05, 2010 10:41 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 05, 2010 3:51 pm     Reply with quote

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 Smile


Thank you guys for your guidelines Very Happy

Have a nice week-end
_________________
Regards,
Laurent

-----------
Here's my first visual theme for the CCS C Compiler. Enjoy!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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