使用Cube库,FreeRTOS,CAN中断接收
Cube Can 中断服务函数如下:
static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
{
/* Get the Id */
hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
if (hcan->pRxMsg->IDE == CAN_ID_STD)
{
hcan->pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
}
else
{
hcan->pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
}
hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
/* Get the DLC */
hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
/* Get the FIFONumber */
hcan->pRxMsg->FIFONumber = FIFONumber;
/* Get the FMI */
hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
/* Get the data field */
hcan->pRxMsg->Data[0U] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
hcan->pRxMsg->Data[1U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
hcan->pRxMsg->Data[2U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
hcan->pRxMsg->Data[3U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
hcan->pRxMsg->Data[4U] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
hcan->pRxMsg->Data[5U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
hcan->pRxMsg->Data[6U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
hcan->pRxMsg->Data[7U] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
/* Release the FIFO */
/* Release FIFO0 */
if (FIFONumber == CAN_FIFO0)
{
__HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
/* Disable FIFO 0 message pending Interrupt */
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP0);
}
/* Release FIFO1 */
else /* FIFONumber == CAN_FIFO1 */
{
__HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
/* Disable FIFO 1 message pending Interrupt */
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP1);
}
if(hcan->State == HAL_CAN_STATE_BUSY_RX)
{
/* Disable Error warning, Error passive, Bus-off, Last error code
and Error Interrupts */
__HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
CAN_IT_EPV |
CAN_IT_BOF |
CAN_IT_LEC |
CAN_IT_ERR);
}
if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)
{
/* Disable CAN state */
hcan->State = HAL_CAN_STATE_BUSY_TX;
}
else
{
/* Change CAN state */
hcan->State = HAL_CAN_STATE_READY;
}
/* Receive complete callback */
HAL_CAN_RxCpltCallback(hcan);
/* Return function status */
return HAL_OK;
}
我的应用程序:
static uint8_t can_rec_ack(uint32_t millisec)
{
if(osSemaphoreWait(can_xSemaphore, millisec) == osOK)
return 1;
else
return 0;
}
uint8_t can_call(uint8_t dt, uint8_t slot)
{
CAN_EXID_UN can_id;
can_id.id.d_id = 0x0;
can_id.id.dir = CAN_ID_M2S;
can_id.id.fun = CF_CALL;
can_id.id.type = dt;
can_id.id.slot = slot;
hcan1.pTxMsg->DLC = 1;
hcan1.pTxMsg->Data[0] = 0xAA;
hcan1.pTxMsg->ExtId = can_id.value;
HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0);
if(HAL_OK == HAL_CAN_Transmit(&hcan1, 10))
{
if(can_rec_ack(100))
{
osDelay(2);
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,
hcan1.Instance->sFIFOMailBox[0].RDHR, hcan1.pRxMsg->Data[0], hcan1.pRxMsg->Data[1], hcan1.pRxMsg->Data[2], *(uint32_t *)&hcan1.pRxMsg->Data[4]);
return 1;
}
else
{
log_printf(LOG_ERR, "%s call dev:%d slot:%d timeout\r\n", __func__, dt, slot);
return 0;
}
}
else
{
log_printf(LOG_ERR, "%s send sta 0x%X\r\n", __func__, hcan1.State);
return 0;
}
}
主设备呼叫从设备,从设备回复8个字节。主设备先启动接收中断,然后发出呼叫帧,马上从设备回复,HAL_CAN_RxCpltCallback函数发信号量,此时去读hcan1.pRxMsg->Data中的8个字节,发现全0,但是直接通过寄存器访问的方式去读,数据都已经收到了。加延时的话也可以从hcan1.pRxMsg->Data中读取正确的值。是哪里有cache吗?还是其他的什么原因?
我在中断服务函数的第71行代码执行之后去读hcan1.pRxMsg->Data,数据不对,那说明中断服务函数的22-29行还没生效? |