LPC11c24 LPC open example CAN not receiving messages

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC11c24 LPC open example CAN not receiving messages

3,593 Views
finalargasio
Contributor II

Dear community,

I am testing two LPC11c24 evaluation boards CAN BUS.

To do so, I have connected the units CAN_H,CAN_L, powered VCC and loaded the LPCopen CAN example on both boards.

In the loaded LPCOpen example the two boards should respond to each other messages thereby transmitting continuosly however this does not happen, as only the first "starting message is sent then nothing else happens.

By using a Can analyzer I can see that messages are being sent successfully by both boards when they are started up, however they do not react at each other, it seems they cannot receive at all messages.

I am saying this because I have put a breakpoint inside the Rx interrupt routine and the program never stops there (this for both boards).

in short

-The code is from LPCopen library for 11c24, so I assume it should be fine

-Boards are plugged in the right way since the CAN analyzer is receiving the correct messages.

-Their CAN is properly configured as messages are transmitted

-Something is wrong with message reception.

Any idea on what could cause this problem?

Labels (3)
8 Replies

2,977 Views
finalargasio
Contributor II

Thanks Jeremy!

Your answer made me realize how to properly configure CAN filters with LPCopen which was a kinf of mistery for me!

To anyone reading this, I attach a document with my considerations on how to properly set upt filters with CAN open I hope it is correct and will help others in my same situation

2,700 Views
kaansarica
Contributor I

That PDF was very helpful for me too. Thank you.

Tags (1)
0 Kudos
Reply

2,977 Views
jeremyzhou
NXP Employee
NXP Employee

Hi mat ric,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
In the LPCOpen library, periph_ccan_rom will transmit the CAN frame prior to initializing the receive function, in the other word, both two board transfer CAN frame to each other, while the receive function is not ready.
So I'd highly recommend you to use the CAN analyzer to simulate another board to contact with one LPC11C24 evaluation board, I think the LPC11C24 evaluation board can response the received CAN frame which is transmitted by the CAN analyzer.
Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

2,977 Views
finalargasio
Contributor II

jeremyzhou ha scritto:

Hi mat ric,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
In the LPCOpen library, periph_ccan_rom will transmit the CAN frame prior to initializing the receive function, in the other word, both two board transfer CAN frame to each other, while the receive function is not ready.
So I'd highly recommend you to use the CAN analyzer to simulate another board to contact with one LPC11C24 evaluation board, I think the LPC11C24 evaluation board can response the received CAN frame which is transmitted by the CAN analyzer.
Have a great day,
TIC

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

Dear jeremy,

Thank you for your answer, I have tried doing as you say however it did not produce the desired result,

I have also tried pushing the transmit routine inside the main loop, placing a 1second delay between each transmisison.

Even though both boards have the same code running at the same time and their CAN is actually transmitting as desired, none of them are reaching the CAN_Rx routine as if the could not see the messages sent by the other board.

The CAN_Tx IRQ is working fine, so I doubt it is a interrupt configuration problem.

The CAN analyzer is properly showing the messages sent by both boards.

I post the code below, maybe you have better luck understanding this enigma than I !

/*
 * @brief CCAN on-chip driver example
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2012
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include "board.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/
#define CANRXOK         (*((volatile unsigned long *) (0x40050004+0x04)))
#define TEST_CCAN_BAUD_RATE 500000
#define T0MR0          (*((volatile unsigned long *) 0x40014014))
#define T0TC          (*((volatile unsigned long *) 0x40014008))
CCAN_MSG_OBJ_T msg_obj;
int tieniconto = 0;
uint32_t timerFreq;
/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/
void Delay(int Ms){
    /* Timer rate is system clock rate */
    timerFreq = Chip_Clock_GetSystemClockRate();
    uint32_t CurrentTime;
    /* Timer setup for match and interrupt at TICKRATE_HZ */
    //Chip_TIMER_Reset(LPC_TIMER32_0);
    Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 0);
    CurrentTime = T0TC;
    Chip_TIMER_SetMatch(LPC_TIMER32_0, 0, CurrentTime+Ms*(timerFreq / 1000));
    Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 0);
    Chip_TIMER_Enable(LPC_TIMER32_0);
    while(((T0MR0)&(0x01))==0x01);
    //Chip_TIMER_Disable(LPC_TIMER32_0);
    //Chip_TIMER_Reset(LPC_TIMER32_0);

}
void baudrateCalculate(uint32_t baud_rate, uint32_t *can_api_timing_cfg)
{
    uint32_t pClk, div, quanta, segs, seg1, seg2, clk_per_bit, can_sjw;
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN);
    pClk = Chip_Clock_GetMainClockRate();

    clk_per_bit = pClk / baud_rate;

    for (div = 0; div <= 15; div++) {
        for (quanta = 1; quanta <= 32; quanta++) {
            for (segs = 3; segs <= 17; segs++) {
                if (clk_per_bit == (segs * quanta * (div + 1))) {
                    segs -= 3;
                    seg1 = segs / 2;
                    seg2 = segs - seg1;
                    can_sjw = seg1 > 3 ? 3 : seg1;
                    can_api_timing_cfg[0] = div;
                    can_api_timing_cfg[1] =
                        ((quanta - 1) & 0x3F) | (can_sjw & 0x03) << 6 | (seg1 & 0x0F) << 8 | (seg2 & 0x07) << 12;
                    return;
                }
            }
        }
    }
}

