找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1937|回复: 15
收起左侧

单片机软件模拟UART,无法实现+1发回,怎么回事

[复制链接]
ID:722595 发表于 2021-10-8 19:13 | 显示全部楼层 |阅读模式
用串口助手模拟UART,发送数据+1,发回,但是这段程序发回的数据不是+1,好像有点没规律,请问是什么原因,看了大半天没看出来问题。
单片机源程序如下:
  1. #include<reg52.h>
  2. sbit pRXD=P3^0;
  3. sbit pTXD=P3^1;        
  4. bit RxDorTXD=0;            //给中断程序来判断是处于接收状态还是发送状态,   1:表示发送          0:表示接收
  5. bit  RXDEnd=0;                       //接收结束标识
  6. bit  TXDEnd=0;
  7. unsigned char RXDBuf;      //接收缓冲器
  8. unsigned char TXDBuf;           //发送缓冲器

  9. void configUART(unsigned int baud);
  10. void receive();
  11. void sent(unsigned char dat);
  12.         
  13. void main(){
  14. EA=1;                      //开启中断总开关
  15. configUART(9600);                           //配置波特率

  16. while(1){
  17. while (pRXD);
  18. receive();                  //接收数据
  19. sent(RXDBuf);                                 //发送数据
  20. while(!TXDEnd);

  21. }
  22. }

  23. void configUART (unsigned int baud){
  24. TMOD=0x02;                                         //让TMOD工作在02模式下,即TH0可以直接重置到TL0上 书本P59
  25. TH0=256-11059200/baud/12;        //配置TH0的重置值
  26. }               

  27. void receive (){
  28. TR0=1;
  29. ET0=1;
  30. TL0=256-((256-TH0)>>1);
  31. RxDorTXD=0;
  32. }

  33. void sent(unsigned char dat){
  34. ET0=1;
  35. TR0=1;
  36. RxDorTXD=1;
  37. TXDBuf=dat+1;
  38. }
  39.    
  40. void interrupttimer0() interrupt 1{
  41. static int cnt=0;
  42. if(RxDorTXD==0){                                                //如果RXDorTXD为0,则开始接收数据
  43.     if(cnt==0){
  44.            if(pRXD==0){
  45.               RXDBuf=0;
  46.                   cnt++;
  47.                   }
  48.            else {
  49.                  TR0=0;
  50.                   }
  51.                   }
  52. else if(cnt<=8){
  53.             RXDBuf>>=1;
  54.                 if(pRXD==1){
  55.                 RXDBuf|=0x80;
  56.                 }
  57.                 cnt++;
  58.                  }
  59. else {
  60.           cnt=0;
  61.           TR0=0;
  62.           if(pRXD==1){
  63.           RXDEnd=1;
  64.           }
  65.           }        }
  66.   
  67.          
  68. if(RxDorTXD==1){                                                 //RXDorTXD为1,则开始发送数据
  69.     cnt++;
  70.     if(cnt<=8){
  71.        pTXD=TXDBuf & 0x01;
  72.        TXDBuf>>=1;
  73.               }
  74.     else if(cnt==9){
  75.          pTXD=1;}
  76.     else {
  77.         cnt=0;
  78.         TR0=0;
  79.         TXDEnd=1;
  80.   }
  81.   }
  82.   }
复制代码

回复

使用道具 举报

ID:624769 发表于 2021-10-8 22:20 | 显示全部楼层
void receive (){
TR0=1;
ET0=1;
TL0=256-((256-TH0)>>1);
RxDorTXD=0;
}

按你的代码,你必须要主动运行了  receive () 才开定时器,才定义半步步进值,才开始接收上位机数据,你觉得上位机会乖乖配合这个时候才发数据么?

软件模拟串口,如果光发送,随便你怎么玩,但是,如果要正常接收,只有两条路。
要么,4分或者3分波特率,定时器常开,反复查验上位机有没有送数据,
要么,开外部中断,上位机一有动作,通过外部中断,开定时器,以及设置半波特率步进。
回复

使用道具 举报

