找回密码
 立即注册
查看: 142|回复: 17

STC15W408AS串口调试不通

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-30 14:36:57
已绑定手机

1

主题

8

回帖

29

积分

新手上路

积分
29
发表于 4 天前 | 显示全部楼层 |阅读模式
使用的芯片是STC15W408AS,使用ISP的CDC/HID串口助手,只有发送没有接收,串口调不通。软件代码如下:


#include <STC15.h>
#include <intrins.h>

typedef unsigned int u16;       
typedef unsigned char u8;

sbit Beep = P1^6;  // 定义LED控制引脚
void UART_SendByte(u8 dat);
void UART_SendString(const char *s);

bit tx_busy = 0;  // 发送忙标志

void Uart1_Init(void)        //115200bps@24.000MHz
{
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x40;                //定时器时钟1T模式
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //设置定时器模式
        TL1 = 0xCC;                        //设置定时初始值
        TH1 = 0xFF;                        //设置定时初始值
        ET1 = 0;                        //禁止定时器中断
        TR1 = 1;                        //定时器1开始计时
        ES = 1;                            //打开接收中断
        EA = 1;                            //打开总中断
}

void main()
{       
        u16 i;
        Beep=0;
        Uart1_Init();
       
        while(1)
        {               
                Beep=0;       
                UART_SendString("System Started!\r\n");
                for(i = 0; i < 30000; i++)
                {
                    _nop_();
                }
                Beep=1;
               
        }       
       
}

// 发送字符串函数
void UART_SendString(const char *s)
{
    while(*s)          // 遍历字符串直到结束符
    {
        UART_SendByte(*s++); // 发送每个字符
    }
}

// 发送单字节函数
void UART_SendByte(u8 dat)
{
    while(tx_busy);   // 等待前一个字节发送完成
    tx_busy = 1;      // 设置发送忙标志
    SBUF = dat;       // 启动发送

}


//=======================串口中断========================
void uart() interrupt 4 // 串口通信中断函数
{
    u8 rec_data;
        if(RI)
    {
                RI = 0;                            // 清除接收中断标志位
                rec_data = SBUF;        // 存储接收到的数据
                SBUF = rec_data;        // 将接收到的数据放入发送寄存器
        }
       
        if(TI)
    {
                TI = 0;                            // 清除发送完成标志位
                tx_busy = 0;
        }
}


回复

使用道具 举报 送花

3

主题

1928

回帖

704

积分

等待验证会员

积分
704
发表于 4 天前 | 显示全部楼层
你好,关于你使用 STC15W408AS 芯片进行串口通信调试过程中出现“只有发送没有接收”的问题,下面我将从硬件、软件、配置、调试工具等多个方面进行分析,并给出可能的排查建议和优化方向。

一、问题描述总结

你当前使用的芯片为 STC15W408AS,使用 ISP 的 CDC/HID 串口助手进行串口通信调试,发现:
发送功能正常(可以打印“System Started!”);
接收无响应(没有收到任何数据);
已开启接收中断(ES = 1),也开启了总中断(EA = 1);
使用的是 串口1(UART1),波特率为 115200 bps,晶振为 24MHz。

二、代码分析

我们先来看你的串口初始化函数:
  1. c
  2. void Uart1Init(void)        //115200bps@24000MHz
  3. {
  4.         SCON = 0x50;                //8位数据,可变波特率
  5.         AUXR |= 0x40;                //定时器时钟1T模式
  6.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  7.         TMOD &= 0x0F;                //设置定时器模式
  8.         TL1 = 0xCC;                        //设置定时初始值
  9.         TH1 = 0xFF;                        //设置定时初始值
  10.         ET1 = 0;                        //禁止定时器中断
  11.         TR1 = 1;                        //定时器1开始计时
  12.         ES = 1;                            //打开接收中断
  13.         EA = 1;                            //打开总中断
  14. }
复制代码

这段代码看起来是标准的 STC15 系列 UART 初始化配置,但有几个细节需要进一步确认:

1. 波特率是否准确?

你使用的是 24MHz 晶振,波特率为 115200 bps,使用定时器1在1T模式下作为波特率发生器。

计算公式如下:
  1. Baud = Fosc / (32  12  (256 - TH1))