/*    CAN receive callback */
/*    Function is executed by the Callback handler after
    a CAN message has been received */
void CAN_rx(uint8_t msg_obj_num) {
    /* Determine which CAN message has been received */
    msg_obj.msgobj = msg_obj_num;
    /* Now load up the msg_obj structure with the CAN message */
    LPC_CCAN_API->can_receive(&msg_obj);
    if (msg_obj_num == 1) {
        /* Simply transmit CAN frame (echo) with with ID +0x100 via buffer 2 */
        msg_obj.msgobj = msg_obj.msgobj+1;
        msg_obj.mode_id = 600;
        LPC_CCAN_API->can_transmit(&msg_obj);
    }
}

/*    CAN transmit callback */
/*    Function is executed by the Callback handler after
    a CAN message has been transmitted */
void CAN_tx(uint8_t msg_obj_num) {
    tieniconto++;
}

/*    CAN error callback */
/*    Function is executed by the Callback handler after
    an error has occured on the CAN bus */
void CAN_error(uint32_t error_info) {}

/**
 * @brief    CCAN Interrupt Handler
 * @return    Nothing
 * @note    The CCAN interrupt handler must be provided by the user application.
 *    It's function is to call the isr() API located in the ROM
 */
void CAN_IRQHandler(void) {
    LPC_CCAN_API->isr();
}

/*Timer Interrupt*/

void TIMER32_0_IRQHandler(void)
{
    if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 0)) {
        /*Clear Interrupt*/
        Chip_TIMER_ClearMatch(LPC_TIMER32_0, 0);
        /*Disable further interrupt*/
        Chip_TIMER_MatchDisableInt(LPC_TIMER32_0, 0);
    }
}
/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief    Main routine for CCAN_ROM example
 * @return    Nothing
 */
int main(void)
{

    uint32_t CanApiClkInitTable[2];
    /* Publish CAN Callback Functions */
    CCAN_CALLBACKS_T callbacks = {
        CAN_rx,
        CAN_tx,
        CAN_error,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
    };
    SystemCoreClockUpdate();
    Board_Init();
    baudrateCalculate(TEST_CCAN_BAUD_RATE, CanApiClkInitTable);

    LPC_CCAN_API->init_can(&CanApiClkInitTable[0], TRUE);
    /* Configure the CAN callback functions */
    LPC_CCAN_API->config_calb(&callbacks);
    /* Enable the CAN Interrupt */
    NVIC_EnableIRQ(CAN_IRQn);

    /*Configure Timer 0*/
    Chip_TIMER_Init(LPC_TIMER32_0);
    NVIC_ClearPendingIRQ(TIMER_32_0_IRQn);
    NVIC_EnableIRQ(TIMER_32_0_IRQn);

    /* Send a simple one time CAN message */
    msg_obj.msgobj  = 0;
    msg_obj.mode_id = 0x345;
    msg_obj.mask    = 0x7F0;
    msg_obj.dlc     = 4;
    msg_obj.data[0] = 'T';    // 0x54
    msg_obj.data[1] = 'E';    // 0x45
    msg_obj.data[2] = 'S';    // 0x53
    msg_obj.data[3] = 'T';    // 0x54
    LPC_CCAN_API->can_transmit(&msg_obj);

    /* Configure message object 1 to receive all 11-bit messages 0x400-0x4FF */
    msg_obj.msgobj = 1;
    msg_obj.mode_id = 0x400;
    msg_obj.mask = 0x700;
    LPC_CCAN_API->config_rxmsgobj(&msg_obj);

    while (1) {
        msg_obj.mode_id = 0x500;
        LPC_CCAN_API->can_transmit(&msg_obj);
        Delay(1000);
    }
}
0 Kudos
Reply