ID:722595 发表于 2021-10-9 08:57 | 显示全部楼层
188610329 发表于 2021-10-8 22:20
void receive (){
TR0=1;
ET0=1;

receive ()前面有句while (pRXD),也就是当P3.0接收到低电平时就会配置到receive函数。
回复

使用道具 举报

ID:624769 发表于 2021-10-9 11:52 | 显示全部楼层
召唤师 发表于 2021-10-9 08:57
receive ()前面有句while (pRXD),也就是当P3.0接收到低电平时就会配置到receive函数。

那么,假如你正在运行 while(1)里面的 sent(RXDBuf);    的时候, 上位机发数据的话,这时候,怎么处理?
回复

使用道具 举报

ID:722595 发表于 2021-10-9 12:57 | 显示全部楼层
188610329 发表于 2021-10-9 11:52
那么,假如你正在运行 while(1)里面的 sent(RXDBuf);    的时候, 上位机发数据的话,这时候,怎么处理?

因为这是简单的模拟,都是一应一答,就是说这是我自己用串口助手来给单片机发数据的。目前还不会在发送的时候还接收到数据。
回复

使用道具 举报

ID:624769 发表于 2021-10-9 13:26 | 显示全部楼层
这就不好说了,

要不你试试3分波特率的方法吧,个人觉得没有外部中断触发的情况,还是三分波特率靠谱,

STC15F104E_模拟串口三分波特率.rar (34.28 KB, 下载次数: 11)
回复

使用道具 举报

ID:722595 发表于 2021-10-9 13:33 | 显示全部楼层
188610329 发表于 2021-10-9 13:26
这就不好说了,

要不你试试3分波特率的方法吧,个人觉得没有外部中断触发的情况,还是三分波特率靠谱,
...

谢谢,我还在学,我是对着教材自己写的,教材上是可以。。。真见鬼,看了半天看不出来问题。
回复

使用道具 举报

ID:624769 发表于 2021-10-9 13:42 | 显示全部楼层
召唤师 发表于 2021-10-9 13:33
谢谢,我还在学,我是对着教材自己写的,教材上是可以。。。真见鬼,看了半天看不出来问题。

嗯,串口通讯这东西确实有点搞,毕竟没有时钟线,尤其是 起始位,停止位,还要算宽度,当初也是搞了很久,后来的结论是:发送这块简单,接收的话……,要么三分波特率(甚至4分5分),要么只能靠外部中断,只有这两个选择。

时间隔得太久,看你的代码,也看不出明显的错误,只好给你一个我这里测试没问题的,你去看看了。
回复

使用道具 举报

ID:123289 发表于 2021-10-9 14:04 | 显示全部楼层
能收就能发,你收到了吗?
回复

使用道具 举报

ID:964463 发表于 2022-12-8 20:17 | 显示全部楼层
这个我也有问题,发的是1,收的是0x81
回复

使用道具 举报

ID:964463 发表于 2022-12-8 20:17 | 显示全部楼层
奇怪,不知道是不是代码问题,和书上一样都不行
回复

使用道具 举报

ID:964463 发表于 2022-12-8 23:25 | 显示全部楼层
希望后来人可以看到,这是宋雪松老师的代码,可能因电脑而异,修改为发送什么返回什么之后,我的是发送1,返回0x81,但是把TL0改成数字211这些,就没问题了,也就是说,代码中的TL0计算是不准确的,可能是我电脑的问题。
回复

使用道具 举报

ID:883242 发表于 2022-12-9 13:42 | 显示全部楼层
杠精本人 发表于 2022-12-8 23:25
希望后来人可以看到,这是宋雪松老师的代码,可能因电脑而异,修改为发送什么返回什么之后,我的是发送1, ...

232的最高位在最前面,你现在的现象明显是波特率不对,误差在前7位还在忍受范围之内,到第8位就出错了。
回复

使用道具 举报

ID:401564 发表于 2022-12-9 14:15 | 显示全部楼层
单片机本身就有串口,为什么要模拟串口呢?
这玩意就像ADC0832一样,上古时期的产物,不学也罢
回复

使用道具 举报

ID:284226 发表于 2023-5-11 19:21 | 显示全部楼层
楼主。我也在看。你那个看懂了?    发送时,pTXD=TXDBuf & 0x01;为什么先要&这个一步,还有接收时
RXDBuf|=0x80;为什么要走这一步
回复

使用道具 举报

ID:1064915 发表于 2023-5-24 15:25 | 显示全部楼层
TH0=256-11059200/baud/12;
改成TH0=256-11059200/baud/12/16;
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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