复制代码

代入你设置的 TH1 = 0xFF, TL1 = 0xCC:
  1. TH1 = 0xFF, TL1 = 0xCC → 重载值为 0xFFCC → 十进制为 65484
  2. 256 - (65484 / 256) ≈ 256 - 255.816 ≈ 0.184
  3. Baud = 24000000 / (32  12  0.184) ≈ 33690 bps
复制代码

结论:波特率设置错误!

你当前设置的定时器初值无法达到 115200 bps,实际波特率约为 33k bps,与串口助手设置的 115200 不匹配,会导致接收失败。

✅ 建议:重新计算正确的波特率初值

推荐使用 STC 官方提供的 波特率计算工具或以下公式重新设置:
  1. TH1 = TL1 = 256 - Fosc / (32  12  Baud)
复制代码

代入 Fosc = 24MHz,Baud = 115200:
  1. TH1 = TL1 = 256 - 24000000 / (32  12  115200)
  2.      ≈ 256 - 24000000 / 4423680
  3.      ≈ 256 - 5.426 ≈ 250.574 → 取 250 → 0xFA
复制代码

因此,应修改为:
  1. c
  2. TL1 = 0xFA;
  3. TH1 = 0xFA;
复制代码

三、接收中断未定义处理函数

你在代码中开启了接收中断:
  1. c
  2. ES = 1;
  3. EA = 1;
复制代码

但你没有提供接收中断服务函数,如:
  1. c
  2. void UART1ISR(void) interrupt 4
  3. {
  4.     if(RI)
  5.     {
  6.         RI = 0;
  7.         // 处理接收数据
  8.     }
  9.     if(TI)
  10.     {
  11.         TI = 0;
  12.         txbusy = 0;
  13.     }
  14. }
复制代码

问题: 没有定义中断服务函数,会导致中断触发后无法处理,甚至程序跑飞。

✅ 建议:补充串口接收中断服务函数

例如:
  1. c
  2. void UART1ISR(void) interrupt 4
  3. {
  4.     if(RI)
  5.     {
  6.         RI = 0;
  7.         u8 dat = SBUF;
  8.         // 可以回显或者处理接收到的数据
  9.         UARTSendByte(dat);
  10.     }
  11.     if(TI)
  12.     {
  13.         TI = 0;
  14.         txbusy = 0;
  15.     }
  16. }
复制代码

四、硬件连接问题排查

1. 串口引脚是否正确连接?

STC15W408AS 的串口1引脚为:
P3.0(RXD):接收;
P3.1(TXD):发送。

请确认:
你是否将 TXD 接到 USB 转 TTL 模块的 RX;
RXD 是否接到 USB 模块的 TX;
GND 是否共地;
电平是否匹配(3.3V / 5V);

2. 使用的是 ISP 下载口自带的串口?

有些 ISP 下载器(如 STC-USB)内部使用的是虚拟串口(CDC),在使用时需注意:
驱动是否安装;
串口号是否正确;
是否与其他串口冲突;
是否支持全双工通信(有些只支持下载,不支持调试);

五、调试建议

1. 使用逻辑分析仪或示波器查看 TXD 波形
确认 TXD 是否有发送数据;
查看波特率是否与设置一致;
判断是否因电平、波特率不匹配导致接收失败。

2. 使用串口助手发送数据测试
手动发送“HELLO”等字符;
观察是否能触发接收中断;
在中断中添加 LED 闪烁或打印回显判断是否收到数据。

