Проблема, связанная с программированием микроконтроллера STM32 с шиной CAN

Я новичок в микроконтроллерах STM32 и протоколе связи CAN-шины, и я работаю над программированием STM32F103xx микроконтроллер. Я хочу использовать CAN-шину для передачи данных на другой микроконтроллер из того же семейства.

Я установил все необходимые настройки, но при отладке кода он застревает в функции ожидания передачи и не передает. Я хочу, чтобы данные передавались, но это не так.

Я не верю, что у меня проблема с оборудованием.

PS: Я пробовал как нормальный режим, так и режим LOOPBACK для обработчика CAN, и они оба не работали.

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");
        }
    }
}

person Ward Mas    schedule 02.07.2019    source источник


Ответы (1)


Вы используете STM32CubeF1 HAL (возможно, через STM32CubeMX). Проверьте соответствующий Руководство пользователя - раздел 9.2.1 рекомендует следующую процедуру:

  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
      • Сконфигурируйте контакты CAN как альтернативную функцию с открытым стоком
    • В случае использования прерываний [...]
  2. Инициализируйте периферийное устройство CAN с помощью функции HAL_CAN_Init(). Эта функция обращается к HAL_CAN_MspInit() для инициализации низкого уровня.
  3. Configure the reception filters using the following configuration functions:
    • HAL_CAN_ConfigFilter()
  4. Запустите модуль CAN с помощью функции HAL_CAN_Start(). На этом уровне узел активен на шине: он принимает сообщения и может отправлять сообщения.
  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(), чтобы проверить, ожидает ли сообщение в почтовом ящике Tx.
    • [...]
  6. Когда сообщение получено в FIFO CAN Rx, его можно получить с помощью функции HAL_CAN_GetRxMessage(). Функция HAL_CAN_GetRxFifoFillLevel () позволяет узнать, сколько сообщений Rx хранится в Rx Fifo.
  7. Вызов функции HAL_CAN_Stop() останавливает модуль CAN.
  8. Деинициализация достигается с помощью функции HAL_CAN_DeInit().

[...]

Работа в режиме опроса / передача:

  • Контролируйте доступность почтовых ящиков Tx до тех пор, пока не освободится хотя бы один почтовый ящик Tx, используя HAL_CAN_GetTxMailboxesFreeLevel().
  • Затем запросите передачу сообщения, используя HAL_CAN_AddTxMessage().

В вашем примере кода не показаны подфункции, вызываемые из main(), поэтому вам нужно проверить себя :-), что

  • Часы CAN / GPIO были включены до того, как были назначены соответствующие регистры.
  • Контакты GPIO настроены в соответствии с рекомендациями.

Другая мысль - может быть, нужно проверять HAL_CAN_GetTxMailboxesFreeLevel() после запуска CAN, даже до добавления первого сообщения для передачи?

Шаги (2.), (4.), (5.) уже учтены вашим кодом, а шаги (3.), (6.), (7.), (8.) не связаны с вашим кодом. проблема (но только с приемом / деинитом).


Если вы не хотите выполнять всю ручную работу самостоятельно, вы также можете использовать один из следующих инструментов в качестве отправной точки. Оба инструмента далеки от совершенства (и некоторые из наших коллег по StackOverflow вообще не согласны рекомендовать их), но часто они уже предоставляют базовую структуру с большинством необходимых шагов:

person HelpingHand    schedule 01.06.2020