mPiDDR 发表于 2021-1-29 19:37:01

STC8G1K17串口9600通信,丢数据,请问如何解决。

新手,第一次用STC8G单片机,程序从ISP下载软件复制过来的,时钟11.592M,波特率设置的9600,
在用串口调试助手 进行数据收发测试的时候,丢数据。每秒发12字节数据。20%的机率丢一个字节数据。
具体代码如下

void UartIsr() interrupt 4
{
        uint8_t rx;
    if (TI)
    {
      TI = 0;
      busy0 = 0;
    }
    if (RI)
    {
      RI = 0;
                                rx = SBUF;
                                SBUF = rx;LED = !LED; //收到的数据直接发送回去
                                busy0 = 1;
    }
}
初始化
#define FOSC         11059200UL
#define BRT             (65536 - FOSC / 9600 / 4)

TMOD = 0x00;//UART1
SCON = 0x50;
AUXR |= 0x40;
TL1 = BRT;
TH1 = BRT >> 8;
TR1 = 1;
ES = 1;
EA = 1;

mPiDDR 发表于 2021-1-29 19:42:00

宇宙第一强的单片机,肯定不会是这个样子。大神帮帮我。
目前尝试,
1. 数据处理不过来? 将时钟调高到18.432M,无果
2.难道是这个UART1 不行?我又调了UART2进行测试,仍是会丢数据。
3.波特率太高了??使用4800bps.仍是一样会丢

丢数据可以理解,但是约20%的概率。这个什么保证通信正常。。。

magiczero 发表于 2021-1-29 19:46:32

是不是你单片机的振荡频率不准,误差过大

mPiDDR 发表于 2021-1-29 19:48:03

magiczero 发表于 2021-1-29 19:46
是不是你单片机的振荡频率不准,误差过大

用的是IRC 频率11.592M
下载程序的时候提示
. 用户设定频率: 11.059MHz
. 调节后的频率: 11.062MHz
. 频率调节误差: 0.022%

这个用9600波特率 不够吗

mPiDDR 发表于 2021-1-29 19:49:41

同时考虑到是不是串口转换器 时钟不准。可是
我的UART1 接CP2102   UART2 接CH341 。不会两个都不准吧?
另外, 整个系统目前就用了串口,没有别的中断干扰。

magiczero 发表于 2021-1-29 19:51:31

看你的RC误差是没有问题的,不过还是接一个实际的外部晶振测试下看看

不舍的六年 发表于 2021-1-29 20:44:30

就是这样的结果,我的也是丢数据。

mPiDDR 发表于 2021-1-29 20:46:48

magiczero 发表于 2021-1-29 19:51
看你的RC误差是没有问题的,不过还是接一个实际的外部晶振测试下看看

整个电路 我都没有放置晶振
也不打算放置晶体了,相同的hex文件 刷到STC8A8K64S4A12这个芯片上,收发数据正常无丢数据
现在真的是没辙了

mPiDDR 发表于 2021-1-29 20:56:40

不舍的六年 发表于 2021-1-29 20:44
就是这样的结果,我的也是丢数据。

有解决办法吗,丢的数据没有规律,可靠性不行啊。。。

1a2b3c 发表于 2021-1-29 21:03:28

从0-255发256个数据看哪个数据丢失,有没有规律

wye11083 发表于 2021-1-29 21:04:41

mPiDDR 发表于 2021-1-29 20:56
有解决办法吗,丢的数据没有规律,可靠性不行啊。。。

你难道没听说过时钟漂移? 你这样写不丢才怪了!自己搜 ring buffer,写个小fifo

mPiDDR 发表于 2021-1-29 21:19:56

wye11083 发表于 2021-1-29 21:04
你难道没听说过时钟漂移? 你这样写不丢才怪了!自己搜 ring buffer,写个小fifo ...

感谢你们的回复,这些简单的可能,我还是会考虑得到的。
1. 9600的波特率已够低,时钟再偏5% 也不会有问题。
2. FIFO 我一直有在用。贴上来的程序只是做简明环回测试、 正常程序是中断填充FIFO 在主程序取数据处理。
3. 用FIFO 来收,主程序处理的时候,环回发送,也一样会丢,

楼上的楼上,目前看没有规律。、

youkebing 发表于 2021-1-29 21:57:38

这个写法应该是有问题的(至少我不会这样写),如果单片机自带fifo的(或发送寄存器有两个的),这样写一般不会有问题。我个人猜测可能是这样的,数据收到写道发送寄存器,这个时间不会完全一致,在发送还没有发送完成的时候,这个时候写道发送寄存器,会导致你写入sbuf失败,你说你用过fifo也有问题,不妨把fifo的代码也发上来,让大家分析一下,问题很可能就在细微处。

