STM32F4 - Может ли TX успешно работать каждый раз, но CAN RX успешен только при первом вызове

Я использую плату обнаружения STM32F469 и пытаюсь использовать функции CAN.

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

Мой код для конфигурации / обратного вызова выглядит следующим образом:

/* CAN1 Values */
#define CAN1_CLK_ENABLE()               __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN1_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN1_FORCE_RESET()              __HAL_RCC_CAN1_FORCE_RESET()
#define CAN1_RELEASE_RESET()            __HAL_RCC_CAN1_RELEASE_RESET()
#define CAN1_TX_PIN                    GPIO_PIN_9
#define CAN1_TX_GPIO_PORT              GPIOB 
#define CAN1_TX_AF                     GPIO_AF9_CAN1
#define CAN1_RX_PIN                    GPIO_PIN_8
#define CAN1_RX_GPIO_PORT              GPIOB 
#define CAN1_RX_AF                     GPIO_AF9_CAN1
#define CAN1_RX_IRQn                   CAN1_RX0_IRQn
#define CAN1_RX_IRQHandler             CAN1_RX0_IRQHandler

/* CAN2 Values */
#define CAN2_CLK_ENABLE()               __HAL_RCC_CAN2_CLK_ENABLE()
#define CAN2_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN2_FORCE_RESET()              __HAL_RCC_CAN2_FORCE_RESET()
#define CAN2_RELEASE_RESET()            __HAL_RCC_CAN2_RELEASE_RESET()
#define CAN2_TX_PIN                    GPIO_PIN_13
#define CAN2_TX_GPIO_PORT              GPIOB 
#define CAN2_TX_AF                     GPIO_AF9_CAN2
#define CAN2_RX_PIN                    GPIO_PIN_5
#define CAN2_RX_GPIO_PORT              GPIOB 
#define CAN2_RX_AF                     GPIO_AF9_CAN2
#define CAN2_RX_IRQn                   CAN2_RX0_IRQn
#define CAN2_RX_IRQHandler             CAN2_RX0_IRQHandler

CAN_HandleTypeDef    CanHandle1;
CAN_HandleTypeDef    CanHandle2;

static uint8_t Message_Data[8];

static void CAN1_Config( void )
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    CAN_FilterConfTypeDef CAN_FilterInitStructure;

    static CanTxMsgTypeDef        TxMessage;
    static CanRxMsgTypeDef        RxMessage;

    /* CAN1 Periph clock enable */
    CAN1_CLK_ENABLE();
    CAN1_GPIO_CLK_ENABLE();

    /* CAN1 TX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN1_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN1_TX_AF;

    HAL_GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStruct);

    /* CAN1 RX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN1_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN1_RX_AF;

    HAL_GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStruct);

    /* NVIC configuration for CAN1 Reception complete interrupt */
    HAL_NVIC_SetPriority(CAN1_RX_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX_IRQn);

    CanHandle1.Instance = CAN1;
    CanHandle1.pTxMsg = &TxMessage;
    CanHandle1.pRxMsg = &RxMessage;

    /* CAN peripheral init */
    CanHandle1.Init.TTCM = DISABLE;
    CanHandle1.Init.ABOM = DISABLE;
    CanHandle1.Init.AWUM = DISABLE;
    CanHandle1.Init.NART = DISABLE;
    CanHandle1.Init.RFLM = DISABLE;
    CanHandle1.Init.TXFP = DISABLE;
    CanHandle1.Init.Mode = CAN_MODE_LOOPBACK;
    CanHandle1.Init.SJW = CAN_SJW_1TQ;
    CanHandle1.Init.BS1 = CAN_BS1_6TQ;
    CanHandle1.Init.BS2 = CAN_BS2_8TQ;
    CanHandle1.Init.Prescaler = 2;

    HAL_CAN_Init( &CanHandle1 );

    /* CAN filter init */
    CAN_FilterInitStructure.FilterNumber = 0;
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;
    CAN_FilterInitStructure.FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterIdLow = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.FilterActivation = ENABLE;
    CAN_FilterInitStructure.BankNumber = 0;

    HAL_CAN_ConfigFilter( &CanHandle1, &CAN_FilterInitStructure );

    /* Configure transmission */
    CanHandle1.pTxMsg->StdId = 0x7DF; 
    CanHandle1.pTxMsg->ExtId = 0x7DF; 
    CanHandle1.pTxMsg->RTR = CAN_RTR_DATA;
    CanHandle1.pTxMsg->IDE = CAN_ID_STD;
    CanHandle1.pTxMsg->DLC = 8;
}    

