找回密码
 立即注册
查看: 365|回复: 9

如何清空接收缓存返回的数据

[复制链接]
已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:17:00 | 显示全部楼层 |阅读模式
需要用CAN发两个指令,但我只想读其中1个指令返回的内容。目前我的情况是一直发一条指令,读出的数据正常,但如果轮流发两条指令(两条指令都有返回数据:串口助手看到返回数据正常),但can读出的数据就有错误?
回复

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:25:13 | 显示全部楼层
  1.   while(1)
  2. {
  3.    be=0;
  4.    encoder();                      //读编码(0x60)  
  5.    CanSendMsg(0x141,TxData);       //发送数据到 ID = 0x141;
  6.    delay_ms(10);
  7.   
  8.                
  9.    CanReadMsg(pdat);               //接受返回数据
  10.                
  11.    RX[0]=pdat[4];
  12.    RX[1]=pdat[5];
  13.    RX[2]=pdat[6];
  14.    RX[3]=pdat[7];      
  15.    codedata = (RX[0] | RX[1]<<8 | RX[2]<<16 | RX[3]<<24);  //合成long型
  16.          
  17. ///////////////////////////////////////////////////////////////  
  18.    Cdata = (codedata + 0x30);
  19.    decimal(0);                      //显示目前的
  20.    delay_ms(300);     
  21. ///////////////////////////////////////////////////////////////
  22.                
  23.                
  24.                         CanSendMsg(0x141,TxData);        //发送数据到  ID = 0x141;
  25.                         delay_ms(10);          
  26.         }
