I'm planning to use my STM32 board to send CAN frames. I implemented a simple scheduler that contains 10 tasks; one task will be responsible for sending frames. To do the job I declared a structure for the CAN frame:

typedef struct
    unsigned int id;
    unsigned char data[];
    unsigned char dlc;
    unsigned int timeOfSend  //This is the time in ms in which a frame should be sent
} tFrame;

And then I declared a table of the frames to be sent:

aubFrames[MAX_FRAMES] = {
    {0x12, 0xAABBCC, 4, 100},
    {0x12, 0xAABBCC, 4, 1000},
    {0x12, 0xAABBCC, 4, 2000},
    {0x12, 0xAABBCC, 4, 2010}

This tells the board to send the first frame after 100 ms, the second after 1000 ms, etc.

What I actually do:

I added a new task in the scheduler with a period of 10 ms. This task will check the aubFrames table, and if it's time to send a frame, it sends the concerned frame. Else nothing is to be done. The probem with this solution is that there is a big loss of time. For example, to send the first frame, the scheduler accesses this task nine times, but with nothing to do.

Is there another solution so that the scheduling will be more effective?

I thought to use a timer interrupt, but I don't think that's the good solution since there are only four timers on the board and the number of frames is more than four, so in my opinion configuring the timers to generate interrupts for different periods of time won't work.

  • \$\begingroup\$ have scheduler initialize timer/interrupt then never look at it again. The timer/interrupt will handle all the work and kill itself when all frames sent. One result is the 10msec scheduler will not be needed (at least for this function) See my answer for a pseudo code example. If that is still too much overhead, then at each interrupt, calculate when the next interrupt needs to occur, more code but less overhead \$\endgroup\$ Aug 16, 2015 at 22:36

1 Answer 1

  • Use a single timer.

  • Setup the timer for 10 ms.

  • Define elapsed time as static and initialize to 0

  • Define albtable selector as static and initialize to 0

  • At each interrupt:

    • Increment elapsed time by 10

    • Check albtable[albtable selector] to see if time field matches elapsed time

    • If times match,
    • then
      • Send frame using albtable[albtable selector]
      • Increment albtable selector
    • Endif

    • If albtable selector >= number of entries in albtable[]:

      • Turn off timer
    • Return from interrupt

  • \$\begingroup\$ Thanks the clarification, i have an extra question : imagine if i have to check if the transmitted frame is acquited (as in TCP/IP) so i should send a frame and wait an amount of time to check if i receive an acquitement. for me i added a callback to the structure tFrame for the checking do you agree with me? ,i think it becomes a little bit complicated, do you have any suggestion or reference that helps me to get out of this problem \$\endgroup\$
    – fedi
    Aug 19, 2015 at 8:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.