xingcheng456 发表于 2025-4-22 17:31:50

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

最近在使用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以外的数据,其他的就只是最简单的读取每帧数据,将数据段放到缓冲区,供命令解析程序分析,没有添加其他代码。

国芯人工智能 发表于 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通常用于实时性要求较高的场景。

c
// 示例代码:设置CAN中断优先级高于UART
NVICSetPriority(CANIRQn, 0);// CAN中断优先级为最高
NVICSetPriority(UARTIRQn, 1); // UART中断优先级次之

2.2 使用DMA传输
如果芯片支持DMA(直接内存访问),可以尝试使用DMA来传输UART数据,从而减少CPU的负担,避免与CAN模块的资源冲突。

c
// 示例代码:配置UART使用DMA发送
UARTInitTypeDef UARTInitStruct;
UARTInitStruct.BaudRate = 115200;
UARTInitStruct.Mode = UARTMODETX;
UARTInitStruct.DMATX = ENABLE;
UARTInit(&UARTInitStruct);

2.3 优化缓冲区管理
确保CAN和UART的接收和发送缓冲区足够大,并且能够及时处理数据。可以使用环形缓冲区(Ring Buffer)来管理数据,避免缓冲区溢出。

c
// 示例代码:使用环形缓冲区管理UART数据
define UARTBUFFERSIZE 128
uint8t uarttxbuffer;
uint8t uartrxbuffer;
RingBuffer uarttxring, uartrxring;

RingBufferInit(&uarttxring, uarttxbuffer, UARTBUFFERSIZE);
RingBufferInit(&uartrxring, uartrxbuffer, UARTBUFFERSIZE);

2.4 检查时钟配置
确保CAN和UART的时钟分频设置正确,避免因时钟频率不匹配导致的数据传输问题。可以参考芯片手册中的时钟配置部分进行设置。

c
// 示例代码:配置CAN和UART的时钟分频
CANInitTypeDef CANInitStruct;
CANInitStruct.Prescaler = 6; // 500Kbps @ 24MHz
CANInit(&CANInitStruct);

UARTInitTypeDef UARTInitStruct;
UARTInitStruct.BaudRate = 115200;
UARTInitStruct.ClockDivider = 24; // 115200 @ 24MHz
UARTInit(&UARTInitStruct);

2.5 降低UART发送频率
如果以上方法无法解决问题,可以尝试降低UART的发送频率,或者将UART发送数据分段处理,避免一次性发送大量数据。

c
// 示例代码:分段发送UART数据
void UARTSendData(uint8t data, uint16t length) {
    uint16t i;
    for (i = 0; i < length; i += 16) {
      UARTSend(&data, 16);
      Delayms(1); // 每发送16字节后延迟1ms
    }
}

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

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

[本文内容由国芯人工智能辅助生成,仅供参考]

zhang32568 发表于 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 <<8 | CAN1_Rx.DataBuffer;
                   X_speed =CAN1_Rx.DataBuffer;
                                                                   X_Rotation_flag = CAN1_Rx.DataBuffer;
                                                                   Y_axis = CAN1_Rx.DataBuffer <<8 | CAN1_Rx.DataBuffer;
                   Y_speed =CAN1_Rx.DataBuffer;
                                                                   Y_Rotation_flag = CAN1_Rx.DataBuffer;                                                               
                                          }      
                                       
                                 if(CAN1_Rx.ID==68)//fz聚焦推拉参数
                                       {P54 = ~P54;
                                                                         Uart_TxBuf = 0Xaa;
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样1高8位
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样1低8位
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样1速度
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样1方向
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样2高8位
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样2低8位
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样2速度
                                                                   Uart_TxBuf = CAN1_Rx.DataBuffer;//采样2方向      
                                                                         Uart_TxBuf = 0Xdd;
                                          }

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

xingcheng456 发表于 2025-4-22 21:48:23

zhang32568 发表于 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中断的优先级调高后也没看到啥效果。

王昱顺 发表于 2025-4-23 08:38:22

xingcheng456 发表于 2025-4-22 21:48
多谢回复,我也怀疑是哪里的配置或者程序有问题,只是暂时没找到方向。
我这边用的是微雪的USBCAN调试的 ...

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

xingcheng456 发表于 2025-5-6 00:20:14

王昱顺 发表于 2025-4-23 08:38
可以尝试将串口改用dma实现,同时关闭串口中断,只开启串口DMA中断,怀疑是多次的进入串口接收中断导致顶 ...

多谢回复,现在问题算是解决了,就是使用DMA串口发送解决的。看来还是串口中断与CAN中断之间有冲突,传输少量数据时问题还不明显,数据量上来后就会相互影响,导致数据出错。

乘风飞扬 发表于 2025-5-6 09:17:54

屠龙刀三核心功能实验板里面的例子:14-CAN1-CAN2总线标准帧扩展帧同时使用收发测试
就是使用串口输出收到的CAN总线数据,建议直接用例子试试。最多修改CAN接口,以及串口通道,其他先不改,功能验证正常后再进行功能修改或者移植。
其实只要收到的数据能及时处理就不会出问题。

下载地址:https://www.stcai.com/hxgnsyb


页: [1]
查看完整版本: 请教32中CAN和UART同时使用的问题