21ic电子技术开发论坛 单片机与嵌入式系统 侃单片机论坛 关于串口很奇怪的一个问题
发新帖我要提问
12下一页
返回列表
打印

关于串口很奇怪的一个问题

[复制链接]
4051|36
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
shaojunyun|  楼主 | 2012-1-14 22:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg51.h>

#define uchar unsigned char

uchar table[8];
uchar i;

void Uart_Init();
void receive();
void send();

void main()
{
     Uart_Init();
    while(1)
    {
          receive();        
         send();
    }           
}

void Uart_Init()
{
     TMOD=0x20;
    TH1=0xfd;
    TL1=0xfd;
    SCON=0x50;
    TR1=1;
}
void receive()
{
     for(i=0;i<8;i++)
    {
         while(!RI);
        RI=0;
        table[i]=SBUF;
    }
}   
void send()
{
     for(i=0;i<8;i++)
    {
        SBUF=table[i];
        while(!TI);
        TI=0;
    }     
}   

这是我写的一个串口程序:将收到的八位数字原样返回。
结果出现了很奇怪的现象:大部分的时间都能正常执行,但是在烧进程序,或者偶尔复位的时候会出现混乱。例如我输入12345678,返回给电脑的是1234567(有时也返回01234567),再点发送,返回给电脑的是81234567,然后就会一直以81234567的形式返回给电脑。复位之后又会恢复正常。
以上我说的仅仅是我验证时碰到的一种情况。
总是在数据返回给电脑的时会出现极个别的错误,大部分情况还是正常的。
本人是菜鸟,想了很久也没头绪,哪位大神帮帮忙,解释解释这种情况啊!

相关帖子

沙发
李富贵| | 2012-1-14 22:17 | 只看该作者
用存储示波器或者逻辑分析仪抓一下波形。

使用特权

评论回复
板凳
NE5532| | 2012-1-14 22:37 | 只看该作者
1.低级错误。
2.楼主对程序二字理解不够。
3.收发都用查询,接收不会掉么?

使用特权

评论回复
地板
shaojunyun|  楼主 | 2012-1-15 15:24 | 只看该作者
3# NE5532
我不是很懂你的意思。程序不是一直停在 while(!RI);么?直到电脑向单片机发送数据时才会向下执行?

使用特权

评论回复
5
cjseng| | 2012-1-15 16:02 | 只看该作者
本帖最后由 cjseng 于 2012-1-15 16:10 编辑

发送建议改成这样试试:
SBUF=table;
while(!TI);
TI=0;
Delay(100);             //延时一段时间


因为单片机的波特率和电脑的波特率可能存在一定的误差,有时候会发生帧错误,尤其是在连续发数据给电脑的时候,有时候会丢失数据(电脑没收到),发送一个字节后略作延时有利于重新同步(帧对齐)。

既然楼主说是发生在单片机复位重启的时候,而此时电脑正在发数据的话,很容易少收几个字节,这样,电脑发8个字节数据,单片机只收到7个或更少,此时单片机不会向电脑发数据,而是要等到电脑下一次发数据,接收到的数据凑满8个字节才会发,这样就出现了错位。

不知我这样说,楼主是否明白我的意思?

使用特权

评论回复
6
NE5532| | 2012-1-15 16:33 | 只看该作者
接收收完一个字节,需要程序读出来,发送这边却在傻等发送完成标志,等发完了,接收那边也溢出了。想双工就别傻等,这是基本原则了。

使用特权

评论回复
7
cjseng| | 2012-1-15 16:49 | 只看该作者
接收收完一个字节,需要程序读出来,发送这边却在傻等发送完成标志,等发完了,接收那边也溢出了。想双工就别傻等,这是基本原则了。
NE5532 发表于 2012-1-15 16:33


你没仔细看楼主程序,他的程序是单工的。

使用特权

评论回复
8
NE5532| | 2012-1-15 17:18 | 只看该作者
你没仔细看楼主程序,他的程序是单工的。
cjseng 发表于 2012-1-15 16:49


别误导楼主啊,他是拿串口助手在收发数据的,电脑发过来的每个数据之间是连续的。这种边收边发的程序,看一眼,没有看到包结构和超时退出,就肯定是双工的。

使用特权

