最近因工作需要,研究了一下单片机IO口模拟串口通讯的相关知识。相关内容主要参考了网上《51单片机模拟串口的三种方法》和《单片机IO口模拟串口程序(发送+接收)》两篇文档,并动手做了一下实验。感受颇多。
硬件环境:STC89C52
软件环境:IDE Keil uVision V4.10
编译器 C51 V9.0
代码如下:
/**********************************************
方法1:延时法
硬件:11.0592MHz晶振,STC89C52,RXD P1.0 TXD P1.1
波特率:9600
描述:所谓延时法是指根据模拟出的波特率,每1位持续的时间的长短是通过循环空指令来延时的。
测试1:上电发送1个0x01的字符
测试2:上电后等待接收,接收到PC发送的0x01字符后,将此字符+1后再发送
结果:
测试1:正确!接收到1个0x01的字符
测试2-1:正确!分别一个一个发送0x01,0x02,0x03,0x04,0x05,均正常接收
测试2-2: 错误!一起发送0x01,0x02,0x03,0x04,0x05,丢包,只能接收0x02,0x04,0x06
时间: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 WByte(uchar input)
{
uchar i=8;
TXD=(bit)0; //发送启始位
Delay2cp(39);
//发送8位数据位
while(i--)
{
TXD=(bit)(input&0x01); //先传低位
Delay2cp(36);
input=input>>1;
}
//发送校验位(无)
TXD=(bit)1; //发送结束位
Delay2cp(46);
}
//从串口读一个字节
uchar RByte(void)
{
uchar Output=0;
uchar i=8;
uchar temp=RDDYN;
//发送8位数据位
Delay2cp(RDDYN*1.5); //此处注意,等过起始位
while(i--)
{
Output >>=1;
if(RXD) Output |=0x80; //先收低位
Delay2cp(35); //(96-26)/2,循环共占用26个指令周
}
while(--temp) //在指定的时间内搜寻结束位。
{
Delay2cp(1);
if(RXD)break; //收到结束位便退
}
return Output;
}
//延时程序*
void Delay2cp(unsigned char i)
{
while(--i); //刚好两个指令周期。
}
void main()
{ uchar ccc;
//测试1
//WByte(0x01);
//while(1){;}
//测试2
while(1)
{
if(RXD==0)
{
ccc=RByte();
WByte(ccc+1);
}
}
}
附几张抓到的波形:
测试1:十六进制字符0x01的波形
测试1:发送出来的字符
测试2:依次发送0x01,0x02,0x03,0x04,0x05接收到的字符
测试2:一起发送0x01,0x02,0x03,0x04,0x05字符
结论:发送和接收字符均正常,没加缓冲,大数据量未测试。