六、完整修正后的代码示例
  1. c
  2. include
  3. include
  4. typedef unsigned int u16;       
  5. typedef unsigned char u8;
  6. sbit Beep = P1^6;
  7. bit txbusy = 0;
  8. void UARTSendByte(u8 dat)
  9. {
  10.     while(txbusy);        // 等待上次发送完成
  11.     SBUF = dat;
  12.     txbusy = 1;
  13. }
  14. void UARTSendString(const char s)
  15. {
  16.     while(s)
  17.     {
  18.         UARTSendByte(s++);
  19.     }
  20. }
  21. void Uart1Init(void)
  22. {
  23.     SCON = 0x50;           // 8位数据,可变波特率
  24.     AUXR |= 0x40;          // 定时器时钟为1T模式
  25.     AUXR &= 0xFE;          // 串口1选择定时器1为波特率发生器
  26.     TMOD &= 0x0F;          // 设置定时器模式
  27.     TL1 = 0xFA;            // 115200@24MHz
  28.     TH1 = 0xFA;
  29.     ET1 = 0;               // 禁止定时器1中断
  30.     TR1 = 1;               // 启动定时器1
  31.     ES = 1;                // 使能串口中断
  32.     EA = 1;                // 使能全局中断
  33. }
  34. void UART1ISR(void) interrupt 4
  35. {
  36.     if(RI)
  37.     {
  38.         RI = 0;
  39.         u8 dat = SBUF;
  40.         UARTSendByte(dat);  // 回显
  41.     }
  42.     if(TI)
  43.     {
  44.         TI = 0;
  45.         txbusy = 0;
  46.     }
  47. }
  48. void main()
  49. {
  50.     u16 i;
  51.     Beep = 0;
  52.     Uart1Init();
  53.     while(1)
  54.     {
  55.         Beep = 0;       
  56.         UARTSendString("System Started!\r\n");
  57.         for(i = 0; i < 30000; i++);
  58.     }
  59. }
复制代码

七、总结

| 问题点 | 原因 | 解决方案 |
|--------|------|-----------|
| 波特率设置错误 | TH1/TL1 初值不匹配 115200 | 修改为 0xFA |
| 无接收中断处理 | 没有定义中断函数 | 添加 UART1ISR 函数 |
| 硬件连接问题 | 引脚接错或电平不匹配 | 检查串口连接、电平、共地 |
| 调试工具问题 | ISP 串口不支持接收 | 使用独立 USB 转 TTL 模块 |

八、扩展建议
使用串口调试助手(如 XCOM、SSCOM)进行收发测试;
使用串口缓冲区实现更复杂的接收逻辑;
使用定时器或延时函数控制发送频率;
若需更高波特率或稳定通信,可考虑使用 定时器2 或 独立波特率发生器模块(部分 STC15 支持)。

如仍有问题,欢迎提供更详细的硬件连接图、串口助手截图或波形图,我可以进一步协助排查。

祝调试顺利!

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

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:315
  • 最近打卡:2025-10-02 12:32:59
已绑定手机

83

主题

3209

回帖

7092

积分

荣誉版主

无情的代码机器

积分
7092
发表于 4 天前 | 显示全部楼层
注意此型号无定时器1
截图202509291115266533.jpg
  1.   SCON = 0x50;                //8位数据,可变波特率
  2.         AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
  3.         AUXR |= 0x04;                //定时器时钟1T模式
  4.         T2L = 0xCC;                        //设置定时初始值
  5.         T2H = 0xFF;                        //设置定时初始值
  6.         AUXR |= 0x10;                //定时器2开始计时
  7.         ES = 1;                                //使能串口1中断
  8.        
  9.         EA = 1;                            //打开总中断
复制代码


三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-30 14:36:57
已绑定手机

1

主题

8

回帖

29

积分

新手上路

积分
29
发表于 4 天前 | 显示全部楼层
erci*** 发表于 2025-9-29 11:15
注意此型号无定时器1

我把定时器改为T2了,重新修改了代码,但是和之前现象一样,也没有发送数据的回显,也没有接收,能帮我再看下代码吗,有劳您?代码如下:

#include <STC15.h>
#include <intrins.h>

typedef unsigned int u16;        
typedef unsigned char u8;

sbit Beep = P1^6;  // 定义LED控制引脚
void UART_SendByte(u8 dat);
void UART_SendString(const char *s);

bit tx_busy = 0;  // 发送忙标志

void Uart1_Init(void)        //9600bps @24.000MHz
{
        SCON = 0x50;                //8位数据,可变波特率
        //PCON = 0x00;                //波特率不加倍
        AUXR = 0x05;                //定时器时钟1T模式 串口1选择定时器2为波特率发生器
        T2L = 0x8F;                        //设置定时初始值
        T2H = 0xFD;                        //设置定时初始值
        AUXR |= 0x10;                //启动定时器2
        ES = 1;                            //打开接收中断
        EA = 1;                            //打开总中断
}