yy625 发表于 2021-1-29 22:16:49

楼上应该是正解!
9600bps,又是这么简单的测试,就是查询方式也不会有什么问题。

modbus 发表于 2021-1-29 22:44:30

设置IO模式

modbus 发表于 2021-1-29 22:45:51

把串口发送管脚设置为推挽输出

wye11083 发表于 2021-1-30 00:07:39

youkebing 发表于 2021-1-29 21:57
这个写法应该是有问题的(至少我不会这样写),如果单片机自带fifo的(或发送寄存器有两个的),这样写一般 ...

估计lz的fifo也是按那个方法写的。。事实上程序需要先填fifo,如果busy就通过中断继续写,否则程序立刻发起写。我921600bps都跑得欢,lz这9600都能丢数据也是太牛13了(不排除lz电路连接有问题,通常是地电平不相等,etc)。

华芯 发表于 2021-1-30 06:14:21

等等官方权威回复……
不过这种很基础的操作,官方肯定测试过吧,真有问题也应该发现了

mPiDDR 发表于 2021-1-30 09:00:55

本帖最后由 mPiDDR 于 2021-1-30 09:07 编辑

youkebing 发表于 2021-1-29 21:57
这个写法应该是有问题的(至少我不会这样写),如果单片机自带fifo的(或发送寄存器有两个的),这样写一般 ...

是的,我也不会这样写。但是为了方便大家看得清楚、
目前经过折腾 可以确定的是: 是在接收的时候出现丢失。这个字节没有收到,也就没法发送回去。

再次对上面的回复,发送程序是没有问题的。

wye11083 提醒的好,希望是硬件连接的问题。买的是简单开发板,连接了5VGNDTX RX 四条线。下载程序也是用这条线。如果是连接线有问题,为何官方ISP能顺序刷?
另外,说TX端口需要推挽输出的,这个也尝试过了。没有改变。

发这帖子,希望能找到低级的错误。初始化的代码楼主位

相同的hex 一个字节不改,刷到STC8A8K64S4A12上,跑得很好,数据环回没有丢失。都是用相同内部IRC时钟
把代码贴出来。
xdata uint8_t wptr;    //不管有没有加xdata 结果一样
xdata uint8_t rptr;
xdata uint8_t ucUartRxbuf = {0}; //接收缓冲
void Uart2Isr() interrupt 8
{
    if (S2CON & 0x02)
    {
      S2CON &= ~0x02;
      busy = 0;
    }
    if (S2CON & 0x01)
    {
      S2CON &= ~0x01;
        ucUartRxbuf = S2BUF;
      wptr &= 0x3f;
    }
}
//主程序读取接收数据
uint8_t UART2_Read(uint8_t* dat){
        if(rptr == wptr)return 0;
        dat = ucUartRxbuf;
        rptr &= 0x3f;
}
//发送
void Uart2Send(uint8_t dat)
{
    while (busy);
                _nop_();_nop_();_nop_();
    busy = 1;
    S2BUF = dat;
}
//主循环while (1)
uint8_t Usart_Rx_Num;uint8_t UARTRX;
                Usart_Rx_Num = UART2_Read(&UARTRX);
                if(Usart_Rx_Num!=0){
                                        Uart2Send(UARTRX);
                        }

mPiDDR 发表于 2021-1-30 09:05:42

本帖最后由 mPiDDR 于 2021-1-30 09:20 编辑

mPiDDR 发表于 2021-1-30 09:00
是的,我也不会这样写。但是为了方便大家看得清楚、
目前经过折腾 可以确定的是: 是在接收的时候出现丢 ...

由于对STC8 不熟悉,下载程序的界面也一并截图,看哪里有不对的


正在检测目标单片机 ...
单片机型号: STC8G1K17-20/16PIN
固件版本号: 7.3.10U

当前芯片的硬件选项为:
. 内部IRC振荡器的频率: 11.062MHz
. 掉电唤醒定时器的频率: 35.475KHz
. 振荡器放大增益使能
. P3.2和P3.3与下次下载无关
. 上电复位时增加额外的复位延时
. 复位引脚用作普通I/O口
. 检测到低压时复位
. 低压检测门槛电压 : 2.00 V
. 上电复位时,硬件不启动内部看门狗
. 上电自动启动内部看门狗时的预分频数为 : 256
. 空闲状态时看门狗定时器停止计数
. 启动看门狗后,软件可以修改分频数,但不能关闭看门狗
. 下次下载用户程序时,将用户EEPROM区一并擦除
. 下次下载用户程序时,没有相关的端口控制485
. 下次下载时不需要校验下载口令
. 内部参考电压: 1195 mV (参考范围: 1100~1300mV)
. 内部安排测试时间: 2020年3月16日

