OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4372|回复: 5

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

[复制链接]

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7573
金钱
7573
注册时间
2016-11-30
在线时间
643 小时
发表于 2019-3-12 16:12:19 | 显示全部楼层 |阅读模式
50金钱
本帖最后由 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总线初始化成功\r\n");

        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\r\n");
        /*printf("StdId = %X\r\n",RxMessage.StdId);
        printf("ExtId = %X\r\n",RxMessage.ExtId);
        printf("IDE = %X\r\n",RxMessage.IDE);
        printf("RTR = %X\r\n",RxMessage.RTR);
        printf("DLC = %X\r\n",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\r\n",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 发送失败\r\n");
        }
        CAN_Transceiver_Sleep();
}

CAN错误波形1

CAN错误波形1

CAN错误波形2

CAN错误波形2
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2019-3-13 02:24:04 | 显示全部楼层
回复

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7573
金钱
7573
注册时间
2016-11-30
在线时间
643 小时
 楼主| 发表于 2019-3-13 10:16:17 | 显示全部楼层
通过读取错误寄存器CAN->ESR发现 LRC=5:显性错误。说明CAN总线上的数据被休眠模式的VP230接收到,并从RXD引脚输出给STM32的CAN控制器。那么,问题就在于CAN控制器接收到正确的数据之后没有在ACK间隙输出显性位,导致主机认为CAN发送失败?那ACK回复又是怎么实现的呢?
回复

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7573
金钱
7573
注册时间
2016-11-30
在线时间
643 小时
 楼主| 发表于 2019-3-13 15:24:04 | 显示全部楼层
通过观察CAN->MSR寄存器发现,原来是WKUP中断一直没有置位。原因是CAN控制器没有进入休眠模式。而EER位一直是在置位状态,说明检测到总线有错误。
最终采取的策略是:CAN1_SCE_IRQHandler中断里进行处理,切换CAN收发器到正常模式,这样就可以正常接收了,所有节点都可以正常进入休眠状态而不丢数据。但是如果发送连续大量数据的话,还是会丢数据,但是可以让节点提前进入正常模式,实现不丢数据。
不知有没有更好的解决方案了,期待大神!!!!
回复

使用道具 举报

1

主题

48

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2018-8-16
在线时间
70 小时
发表于 2019-3-13 16:59:10 | 显示全部楼层
VP230  都休眠了  系统怎么能获取数据呢  VP230 是收发器 类似解码器    解码器休眠等于不工作了  数据没法通讯的  除非 VP230有数据唤醒功能  STM32休眠也不能让 VP230休眠  
回复

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7573
金钱
7573
注册时间
2016-11-30
在线时间
643 小时
 楼主| 发表于 2019-3-13 17:30:56 | 显示全部楼层
swa00000 发表于 2019-3-13 16:59
VP230  都休眠了  系统怎么能获取数据呢  VP230 是收发器 类似解码器    解码器休眠等于不工作了  数据没法 ...

VP230有休眠模式,是只听不发的。我用示波器再RX脚是可以抓到波形的。
TIM截图20190313173117.jpg
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-24 01:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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