void main()
{        
        u16 i;
        Beep=0;
        Uart1_Init();
        
        while(1)
        {               
                Beep=0;        
                UART_SendString("System Started!\r\n");
                for(i = 0; i < 30000; i++)
                {
                    _nop_();
                }
                Beep=1;
               
        }        
        
}

// 发送字符串函数
void UART_SendString(const char *s)
{
    while(*s)          // 遍历字符串直到结束符
    {
        UART_SendByte(*s++); // 发送每个字符
    }
}

// 发送单字节函数
void UART_SendByte(u8 dat)
{
    while(tx_busy);   // 等待前一个字节发送完成
    tx_busy = 1;      // 设置发送忙标志
    SBUF = dat;       // 启动发送

}


//=======================串口中断========================
void uart() interrupt 4 // 串口通信中断函数
{
    u8 rec_data;
        if(RI)
    {
                RI = 0;                            // 清除接收中断标志位
                rec_data = SBUF;        // 存储接收到的数据
                UART_SendByte(rec_data);
                SBUF = rec_data;        // 将接收到的数据放入发送寄存器
        }
        
        if(TI)
    {
                TI = 0;                            // 清除发送完成标志位
                tx_busy = 0;
        }
}
串口情况如下:
截图202509291449387952.jpg


点评

早上在15W408AS测过的代码,24M下载,波特率115200,还不行的话检查下硬件连接:  详情 回复 发表于 4 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:315
  • 最近打卡:2025-10-02 12:32:59
已绑定手机

83

主题

3209

回帖

7092

积分

荣誉版主

无情的代码机器

积分
7092
发表于 4 天前 | 显示全部楼层
张*** 发表于 2025-9-29 14:47
我把定时器改为T2了,重新修改了代码,但是和之前现象一样,也没有发送数据的回显,也没有接收,能帮我再 ...

早上在15W408AS测过的代码,24M下载,波特率115200,还不行的话检查下硬件连接:

  1. #include <STC15.h>
  2. #include <intrins.h>
  3. typedef unsigned int u16;      
  4. typedef unsigned char u8;
  5. sbit Beep = P1^6;  // 定义LED控制引脚
  6. void UART_SendByte(u8 dat);
  7. void UART_SendString(const char *s);
  8. bit tx_busy = 0;  // 发送忙标志
  9. void Uart1_Init(void)        //115200bps@24.000MHz
  10. {
  11. //        SCON = 0x50;                //8位数据,可变波特率
  12. //        AUXR |= 0x40;                //定时器时钟1T模式
  13. //                                AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
  14. //        //AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  15. //        TMOD &= 0x0F;                //设置定时器模式
  16. //        TL1 = 0xCC;                        //设置定时初始值
  17. //        TH1 = 0xFF;                        //设置定时初始值
  18. //        ET1 = 0;                        //禁止定时器中断
  19. //        TR1 = 1;                        //定时器1开始计时
  20. //        ES = 1;                            //打开接收中断
  21.        
  22.                 SCON = 0x50;                //8位数据,可变波特率
  23.         AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
  24.         AUXR |= 0x04;                //定时器时钟1T模式
  25.         T2L = 0xCC;                        //设置定时初始值
  26.         T2H = 0xFF;                        //设置定时初始值
  27.         AUXR |= 0x10;                //定时器2开始计时
  28.         ES = 1;                                //使能串口1中断
  29.        
  30.         EA = 1;                            //打开总中断
  31. }
  32. void main()
  33. {      
  34.         u16 i;
  35.         Beep=0;
  36.         Uart1_Init();
  37.       
  38.         while(1)
  39.         {               
  40.                 Beep=0;      
  41.                 UART_SendString("System Started!\r\n");
  42.                 for(i = 0; i < 30000; i++)
  43.                 {
  44.                     _nop_();
  45.                 }
  46.                 Beep=1;
  47.                
  48.         }      
  49.       
  50. }
  51. // 发送字符串函数
  52. void UART_SendString(const char *s)
  53. {
  54.     while(*s)          // 遍历字符串直到结束符
  55.     {
  56.         UART_SendByte(*s++); // 发送每个字符
  57.     }
  58. }
  59. // 发送单字节函数
  60. void UART_SendByte(u8 dat)
  61. {
  62.     while(tx_busy);   // 等待前一个字节发送完成
  63.     tx_busy = 1;      // 设置发送忙标志
  64.     SBUF = dat;       // 启动发送
  65. }
  66. //=======================串口中断========================
  67. void uart() interrupt 4 // 串口通信中断函数
  68. {
  69.     u8 rec_data;
  70.         if(RI)
  71.     {
  72.                 RI = 0;                            // 清除接收中断标志位
  73.                 rec_data = SBUF;        // 存储接收到的数据
  74.                 SBUF = rec_data;        // 将接收到的数据放入发送寄存器
  75.         }
  76.       
  77.         if(TI)
  78.     {
  79.                 TI = 0;                            // 清除发送完成标志位
  80.                 tx_busy = 0;
  81.         }
  82. }