单片机型号: STC8G1K17-20/16PIN
固件版本号: 7.3.10U

开始调节频率 ...                       
调节后的频率: 11.062MHz (0.022%)

正在重新握手 ... 成功                       
当前的波特率: 115200
正在擦除目标区域 ... 完成 !               
芯片出厂序列号 : F757C465094F53
正在下载用户代码 ... 完成 !               
正在设置硬件选项 ... 完成 !               

更新后的硬件选项为:
. 内部IRC振荡器的频率: 11.062MHz
. 掉电唤醒定时器的频率: 35.475KHz
. 振荡器放大增益使能
. P3.2和P3.3与下次下载无关
. 上电复位时增加额外的复位延时
. 复位引脚用作普通I/O口
. 检测到低压时复位
. 低压检测门槛电压 : 2.00 V
. 上电复位时,硬件不启动内部看门狗
. 上电自动启动内部看门狗时的预分频数为 : 256
. 空闲状态时看门狗定时器停止计数
. 启动看门狗后,软件可以修改分频数,但不能关闭看门狗
. 下次下载用户程序时,将用户EEPROM区一并擦除
. 下次下载用户程序时,没有相关的端口控制485
. 下次下载时不需要校验下载口令
. 内部参考电压: 1195 mV (参考范围: 1100~1300mV)
. 内部安排测试时间: 2020年3月16日

. 芯片出厂序列号 : F757C465094F53
单片机型号: STC8G1K17-20/16PIN
固件版本号: 7.3.10U

. 用户设定频率: 11.059MHz
. 调节后的频率: 11.062MHz
. 频率调节误差: 0.022%


操作成功 !(2021-01-30 09:03:39)

youkebing 发表于 2021-1-30 09:34:56

mPiDDR 发表于 2021-1-30 09:00
是的,我也不会这样写。但是为了方便大家看得清楚、
目前经过折腾 可以确定的是: 是在接收的时候出现丢 ...

楼主,你仔细看看,这个和你写的是一样吗?

mPiDDR 发表于 2021-1-30 09:45:23

本帖最后由 mPiDDR 于 2021-1-30 09:48 编辑

youkebing 发表于 2021-1-30 09:34
楼主,你仔细看看,这个和你写的是一样吗?

大致说一下吧,整个硬件串口1 专用下载的,串口2我用来与主控制器通信。
目前测试,在9600下,串口2的丢码率高于串口1。

谢谢你的提醒。因为串口2丢码的情况下,我才去调的串口1 想对比看。结果很失望
void Uart2Init()
{
    S2CON = 0x10;
    T2L = BRT;
    T2H = BRT >> 8;
    AUXR = 0x14;
    busy = 0;
    TMOD = 0x00;//UART1
    SCON = 0x50;
    AUXR |= 0x40;
    TL1 = BRT;
    TH1 = BRT >> 8;
    TR1 = 1;
    wptr = 0x00;
    rptr = 0x00;
    busy0 = 0;
}

ps :
11.592M   确是我打字错了 实际代码中。
#define FOSC         11059200UL//22118400UL//
#define BRT             (65536 - FOSC / 9600 / 4)


takashiki 发表于 2021-1-30 09:46:33

>>>程序从ISP下载软件复制过来的,时钟11.592M,波特率设置的9600,

. 用户设定频率: 11.059MHz
. 调节后的频率: 11.062MHz
. 频率调节误差: 0.022%

11.592M、11.0592M,总感觉好神奇

youkebing 发表于 2021-1-30 09:57:30

mPiDDR 发表于 2021-1-30 09:45
大致说一下吧,整个硬件串口1 专用下载的,串口2我用来与主控制器通信。
目前测试,在9600下,串口2的丢 ...

上次买过一个小板,晚上抽空测试一下

youkebing 发表于 2021-1-30 10:42:42

mPiDDR 发表于 2021-1-30 09:05
由于对STC8 不熟悉,下载程序的界面也一并截图,看哪里有不对的




方便的话,把你的测试工程也发上来,我一会测试一下看看,我就不用重新建项目了‘

qq325600 发表于 2021-1-30 11:02:47

为什么不用个数组先接收完全部数据后,再一一发出呢? 这样收到就发,收到就发.串口时序不会错乱吗?

youkebing 发表于 2021-1-30 11:26:38

mPiDDR 发表于 2021-1-30 09:45
大致说一下吧,整个硬件串口1 专用下载的,串口2我用来与主控制器通信。
目前测试,在9600下,串口2的丢 ...

刚才随便找了个程序测试,我都是正常的,完全没有丢包,我的单片机型号: STC8G1K08-20/16PIN

