打印
[STM32F4]

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

[复制链接]
3024|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
captainliuy|  楼主 | 2017-4-21 12:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用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行还没生效?
沙发
captainliuy|  楼主 | 2017-4-21 14:58 | 只看该作者
问题出在信号量上了CMSIS-RTOS的osSemaphoreCreate(osSemaphore(CAN_SEM) , 1 ),创建了一个信号量,并初始化成有效,所以第一次就没收到CAN数据就进去读了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

1

粉丝