2,977 Views
jeremyzhou
NXP Employee
NXP Employee

Hi mat ric,

Thanks for your reply.
I'd like to illustrate the testing I did.
1. Program the periph_ccan_rom an LPCXpress LPC11C24 board.
2. The CAN analyzer simulates an LPCXpress LPC11C24 board, then connect the really LPCXpress LPC11C24 board.
3. The CAN analyzer repeat send 10 of frames, and it receives 10 responses from the LPCXpress LPC11C24 board.

pastedImage_1.png

Fig1 CAN analyzer tool

pastedImage_4.png

Fig2 Hardware connection


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

2,977 Views
finalargasio
Contributor II

Dear Jeremy,

I have found out that the Board does receive the message as when a message is received, the interrupt is generated, however the IRQ handler does not call or at list does not jump to the CAN_rx isr, how come is that? Do you have any clue?

0 Kudos
Reply

2,977 Views
jeremyzhou
NXP Employee
NXP Employee

Hi mat ric,

Thanks for your reply.
I've not encountered the phenomenon you describe, actually, your code works well with LPC11C24 board.
Note; I modify a bit segment of code, however, it doesn't affect the main function of the code.
You can review the modified code and testing result at below.

#include "board.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/
#define CANRXOK         (*((volatile unsigned long *) (0x40050004+0x04)))
#define TEST_CCAN_BAUD_RATE 500000
#define T0MR0          (*((volatile unsigned long *) 0x40014014))
#define T0TC          (*((volatile unsigned long *) 0x40014008))
CCAN_MSG_OBJ_T msg_obj,msg_obj_tranmit;
int tieniconto = 0;
uint32_t timerFreq;
/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/
void Delay(int Ms){
    /* Timer rate is system clock rate */
    timerFreq = Chip_Clock_GetSystemClockRate();
    uint32_t CurrentTime;
    /* Timer setup for match and interrupt at TICKRATE_HZ */
    //Chip_TIMER_Reset(LPC_TIMER32_0);
    Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 0);
    CurrentTime = T0TC;
    Chip_TIMER_SetMatch(LPC_TIMER32_0, 0, CurrentTime+Ms*(timerFreq / 1000));
    Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 0);
    Chip_TIMER_Enable(LPC_TIMER32_0);
    while(((T0MR0)&(0x01))==0x01);
    //Chip_TIMER_Disable(LPC_TIMER32_0);
    //Chip_TIMER_Reset(LPC_TIMER32_0);

}
void baudrateCalculate(uint32_t baud_rate, uint32_t *can_api_timing_cfg)
{
    uint32_t pClk, div, quanta, segs, seg1, seg2, clk_per_bit, can_sjw;
    Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN);
    pClk = Chip_Clock_GetMainClockRate();

    clk_per_bit = pClk / baud_rate;

    for (div = 0; div <= 15; div++) {
        for (quanta = 1; quanta <= 32; quanta++) {
            for (segs = 3; segs <= 17; segs++) {
                if (clk_per_bit == (segs * quanta * (div + 1))) {
                    segs -= 3;
                    seg1 = segs / 2;
                    seg2 = segs - seg1;
                    can_sjw = seg1 > 3 ? 3 : seg1;
                    can_api_timing_cfg[0] = div;
                    can_api_timing_cfg[1] =
                        ((quanta - 1) & 0x3F) | (can_sjw & 0x03) << 6 | (seg1 & 0x0F) << 8 | (seg2 & 0x07) << 12;
                    return;
                }
            }
        }
    }
}

/*    CAN receive callback */
/*    Function is executed by the Callback handler after
    a CAN message has been received */
