AnsweredAssumed Answered

Wake up on CAN receive

Question asked by Whitehorn on Sep 26, 2017
Latest reply on Nov 5, 2017 by Daniel Martynek

Hi,

 

I have a working CAN interface code and now want the micro to go to sleep when there are no CAN messages on the bus and to wake on reception of a CAN message.

 

To test this I have a variable I write to with the debug interface to tell it to sleep.  This works as I can see the current supply drop when I activate my sleep.

 

Then I send some CAN frames and nothing happens.

 

I have 3 CAN interfaces active although only one will provide the wake up event.  I have code to re-initialise the other CANs inside their Wake interrupts.

 

This is a sample of my code.  For brevity I show only CAN0 where possible.


    if (Go_to_Sleep == 99)            // Test if I must sleep ?
      {
        CAN0CTL0 |= WUPE;
        CAN1CTL0 |= WUPE;
        CAN4CTL0 |= WUPE;

 

        CAN0RIER |= WUPIE;
        CAN1RIER |= WUPIE;
        CAN4RIER |= WUPIE;

 

        CAN0CTL0 |= SLPRQ;            // Request sleep mode
        CAN1CTL0 |= SLPRQ;            // Request sleep mode
        CAN4CTL0 |= SLPRQ;            // Request sleep mode
        while ((CAN0CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1
        while ((CAN1CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1
        while ((CAN4CTL1 & SLPAK) != 0) ;    // Wait for SLPAK to == 1

 

        _asm ("ANDCC  #$7f");        // Clear S bit
        _asm ("nop");
        _asm ("STOP");            // Enter STOP mode
                                    // Processor will now SLEEP here
                                    // And wakeup here.
      }


ISR                                          // Interrupt on wake
void Isr_CAN0_Wake(void)    // Triggers when the procesor wakes on a Can packet receive
{
    if ((CAN0CTL1 & INITAK) != 0)
      return;            // Not initialised yet

 

    if (((CAN0CTL0 & SLPRQ) != 0) && ((CAN0CTL1 & SLPAK) == 0))
      return;                  // Not yet in Sleep mode: cannot clear SLPRQ
    else
      {
        DisableInterrupts;              // SEI
        CAN0RIER |= WUPIE;        // clear wakeup interrupt
        CAN1RIER |= WUPIE;
        CAN4RIER |= WUPIE;
        EnableInterrupts;                 // CLI

 

        CAN0CTL0 &= ~SLPRQ;        // clear SLPRQ
        CAN1CTL0 &= ~SLPRQ;        //
        CAN4CTL0 &= ~SLPRQ;        //
      }
    Go_to_Sleep = 0;        // Clear my Variable
}

 

void CAN_Init_(void)                        // CAN initialisation called at start up.
{
    CAN0CTL0 |= INITRQ;            // set INITRQ, this will also set INITAK

    while ((CAN0CTL1 & INITAK) != 1) ;    // wait for init mode to occur
    CAN0CTL1 = CTL1;                     // == CANE | BORM
                     
    CAN0BTR0 = BTR0_500;            // == 0xc0
    CAN0BTR1 = BTR1_500;            // == 0x34

 

    CAN0IDAC = IDAM0;            // Four 16 bit acceptance filters

 

    CAN0_Dont_care();               // Setup Acceptance registers
    CAN0CTL0 &= ~INITRQ;            // clear INITRQ.  Restart and synchronise

 

    while ((CAN0CTL1 & INITAK) != 0) ;    // Wait for acknowledge

 

    CAN0RIER = CSCIE | RSTATE0 | TSTATE0 | OVRIE | RXFIE;    // enable receive interrupt RXFIE
    CAN0RFLG = WUPIF | OVRIF | RXF;                // Reset Error Flags
}

 

The CAN1 and CAN4 are initialised with the same values.  The Wake is also the same.

 

My debug interface disconnects when I enter sleep so this is rather difficult to debug.

 

Can you help?

 

Regards,

Wade

Outcomes