10 years, 1 month ago.

CAN Interrupts

I am currently working on using CAN Interrupts for a larger project for a motor controller. However, I can't seem to get the CAN Interrupts to work properly.

I've written a small test program to demonstrate this. The problem is that the CAN Interrupt works the first time (i.e. led1 toggles from off to on), but it doesn't seem to resume the original process that it was running and the second interrupt does not happen at all. Previously I put a printf function in the while loop and I can see that it cuts off and stops printing when the led flips for the first time.

I've tested the CAN functionality independently and the motor controller (CAN device) does transmit the message correctly over the CAN BUS (I used the .read function to determine this), so I don't think that that would be the issue.

Code is below; any help would be much appreciated.

CAN Test

#include "mbed.h"

CAN canObject(p30,p29);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
Serial pc(USBTX, USBRX);

void test(void) {
    led1= !led1;
    return;  
}

bool speed() {
    char can_msg[3];
    can_msg[0] = 0x3D;
    can_msg[1] = 0x30; 
    can_msg[2] = 0x00;
   
    bool success = canObject.write(CANMessage(0x211, can_msg, 3));
    led2 = !led2;
    return success;
}

int main()
{
    pc.baud(115200);
    wait(0.2);
    canObject.frequency(250000);
    wait(0.2);
    
    canObject.attach(&test, CAN::RxIrq);
    
    wait(1);
    if(speed());
    wait(1);
    if(speed());
    
    while(1) {
        
    }
}

<< program http://mbed.org/users/alexliao1995/code/TestProgramCANInterrupt/ >>

2 Answers

10 years, 1 month ago.

Never used CAN, so might be mistaken, but if you would do this with Serial you would also observe what I think you are observing.

Since you say the while(1) loop also stops functioning I don't think your interrupt is called once: It is called continiously. Your LED is simply flashing fast enough you think it is burning constantly, while it is on 50% of the time at a high frequency. For Serial you need to read the receives character to make the interrupt stop, could it be the same for Can?

From a completely random other program using Can and interrupts:

void recieve1() {
    CANMessage msg1;
    secsIdle=0; // reset deadman switch
    can1.read(msg1);
    if(logOpen)
        logCan(2, msg1);
    led1 = !led1;
}

That is his (/her) interrupt handler, which reads the received message and does something.

6 years, 6 months ago.

Just to confirm that Erik's observation is correct. I had the same issue with my CAN receive interrupt and came across this thread. Putting the CAN.read in the interrupt function clears the interrupt and allows the next receive frame to trigger it again. Thanks Eric!