We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
My goal is to send out a CAN message every 3s. I am using Timer3 to check for the 3s expiry condition and then trigger the transmission of a CAN message. The problem with my code is that the CAN message does not go out at all (I am sure my CAN stuff is all ok). My Timer3 code is below:
void timer3(void)//initializing timer for 3s { T3CON = 0x0007;//initializing timer3 control register while 'counting up' T3 = 0; //setting maximum value for Timer3 counter T3R = 1; switch(T3){ case 58593: CAN_tx_testerpresent(); case 65625: T3 = 0; default: break; } //CAN_tx_testerpresent(); }
If I uncomment the CAN_tx_testerpresent() function after the "switch" statement I am able to see 1 message go out after initialization. Commenting that step out amounts to no CAN message. Why do I have a switch case? So I can send out other messages with different periodicities. Can someone help me out please? Thanks.
You can not poll the timer and expect to do something at an _exact_ tick.
Let's say that you stand and look at a chronograph that ticks 100 steps/second.
Now, I give you the instruction that you should press a button when you see the clock reach 60 seconds. Are you fast enough to see every single 0.01 s step of the clock? What happens if you blink when it reaches 60.00? Would you press the button anyway?
Initialize the timer to generate one interrupt every 10ms. Every interrupt, let the ISR increment an unsigned variable.
Have a main loop that constantly looks at this variable.
volatile unsigned timer_ticks; unsigned last_can; unsigned last_something_else; last_can = timer_ticks; last_something_else = timer_ticks; for (;;) { if ((timer_ticks - last_can_msg) >= 300) { // Something to do every 3 seconds. last_can += 300; send_can(); } if ((timer_ticks - last_something_else) >= 50) { // Something to do every 500ms. last_something_else += 50; do_something_else(); } other_stuff(); }
Just make sure that the total amount of work to do is less than the total processing power, or your variables will fall behind.
If you do have events that have so short interval that you are likely to not manage, it may be better to write:
if ((timer_ticks - last_something_else) >= 50) { do_something_else(); last_something_else = timer_ticks; }
and basically take time from the end of an event until the start of the next. The first example will - as long as the processor is fast enough - always start the events after a fixed delay, plus or minus a bit of jitter depending on what other tasks you have that may get the processor to miss the exact tick.