void CAN_rx(uint8_t msg_obj_num) {
    /* Determine which CAN message has been received */
    msg_obj.msgobj = msg_obj_num;
    /* Now load up the msg_obj structure with the CAN message */
    LPC_CCAN_API->can_receive(&msg_obj);
    if (msg_obj_num == 1) {
        /* Simply transmit CAN frame (echo) with with ID +0x100 via buffer 2 */
        msg_obj.msgobj = msg_obj.msgobj+1;
        msg_obj.mode_id = 600;
        LPC_CCAN_API->can_transmit(&msg_obj);
    }
}

/*    CAN transmit callback */
/*    Function is executed by the Callback handler after
    a CAN message has been transmitted */
void CAN_tx(uint8_t msg_obj_num) {
    tieniconto++;
}

/*    CAN error callback */
/*    Function is executed by the Callback handler after
    an error has occured on the CAN bus */
void CAN_error(uint32_t error_info) {}

/**
 * @brief    CCAN Interrupt Handler
 * @return    Nothing
 * @note    The CCAN interrupt handler must be provided by the user application.
 *    It's function is to call the isr() API located in the ROM
 */
void CAN_IRQHandler(void) {
    LPC_CCAN_API->isr();
}

/*Timer Interrupt*/

void TIMER32_0_IRQHandler(void)
{
    if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 0)) {
        /*Clear Interrupt*/
        Chip_TIMER_ClearMatch(LPC_TIMER32_0, 0);
        /*Disable further interrupt*/
        Chip_TIMER_MatchDisableInt(LPC_TIMER32_0, 0);
    }
}
/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief    Main routine for CCAN_ROM example
 * @return    Nothing
 */
int main(void)
{

    uint32_t CanApiClkInitTable[2];
    /* Publish CAN Callback Functions */
    CCAN_CALLBACKS_T callbacks = {
        CAN_rx,
        CAN_tx,
        CAN_error,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL,
    };
    SystemCoreClockUpdate();
    Board_Init();
    baudrateCalculate(TEST_CCAN_BAUD_RATE, CanApiClkInitTable);

    LPC_CCAN_API->init_can(&CanApiClkInitTable[0], TRUE);
    /* Configure the CAN callback functions */
    LPC_CCAN_API->config_calb(&callbacks);
    /* Enable the CAN Interrupt */
    NVIC_EnableIRQ(CAN_IRQn);

    /*Configure Timer 0*/
    Chip_TIMER_Init(LPC_TIMER32_0);
    NVIC_ClearPendingIRQ(TIMER_32_0_IRQn);
    NVIC_EnableIRQ(TIMER_32_0_IRQn);

    /* Send a simple one time CAN message */
    msg_obj.msgobj  = 0;
    msg_obj.mode_id = 0x345;
    msg_obj.mask    = 0x7F0;
    msg_obj.dlc     = 4;
    msg_obj.data[0] = 'T';    // 0x54
    msg_obj.data[1] = 'E';    // 0x45
    msg_obj.data[2] = 'S';    // 0x53
    msg_obj.data[3] = 'T';    // 0x54
    LPC_CCAN_API->can_transmit(&msg_obj);

    /* Configure message object 1 to receive all 11-bit messages 0x400-0x4FF */
    msg_obj.msgobj = 1;
    msg_obj.mode_id = 0x400;
    msg_obj.mask = 0x700;
    LPC_CCAN_API->config_rxmsgobj(&msg_obj);

    while (1) {
         msg_obj_tranmit.msgobj  = 3;
         msg_obj_tranmit.mode_id = 0x345;
         msg_obj_tranmit.mask    = 0x7F0;
         msg_obj_tranmit.dlc     = 4;
         msg_obj_tranmit.data[0] = 'O';   
         msg_obj_tranmit.data[1] = 'K';    
         msg_obj_tranmit.data[2] = 'a';    
         msg_obj_tranmit.data[3] = 'y';   
        LPC_CCAN_API->can_transmit(&msg_obj_tranmit);
        Delay(1000);
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

pastedImage_1.png

Fig 1 Testing result.


Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,977 Views
finalargasio
Contributor II

Dear Jeremy,

Thanks for your reply, but I still cannot get it working, even if I send packets via CAN analyzer my LPC11c24 won't get inside the Rx routine, this happens in both boards!

Did you by any chance try the code I posted? Was it working for you?

0 Kudos
Reply