static void CAN2_Config( void )
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    CAN_FilterConfTypeDef CAN_FilterInitStructure;

    static CanTxMsgTypeDef        TxMessage;
    static CanRxMsgTypeDef        RxMessage;

    /* CAN2 Periph clock enable */
    CAN2_CLK_ENABLE();
    CAN2_GPIO_CLK_ENABLE();

    /* CAN2 TX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN2_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN2_TX_AF;

    HAL_GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStruct);

    /* CAN2 RX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN2_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN2_RX_AF;

    HAL_GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStruct);

    /* NVIC configuration for CAN2 Reception complete interrupt */
    HAL_NVIC_SetPriority(CAN2_RX_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN2_RX_IRQn);

    CanHandle2.Instance = CAN2;
    CanHandle2.pTxMsg = &TxMessage;
    CanHandle2.pRxMsg = &RxMessage;

    /* CAN peripheral init */
    CanHandle2.Init.TTCM = DISABLE;
    CanHandle2.Init.ABOM = DISABLE;
    CanHandle2.Init.AWUM = DISABLE;
    CanHandle2.Init.NART = DISABLE;
    CanHandle2.Init.RFLM = DISABLE;
    CanHandle2.Init.TXFP = DISABLE;
    CanHandle2.Init.Mode = CAN_MODE_LOOPBACK;
    CanHandle2.Init.SJW = CAN_SJW_1TQ;
    CanHandle2.Init.BS1 = CAN_BS1_6TQ;
    CanHandle2.Init.BS2 = CAN_BS2_8TQ;
    CanHandle2.Init.Prescaler = 2;

    HAL_CAN_Init( &CanHandle2 );

    /* CAN filter init */
    CAN_FilterInitStructure.FilterNumber = 0; //14 enables CAN1;
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;
    CAN_FilterInitStructure.FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterIdLow = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.FilterActivation = ENABLE;
    CAN_FilterInitStructure.BankNumber = 0; //14 enables CAN1

    HAL_CAN_ConfigFilter( &CanHandle2, &CAN_FilterInitStructure );

    /* Configure transmission */
    CanHandle2.pTxMsg->StdId = 0x7DF; 
    CanHandle2.pTxMsg->ExtId = 0x7DF; 
    CanHandle2.pTxMsg->RTR = CAN_RTR_DATA;
    CanHandle2.pTxMsg->IDE = CAN_ID_STD;
    CanHandle2.pTxMsg->DLC = 8;
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
  EwBspYellowLedOn();

  Message_Data[0] = CanHandle->pRxMsg->Data[0];
  Message_Data[1] = CanHandle->pRxMsg->Data[1];
  Message_Data[2] = CanHandle->pRxMsg->Data[2];
  Message_Data[3] = CanHandle->pRxMsg->Data[3];
  Message_Data[4] = CanHandle->pRxMsg->Data[4];
  Message_Data[5] = CanHandle->pRxMsg->Data[5];
  Message_Data[6] = CanHandle->pRxMsg->Data[6];
  Message_Data[7] = CanHandle->pRxMsg->Data[7];

  if ( HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
  {
    EwBspRedLedOn();
  }
}

CAN_Transmit_Message( void )
{
  CanHandle2.pTxMsg->StdId = 0x7DF;
  CanHandle2.pTxMsg->ExtId = 0x7DF;
  CanHandle2.pTxMsg->Data[0] = 0x02;
  CanHandle2.pTxMsg->Data[1] = 0x01;
  CanHandle2.pTxMsg->Data[2] = 0x0D;
  CanHandle2.pTxMsg->Data[3] = 0x55;
  CanHandle2.pTxMsg->Data[4] = 0x55;
  CanHandle2.pTxMsg->Data[5] = 0x55;
  CanHandle2.pTxMsg->Data[6] = 0x55;
  CanHandle2.pTxMsg->Data[7] = 0x55;

  if ( HAL_CAN_Transmit(&CanHandle, 10) != HAL_OK )
  {
    EwBspOrangeLedOn();
  }

  HAL_Delay(10);
}

Затем я запускаю следующее в моей основной функции для настройки CAN1, CAN2 и прерывания:

/* Configure interrupt for CAN transmission */
CAN1_Config();
CAN2_Config();
HAL_CAN_Receive_IT(&CanHandle2, CAN_FIFO0);

И тогда я бегу CAN_Transmit_Message(),

При этом я проверил, что сообщение успешно передается (оранжевый светодиод НЕ включается), затем выполняется обработчик прерывания приема (включается желтый светодиод) и сообщение успешно принимается (красный светодиод НЕ включается).

Тем не менее, при второй передаче сообщения (еще один вызов CAN_Transmit_Message()) передача еще раз успешна, но прием не удается (горит красный светодиод).

Я создал этот код, следуя структуре в примере кода CAN_Networking, но я не могу понять, почему он не работает на HAL_CAN_Receive_IT функция второго сообщения (после того, как первое сообщение успешно получено).

ПРИМЕЧАНИЕ. После прочтения файла библиотеки stm32f4xx_HAL_CAN я заметил, что существует два типа приема / передачи:

  1. HAL_CAN_Transmit_IT / HAL_CAN_Receive_IT
  2. HAL_CAN_Transmit / HAL_CAN_Receive

Это говорит о том, что 1. не является блокирующим - я так понимаю, это означает, что другое прерывание может быть запущено, пока эта передача / прием еще выполняется?

В моем случае я хочу убедиться, что я получаю ответные данные после отправки передачи, чтобы запросить ее, поэтому я должен использовать функцию 2.? Т.е. я бы вызвал HAL_CAN_Transmit с подходящим тайм-аутом, затем после его завершения вызову HAL_CAN_Receive, снова с подходящим тайм-аутом.

1 ответ

Вы звоните HAL_CAN_Receive_IT каждый раз, когда получаете ответ?

Это один выстрел. Для продолжения приема вызовите его снова в обработчике прерываний.

Другие вопросы по тегам