找回密码
 立即注册
查看: 82|回复: 4

请教32中CAN和UART同时使用的问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-04-22 17:31:50
已绑定手机

1

主题

1

回帖

15

积分

新手上路

积分
15
发表于 2025-4-22 17:31:50 | 显示全部楼层 |阅读模式
最近在使用32G12K128的芯片,需要通过CAN从上位机接收数据,再通过UART发出去。
MCU是使用的内部时钟,24M。
CAN通讯使用的是标准帧,频率500K,每帧8个字节,在下位机收到后重新组合成完整的命令再下发,波特率是115200,一次可能最多需要发送110个字节,常用的一次大概发送50个字节左右。
现在遇到一个问题,就是UART与CAN之间似乎存在冲突。在程序中屏蔽了uart发送后,CAN通讯一切正常;
一旦开启了UART发送,上位机的CAN通讯就会出现发送错误,需要降低CAN的发送频率,大概降低到每帧间隔500ms左右才能正常工作。
想请教一下,可能是哪里的问题?有没有什么办法能解决这个问题?
我目前是手动发送每帧数据的,在115200的波特率下,就算是110个字节,10ms左右也就发送完毕了,后面程序就在等待新的命令了,可我这边的体验是CAN的每帧要间隔接近1秒发送才能正常工作,实在想不到是哪里的问题。

谢谢!

对了,补充一下,CAN通讯的代码是移植的例程里面的,增加了帧ID过滤,过滤除了ID为0和本机ID以外的数据,其他的就只是最简单的读取每帧数据,将数据段放到缓冲区,供命令解析程序分析,没有添加其他代码。
回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-22 17:33:00 | 显示全部楼层
在STC32G12K128芯片中同时使用CAN和UART时,确实可能会遇到资源冲突或优先级问题,尤其是在高频率数据传输的场景下。以下是对您问题的详细分析和可能的解决方案。

1. 问题分析
1.1 资源冲突
STC32G12K128的CAN和UART模块共享部分硬件资源,例如中断控制器、DMA通道或内存缓冲区。如果两者同时工作,可能会导致资源竞争,进而影响数据传输的稳定性。

1.2 中断优先级
CAN和UART的中断优先级设置不当,可能会导致高优先级的中断频繁抢占低优先级的中断,从而影响另一模块的正常工作。例如,如果UART的中断优先级高于CAN,UART的频繁中断可能会延迟CAN的数据处理。

1.3 时钟配置
内部时钟24MHz的配置需要确保CAN和UART的时钟分频设置正确。如果时钟分频不合理,可能会导致模块工作频率不匹配,进而影响数据传输。

1.4 缓冲区管理
CAN和UART的接收和发送缓冲区管理不当,可能会导致数据丢失或冲突。例如,如果UART发送数据时占用了大量CPU时间,CAN的接收缓冲区可能会溢出。

2. 解决方案
2.1 优化中断优先级
检查并调整CAN和UART的中断优先级,确保两者不会互相干扰。建议将CAN的中断优先级设置为高于UART,因为CAN通常用于实时性要求较高的场景。
  1. c
  2. // 示例代码:设置CAN中断优先级高于UART
  3. NVICSetPriority(CANIRQn, 0);  // CAN中断优先级为最高
  4. NVICSetPriority(UARTIRQn, 1); // UART中断优先级次之
复制代码

2.2 使用DMA传输
如果芯片支持DMA(直接内存访问),可以尝试使用DMA来传输UART数据,从而减少CPU的负担,避免与CAN模块的资源冲突。
  1. c
  2. // 示例代码:配置UART使用DMA发送
  3. UARTInitTypeDef UARTInitStruct;
  4. UARTInitStruct.BaudRate = 115200;
  5. UARTInitStruct.Mode = UARTMODETX;
  6. UARTInitStruct.DMATX = ENABLE;
  7. UARTInit(&UARTInitStruct);
复制代码

