[技术问答] HC32F460 CAN通讯问题

[复制链接]
 楼主| luckyren 发表于 2023-1-13 09:01 | 显示全部楼层 |阅读模式
本帖最后由 luckyren 于 2023-1-13 09:04 编辑

我在调试HC32F460的CAN通讯时发现如果同时收到了两帧数据,第二帧数据会保存下来,导致下面接收的数据是上一帧的数据,然后后面的接收都错位了,中断里也清标志位了,有人指导一下吗?我的初始化及中断接收处理如下:
  1. static void CanInitConfig(uint16_t CAN_Baud_Rate)
  2. {
  3.     stc_can_init_config_t stcCanInitCfg;
  4.     stc_can_filter_t astcFilters[CAN_FILTERS_COUNT] = \
  5.     {
  6.         {0x00000000ul, 0x111ul, CanFilterSel1, CanAllFrames}
  7.     };

  8.     //<< Enable can peripheral clock and buffer(ram)
  9.     PWC_RamOpMdConfig(HighSpeedMd);
  10.     PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
  11.     PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);

  12.     //<< CAN GPIO config
  13.     PORT_SetFunc(PortC, Pin06, Func_Can1_Rx, Disable);
  14.     PORT_SetFunc(PortC, Pin07, Func_Can1_Tx, Disable);

  15.     MEM_ZERO_STRUCT(stcCanInitCfg);
  16.     //<< Can bit time config
  17.     switch(CAN_Baud_Rate)
  18.     {
  19.         case 1000:      //1M
  20.             stcCanInitCfg.stcCanBt.PRESC = 1u-1u;
  21.             break;
  22.         case 500:       //500K
  23.             stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
  24.         break;
  25.         case 250:       //250K
  26.             stcCanInitCfg.stcCanBt.PRESC = 4u-1u;
  27.         break;
  28.         case 125:       //125K
  29.             stcCanInitCfg.stcCanBt.PRESC = 8u-1u;
  30.         break;
  31.         case 100:       //100K
  32.             stcCanInitCfg.stcCanBt.PRESC = 10u-1u;
  33.         break;
  34.         default:
  35.             stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
  36.         break;                                                                       
  37.     }
  38.    
  39.     stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
  40.     stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
  41.     stcCanInitCfg.stcCanBt.SJW   = 3u-1u;

  42.     stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
  43.     stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;

  44.     stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
  45.     stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
  46.     stcCanInitCfg.enCanSAck      = CanSelfAckDisable;
  47.     stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

  48.     stcCanInitCfg.pstcFilter     = astcFilters;

  49.     stcCanInitCfg.u8FilterCount  = CAN_FILTERS_COUNT;

  50.     CAN_Init(&stcCanInitCfg);

  51.     stc_irq_regi_conf_t     stcIrqRegiConf;

  52.     stcIrqRegiConf.enIRQn = Int000_IRQn;
  53.     stcIrqRegiConf.enIntSrc = INT_CAN_INT;
  54.     stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
  55.     enIrqRegistration(&stcIrqRegiConf);
  56.     NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
  57.     NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
  58.     NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
  59. }
  1. static void CAN_RxIrqCallBack(void)
  2. {
  3.     if(true == CAN_Irq**Get(CanRxIrq**))
  4.     {
  5.         CAN_Irq**Clr(CanRxIrq**);
  6.         CAN_IrqCmd(CanRxIrqEn, Disable);         
  7.         CAN_Receive(&stcRxFrame);
  8. //        rt_kprintf("stcRxFrame.Cst.Control_f.DLC = %d\r\n",stcRxFrame.Cst.Control_f.DLC);
  9. //        rt_kprintf("stcRxFrame.Cst.Control_f.IDE = %d\r\n",stcRxFrame.Cst.Control_f.IDE);


  10.         can_RX_flag = 1;
  11.         
  12.     }
  13.     if(true == CAN_Irq**Get(CanTxPrimaryIrq**))
  14.     {
  15.         CAN_Irq**Clr(CanTxPrimaryIrq**);
  16.         CAN_IrqCmd(CanRxIrqEn, Enable);
  17.     }
  18.     //总线忙碌中断
  19.     if(true == CAN_Irq**Get(CanBusErrorIrq**))
  20.     {
  21.         CAN_Irq**Clr(CanBusErrorIrq**);
  22.     }   
  23.     //仲裁失败中断
  24.     if(true == CAN_Irq**Get(CanArbiLostIrq**))
  25.     {
  26.         CAN_Irq**Clr(CanArbiLostIrq**);
  27.     }
  28.     if(true == CAN_Irq**Get(CanRxOverIrq**))  
  29.     {
  30.         CAN_Irq**Clr(CanRxOverIrq**);
  31. //        for (size_t i = 0; i < 10; i++)
  32. //        {
  33. //            CAN_Receive(&stcRxFrame);
  34. //            rt_kprintf("stcRxFrame.Cst.Control_f.DLC = %d\r\n",stcRxFrame.Cst.Control_f.DLC);
  35. //            rt_kprintf("stcRxFrame.Cst.Control_f.IDE = %d\r\n",stcRxFrame.Cst.Control_f.IDE);
  36. //        }

  37.     }
  38.     if(true == CAN_Irq**Get(CanErrorIrq**))  
  39.     {
  40.         //gData.ResetCanF=1;
  41.         CAN_Irq**Clr(CanErrorIrq**);      
  42.     }   
  43.     if(true == CAN_Irq**Get(CanErrorWarningIrq**))  
  44.     {
  45.         //gData.ResetCanF=1;
  46.         CAN_Irq**Clr(CanErrorWarningIrq**);      
  47.     }      
  48.     if(true == CAN_Irq**Get(CanErrorPassivenodeIrq**))  
  49.     {
  50.         //gData.ResetCanF=1;
  51.         CAN_Irq**Clr(CanErrorPassivenodeIrq**);      
  52.     }
  53.    
  54.     if(true == CAN_Irq**Get(CanTxBufFullIrq**))  
  55.     {
  56.         CAN_Irq**Clr(CanTxBufFullIrq**);      
  57.     }
  58.      
  59.     if(true == CAN_Irq**Get(CanRxBufFullIrq**))  
  60.     {
  61.         CAN_Irq**Clr(CanRxBufFullIrq**);
  62.         //CAN_Receive(&stcRxFrame);

  63. //        memset(rxCanBuff,0,sizeof(rxCanBuff));
  64. //        memset(txCanBuff,0,sizeof(txCanBuff));
  65. //        memset(&stcRxFrame,0,sizeof(stcRxFrame));
  66. //        putCan_Data(txCanBuff,8,rxCanBuff[2]);
  67.             
  68.     }

  69.     if(true == CAN_Irq**Get(CanRxBufAlmostFullIrq**))  
  70.     {
  71.         CAN_Irq**Clr(CanRxBufAlmostFullIrq**);      
  72.     }
  73.    
  74.     if(true == CAN_Irq**Get(CanTxSecondaryIrq**))  
  75.     {
  76.         CAN_Irq**Clr(CanTxSecondaryIrq**);      
  77.     }
  78.    
  79.     if(true == CAN_Irq**Get(CanAbortIrq**))  
  80.     {
  81.         CAN_Irq**Clr(CanAbortIrq**);      
  82.     }

  83.     if(true == CAN_Irq**Get(CanErrorPassiveIrq**))  
  84.     {
  85.         CAN_Irq**Clr(CanErrorPassiveIrq**);      
  86.     }        
  87. }


