1277120515 发表于 昨天 13:44

疑似bug: ISP "设置RTC"按键,会截断接收缓冲器的输出

我在做单片机接收RTC对时数据的功能,我原本想做的功能是,如果单片机接收到RTC对时数据(11个字节),就用串口发送一条消息,表示单片机对时成功。
程序写好后,调试过程中,我发现,我一点"设置RTC"按钮,原本该正常打印的字符串,被截断了。串口助手只输出,字符串的前半部分。
发生频率大概是:我点10次"设置RTC"按钮,有大约2次的输出被截断了。
下面是输出截图:

我点了3次"设置RTC"按钮, 前两次的输出被截断了,第3次是正常的。




还有几个发现:
- 我用逻辑分析仪,抓串口输出的数据,发现输出的字符串是完整的,但是,串口助手的显示被截断了。
- 如果我用串口助手的发送功能,模拟发送11个字节,输出是完全正常的。
- 我用双串口的串口2接收,(串口1发送RTC数据,串口2接收),输出是完全正常的。
疑似是,“设置RTC”按钮的响应函数里面有bug,导致了输出的截断。

下面是测试代码,我用的单片机型号,是STC32G12K128,可复现。

#include "stc32g.h"
typedef unsigned char uint8_t;
typedef long int32_t;


// 串口1初始化
void Uart1Init() {
int32_t T2value;
SM0 = 0;
SM1 = 1;   // 串口1: 8位可变波特率
REN = 1;   // 允许串口1接收数据


TI = 0;    // 清除中断标志位
RI = 0;    // 清除中断标志位


// 定时器2设置
T2x12 = 1; // 0表示定时器2处于12T模式 ; 1表示定时器2处于1T模式
// T2 = 65536 - SYSclk / 4 / 波特率
T2value = (int32_t)(65536 - 12000000L / 4 / 115200);// MAIN_Fosc = 12MHz
T2L = T2value & 0xFF;   
T2H = T2value >> 8;
T2R = 1;      // 定时器2开始计数
ES = 1;       // 允许串口1中断
}

uint8_t cnt = 0;   // 接收到的数据个数
uint8_t recvBuf; // 接收到的数据


// 串口1接受数据
void Uart1Recv_isr() interrupt 4 {
if(RI) {
    RI = 0;   
    // 从SBUF读取数据   
    recvBuf = SBUF;
    cnt++;
}
}

// 串口1发送数据
void Uart1Send(uint8_t dat) {
SBUF = dat;
while(!TI);
TI = 0;
}


void main() {
    uint8_t i;
    char * msg = "RTC message: RTC set time finished! Congradulation!\n"; // 规律是,字符串越长,bug越容易出现
   
    P54RST = 1;
    EAXFR = 1; // 允许访问XFR存储区
    CKCON = 0; // 访问外设等待时间
    WTST = 0;// 每次读取FLASH存储区的等待时间   
    EA = 1;
   
    Uart1Init();
    while(1) {
      // 每接收到11个数据,就发送成功消息
      if(cnt >= 11) {
            cnt = 0;
            // 发送成功消息
            for(i = 0; msg; i++) {
                Uart1Send(msg);
            }   
      }
    }
}

梁工 发表于 昨天 13:53

这种情况一定要从自己的程序里找原因,串口只负责收或发一个字节,别的功能都是程序的事。

乘风飞扬 发表于 昨天 14:12

主循环里发送指令再改改:
for(i = 0; msg; i++) {
    Uart1Send(msg);
}

例如改成:
for(i = 0; i<52; i++) {
    Uart1Send(msg);
}

lcwswust 发表于 昨天 14:44

用这个插入代码,否则会显示不完整


1277120515 发表于 昨天 15:29

乘风飞扬 发表于 2026-7-21 14:12
主循环里发送指令再改改:




哎呀 刚发现,刚才往论坛上贴代码的时候,复制错了。。。。
for(i = 0; msg; i++) {
                Uart1Send(msg);
}
我用上面这段代码测试的,我点了设置RTC按钮,输出仍然是截断的。可是,逻辑分析仪,已经捕获了完整的字符串,但是,串口助手被截断了。

lcwswust 发表于 昨天 15:48

这段代码存在数组越界的可能,越界的后果可能会严重。
建议先限制cnt,再存入数组。如这样:u8 d;d=SBUF;if(cnt<11){recvBuf=d;cnt++;}

// 串口1接受数据
void Uart1Recv_isr() interrupt 4 {
if(RI) {
    RI = 0;   
    // 从SBUF读取数据   
    recvBuf = SBUF;
    cnt++;
}
}


1277120515 发表于 昨天 16:13

lcwswust 发表于 2026-7-21 15:48
这段代码存在数组越界的可能,越界的后果可能会严重。
建议先限制cnt,再存入数组。如这样:u8 d;d=SBUF;if ...串口发送的是完整的字符串,已经被逻辑分析仪验证过了,说明问题不在程序。问题是,串口助手显示的是截断的。

lcwswust 发表于 昨天 16:22

1277120515 发表于 2026-7-21 16:13
串口发送的是完整的字符串,已经被逻辑分析仪验证过了,说明问题不在程序。问题是,串口助手显示的是截断的 ...

如果确定发送没问题,那问题可能出在USB转串口或串口助手,换一种USB转串口线(如CH340)、换一种串口助手(如sscom5.13.1.exe)试试。

1277120515 发表于 昨天 16:39

lcwswust 发表于 2026-7-21 16:22
如果确定发送没问题,那问题可能出在USB转串口或串口助手,换一种USB转串口线(如CH340)、换一种串口助 ...

都试了。我用ISP的串口助手,直接发送11个字节的数据,没问题。换成CH340,发送11个字节的数据,也没有问题。但是,就是用RTC对时模块,实际上,也是发送了11个字节的数据,就有问题了。 所以, 问题就是出在RTC对时模块的"设置RTC"按钮上。
页: [1]
查看完整版本: 疑似bug: ISP "设置RTC"按键,会截断接收缓冲器的输出