使用51单片机与pc串口通信中数据不一致问题

fsnet 2010-04-13 05:26:18
我用51单片机与pc机进行串口通讯,上位机软件用的是出口调试助手3.0,下位机是我自己编的,主要目的是pc向单片机发个数据,单片机接收后向p2口输出,之后再把接收到的数据发给pc。但是我发现pc上发出与收到的数据总是不一致。例如,我用pc输出字符“123”,经单片机传回的字符就变成了“pp?p滎”。不知道是什么原因,还请各位高手赐教。
这使我编的下位机程序:
ORG 00
AJMP MAIN
ORG 23H
LJMP RECEIVE
MAIN:
mov p2,#21h
LCALL URTINIT
AJMP $
RECEIVE:
MOV A,SBUF ;将缓冲区的数据送到A
MOV P2,A
MOV SBUF,a ;将A的数据发回到电脑
JNB TI,$ ;等待数据发送完毕
CLR TI ;清发送中断标志
CLR RI ;清接收中断标志
RETI ;中断返回
URTINIT:
MOV SCON,#50H ;设置成串口1方式
MOV TMOD,#20H ;波特率发生器T1工作在模式2上
MOV TH1,#0FBH ;预置初值 9BTL=2^SMOD/32*FOSC/12/(256-TH1)
MOV TL1,#0FBH ;波特率9600
SETB TR1;启动定时器T1
SETB EA ;CPU所有中断开(IE最高位MSB)
SETB ES ;串口中断标志位
RET
end
...全文
2643 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
wyzwt 2011-04-14
  • 打赏
  • 举报
回复
太好了,我和他问题一样,看到这条回复,我试了一下,果然是这个原因[Quote=引用 11 楼 wslxs2008 的回复:]

楼主晶振是多少的
[/Quote]
schlafenhamster 2010-04-29
  • 打赏
  • 举报
回复
晶振为11.059MHz时?
晶振是硬件怎么能‘设’
fsnet 2010-04-19
  • 打赏
  • 举报
回复
感谢楼上各位高手,我大致知道我的问题了。我把pcon设成80h,th1和tl1设成f3h,晶振设为12MHz,也就是说把单片机的波特率调成4800所有问题就都解决了,而且还能连续发送字符,不用建立缓冲区。但是我仍然很奇怪,当我把pcon设成00h,th1和tl1设成fah,晶振设为11.059MHz时,理论上单片机的波特率也应该是4800,可这时通讯就不成功,还是收到错误的数据。再把波特率调成9600或19200也都不行,不知什么原因。难道是硬件问题吗?真的需要用示波器测一下吗?
fsnet 2010-04-16
  • 打赏
  • 举报
回复
另外还有个问题,就是我单个发送60 61 62 63 64 65 66 67 68 69 70这几个十六进制数,TH1和TL1设为fb时,收到的结果是十六进制60 60 62 62 6C 6C 6E 6E 60 60 70 ,所以即便是单个发送结果也是不对的。而且我在在单片机上接了led显示每次收到数据的情况,单片机上显示收到的数据是十六进制的e8 e8 e9 e9 ea ea eb eb e8 e8 ec;当TH1和TL1设为fa时,单个发送60 61 62 63 64 65 66 67 68 69 70,收到20 20 26 26 20 20 26 26 38 38 20 ,单片机显示收到f4 f4 f5 f5 f4 f4 f5 f5 f6 f6 f4。
我记得在看书时写单片机串口工作在方式1时,使用10位异步通信,每个数据帧由一个起始位“0”、8个数据位和1个停止位1构成,而且起始位和停止位是硬件自动加的,而PC在设置串口通信方式时用9600,n,8,1方式发送和接收数据无法设置起始位,那是不是说PC用9600,n,8,1串口通信时每个数据帧是9位呢,这样造成单片机和PC通讯无法成功?
fsnet 2010-04-16
  • 打赏
  • 举报
