51单片机IO口模拟串口通讯3-中断法


硬件环境:STC89C52

软件环境:IDE Keil uVision V4.10

                    编译器 C51 V9.0

代码如下:

[cpp]  view plain copy
  1. /********************************************** 
  2. 方法3:中断法 
  3. 硬件:11.0592MHz晶振,STC89C52,RXD P1.0 TXD P1.1 
  4. 波特率:9600 
  5. 描述:所谓中断法是指根据模拟出的波特率,每1位持续的时间的长短是通过定时器计数 
  6.       溢出产生中断来延时的。 
  7.  
  8. 测试1:上电发送1个0x03的字符 
  9. 测试2:上电先发送1个0x03的字符,然后等待接收,将收到的字符再发送出去(分别一个一个发送0x01,0x02,0x03,0x04,0x05) 
  10. 测试3:上电等待接收,将收到的字符再发送出去(分别一个一个发送0x01,0x02,0x03,0x04,0x05) 
  11.  
  12. 结果: 
  13. 测试1:错误!上电发送0x03,接到到0xE0 
  14. 测试1:错误!上电发送0x00,接到到0x80 
  15. 测试1:错误!上电发送0x01,接到到0xC0 
  16. 测试1:错误!上电发送0x02,接到到0x81 
  17.  
  18. 测试2:错误!上电接收到错误字符0xE0,此后分别接收到0x01,0x02,0x03,0x04,0x05,均正确 
  19.  
  20. 测试3:错误!接收到第1个字符错误0x82,此后分别接收到0x02,0x03,0x04,0x05,均正确。第1个错误的字符有时会是0x81 
  21.  
  22. 注意:初始化时,要将定时器T0的溢出标志位清0 
  23.  
  24. 时间:2012.07.25 于单位 
  25. **********************************************/  
  26. #include "reg52.h"  
  27. #define uchar unsigned char  
  28.   
  29. sbit P1_0 = 0x90;  
  30. sbit P1_1 = 0x91;  
  31. sbit P1_2 = 0x92;  
  32.   
  33. #define RXD P1_0  
  34. #define TXD P1_1  
  35. #define WRDYN 44                    //写延时  
  36. #define RDDYN 43                    //读延时  
  37.   
  38. void Delay2cp(unsigned char i);  
  39. void WaitTF0( void );  
  40.   
  41. #define TM0_FLAG P1_2               //设传输标志位  
  42.   
  43. //计数器及中断初始化  
  44. void S2INI(void)  
  45. {  
  46.     TMOD |=0x02;                    //计数器0,方式2  
  47.     TH0=0xA0;                       //预值为256-96=140,十六进制A0  
  48.     TL0=TH0;          
  49.     TR0=0;                          //在发送或接收才开始使用  
  50.     TF0=0;   
  51.     ET0=1;                          //允许定时器0中断  
  52.     EA=1;                           //中断允许总开关  
  53. }  
  54.   
  55. //发送一个字符  
  56. void WByte(uchar input)  
  57. {  
  58.      //发送启始位  
  59.      uchar i=8;  
  60.      TR0=1;  
  61.      TXD=(bit)0;  
  62.      WaitTF0();  
  63.   
  64.      //发送8位数据位  
  65.      while(i--)  
  66.      {  
  67.          TXD=(bit)(input&0x01);   //先传低位  
  68.          WaitTF0();  
  69.          input=input>>1;  
  70.      }  
  71.   
  72.      //发送校验位(无)  
  73.   
  74.      //发送结束位  
  75.      TXD=(bit)1;  
  76.      WaitTF0();  
  77.      TR0=0;  
  78. }  
  79.   
  80. //接收一个字符  
  81. uchar RByte()  
  82. {  
  83.     uchar Output=0;  
  84.     uchar i=8;  
  85.     TR0=1;                          //启动Timer0  
  86.     TL0=TH0;  
  87.     WaitTF0();                      //等过起始位  
  88.   
  89.     //发送8位数据位  
  90.     while(i--)  
  91.     {  
  92.         Output >>=1;  
  93.         if(RXD)  
  94.             Output   |=0x80;        //先收低位  
  95.         WaitTF0();                  //位间延时  
  96.     }  
  97.     while(!TM0_FLAG) if(RXD) break;  
  98.   
  99.     TR0=0;                          //停止Timer0  
  100.   
  101.     return Output;  
  102. }  
  103.   
  104. //中断1处理程序  
  105. void IntTimer0() interrupt 1  
  106. {  
  107.      TM0_FLAG=1;                    //设置标志位。  
  108. }  
  109.   
  110. //查询传输标志位  
  111. void WaitTF0( void )  
  112. {  
  113.     while(!TM0_FLAG);   
  114.     TM0_FLAG=0;                      //清标志  
  115. }  
  116.   
  117. //检查是不是有起始位  
  118. bit StartBitOn()  
  119. {  
  120.     return   (RXD==0);   
  121. }  
  122.   
  123. void main()  
  124. {  
  125.     uchar ccc;  
  126.     S2INI();  
  127.   
  128.     //2012.07. 25 李响添加  
  129.     //计时器T0启用之前要把溢出标志清0,计时满TF0=1  
  130.     //缺少如下的语句,将发生描述中的错误  
  131.     TM0_FLAG=0;  
  132.   
  133.     //测试1  
  134.     /* 
  135.     WByte(0x03); 
  136.     WByte(0x01); 
  137.     WByte(0x02); 
  138.     WByte(0x03); 
  139.     WByte(0x04); 
  140.     WByte(0x05); 
  141.     while(1){;} 
  142.     */  
  143.   
  144.     //测试2  
  145.       
  146.     WByte(0x03);  
  147.     while(1)  
  148.     {  
  149.         if(StartBitOn())  
  150.         {  
  151.             ccc=RByte();  
  152.             WByte(ccc);  
  153.         }  
  154.     }     
  155.   
  156.     //测试3     
  157.     /* 
  158.     while(1) 
  159.     { 
  160.         if(StartBitOn()) 
  161.         { 
  162.             ccc=RByte(); 
  163.             WByte(ccc); 
  164.         } 
  165.     } 
  166.     */  
  167. }  

 