复制代码


三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-30 14:36:57
已绑定手机

1

主题

8

回帖

29

积分

新手上路

积分
29
发表于 4 天前 | 显示全部楼层
erci*** 发表于 2025-9-29 15:13
早上在15W408AS测过的代码,24M下载,波特率115200,还不行的话检查下硬件连接:

我用你测试的这个代码也测了一下,我只发了数字9,能正常进入中断和发送波形,但是串口助手选择了串口,设置波特率,打开串口后,却没有任何接收。麻烦帮我再看下哈,
截图202509291706563059.jpg 截图202509291707075601.jpg
串口界面如下(帮看下是否有设置不对的地方):
截图202509291708174645.jpg

点评

按你编写的逻辑这个代码正常运行应一直在发送: System Started!\r\n 收到PC消息后原文回传。 可以发下硬件原理图和实物连接看看  详情 回复 发表于 4 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:315
  • 最近打卡:2025-10-02 12:32:59
已绑定手机

83

主题

3209

回帖

7092

积分

荣誉版主

无情的代码机器

积分
7092
发表于 4 天前 | 显示全部楼层
张*** 发表于 2025-9-29 17:06
我用你测试的这个代码也测了一下,我只发了数字9,能正常进入中断和发送波形,但是串口助手选择了串口,设 ...

按你编写的逻辑这个代码正常运行应一直在发送:

System Started!\r\n


收到PC消息后原文回传。


可以发下硬件原理图和实物连接看看
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-30 14:36:57
已绑定手机

1

主题

8

回帖

29

积分

新手上路

积分
29
发表于 4 天前 | 显示全部楼层
硬件原理图:P31和P30复用为IIC的时钟线和数据线,但现在应该不影响串口,
截图202509291729153887.jpg
实物连接如下:

截图202509291732583514.jpg
截图202509291733104764.jpg
另外打开串口前,使用外部电源给板子供电。

点评

这工具看着是短接的I2C当前不在串口模式? 先换个不复用的板子和常规串口工具测吧,测正常了再替换图里这个工具和板子,对比差异。  详情 回复 发表于 4 天前
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:315
  • 最近打卡:2025-10-02 12:32:59
已绑定手机

83

主题

3209

回帖

7092

积分

荣誉版主

无情的代码机器

积分
7092
发表于 4 天前 | 显示全部楼层
张*** 发表于 2025-9-29 17:28
硬件原理图:P31和P30复用为IIC的时钟线和数据线,但现在应该不影响串口,

实物连接如下:


这工具看着是短接的I2C当前不在串口模式?

先换个不复用的板子和常规串口工具测吧,测正常了再替换图里这个工具和板子,对比差异。

三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-09-30 14:36:57
已绑定手机

1

主题

8

回帖

29

积分

新手上路

积分
29
发表于 4 天前 | 显示全部楼层
erci*** 发表于 2025-9-29 17:57
这工具看着是短接的I2C当前不在串口模式?

先换个不复用的板子和常规串口工具测吧,测正常了再替换图里 ...

换了一个串口工具测试,串口助手可以正常接收mcu发来的数据,在接收数据之前需要在串口助手的发送窗预先发送一个信令,以启动串口助手的接收。
所以,ISP的CDC/HID助手是否也需要一个类似的启动接收信令啊

点评

不需要的打开就能收到,还是检查工具问题。  详情 回复 发表于 4 天前
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-10-3 08:52 , Processed in 0.211068 second(s), 112 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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