2.3 优化缓冲区管理
确保CAN和UART的接收和发送缓冲区足够大,并且能够及时处理数据。可以使用环形缓冲区(Ring Buffer)来管理数据,避免缓冲区溢出。
  1. c
  2. // 示例代码:使用环形缓冲区管理UART数据
  3. define UARTBUFFERSIZE 128
  4. uint8t uarttxbuffer[UARTBUFFERSIZE];
  5. uint8t uartrxbuffer[UARTBUFFERSIZE];
  6. RingBuffer uarttxring, uartrxring;
  7. RingBufferInit(&uarttxring, uarttxbuffer, UARTBUFFERSIZE);
  8. RingBufferInit(&uartrxring, uartrxbuffer, UARTBUFFERSIZE);
复制代码

2.4 检查时钟配置
确保CAN和UART的时钟分频设置正确,避免因时钟频率不匹配导致的数据传输问题。可以参考芯片手册中的时钟配置部分进行设置。
  1. c
  2. // 示例代码:配置CAN和UART的时钟分频
  3. CANInitTypeDef CANInitStruct;
  4. CANInitStruct.Prescaler = 6; // 500Kbps @ 24MHz
  5. CANInit(&CANInitStruct);
  6. UARTInitTypeDef UARTInitStruct;
  7. UARTInitStruct.BaudRate = 115200;
  8. UARTInitStruct.ClockDivider = 24; // 115200 @ 24MHz
  9. UARTInit(&UARTInitStruct);
复制代码

2.5 降低UART发送频率
如果以上方法无法解决问题,可以尝试降低UART的发送频率,或者将UART发送数据分段处理,避免一次性发送大量数据。
  1. c
  2. // 示例代码:分段发送UART数据
  3. void UARTSendData(uint8t data, uint16t length) {
  4.     uint16t i;
  5.     for (i = 0; i < length; i += 16) {
  6.         UARTSend(&data[i], 16);
  7.         Delayms(1); // 每发送16字节后延迟1ms
  8.     }
  9. }
复制代码

3. 总结
在STC32G12K128芯片中同时使用CAN和UART时,可能会遇到资源冲突、中断优先级不当、时钟配置不合理或缓冲区管理问题。通过优化中断优先级、使用DMA传输、优化缓冲区管理、检查时钟配置以及降低UART发送频率等方法,可以有效解决CAN和UART之间的冲突问题。建议根据具体应用场景选择合适的解决方案,并进行充分的测试以确保系统的稳定性和可靠性。

希望以上分析和解决方案能够帮助您解决问题。如果仍有疑问,建议进一步查阅芯片手册或联系技术支持获取更多帮助。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:385
  • 最近打卡:2025-05-01 08:05:45

25

主题

113

回帖

725

积分

高级会员

