找回密码
 立即注册
查看: 72|回复: 3

32G8K64单片机遇到的CAN和串口同时使用的问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-04-10 14:55:40
已绑定手机

5

主题

22

回帖

105

积分

注册会员

积分
105
发表于 2025-4-10 14:55:40 | 显示全部楼层 |阅读模式
void main(void)
{
        u8 sr,i,n;

    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

        CANInit();
    //串口设置(位置1)
  UART1_config(2);
  delay_ms(100);
  printf("can test 1\n");



        EA = 1;                 //打开总中断

        CAN1_Tx.FF = EXTENDED_FRAME;    //扩展帧
        CAN1_Tx.RTR = 0;                //0:数据帧,1:远程帧
        CAN1_Tx.DLC = 0x08;             //数据长度
        CAN1_Tx.ID = 0x01234567;        //CAN ID
        CAN1_Tx.DataBuffer[0] = 0x21;   //数据内容
        CAN1_Tx.DataBuffer[1] = 0x22;
        CAN1_Tx.DataBuffer[2] = 0x23;
        CAN1_Tx.DataBuffer[3] = 0x24;
        CAN1_Tx.DataBuffer[4] = 0x25;
        CAN1_Tx.DataBuffer[5] = 0x26;
        CAN1_Tx.DataBuffer[6] = 0x27;
        CAN1_Tx.DataBuffer[7] = 0x28;
  B_CanSend = 0;

  //串口设置(位置2,会一直发送c这个字符,程序到此阻塞)
  UART1_config(2);
  delay_ms(100);
  printf("can test 1\n");
while(1)


以上代码是while循环之前的初始化,串口设置放在(位置1)的时候正常运行, 串口和CAN通信都正常。但是把串口设置放在(位置2)的时候,串口会一直发送‘c’这个字符(也就是"can test\n"的第一个字符),程序一直处于阻塞状态。进入不到while循环。
如果把printf("can test\n");该成SendByte(0x31),放在位置2的时候,会一直发送0x31这个字符。
不知道什么原因啊。

截图202504101454454001.jpg

位置2,阻塞

位置2,阻塞


回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-04-10 14:55:40
已绑定手机

5

主题

22

回帖

105

积分

注册会员

积分
105
发表于 2025-4-10 14:58:00 | 显示全部楼层
串口设置的Serial.c文件如下:
#include "STC32G.h"
#include "stdio.h"
#include "intrins.h"
#include "Serial.h"


//========================================================================
// 函数: SetTimer2Baudraye(u32 dat)
// 描述: 设置Timer2做波特率发生器。
// 参数: dat: Timer2的重装值.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注:
//========================================================================
void SetTimer2Baudraye(u32 dat)
{
    T2R = 0;                //Timer stop
    T2_CT = 0;        //Timer2 set As Timer
    T2x12 = 1;        //Timer2 set as 1T mode
    T2H = (u8)(dat / 256);
    T2L = (u8)(dat % 256);
    ET2 = 0;    //禁止中断
    T2R = 1;                //Timer run enable
}

//========================================================================
// 函数: void UART1_config(u8 brt)
// 描述: UART1初始化函数。
// 参数: brt: 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注: 注意端口号选择,定时器不要被占用
//========================================================================
void UART1_config(u8 _TimerSelect)
{
    /*********** 波特率使用定时器2 *****************/
    if(_TimerSelect == 2)
    {
        S1BRT = 1;        //S1 BRT Use Timer2;
        SetTimer2Baudraye(BaudrateTimerData);
    }

    /*********** 波特率使用定时器1 *****************/
    else
    {
        TR1 = 0;
        S1BRT = 0;                //S1 BRT Use Timer1;
        T1_CT = 0;                //Timer1 set As Timer
        T1x12 = 1;                //Timer1 set as 1T mode
        TMOD &= ~0x30;//Timer1_16bitAutoReload;
        TH1 = (u8)(BaudrateTimerData / 256);
        TL1 = (u8)(BaudrateTimerData % 256);
        ET1 = 0;    //禁止中断
        TR1 = 1;
    }
    /*************************************************/

    SCON = (SCON & 0x3f) | 0x40;    //UART1模式, 0x00: 同步移位输出, 0x40: 8位数据,可变波特率, 0x80: 9位数据,固定波特率, 0xc0: 9位数据,可变波特率
//  PS  = 1;    //高优先级中断
    ES  = 1;    //允许中断
    REN = 1;    //允许接收
   
    P_SW1 &= 0x3f;
    P_SW1 |= 0x00;      //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4 //端口号选择

}



//需要将发送函数和中断函数放到main函数中使用

//========================================================================
// 函数: void PrintString1(u8 *puts)
// 描述: 串口1发送字符串函数。
// 参数: puts:  字符串指针.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注:
//========================================================================
void PrintString1(u8 *puts)
{
    for (; *puts != 0;  puts++)     //遇到停止符0结束
    {
        SBUF = *puts;
        while(TI==0);
        TI=0;
    }
}
void SendByte(u8 sendData){
  SBUF = sendData;
  while(TI==0);
  TI=0;
}
void SendBytes(u8 *ptr,int len){
        
  u8 i;
  for (i = 0; i < len; i++)
  {
    SBUF = *(ptr + i);
    while (TI == 0);
    TI = 0;
  }
}

char putchar(char c){
  SendByte(c);
  return c;
}
////========================================================================
//// 函数: void UART1_int (void) interrupt UART1_VECTOR
//// 描述: UART1中断函数。包含接受和发送中断
//// 参数: nine.
//// 返回: none.
//// 版本: VER1.0
//// 日期: 2014-11-28
//// 备注:
////========================================================================
//void UART1_int (void) interrupt UART1_VECTOR
//{
//    if(RI)
//    {
//        RI = 0;
////        RX1_Buffer[RX1_Cnt] = SBUF;
////        if(++RX1_Cnt >= UART1_BUF_LENGTH)   RX1_Cnt = 0;
//    }

//    if(TI)
//    {
//        TI = 0;
//        B_TX1_Busy = 0;
//    }
//}


回复 支持 反对

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-10 14:58:00 | 显示全部楼层
在使用STC32G8K64单片机时,同时使用CAN和串口功能可能会遇到一些问题,尤其是在资源分配和中断处理方面。以下是对该问题的详细分析和解决方案建议。

问题分析

1. 资源冲突:
CAN和串口功能可能共享某些硬件资源,例如定时器或中断向量。如果配置不当,可能会导致功能冲突或性能下降。

2. 中断优先级:
CAN和串口通信通常依赖于中断来处理数据收发。如果中断优先级设置不当,可能会导致一个功能抢占另一个功能的资源,从而影响通信的实时性和可靠性。

3. 时钟配置:
CAN和串口通信对时钟精度要求较高。如果时钟配置不当,可能会导致通信错误或数据丢失。

解决方案

1. 合理配置硬件资源:
确保CAN和串口使用的硬件资源不冲突。例如,使用不同的定时器或DMA通道来分别处理CAN和串口的数据传输。

2. 设置中断优先级:
根据应用需求,合理设置CAN和串口中断的优先级。通常,CAN通信对实时性要求较高,可以将其中断优先级设置为高于串口中断。

3. 优化时钟配置:
确保系统时钟配置满足CAN和串口通信的精度要求。可以使用外部晶振或高精度内部时钟源来提高时钟稳定性。

代码示例

以下是一个优化后的代码示例,展示了如何合理配置CAN和串口功能:
  1. c
  2. void main(void)
  3. {
  4.     u8 sr, i, n;
  5.     WTST = 0;  // 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  6.     EAXFR = 1; // 扩展寄存器(XFR)访问使能
  7.     CKCON = 0; // 提高访问XRAM速度
  8.     P0M1 = 0x30;   P0M0 = 0x30;   // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  9.     P1M1 = 0x32;   P1M0 = 0x32;   // 设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
  10.     P2M1 = 0x3c;   P2M0 = 0x3c;   // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
  11.     P3M1 = 0x50;   P3M0 = 0x50;   // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
  12.     P4M1 = 0x3c;   P4M0 = 0x3c;   // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
  13.     P5M1 = 0x0c;   P5M0 = 0x0c;   // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
  14.     P6M1 = 0xff;   P6M0 = 0xff;   // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
  15.     P7M1 = 0x00;   P7M0 = 0x00;   // 设置为准双向口
  16.     CANInit();  // 初始化CAN
  17.     UART1config(2);  // 配置串口1
  18.     // 设置中断优先级
  19.     IP = 0x10;  // 设置CAN中断优先级高于串口中断
  20.     while (1) {
  21.         // 主循环
  22.     }
  23. }
复制代码

总结

通过合理配置硬件资源、设置中断优先级和优化时钟配置,可以有效解决STC32G8K64单片机在同时使用CAN和串口功能时遇到的问题。建议在实际应用中根据具体需求进行进一步优化和调试。

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-10 17:15:10 | 显示全部楼层
检查是否打开总中断后设置串口才会阻塞
串口收发程序供参考:
https://www.stcaimcu.com/thread-4598-1-1.html


DebugLab
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:19 , Processed in 0.133806 second(s), 66 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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