附解决问题过程中所抓的波形:

测试1:错误!上电发送0x00时的波形。

测试1:错误!上电发送0x00时接收到的数据。

分析:上电发送0x00,理应也收到数据0x00,波形的形状也应该如上图所示,但接收到的数据为0x80则显示这波形是错误的。且往下看。

----------------------------------------------------------------------------------------------------------------------------------------

测试1:错误!上电发送0x01时的波形。

测试1:错误!上电发送0x01时接收到的数据。

分析:波形错误,接收到的数据也错误。起始位为低电平,理应持续1位的时间,但可以看出,起始位保持很短的时间就跳为高电平了。说明起始位到来以后,相应的延时时间那里出了问题。

正确的0x01的波形如下图所示: 

----------------------------------------------------------------------------------------------------------------------------------------

测试1:错误!上电发送0x02时的波形。

测试1:错误!上电发送0x02时接收到的数据。

正确的0x02的波形如下图所示: 

----------------------------------------------------------------------------------------------------------------------------------------

测试1:错误!上电发送0x03时的TXD的波形。

上电发送0x03时接收到的数据。

正确的0x03的波形如下:

----------------------------------------------------------------------------------------------------------------------------------------

测试2:错误!上电本应先接到一个0x03的字符,但实际接收到的为0xE0,此后收发均正确。

测试2:错误!上电本应先接到一个0x03的字符,但实际接收到的为0xE0,此后收发均正确。

此图仅用于证明除第一个字符错误外,此后其它接收到的字符均正确。

----------------------------------------------------------------------------------------------------------------------------------------

测试3:错误!先手动发送第1个字符0x01,此时接收到的错误数据81,此时的波形

接收到的错误数据0x81

上电后,依次发送0x01,0x02,0x03,0x04,0x05,接收到第1个字符0x81错误,后4个字符正确

上边的那个实验,有的时候偶尔会出现第1个字符是0x82的错误数据。

----------------------------------------------------------------------------------------------------------------------------------------

以下两图为0x04和0x05的正确的波形

0x04时的波形

0x05时的波形

 ----------------------------------------------------------------------------------------------------------------------------------------

分析:可以看出,起始位持续的时间不正确。

原因为:中断标志位上电后默认为1,高电平,需要手动将其清0。本程序利用了P1^2做为中断标志位,P1^2上电后为高电平。在程序中,S2INI();之后,添加TM0_FLAG=0;解决此问题。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值