modbus 发表于 2021-1-30 11:34:51

在SBUF = rx上面加入TI=0试试,印象中51的标准串口写SBUF时必须要确保TI已清除,而你这程序存在执行SBUF = rx时TI为1的可能

mPiDDR 发表于 2021-1-30 11:38:19

youkebing 发表于 2021-1-30 10:42
方便的话,把你的测试工程也发上来,我一会测试一下看看,我就不用重新建项目了‘ ...

问题找到了。
uint8_t UART2_Read(uint8_t* dat){
        if(rptr == wptr)return 0;
        dat = ucUartRxbuf;
        rptr &= 0x3f;
        return 1; //之前省了此处   属于代码bug
}
总结一下,STC8G 不能在中断里直接发送。STC8A却可以?
现在使用FIFO接收处理,已无丢失数据。

感谢 楼上各位的回复。

再次证明STC处理器 宇宙最强。

附工程代码。

youkebing 发表于 2021-1-30 11:43:54

mPiDDR 发表于 2021-1-30 09:45
大致说一下吧,整个硬件串口1 专用下载的,串口2我用来与主控制器通信。
目前测试,在9600下,串口2的丢 ...

上传个测试图片


youkebing 发表于 2021-1-30 11:46:40

mPiDDR 发表于 2021-1-30 11:38
问题找到了。
uint8_t UART2_Read(uint8_t* dat){
        if(rptr == wptr)return 0;


既然找到原因了,那我就不测试了

modbus 发表于 2021-1-30 13:09:24

youkebing 发表于 2021-1-30 11:46
既然找到原因了,那我就不测试了

找到什么呀,“STC8G 不能在中断里直接发送”,想想可能不可能

fxhfxh 发表于 2021-1-30 14:26:54

“STC8G 不能在中断里直接发送”,这个结论不可能吧?

mPiDDR 发表于 2021-1-30 15:53:19

fxhfxh 发表于 2021-1-30 14:26
“STC8G 不能在中断里直接发送”,这个结论不可能吧?

可以在中断里发,但是会有机率丢失数据, 这样的回答更严谨吧
具体看上面的代码,只希望这样的情况,只出现在个别的芯片。至少我手上的块是这样。




fxhfxh 发表于 2021-1-30 16:11:36

mPiDDR 发表于 2021-1-30 15:53
可以在中断里发,但是会有机率丢失数据, 这样的回答更严谨吧
具体看上面的代码,只希望这样的情况,只出 ...

好的,手上也有8G的芯片,有时间了,在中断里收发试一试。

youkebing 发表于 2021-1-30 16:27:18

mPiDDR 发表于 2021-1-30 15:53
可以在中断里发,但是会有机率丢失数据, 这样的回答更严谨吧
具体看上面的代码,只希望这样的情况,只出 ...

我的测试程序就在中断里发的

rootxie 发表于 2021-1-30 20:48:07

宇宙最强STC处理器 肯定不会存在如此问题了,不然怎么叫宇宙最强

mangolu 发表于 2021-1-31 04:13:18

youkebing 发表于 2021-1-30 11:43
上传个测试图片

你这个代码可以共享一下吗?谢谢

rei1984 发表于 2021-1-31 07:36:31

中断里发送的前提是 清除 发送完毕的标志位(sfr)。

然后 把数据放到sbuf里面。最后会发出去

ordman 发表于 2021-1-31 09:04:31

检查硬件。
tx,rx的线尽量短,太长了就会发生错误。

ordman 发表于 2021-1-31 09:04:59

检查硬件。
tx,rx的线尽量短,太长了就会发生错误。

youkebing 发表于 2021-1-31 09:38:28

mangolu 发表于 2021-1-31 04:13
你这个代码可以共享一下吗?谢谢

就是官方的例程

mangolu 发表于 2021-1-31 10:01:02

youkebing 发表于 2021-1-31 09:38
就是官方的例程

不懂是官方哪个例程?我其实不是STC,最近也发现丢失数据,我程序写得不好吧,所以想参考一下。

youkebing 发表于 2021-1-31 19:05:55

mangolu 发表于 2021-1-31 10:01
不懂是官方哪个例程?我其实不是STC,最近也发现丢失数据,我程序写得不好吧,所以想参考一下。 ...

第6个例程(06-串口1中断模式与电脑收发测试),你参考一下吧

mangolu 发表于 2021-1-31 20:39:38

youkebing 发表于 2021-1-31 19:05
第6个例程(06-串口1中断模式与电脑收发测试),你参考一下吧

好的,谢谢

cooltommy 发表于 2021-2-8 15:19:01

不要使用中断方式发送数据
页: [1]
查看完整版本: STC8G1K17串口9600通信,丢数据,请问如何解决。