积分
725
发表于 2025-4-22 21:15:42 | 显示全部楼层
估计是程序的问题。  我现在使用CAN 通信。主机和从机都是32G单片机。主机和从机通过50米左右的CAN数据线连接。从机将收到的数据一部分通过PWM 驱动电机正反转,调速。另外数据通过串口分发到另外一个单片机。没有任何问题。
                if(B_Can1Read)          //当CAN1模块收到主机数据的时候还原数据
                  {        
                                
                          No_Signal_delay = 20; //第三帧数据收到表示接收正常。复位无信号延时。               
                          CANSEL = 0;         //选择CAN1模块            
                    n = CanReadMsg(CAN1_Rx);
                          if(n>0)
                           {
           for(i=0;i<n;i++)
                                           {
                                 if(CAN1_Rx.ID==58)  //xy参数
                                         {
                                                                   X_axis = CAN1_Rx.DataBuffer[0] <<8 | CAN1_Rx.DataBuffer[1];
                   X_speed =  CAN1_Rx.DataBuffer[2];
                                                                   X_Rotation_flag = CAN1_Rx.DataBuffer[3];
                                                                   Y_axis = CAN1_Rx.DataBuffer[4] <<8 | CAN1_Rx.DataBuffer[5];
                   Y_speed =  CAN1_Rx.DataBuffer[6];
                                                                   Y_Rotation_flag = CAN1_Rx.DataBuffer[7];                                                                 
                                          }        
                                         
                                 if(CAN1_Rx.ID==68)//fz聚焦推拉参数
                                         {P54 = ~P54;
                                                                         Uart_TxBuf[0] = 0Xaa;
                                                                   Uart_TxBuf[1] = CAN1_Rx.DataBuffer[0];//采样1高8位
                                                                   Uart_TxBuf[2] = CAN1_Rx.DataBuffer[1];//采样1低8位
                                                                   Uart_TxBuf[3] = CAN1_Rx.DataBuffer[2];//采样1速度
                                                                   Uart_TxBuf[4] = CAN1_Rx.DataBuffer[3];//采样1方向
                                                                   Uart_TxBuf[5] = CAN1_Rx.DataBuffer[4];//采样2高8位
                                                                   Uart_TxBuf[6] = CAN1_Rx.DataBuffer[5];//采样2低8位
                                                                   Uart_TxBuf[7] = CAN1_Rx.DataBuffer[6];//采样2速度
                                                                   Uart_TxBuf[8] = CAN1_Rx.DataBuffer[7];//采样2方向        
                                                                         Uart_TxBuf[10] = 0Xdd;
                                          }

                                        for(i=0;i<10;i++)                     //串口将采样1,2数据转发给下位机。
        {
          UART1_TxByte( Uart_TxBuf);
        }               
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-04-22 17:31:50
已绑定手机

1

主题

1

回帖

15

积分

新手上路

积分
15
发表于 2025-4-22 21:48:23 | 显示全部楼层
zhang*** 发表于 2025-4-22 21:15
估计是程序的问题。  我现在使用CAN 通信。主机和从机都是32G单片机。主机和从机通过50米左右的CAN数据线连 ...

多谢回复,我也怀疑是哪里的配置或者程序有问题,只是暂时没找到方向。
我这边用的是微雪的USBCAN调试的,如果只是单纯的接收CAN数据,不通过串口转发,那即使把帧之间的延时设置为1ms也不会出错。
另外,因为我是用CAN帧来传递自己的命令,解析后再通过串口转发的,一个完整的命令可能要十几个包来传递。只要在发完所有的帧之后延时200ms就不会出错,一条命令内的CAN帧与CAN帧之间设置为1ms的延时也不会出问题。这说明问题就是出在串口转发的过程中,因为只有最后一帧数据发完后才会启动串口的转发。
目前想不通的就是,在115200的波特率下,即便是100个字节的命令,也只需要10ms就可以发送完毕,为什么这边要等待200ms才能确保不出问题。
刚刚把串口中断里面的ES=0改成了EA=0,直接关总中断,似乎能在50ms的延时下工作了。但不知道会不会出其他的问题。
我目前怀疑的就是中断嵌套导致的问题,但把CAN中断的优先级调高后也没看到啥效果。

点评

可以尝试将串口改用dma实现,同时关闭串口中断,只开启串口DMA中断,怀疑是多次的进入串口接收中断导致顶掉了can接收完整帧造成的问题  详情 回复 发表于 2025-4-23 08:38
回复 支持 反对

使用道具 举报 送花

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

110

主题

2218

回帖

5450

积分

版主

积分
5450
发表于 2025-4-23 08:38:22 | 显示全部楼层
xingch*** 发表于 2025-4-22 21:48
多谢回复,我也怀疑是哪里的配置或者程序有问题,只是暂时没找到方向。
我这边用的是微雪的USBCAN调试的 ...

可以尝试将串口改用dma实现,同时关闭串口中断,只开启串口DMA中断,怀疑是多次的进入串口接收中断导致顶掉了can接收完整帧造成的问题
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 17:48 , Processed in 0.137490 second(s), 80 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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