一个项目中要用到串口,普通经济型单片机又没有串口,在网上搜索了一下单片机普通IO口模拟串口,基本上搜到的都是采用阻塞方式实现的,根本没有实用价值,自己动手写了一个,使用一个定时器完成模拟串口的收发,并且以全双工方式工作。
程序框架采用定时器加状态机实现:
switch (Su8RxStatus)
{
case 0: //接收复位
if (HIGH == RX_CUR_SIG)
{
Su8RxSigTime++;
if (Su8RxSigTime >= 4)
{
Su8RxSigTime = 0;
Su8RxBitCnt = 0;
Su8RxStatus = 1;
}
}
break;
case 1: //接收起始位
if (LOW == RX_CUR_SIG)
{
Su8RxSigTime++;
if (Su8RxSigTime >= 2)
{
Su8RxSigTime = 0;
Su8RxBitCnt = 0;
Su8RxStatus = 2;
}
}
break;
case 2: //循环完成一个字节的接收
Su8RxSigTime++;
if (Su8RxSigTime >= 2)
{
Su8RxSigTime = 0;
Gu8SerialDataBuf >>= 1;
if (RX_CUR_SIG)
{
Gu8SerialDataBuf |= 0x80;
}
else
{
Gu8SerialDataBuf &= 0x7f;
}
Su8RxBitCnt++;
if (Su8RxBitCnt >= 8)
{
Su8RxStatus = 3;
Gu8SerialData = Gu8SerialDataBuf;
RX_BYTE_OK = OK;
}
}
break;
case 3: //接收停止位
if (HIGH == RX_CUR_SIG)
{
Su8RxSigTime++;
if (Su8RxSigTime >= 2)
{
Su8RxSigTime = 0;
Su8RxStatus = 1;
}
}
break;
}
if (EN == TX_EN)
{
switch (Su8TxStatus)
{
case 0: //发送起始位
IO_TX = 0;
Su8TxSigTime++;
if (Su8TxSigTime >= 2)
{
Su8TxSigTime = 0;
Su8TxStatus = 1;
}
break;
case 1:
if (1 == Su8TxBuf.bits.bit0)
{
IO_TX = 1;
}
else
{
IO_TX = 0;
}
Su8TxBitCnt++;
Su8TxBuf.byte >>= 1;
Su8TxStatus = 2;
break;
case 2:
Su8TxStatus = 1;
if (Su8TxBitCnt >= 8)
{
Su8TxBitCnt = 0; //一个字节8位发送完成进入停止位发送
Su8TxSigTime = 0;
Su8TxStatus = 3;
}
break;
case 3: //发送停止位
IO_TX = 1;
Su8TxSigTime++;
if (Su8TxSigTime >= 2)
{
Su8TxSigTime = 0;
TX_EN = DIS;
Su8TxStatus = 0;
}
break;
}
}