STM32+CAN收发器 休眠 通信失败

2019-07-21 04:23发布

本帖最后由 lvkanger 于 2019-3-12 16:50 编辑

1.系统状态:主机+节点*N;
2.使用芯片:STM32+VP230;
3.运行策略:VP230有standby模式,可以降低系统功耗。所有节点的VP230进入休眠模式。主机的VP230不需要进入休眠模式。
4.通信测试:设计通播ID,即所有节点均可接收的ID。主机发出来的通播ID命令,所有节点都收不到,返回主机CAN发送失败。
                   使其中1个节点VP230不休眠,则主机CAN发送成功,所有节点(不止VP230不休眠的节点)就都可以收到正确的命令。

有知道原因的大佬嘛?求助!!!

代码:

void MX_CAN_Init(void)
{
        CAN_FilterConfTypeDef  sFilterConfig;
        CAN_S_Init();
        /*CAN单元初始化*/
        hCAN.Instance = CAN1;             // CAN外设
        hCAN.pTxMsg = &TxMessage;
        hCAN.pRxMsg = &RxMessage;

        //波特率=PCLK1/((BS1+BS2+1)*Prescaler)
        hCAN.Init.Prescaler = SYS_CLK_M/2;          // BTR-BRP 波特率分频器  定义了时间单元的时间长度 2M/((1+6+3)*1)=0.2Mbps
        hCAN.Init.Mode = CAN_MODE_NORMAL; // 正常工作模式CAN_MODE_NORMAL
        hCAN.Init.SJW = CAN_SJW_2TQ;      // BTR-SJW 重新同步跳跃宽度 2个时间单元
        hCAN.Init.BS1 = CAN_BS1_6TQ;      // BTR-TS1 时间段1 占用了6个时间单元
        hCAN.Init.BS2 = CAN_BS2_3TQ;      // BTR-TS1 时间段2 占用了3个时间单元
        hCAN.Init.TTCM = DISABLE;         // MCR-TTCM  关闭时间触发通信模式使能
        hCAN.Init.ABOM = ENABLE;          // MCR-ABOM  自动离线管理
        hCAN.Init.AWUM = ENABLE;          // MCR-AWUM  使用自动唤醒模式
        hCAN.Init.NART = DISABLE;         // MCR-NART  禁止报文自动重传          DISABLE-自动重传
        hCAN.Init.RFLM = DISABLE;         // MCR-RFLM  接收FIFO 锁定模式  DISABLE-溢出时新报文会覆盖原有报文
        hCAN.Init.TXFP = DISABLE;         // MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符
        HAL_CAN_Init(&hCAN);

        /*CAN过滤器初始化*/
        sFilterConfig.FilterNumber = 0;                    //过滤器组0
        sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;  //工作在标识符屏蔽位模式
        sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //过滤器位宽为单个32位。
        /* 使能报文标示符过滤器按照标示符的内容进行比对过滤,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */
        sFilterConfig.FilterIdHigh = (((u32)BROADCAST_ID<<21)&0xFFFF0000)>>16;                                //要过滤的ID高位
        sFilterConfig.FilterIdLow = (((u32)BROADCAST_ID<<21)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
        sFilterConfig.FilterMaskIdHigh = 0xFFE0;                        //过滤器高8位每位必须匹配
        sFilterConfig.FilterMaskIdLow = 0x0004;                        
        sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;           //过滤器被关联到FIFO 0
        sFilterConfig.FilterActivation = ENABLE;          //使能过滤器
        sFilterConfig.BankNumber = 0;
        HAL_CAN_ConfigFilter(&hCAN, &sFilterConfig);/**/

        CAN_Filter_Set();

        if( HAL_BUSY == HAL_CAN_Receive_IT(&hCAN, CAN_FIFO0))//开启中断接收
        {
                /* Enable FIFO 0 overrun and message pending Interrupt */
        }
        __HAL_CAN_ENABLE_IT(&hCAN, CAN_IT_FOV0|CAN_IT_FMP0|CAN_IT_WKU|CAN_IT_SLK);
        printf("CAN总线初始化成功 ");

        CAN_Transceiver_Sleep();
        //CAN_Transceiver_Work();
}


void CAN1_RX0_IRQHandler(void)
{
        HAL_CAN_IRQHandler(&hCAN);
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)       
{
        if( HAL_BUSY == HAL_CAN_Receive_IT(hcan, CAN_FIFO0))//开启中断接收
        {
                __HAL_CAN_ENABLE_IT(&hCAN, CAN_IT_FOV0 | CAN_IT_FMP0|CAN_IT_WKU|CAN_IT_SLK);
        }
        Enqueue_One_Data_Queue_Can(&queue_can,RxMessage);
        //CAN_Transceiver_Work();
        printf("CAN INT ");
        /*printf("StdId = %X ",RxMessage.StdId);
        printf("ExtId = %X ",RxMessage.ExtId);
        printf("IDE = %X ",RxMessage.IDE);
        printf("RTR = %X ",RxMessage.RTR);
        printf("DLC = %X ",RxMessage.DLC);
        printf("Data = %X",RxMessage.Data[0]);
        printf(" %X",RxMessage.Data[1]);
        printf(" %X",RxMessage.Data[2]);
        printf(" %X",RxMessage.Data[3]);
        printf(" %X",RxMessage.Data[4]);
        printf(" %X",RxMessage.Data[5]);
        printf(" %X",RxMessage.Data[6]);
        printf(" %X ",RxMessage.Data[7]);*/
}


void Can_Send(u16 cmd,u8 *buf,u8 len)
{
        //CAN_Work();

        hCAN.pTxMsg->StdId = 0;//0x1314;
        hCAN.pTxMsg->ExtId= (dev_config.dev_id<<18)|cmd;//
        hCAN.pTxMsg->RTR = CAN_RTR_DATA;
        hCAN.pTxMsg->IDE = CAN_ID_EXT;
        hCAN.pTxMsg->DLC = len;
        memcpy(hCAN.pTxMsg->Data,buf,len);

        CAN_Transceiver_Work();
        if(HAL_CAN_Transmit(&hCAN, 1000) != HAL_OK)
        {
                printf("CAN 发送失败 ");
        }
        CAN_Transceiver_Sleep();
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
正点原子
1楼-- · 2019-07-21 09:27
帮顶
lvkanger
2楼-- · 2019-07-21 10:59
通过读取错误寄存器CAN->ESR发现 LRC=5:显性错误。说明CAN总线上的数据被休眠模式的VP230接收到,并从RXD引脚输出给STM32的CAN控制器。那么,问题就在于CAN控制器接收到正确的数据之后没有在ACK间隙输出显性位,导致主机认为CAN发送失败?那ACK回复又是怎么实现的呢?
lvkanger
3楼-- · 2019-07-21 14:27
 精彩回答 2  元偷偷看……
swa00000
4楼-- · 2019-07-21 18:33
VP230  都休眠了  系统怎么能获取数据呢  VP230 是收发器 类似解码器    解码器休眠等于不工作了  数据没法通讯的  除非 VP230有数据唤醒功能  STM32休眠也不能让 VP230休眠  
lvkanger
5楼-- · 2019-07-21 19:14
swa00000 发表于 2019-3-13 16:59
VP230  都休眠了  系统怎么能获取数据呢  VP230 是收发器 类似解码器    解码器休眠等于不工作了  数据没法 ...

VP230有休眠模式,是只听不发的。我用示波器再RX脚是可以抓到波形的。

一周热门 更多>