硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2499|回复: 3
收起左侧

CAN 接收中断,数据接收异常

[复制链接]

29

主题

101

回帖

188

积分

初级会员

积分
188
发表于 2017-4-21 11:51:50 | 显示全部楼层 |阅读模式
使用Cube库,FreeRTOS,CAN中断接收
中断服务函数如下:
  1. static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
  2. {
  3.   /* Get the Id */
  4.   hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
  5.   if (hcan->pRxMsg->IDE == CAN_ID_STD)
  6.   {
  7.     hcan->pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
  8.   }
  9.   else
  10.   {
  11.     hcan->pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
  12.   }
  13.   
  14.   hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
  15.   /* Get the DLC */
  16.   hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
  17.   /* Get the FIFONumber */
  18.   hcan->pRxMsg->FIFONumber = FIFONumber;
  19.   /* Get the FMI */
  20.   hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
  21.   /* Get the data field */
  22.   hcan->pRxMsg->Data[0U] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
  23.   hcan->pRxMsg->Data[1U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
  24.   hcan->pRxMsg->Data[2U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
  25.   hcan->pRxMsg->Data[3U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
  26.   hcan->pRxMsg->Data[4U] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
  27.   hcan->pRxMsg->Data[5U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
  28.   hcan->pRxMsg->Data[6U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
  29.   hcan->pRxMsg->Data[7U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
  30.   /* Release the FIFO */
  31.   /* Release FIFO0 */
  32.   if (FIFONumber == CAN_FIFO0)
  33.   {
  34.     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
  35.    
  36.     /* Disable FIFO 0 message pending Interrupt */
  37.     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP0);
  38.   }
  39.   /* Release FIFO1 */
  40.   else /* FIFONumber == CAN_FIFO1 */
  41.   {
  42.     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
  43.    
  44.     /* Disable FIFO 1 message pending Interrupt */
  45.     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP1);
  46.   }
  47.   
  48.   if(hcan->State == HAL_CAN_STATE_BUSY_RX)
  49.   {   
  50.     /* Disable Error warning, Error passive, Bus-off, Last error code
  51.        and Error Interrupts */
  52.     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
  53.                                CAN_IT_EPV |
  54.                                CAN_IT_BOF |
  55.                                CAN_IT_LEC |
  56.                                CAN_IT_ERR);
  57.   }
  58.   
  59.   if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
  60.   {
  61.     /* Disable CAN state */
  62.     hcan->State = HAL_CAN_STATE_BUSY_TX;
  63.   }
  64.   else
  65.   {
  66.     /* Change CAN state */
  67.     hcan->State = HAL_CAN_STATE_READY;
  68.   }
  69.   /* Receive complete callback */
  70.   HAL_CAN_RxCpltCallback(hcan);
  71.   /* Return function status */
  72.   return HAL_OK;
  73. }
复制代码
应用代码:
  1. uint8_t can_call(uint8_t dt, uint8_t slot)
  2. {
  3.     CAN_EXID_UN can_id;
  4.     can_id.id.d_id = 0x0;
  5.     can_id.id.dir = CAN_ID_M2S;
  6.     can_id.id.fun = CF_CALL;
  7.     can_id.id.type = dt;
  8.     can_id.id.slot = slot;
  9.     hcan1.pTxMsg->DLC = 1;
  10.     hcan1.pTxMsg->Data[0] = 0xAA;
  11.     hcan1.pTxMsg->ExtId = can_id.value;
  12.     HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0);
  13.     if(HAL_OK == HAL_CAN_Transmit(&hcan1, 10))
  14.     {
  15.         if(can_rec_ack(100))
  16.         {
  17.             log_printf(LOG_INFO, "CAN_RX:0x%X-0x%X,Ack:0x%X;soft_ver:%d;hw_ver:%d;build:%d\r\n",hcan1.Instance->sFIFOMailBox[0].RDLR,
  18.             hcan1.Instance->sFIFOMailBox[0].RDHR, hcan1.pRxMsg->Data[0], hcan1.pRxMsg->Data[1], hcan1.pRxMsg->Data[2], *(uint32_t *)&hcan1.pRxMsg->Data[4]);
  19.             return 1;
  20.         }
  21.         else
  22.         {
  23.             log_printf(LOG_ERR, "%s call dev:%d slot:%d timeout\r\n", __func__, dt, slot);
  24.             return 0;
  25.         }
  26.     }
  27.     else
  28.     {
  29.         log_printf(LOG_ERR, "%s send sta 0x%X\r\n", __func__, hcan1.State);
  30.         return 0;
  31.     }
  32. }
  33. static uint8_t can_rec_ack(uint32_t millisec)
  34. {
  35.     if(osSemaphoreWait(can_xSemaphore, millisec) == osOK)
  36.         return 1;
  37.     else
  38.         return 0;
  39. }
复制代码
主设备呼叫从设备,从设备回复8个字节。主设备先启动接收中断,然后发出呼叫帧,马上从设备回复,HAL_CAN_RxCpltCallback函数发信号量,此时去读hcan1.pRxMsg->Data中的8个字节,发现全0,但是直接通过寄存器访问的方式去读,数据都已经收到了。加延时的话也可以从hcan1.pRxMsg->Data中读取正确的值。是哪里有cache吗?还是其他的什么原因?
回复

使用道具 举报

29

主题

101

回帖

188

积分

初级会员

积分
188
 楼主| 发表于 2017-4-21 11:55:22 | 显示全部楼层
我在中断服务函数的第71行代码执行之后去读hcan1.pRxMsg->Data,数据不对,那说明中断服务函数的22-29行还没生效?
回复

使用道具 举报

7

主题

114

回帖

135

积分

初级会员

积分
135
发表于 2017-4-21 14:23:58 | 显示全部楼层
公司上一个项目 就是用的 hal 库 + freertos  f105 f429 中断接收然后 环形 缓冲区 都用过,没有出现你说的问题。
回复

使用道具 举报

29

主题

101

回帖

188

积分

初级会员

积分
188
 楼主| 发表于 2017-4-21 14:53:16 | 显示全部楼层
问题出在信号量上了CMSIS-RTOS的osSemaphoreCreate(osSemaphore(CAN_SEM) , 1 ),创建了一个信号量,并初始化成有效,所以第一次就没收到CAN数据就进去读了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 18:10 , Processed in 0.167653 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表