复制代码
最底下的数据不发送,读出的数据就是正常的,发送下面的数据,读出的数据就反复出现错误。
回复 支持 反对

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:28:07 | 显示全部楼层
我想问题应该是出在can的设置里
回复 支持 反对

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:28:25 | 显示全部楼层
  1. //========================================================================
  2. // 函数: u8 ReadReg(u8 addr)
  3. // 描述: CAN功能寄存器读取函数。
  4. // 参数: CAN功能寄存器地址.
  5. // 返回: CAN功能寄存器数据.
  6. // 版本: VER1.0
  7. // 日期: 2020-11-16
  8. // 备注:
  9. //========================================================================
  10. uint8 CanReadReg(uint8 addr)
  11. {
  12. uint8 dat;
  13. CANAR = addr;
  14. dat = CANDR;
  15. return dat;
  16. }
  17. //========================================================================
  18. // 函数: void WriteReg(u8 addr, u8 dat)
  19. // 描述: CAN功能寄存器配置函数。
  20. // 参数: CAN功能寄存器地址, CAN功能寄存器数据.
  21. // 返回: none.
  22. // 版本: VER1.0
  23. // 日期: 2020-11-16
  24. // 备注:
  25. //========================================================================
  26. void CanWriteReg(uint8 addr, uint8 dat)
  27. {
  28. CANAR = addr;
  29. CANDR = dat;
  30. }
  31. //========================================================================
  32. // 函数: void CanReadFifo(u8 *pdat)
  33. // 描述: 读取CAN缓冲区数据函数。
  34. // 参数: *pdat: 存放CAN缓冲区数据.
  35. // 返回: none.
  36. // 版本: VER1.0
  37. // 日期: 2020-11-16
  38. // 备注:
  39. //========================================================================
  40. void CanReadFifo(uint8 *pdat)
  41. {
  42. pdat[0]  = CanReadReg(RX_BUF0);
  43. pdat[1]  = CanReadReg(RX_BUF1);
  44. pdat[2]  = CanReadReg(RX_BUF2);
  45. pdat[3]  = CanReadReg(RX_BUF3);
  46. pdat[4]  = CanReadReg(RX_BUF0);
  47. pdat[5]  = CanReadReg(RX_BUF1);
  48. pdat[6]  = CanReadReg(RX_BUF2);
  49. pdat[7]  = CanReadReg(RX_BUF3);
  50. pdat[8]  = CanReadReg(RX_BUF0);
  51. pdat[9]  = CanReadReg(RX_BUF1);
  52. pdat[10] = CanReadReg(RX_BUF2);
  53. pdat[11] = CanReadReg(RX_BUF3);
  54. pdat[12]  = CanReadReg(RX_BUF0);
  55. pdat[13]  = CanReadReg(RX_BUF1);
  56. pdat[14]  = CanReadReg(RX_BUF2);
  57. pdat[15]  = CanReadReg(RX_BUF3);
  58. }
  59. //========================================================================
  60. // 函数: u16 CanReadMsg(u8 *pdat)
  61. // 描述: CAN发送数据函数。
  62. // 参数: *pdat: 接收数据缓冲区.
  63. // 返回: CAN ID.
  64. // 版本: VER1.0
  65. // 日期: 2020-11-19
  66. // 备注:
  67. //========================================================================
  68. uint16 CanReadMsg(uint8 *pdat)
  69. {
  70. uint8 i;
  71. uint16 CanID;
  72. uint8 buffer[16];
  73. CanReadFifo(buffer);                              //读取CAN缓冲区数据函数
  74. CanID = ((buffer[1] << 8) + buffer[2]) >> 5;      //16位ID
  75. for(i=0;i<8;i++)
  76. {
  77.   pdat[i] = buffer[i+3];
  78. }
  79. return CanID;
  80. }
  81. //========================================================================
  82. // 函数: void CanSendMsg(u16 canid, u8 *pdat)
  83. // 描述: CAN发送数据函数。
  84. // 参数: canid: CAN ID; *pdat: 发送数据缓冲区.
  85. // 返回: none.
  86. // 版本: VER1.0
  87. // 日期: 2020-11-19
  88. // 备注:
  89. //========================================================================
  90. void CanSendMsg(uint16 CAN_ID1, uint8 *TxData)       //*************************************
  91. {
  92. uint16 CanID1;
  93. CanID1 = CAN_ID1 << 5;
  94. CanWriteReg(TX_BUF0,0x08);               //bit7: 标准帧(0)/扩展帧(1), bit6: 数据帧(0)/远程帧(1), bit3~bit0: 数据长度(DLC)
  95. CanWriteReg(TX_BUF1,(uint8)(CanID1>>8));
  96. CanWriteReg(TX_BUF2,(uint8)CanID1);
  97. CanWriteReg(TX_BUF3,TxData[0]);
  98. CanWriteReg(TX_BUF0,TxData[1]);
  99. CanWriteReg(TX_BUF1,TxData[2]);
  100. CanWriteReg(TX_BUF2,TxData[3]);
  101. CanWriteReg(TX_BUF3,TxData[4]);
  102. CanWriteReg(TX_BUF0,TxData[5]);
  103. CanWriteReg(TX_BUF1,TxData[6]);
  104. CanWriteReg(TX_BUF2,TxData[7]);
  105. CanWriteReg(TX_BUF3,0x00);
  106. CanWriteReg(CMR ,0x04);  //发起一次帧传输
  107. }
  108. //========================================================================
  109. // 函数: void CANSetBaudrate()
  110. // 描述: CAN总线波特率设置函数。
  111. // 参数: none.
  112. // 返回: none.
  113. // 版本: VER1.0
  114. // 日期: 2020-11-19
  115. // 备注:
  116. //========================================================================
  117. void CANSetBaudrate()
  118. {
  119. CanWriteReg(BTR0,(SJW << 6) + BRP);
  120. CanWriteReg(BTR1,(SAM << 7) + (TSG2 << 4) + TSG1);
  121. }
  122. //========================================================================
  123. // 函数: void CANInit()
  124. // 描述: CAN初始化函数。
  125. // 参数: none.
  126. // 返回: none.
  127. // 版本: VER1.0
  128. // 日期: 2020-11-19
  129. // 备注:
  130. //========================================================================
  131. void CANInit()
  132. {
  133. CANEN = 1;          //CAN1模块使能
  134. CANSEL = 0;         //选择CAN1模块
  135. P_SW1 = (P_SW1 & ~(3<<4)) | (0<<4); //端口切换(CAN_Rx,CAN_Tx) 0x00:P0.0,P0.1  0x10:P5.0,P5.1  0x20:P4.2,P4.5  0x30:P7.0,P7.1
  136. // CAN2EN = 1;         //CAN2模块使能
  137. // CANSEL = 1;         //选择CAN2模块
  138. // P_SW3 = (P_SW3 & ~(3)) | (0);       //端口切换(CAN_Rx,CAN_Tx) 0x00:P0.2,P0.3  0x01:P5.2,P5.3  0x02:P4.6,P4.7  0x03:P7.2,P7.3
  139. CanWriteReg(MR  ,0x04);      //使能 Reset Mode
  140. CANSetBaudrate();            //设置波特率
  141. CanWriteReg(ACR0,0x00);      //总线验收代码寄存器
  142. CanWriteReg(ACR1,0x00);
  143. CanWriteReg(ACR2,0x00);
  144. CanWriteReg(ACR3,0x00);
  145. CanWriteReg(AMR0,0xFF);      //总线验收屏蔽寄存器
  146. CanWriteReg(AMR1,0xFF);
  147. CanWriteReg(AMR2,0xFF);
  148. CanWriteReg(AMR3,0xFF);
  149. CanWriteReg(IMR ,0xff);      //中断寄存器
  150. CanWriteReg(ISR ,0xff);      //清中断标志
  151. CanWriteReg(MR  ,0x00);      //退出 Reset Mode
  152. CANICR = 0x02;               //CAN中断使能
  153. }
  154. //========================================================================
  155. // 函数: void CANBUS_Interrupt(void) interrupt CAN_VECTOR
  156. // 描述: CAN总线中断函数。
  157. // 参数: none.
  158. // 返回: none.
  159. // 版本: VER1.0
  160. // 日期: 2020-11-19
  161. // 备注:
  162. //========================================================================
  163. void CANBUS_Interrupt(void) interrupt CAN1_VECTOR
  164. {
  165. u8 isr;
  166. u8 arTemp;
  167. arTemp = CANAR;            //CANAR现场保存,避免主循环里写完 CANAR 后产生中断,在中断里修改了 CANAR 内容
  168. isr = CanReadReg(ISR);
  169. if((isr & 0x04) == 0x04)   //TI
  170. {
  171.   CANAR = ISR;
  172.   CANDR |= 0x04;            //CLR FLAG
  173. }
  174. if((isr & 0x08) == 0x08)  //RI
  175. {
  176.   CANAR = ISR;
  177.   CANDR |= 0x08;           //CLR FLAG
  178.   B_CanRead = 1;
  179. }  
  180. if((isr & 0x40) == 0x40)  //ALI
  181. {
  182.   CANAR = ISR;
  183.   CANDR |= 0x40;           //CLR FLAG
  184. }
  185. if((isr & 0x20) == 0x20)   //EWI
  186. {
  187.   CANAR = ISR;
  188.   CANDR |= 0x20;           //CLR FLAG
  189. }
  190. if((isr & 0x10) == 0x10)  //EPI
  191. {
  192.   CANAR = ISR;
  193.   CANDR |= 0x10;           //CLR FLAG
  194. }
  195. if((isr & 0x02) == 0x02)  //BEI
  196. {
  197.   CANAR = ISR;
  198.   CANDR |= 0x02;           //CLR FLAG
  199. }
  200. if((isr & 0x01) == 0x01)  //DOI
  201. {
  202.   CANAR = ISR;
  203.   CANDR |= 0x01;           //CLR FLAG
  204. }
  205. CANAR = arTemp;           //CANAR现场恢复
  206. }
