单片机
返回首页

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

2020-07-07 来源:eefocus

硬件环境:STC89C52


软件环境:IDE Keil uVision V4.10


编译器 C51 V9.0


代码如下:


/**********************************************

方法3:中断法

硬件:11.0592MHz晶振,STC89C52,RXD P1.0 TXD P1.1

波特率:9600

描述:所谓中断法是指根据模拟出的波特率,每1位持续的时间的长短是通过定时器计数

      溢出产生中断来延时的。

测试1:上电发送1个0x03的字符

测试2:上电先发送1个0x03的字符,然后等待接收,将收到的字符再发送出去(分别一个一个发送0x01,0x02,0x03,0x04,0x05)

测试3:上电等待接收,将收到的字符再发送出去(分别一个一个发送0x01,0x02,0x03,0x04,0x05)

结果:

测试1:错误!上电发送0x03,接到到0xE0

测试1:错误!上电发送0x00,接到到0x80

测试1:错误!上电发送0x01,接到到0xC0

测试1:错误!上电发送0x02,接到到0x81

测试2:错误!上电接收到错误字符0xE0,此后分别接收到0x01,0x02,0x03,0x04,0x05,均正确

测试3:错误!接收到第1个字符错误0x82,此后分别接收到0x02,0x03,0x04,0x05,均正确。第1个错误的字符有时会是0x81

注意:初始化时,要将定时器T0的溢出标志位清0

时间:2012.07.25 于单位

**********************************************/

#include 'reg52.h'

#define uchar unsigned char

 

sbit P1_0 = 0x90;

sbit P1_1 = 0x91;

sbit P1_2 = 0x92;

 

#define RXD P1_0

#define TXD P1_1

#define WRDYN 44 //写延时

#define RDDYN 43 //读延时

 

void Delay2cp(unsigned char i);

void WaitTF0( void );

 

#define TM0_FLAG P1_2 //设传输标志位

 

//计数器及中断初始化

void S2INI(void)

{

TMOD |=0x02; //计数器0,方式2

TH0=0xA0;                      //预值为256-96=140,十六进制A0

TL0=TH0;        

TR0=0;                          //在发送或接收才开始使用

TF0=0; 

ET0=1;                          //允许定时器0中断

EA=1;                          //中断允许总开关

}

 

//发送一个字符

void WByte(uchar input)

{

     //发送启始位

     uchar i=8;

     TR0=1;

     TXD=(bit)0;

     WaitTF0();

 

     //发送8位数据位

     while(i--)

     {

         TXD=(bit)(input&0x01);   //先传低位

         WaitTF0();

         input=input>>1;

     }

 

     //发送校验位(无)

 

     //发送结束位

     TXD=(bit)1;

     WaitTF0();

     TR0=0;

}

 

//接收一个字符

uchar RByte()

{

uchar Output=0;

uchar i=8;

TR0=1;                          //启动Timer0

TL0=TH0;

WaitTF0();                      //等过起始位

 

//发送8位数据位

while(i--)

{

Output >>=1;

if(RXD)

Output   |=0x80;    //先收低位

WaitTF0();                  //位间延时

}

while(!TM0_FLAG) if(RXD) break;

 

TR0=0;                          //停止Timer0

 

return Output;

}

 

//中断1处理程序

void IntTimer0() interrupt 1

{

     TM0_FLAG=1;                  //设置标志位。

}

 

//查询传输标志位

void WaitTF0( void )

{

while(!TM0_FLAG); 

TM0_FLAG=0;                  //清标志

}

 

//检查是不是有起始位

bit StartBitOn()

{

return   (RXD==0); 

}

 

void main()

{

uchar ccc;

S2INI();

 

//2012.07. 25 李响添加

//计时器T0启用之前要把溢出标志清0,计时满TF0=1

//缺少如下的语句,将发生描述中的错误

TM0_FLAG=0;

 

//测试1

/*

WByte(0x03);

WByte(0x01);

WByte(0x02);

WByte(0x03);

WByte(0x04);

WByte(0x05);

while(1){;}

*/

 

//测试2

WByte(0x03);

while(1)

{

if(StartBitOn())

{

ccc=RByte();

WByte(ccc);

}

}

 

//测试3

/*

while(1)

{

if(StartBitOn())

{

ccc=RByte();

WByte(ccc);

}

}

*/

}

 


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


测试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;解决此问题。

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 用NE555制作定时器

    相关电子头条文章