最近因工作需要,研究了一下单片机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字符
结论:发送和接收字符均正常,没加缓冲,大数据量未测试。