在单片机实际开发的过程中,可能会出现串口不够用的情形。如果你需要更多的串口,又无奈于手头没有资源更丰富的单片机,那么,软件模拟串口通信也许可以帮到你。
软件模拟串口通信的主要思想是通过定时器来定时产生相应的波特率。
#include<reg52.h>
sbit PIN_RXD = P3^0;
sbit PIN_TXD = P3^1;
bit RxdEnd = 0; //接收完成标志
bit RxdOrTxd = 0; //RXD = 0,TXD = 1
bit TxdEnd = 0; //发送完成标志
unsigned char RxdBuf = 0; //数据接收缓冲区
unsigned char TxdBuf = 0; //数据发送缓冲区
void ConfigUART(unsigned int baud); //配置串口
void StartRXD(); //开始接收
void StartTXD(unsigned char dat); //开始发送
void main()
{
EA = 1; //开总中断
ConfigUART(9600); //波特率9600
while(1)
{
while(PIN_RXD); //检测到起始位0进入下一步
StartRXD(); //开始接收
while(!RxdEnd);
StartTXD(RxdBuf+1);
while(!TxdEnd);
}
}
void ConfigUART(unsigned int baud)
{
TMOD &= 0xF0; //清除定时器低四位
TMOD |= 0x02; //定时器0, 模式2, 8位自动重装载模式
TH0 = 256 - (11059200/12)/baud; //高位预装载值
}
void StartRXD()
{
TL0 = 256 - ((256 - TH0)>>1);
ET0 = 1;
TR0 = 1;
RxdEnd = 0;
RxdOrTxd = 0;
}
void StartTXD(unsigned char dat)
{
TxdBuf = dat;
TL0 = TH0;
ET0 = 1;
TR0 = 1;
PIN_TXD = 0;
TxdEnd = 0;
RxdOrTxd = 1;
}
void InterruptTimer0() interrupt 1
{
static unsigned char cnt = 0; // 接收/发送 到第几位计数
if(RxdOrTxd) //发送部分
{
cnt++;
if(cnt <= 8)
{
PIN_TXD = TxdBuf & 0x01; //每次发一位,从低位发起
TxdBuf >>= 1; //右移一位,次低位为低位
}
else if(cnt == 9)
{
PIN_TXD = 1; //发送停止位
}
else
{
cnt = 0; //清除计数
TR0 = 0; //关闭定时器
TxdEnd = 1; //置发送完成标
}
}
else //接收部分
{
if(cnt == 0)
{
if(!PIN_RXD) //检测到接收起始位0
{
RxdBuf = 0;
cnt++;
}
else
{
TR0 = 0;
}
}
else if(cnt <= 8)
{
RxdBuf >>= 1; //数据右移一位
if(PIN_RXD) //如果接收到的数据为1,就或上0x80让高位为1
{
RxdBuf |= 0x80; //或0x80只会改变最高位,其他位都不变
}
cnt++;
}
else
{
cnt = 0;
TR0 = 0;
if(PIN_RXD) //检测到接收停止位
{
RxdEnd = 1; //置接收完成标志位
}
}
}
}