今天进行的是can的初步测试,主要通过中断函数接收消息,首先是使能CAN和中断:

  HAL_CAN_Start(&hcan1);
  HAL_CAN_Start(&hcan2);
  HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);

配置CAN Filter

  CAN_FilterTypeDef filter;
  filter.FilterBank = 0;
  filter.FilterMode=CAN_FILTERMODE_IDMASK;
  filter.FilterScale=CAN_FILTERSCALE_32BIT;
  filter.FilterIdHigh=0x0000;
  filter.FilterIdLow=0x0000;
  filter.FilterMaskIdHigh=0x0000;
  filter.FilterMaskIdLow=0x0000;
  filter.FilterFIFOAssignment=CAN_FILTER_FIFO0;
  filter.FilterActivation=ENABLE;

  if(HAL_CAN_ConfigFilter(&hcan1, &filter) != HAL_OK)
  {
    Error_Handler();
  }

编写中断处理函数

uint8_t tx_data[8] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};

void delay_us(uint32_t nus)
{
  uint32_t fac_us = 168;
  uint32_t told, tnow;
  uint32_t tcnt = 0;
  uint32_t reload = SysTick->LOAD;
  uint32_t ticks = nus * fac_us;
  told = SysTick->VAL;
  while(1)
  {
    tnow = SysTick->VAL;
    if(tnow != told)
    {
      if(tnow < told)
        tcnt += told - tnow;
      else
        tcnt += reload - tnow + told;
      told = tnow;
      if(tcnt >= ticks)
        break;
    }
  }
}

uint8_t CANx_SendStdData(CAN_HandleTypeDef* hcan, uint16_t ID, uint8_t *pData, uint16_t Len)
{
  static CAN_TxHeaderTypeDef Tx_Header;

  Tx_Header.StdId=ID;
  Tx_Header.ExtId=0;
  Tx_Header.IDE=0;
  Tx_Header.RTR=0;
  Tx_Header.DLC=Len;

  HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0);
  //if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK)
  //{
  //  if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX1) != HAL_OK)
  //  {
  //    HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX2);
  //  }
  //}
  return 0;
}

CAN_RxHeaderTypeDef rx_header1;
CAN_RxHeaderTypeDef rx_header2;
uint8_t rx_msg_1[8] = {0};
uint8_t rx_msg_2[8] = {0};

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  if(hcan->Instance==CAN1)
  {
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    HAL_CAN_GetRxMessage(&hcan1, CAN_FILTER_FIFO0, &rx_header1, rx_msg_1);
    //HAL_UART_Transmit(&huart2, rx_msg_1, 8, 10000);
    // delay 20 us
    //delay_us(20);
    //CANx_SendStdData(&hcan1, 0x01, tx_data, 8);
    // unpack data
  }
  if(hcan->Instance==CAN2)
  {
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    HAL_CAN_GetRxMessage(&hcan2, CAN_FILTER_FIFO0, &rx_header2, rx_msg_2);
    //HAL_UART_Transmit(&huart2, rx_msg_2, 8, 10000);
    // delay 20 us
    //delay_us(20);
    //CANx_SendStdData(&hcan2, 0x01, tx_data, 8);
    // unpack data
  }
}

如果在中断接收中编写耗时过长的部分,很容易导致CAN中断处理失败。我向让CAN在中断接收时进行数据处理并返回消息,结果并没有成功连续接收。按照1ms的间隔发送消息,仅有开头一部分成功处理,后续的全部失败。