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

硬件环境: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时的波形。

20120725-51单片机IO口模拟串口通讯3-中断法_第1张图片

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

20120725-51单片机IO口模拟串口通讯3-中断法_第2张图片

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

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第3张图片

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

20120725-51单片机IO口模拟串口通讯3-中断法_第4张图片

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第5张图片

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第6张图片

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第7张图片

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

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

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

正确的0x03的波形如下:

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

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

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第8张图片

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

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

20120725-51单片机IO口模拟串口通讯3-中断法_第9张图片

接收到的错误数据0x81

20120725-51单片机IO口模拟串口通讯3-中断法_第10张图片

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

20120725-51单片机IO口模拟串口通讯3-中断法_第11张图片

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

20120725-51单片机IO口模拟串口通讯3-中断法_第12张图片

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

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

0x04时的波形

20120725-51单片机IO口模拟串口通讯3-中断法_第13张图片

0x05时的波形

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

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

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


 

你可能感兴趣的:(IO,测试,input,通讯,output)