回复
忘了说了,晶振是11.0592。这个故障还很奇怪,我发送的数据都是十六进制“60 61 62 63 64 65 66 67 68 69 70”不变,当我把TH1和TL1设为fa时单片机波特率应该是9600,可收到的数据是“20 18 E6 C0 D8 E0 1E FE”或“20 F8 C0 D8 E0 1E FE”,而把TH1和TL1设为fb时单片机的波特率应该就不是9600了,可是收到“60 0E 6C 9C F2 1E EC”或者“60 1E 9C EE EE 6E 80”,其中第一个对的。另外不知大家发现没有,我发送的数据一共是11个,但不管怎么设都只能收到8个或7个数据,我个人怀疑是第一个以后的数据在传输过程中丢失或者上位机与下位机的译码方式不一致。至于起因可能就是楼上说的缓冲区问题,不知大家是什么意见。
另外楼上的xmjulytiger大哥提到建缓冲区,我想问一下这缓冲区怎么建呢?用汇编语言便能实现吗?
xmjulytiger 2010-04-16
  • 打赏
  • 举报
回复
"……我想问一下这缓冲区怎么建呢?用汇编语言便能实现吗?"

汇编肯定能实现,可惜我不懂汇编。思路就是你发的是11个十六进制数,就定义一个长度为11的一维数组。然后在接收程序中把SBUF依次赋值给这个数组中的各元素。

看你的程序,感觉大致是下面这样几句, 循环11次可以完成11个十六进制数的接收。
JNB RI,$;
MOV A,SBUF ;
.....;//这里写将A的值赋给数组元素的语句
.....;//写数组变量加1的语句
CLR RI;
schlafenhamster 2010-04-16
  • 打赏
  • 举报
回复
PC用9600,n,8,1,就是10位,启始是固定的1位。晶振是11.0592是不是对(示波器看看),波特率误差不得大于3%
xyhdtc 2010-04-15
  • 打赏
  • 举报
回复
我也有这样的问题,写完再KEIL上仿真都没问题。烧到单片机里就有问题。无论我让它发什么(2个16进制数)收到的都是F0 00 00
sytu_chyq 2010-04-15
  • 打赏
  • 举报
回复
只发送一个16进制数正确的吧
贝隆 2010-04-14
  • 打赏
  • 举报
回复
波特率不正确?有干扰?线路故障?
空影 2010-04-14
  • 打赏
  • 举报
回复
楼主晶振是多少的
xmjulytiger 2010-04-14
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fsnet 的回复:]
我确实用的是16进制发送和接收,波特率都是96000。我明白楼上的意思了,是我应该在串口调试助手里面输入十六进制代码。但是现在我发送十六进制码“60 61 62 63 64 65 66 67 68 69 70”收到的却是“60 0E 6C 9C F2 1E EC”,而且每次收到的结果还不一样,有时是上面那个结果,有时是“60 1E 9C EE EE 6E 80”,还大家帮忙。
[/Quote]

你的程序一次只能收发一个两位的十六进制数据,要收发多个数据得建数据缓冲区。可用数组简单实现,用C来写比较容易。
stude 2010-04-14
  • 打赏
  • 举报
回复 1
CLR TI ;清发送中断标志
CLR RI ;清接收中断标志
区分清除标志
stude 2010-04-14
  • 打赏
  • 举报
回复
波特率不对
fsnet 2010-04-14
  • 打赏
  • 举报
回复
我确实用的是16进制发送和接收,波特率都是96000。我明白楼上的意思了,是我应该在串口调试助手里面输入十六进制代码。但是现在我发送十六进制码“60 61 62 63 64 65 66 67 68 69 70”收到的却是“60 0E 6C 9C F2 1E EC”,而且每次收到的结果还不一样,有时是上面那个结果,有时是“60 1E 9C EE EE 6E 80”,还大家帮忙。
空影 2010-04-13
  • 打赏
  • 举报
回复
楼主上位机发送要选择16进制发送,否则就是发送ascii码了,那么123就在单片机接受时就成了49,50,51(10进制数)
xmjulytiger 2010-04-13
  • 打赏
  • 举报
回复
串口调试用十六进制显示,十六进制发送。从你的程序看,发送两位十六进制字符7B(对应123)。
leileipei 2010-04-13
  • 打赏
  • 举报
回复
单片机内部都是ASCII码,单片机要有解码的程序。串口调试用十六进制显示,十六进制发送。
schlafenhamster 2010-04-13
  • 打赏
  • 举报
回复
波特率对不对?
qzf368 2010-04-13
  • 打赏
  • 举报
回复
PC向单片机发送的时候用的是“十六进制发送”吗?

单片机里收到的数据对不对?
加载更多回复(1)

27,520

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