Ward Mas
Ward Mas

Reputation: 53

Problem related to programing STM32 microcontroller with CAN bus

I am new to STM32 microcontrollers and CAN bus communication protocol and I am working on programing an STM32F103xx microcontroller. I want to use CAN bus for transmitting data to another microcontroller from the same family.

I set up all the necessary settings but when debugging the code it gets stuck in the transmitting pending function and doesn't transmit. I want the data to be transmitted but it is not.

I don't believe I have a problem with my hardware.

PS: I have tried both normal mode and LOOPBACK mode for CAN handler and they both didn't work.

int main(void)
{
    HAL_Init();

    SystemClock_Config();

    uint32_t BUTTON_0;
    uint32_t BUTTON_1;

    uint8_t Data_0[5] = "aaaaa";
    uint8_t Data_1[5] = "ZZZZZ";

    MX_GPIO_Init();
    MX_CAN_Init();

    if(HAL_CAN_Init(&hcan) != HAL_OK){
        Error_Handler();
    }

    if(HAL_CAN_Start(&hcan) != HAL_OK){
        Error_Handler();
    }

    while (1)
    {       
        TxHeader.DLC   = 5;
        TxHeader.StdId = 0x65D;
        TxHeader.IDE   = CAN_ID_STD;
        TxHeader.RTR   = CAN_RTR_DATA;

        BUTTON_0 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

        BUTTON_1 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);

        if (BUTTON_0 == 0U){

            if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_0, &TxMailbox) != HAL_OK ){
                Error_Handler();
            }

        }

        if (BUTTON_1 == 0U){

            if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_1, &TxMailbox) != HAL_OK){
                Error_Handler();
            }

        }

        while (HAL_CAN_IsTxMessagePending(&hcan, TxMailbox));

        if (BUTTON_0 && BUTTON_1 == 0U){
            printf("Please Press a Button");
        }
    }
}

Upvotes: 2

Views: 4830

Answers (1)

HelpingHand
HelpingHand

Reputation: 1468

You are using STM32CubeF1 HAL libraries (probably through STM32CubeMX). Please check the corresponding User Manual - section 9.2.1 recommends the following procedure:

  1. Initialize the CAN low level resources by implementing the HAL_CAN_MspInit():
    • Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE()
    • Configure CAN pins
      • Enable the clock for the CAN GPIOs
      • Configure CAN pins as alternate function open-drain
    • In case of using interrupts [...]
  2. Initialize the CAN peripheral using HAL_CAN_Init() function. This function resorts to HAL_CAN_MspInit() for low-level initialization.
  3. Configure the reception filters using the following configuration functions:
    • HAL_CAN_ConfigFilter()
  4. Start the CAN module using HAL_CAN_Start() function. At this level the node is active on the bus: it receive messages, and can send messages.
  5. To manage messages transmission, the following Tx control functions can be used:
    • HAL_CAN_AddTxMessage() to request transmission of a new message.
    • [...]
    • HAL_CAN_IsTxMessagePending() to check if a message is pending in a Tx mailbox.
    • [...]
  6. When a message is received into the CAN Rx FIFOs, it can be retrieved using the HAL_CAN_GetRxMessage() function. The function HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are stored in the Rx Fifo.
  7. Calling the HAL_CAN_Stop() function stops the CAN module.
  8. The deinitialization is achieved with HAL_CAN_DeInit() function.

[...]

Polling mode operation / Transmission:

  • Monitor the Tx mailboxes availability until at least one Tx mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel().
  • Then request transmission of a message using HAL_CAN_AddTxMessage().

Your code sample doesn't show the sub-functions called from main() so you have to check yourself :-) that

  • CAN/GPIO clocks have been enabled before the corresponding registers are assigned.
  • GPIO pins are configured as recommended.

Another thought - could it be that you have to check HAL_CAN_GetTxMailboxesFreeLevel() after starting the CAN, even before adding the first message for transmission?

Steps (2.), (4.), (5.) are already taken care of by your code, and steps (3.), (6.), (7.), (8.) are not related to your problem (but only to reception / deinit).


If you don't want to do all the manual work yourself, you can also use one of the following tools as a starting point. Both tools are far from perfect (and some of our StackOverflow peers disagree to recommend them at all), but often they already provide a basic structure with most of the relevant steps you need:

Upvotes: 2

Related Questions