请叫我污春 发表于 2023-1-13 09:20 | 显示全部楼层
没明白什么意思,指的是一次接收两帧数据但是保存下来的只有第二帧吗
 楼主| luckyren 发表于 2023-1-13 09:35 | 显示全部楼层
不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应当是不保存数据,应当是只保存一条数据吧,但是在RX接收里保存了两条,我读出来一条,还有一条在里面,导致我下一次再发数据时是上一条的数据,于是我解析的是上一条的数据,新的数据又被保存下来了,然后就这么错位了。。。就是解析的数据和当前发送给MCU的不一致
 楼主| luckyren 发表于 2023-1-13 09:36 | 显示全部楼层
请叫我污春 发表于 2023-1-13 09:20
没明白什么意思,指的是一次接收两帧数据但是保存下来的只有第二帧吗

不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应当是不保存数据,应当是只保存一条数据吧,但是在RX接收里保存了两条,我读出来一条,还有一条在里面,导致我下一次再发数据时是上一条的数据,于是我解析的是上一条的数据,新的数据又被保存下来了,然后就这么错位了。。。就是解析的数据和当前发送给MCU的不一致
请叫我污春 发表于 2023-1-13 09:57 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:11 编辑
luckyren 发表于 2023-1-13 09:36
不是,是同时给MCU发送了两条数据,按我这个配置stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;不应 ...

stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored这个定义意思是只有当接收缓存满了之后新接收的数据不会被存入,并不是说不存数据了,因为你每次接收两帧,肯定不会让接收缓存溢出,两帧还是被存进去了,如果你每次只读一帧肯定下次读里面还剩一帧,就出现你说得问题了,而且时间长了接收缓存满了,新数据就不会被存入了从而有丢失数据的风险
 楼主| luckyren 发表于 2023-1-13 10:13 | 显示全部楼层
请叫我污春 发表于 2023-1-13 09:57
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored这个定义意思是只有当接收缓存满了之后新接收的数据不 ...

那如何清除接收缓存,保证我每次接收的都是最新的?我stcCanInitCfg.enCanRxBufMode = CanRxBufOverwritten;把这个设置成这样也不行
请叫我污春 发表于 2023-1-13 10:18 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:22 编辑

看手册定义,stcCanInitCfg.enCanRxBufMode只是对溢出模式的选择,并不是对存不存数据的选择
截图_20230113101654.png
请叫我污春 发表于 2023-1-13 10:21 | 显示全部楼层
luckyren 发表于 2023-1-13 10:13
那如何清除接收缓存,保证我每次接收的都是最新的?我stcCanInitCfg.enCanRxBufMode = CanRxBufOverwritt ...

看手册怎么说的,释放掉就行 5549763c0bff34c918.png

请叫我污春 发表于 2023-1-13 10:23 | 显示全部楼层
多看看数据手册吧,里面都有
 楼主| luckyren 发表于 2023-1-13 10:23 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:18
看手册定义,stcCanInitCfg.enCanRxBufMode只是对溢出模式的选择,并不是对存不存数据的选择
...

好的,谢谢,再请教你一下,有没有哪个库函数可以把接收的缓存清掉呢?
 楼主| luckyren 发表于 2023-1-13 10:26 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:23
多看看数据手册吧,里面都有

好的,谢啦!
请叫我污春 发表于 2023-1-13 10:27 | 显示全部楼层
本帖最后由 请叫我污春 于 2023-1-13 10:29 编辑
luckyren 发表于 2023-1-13 10:23
好的,谢谢,再请教你一下,有没有哪个库函数可以把接收的缓存清掉呢? ...

不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读了,缓存自然就没了
 楼主| luckyren 发表于 2023-1-13 10:56 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

多谢多谢,现在改好了
tpgf 发表于 2023-2-3 13:47 | 显示全部楼层
你这个前后两帧数据 有发送间隔吗
nawu 发表于 2023-2-3 14:28 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:21
看手册怎么说的,释放掉就行

这个释放缓存 需要我们人为的释放吗
aoyi 发表于 2023-2-3 14:36 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

也就是说只要缓存中的数据被读取了  自然就会清除这个标志位了是吗
zljiu 发表于 2023-2-3 14:58 | 显示全部楼层
归根结底还是缓存数据处理不得当造成的
gwsan 发表于 2023-2-3 15:11 | 显示全部楼层
楼主读取数据的速度太慢了  缓存要爆掉了
tfqi 发表于 2023-2-3 15:29 | 显示全部楼层
请叫我污春 发表于 2023-1-13 10:27
不知道,没用过,可以去相关c文件找,或者自己写一个,两行代码的事,有个简单方法,你每次把两帧数据都读 ...

是不是缓存里边的数据读取之后缓存里边就没有数据呢
通程创品 发表于 2023-2-12 11:25 | 显示全部楼层

HC32F460 CAN通讯问题

在接收CAN数据时,如果同时收到了两帧数据,您应该在中断函数中处理完每一帧数据后再清除标志位。如果没有处理完一帧数据就清除标志位,会导致第二帧数据被覆盖。
因此,请确保在中断函数中完成数据处理,并在处理完后清除标志位,以保证正确的接收CAN数据。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

19

帖子

0

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