captainliuy 发表于 2017-4-21 12:24:18

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

使用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.RIR;
if (hcan->pRxMsg->IDE == CAN_ID_STD)
{
    hcan->pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox.RIR >> 21U);
}
else
{
    hcan->pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox.RIR >> 3U);
}

hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox.RIR;
/* Get the DLC */
hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox.RDTR;
/* Get the FIFONumber */
hcan->pRxMsg->FIFONumber = FIFONumber;
/* Get the FMI */
hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDTR >> 8U);
/* Get the data field */
hcan->pRxMsg->Data = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox.RDLR;
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDLR >> 8U);
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDLR >> 16U);
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDLR >> 24U);
hcan->pRxMsg->Data = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox.RDHR;
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDHR >> 8U);
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.RDHR >> 16U);
hcan->pRxMsg->Data = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox.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 = 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.RDLR,
            hcan1.Instance->sFIFOMailBox.RDHR, hcan1.pRxMsg->Data, hcan1.pRxMsg->Data, hcan1.pRxMsg->Data, *(uint32_t *)&hcan1.pRxMsg->Data);
            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行还没生效?

captainliuy 发表于 2017-4-21 14:58:17

问题出在信号量上了CMSIS-RTOS的osSemaphoreCreate(osSemaphore(CAN_SEM) , 1 ),创建了一个信号量,并初始化成有效,所以第一次就没收到CAN数据就进去读了
页: [1]
查看完整版本: CAN 接收中断,数据接收异常