复制代码


回复 支持 反对

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:29:43 | 显示全部楼层
楼主有空能帮我看看吗?
回复 支持 反对

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 11:42:42 | 显示全部楼层
我读出的数据就发给显示,一直发一条指令(底下的数据不发送),显示的数据显示正常,但如果轮流发两条指令,两条指令都有返回数据:串口助手看到返回数据都是正常的,我只想一直显示我第一调指令的返回数据,而不想管第二调指令的返回数据,要如何做?

点评

我看你代码中的: 是直接使用了延时后读取,这样是不对的,因为不能保证此时是发送完成了还是没有。 我试过同时跟三个CAN设备通讯,收发都是正常的。 如果不想让系统卡住,就使用状态机。 然后发送的时候,使用(注  详情 回复 发表于 2025-1-6 16:56
回复 支持 反对

使用道具 举报 送花

已绑定手机

1

主题

6

回帖

23

积分

新手上路

积分
23
发表于 2025-1-6 13:36:52 | 显示全部楼层
就算两次发送的数据相同,can读来的数据也会出错(显示的数据出错)(用串口助手看到设备返回的数据是正常的)。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-1-6 13:45:04 | 显示全部楼层
CAN总线连续发送多帧数据的话,要等待上一帧数据发送完成,然后再发下一帧数据。
建议到官网下载最新版本的32G实验箱例程包,或者屠龙刀三例程包,参考里面的CAN总线收发例子:
https://www.stcai.com/syx
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:12
  • 最近打卡:2025-04-27 09:44:17

25

主题

252

回帖

2089

积分

超级版主

积分
2089
发表于 2025-1-6 14:42:41 | 显示全部楼层

实验箱 主控芯片使用32G12K128,可以做示波器、波形发生器、TFT彩屏显示、OLED 12864、LCD 12864 等,

范例程序 直接下载: STC32G-DEMO-CODE-V9.6实验箱20241010.zip (25.61 MB, 下载次数: 36)

屠龙刀核心板 32G12K128为主控芯片的核心板,可作为简易示波器,USB总线通信,CAN/LIN总线通信
范例程序直接下载: STC32G12K128-LQFP64-DIP64-DEMO-CODE屠龙刀三.zip (44.64 MB, 下载次数: 34)


QQ:3398500488
微信号:18106296592(小刘)
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2025-1-6 16:56:26 | 显示全部楼层
GUANG*** 发表于 2025-1-6 11:42
我读出的数据就发给显示,一直发一条指令(底下的数据不发送),显示的数据显示正常,但如果轮流发两条指令 ...

我看你代码中的:

  1. CanSendMsg(0x141,TxData);       //发送数据到 ID = 0x141;
  2. delay_ms(10);
  3. CanReadMsg(pdat);               //接受返回数据
复制代码
是直接使用了延时后读取,这样是不对的,因为不能保证此时是发送完成了还是没有。
我试过同时跟三个CAN设备通讯,收发都是正常的。
如果不想让系统卡住,就使用状态机。
然后发送的时候,使用(注意使用对应的)
  1. if (B_Can1Send == 0) // 发送完成标志
复制代码


同样的,接收的时候需要先判断
  1. if (B_Can1Read)
  2. {
  3. B_Can1Read = 0;
  4. n = CanReadMsg(CAN1_Rx); // 读取接收内容
  5. for (can_cnt = 0; can_cnt < n; can_cnt++)
  6.   {
  7.          Can_Dat_Handle(&CAN1_Rx[can_cnt]);//数据解析部分,自行编写
  8.   }
  9. }
复制代码

来判断是否接收完成,否则就有可能造成你所述的这种混乱情况。

因为can部分是带有fifo的,所以,如果数据不是很长的话。可以全部发送完成后再处理接收数据,处理的时候依照ID进行区分就可以了
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 06:52 , Processed in 0.141023 second(s), 110 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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