评论回复
9
cjseng| | 2012-1-15 17:49 | 只看该作者
本帖最后由 cjseng 于 2012-1-15 17:54 编辑
别误导楼主啊,他是拿串口助手在收发数据的,电脑发过来的每个数据之间是连续的。这种边收边发的程序,看一眼,没有看到包结构和超时退出,就肯定是双工的。 ...
NE5532 发表于 2012-1-15 17:18


就是因为是用的串口调试工具,肯定是手工发送8个字节数据,等单片机回传8个字节,再点击发送8个字节,再等回传,如此往复而已,怎么就成了双工呢?除非是电脑端未接收完又点了发送。

要是电脑连续发,那楼主根本看不清接收到的数据啊,又不是黑客帝国。:funk:

使用特权

评论回复
10
ningling_21| | 2012-1-15 20:37 | 只看该作者
为何不用中断接收呢?

使用特权

评论回复
11
aihe| | 2012-1-15 21:25 | 只看该作者
但是在烧进程序,或者偶尔复位的时候会出现混乱


这种状态系统未稳定或不能工作,不出错才怪呢

使用特权

评论回复
12
lphaff| | 2012-1-15 22:52 | 只看该作者
调试助手处理过慢,你这发送速度太快。你在每发一个字符后加个延时,保证好使!手机回答问题不容易

使用特权

评论回复
13
silen071027| | 2012-1-16 11:24 | 只看该作者
:L我也认同是你的电脑太快了/改慢一点是没有问题/
居然改慢了将就一下就可以了/
但是,你想做得更好,就再想方法把调得更快

使用特权

评论回复
14
dzxc| | 2012-1-16 11:25 | 只看该作者
下位机设置一个接收超时,原理如下:
收到第1个字节后开始计时,假设正常最多接收10个字节,从波特率测算出最长接收时间为1ms(假设).那么,下位机从第1个字节开始,5ms(自己定的时间),如果接收数据不全,则判断此包数据无效.依此类推.

使用特权

评论回复
15
刘前辈| | 2012-1-16 12:39 | 只看该作者
书上有,主要概念就是“串口接收缓冲器是2级缓冲”;所以可能第一次最后一字节还未读出就退出循环了,结果你第二次接收串的时候,第一个字节可能是上一个串最后遗留的字节。——所以重新读串的时候,应该清扫串口,置RI=0。
void main()
{
     Uart_Init();
    while(1)
    {
     SCON=0x50;   // 清扫串口   
        receive();        
         send();
    }           
}



、、

使用特权

评论回复
16
shaojunyun|  楼主 | 2012-1-16 12:52 | 只看该作者
15# 刘前辈 试过了还是没用,发送12345678,第一次返回的还是1234567,然后之后返回的是81234567。
复位后有恢复正常。

使用特权

评论回复
17
shaojunyun|  楼主 | 2012-1-16 12:53 | 只看该作者
5# cjseng 但是我复位后一切又是正常的。

使用特权

评论回复
18
NE5532| | 2012-1-16 13:10 | 只看该作者
15# 刘前辈 试过了还是没用,发送12345678,第一次返回的还是1234567,然后之后返回的是81234567。
复位后有恢复正常。
shaojunyun 发表于 2012-1-16 12:52


串口助手发送数据是一起发出来的,中间没有间隔。

使用特权

评论回复
19
shaojunyun|  楼主 | 2012-1-16 14:10 | 只看该作者
12# lphaff
跟这个没关系吧,每次复位之后都是正常 的。不过谢谢你的回答。

使用特权

评论回复
20
shaojunyun|  楼主 | 2012-1-16 15:21 | 只看该作者
楼主先谢热心的各位了,我怀疑是板子的干扰问题,因为我换了几块板子尝试了一下,第一次返回的数字有所差别,如1234567、x1234567,&1234567,在不同的板子上会出现这样几种不同的结果,和原始输入数据12345678或多或少有些区别,但无一例外的是复位后全部恢复正常。我建议你们自己也可以把那个程序下载下来试一试,如果真的解决了,请一定要告诉我。:):)

使用特权

评论回复
下一页 »
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

29

帖子

1

粉丝
关闭 热门推荐
快速回复 在线客服 返回列表 返回顶部