STM32
直播中

刘伟

7年用户 1663经验值
私信 关注
[问答]

如何使用普通IO模拟串口实现非阻塞全双工通讯功能?

如何使用普通IO模拟串口实现非阻塞全双工通讯功能?

回帖(1)

曹丽娜

2021-12-3 14:50:32
期望效果:
使用普通IO模拟串口,实现非阻塞全双工通讯功能。
硬件资源:
1.2个IO口
2.1个外部中断
3.1个定时器
串口相关知识简述:
1.波特率
波特率,即每秒传输的位个数。例9600bps,即每秒传输9600个bit,每位电平状态保持时长为:t = 1000000/9600 ≈104.16us
2.时序
1个起始位+8个数据位+1个停止位
注:起始位为低电平,停止位为高电平,数据位低有效位在前。空闲状态下,TX Line和RX Line均为高电 平。
初始化:
发送IO口配置为推挽输出模式,并设置初始电平状态为高电平。接收IO口配置为上拉输入模式。定时器配置为向上计数模式并使能更新中断,每隔104us产生一次中断事件。外部中断配置为下降沿触发模式,当检测到下降沿时,产生一次中断事件。
发送:
先将待发送数据存入FIFO(先入先出队列)中,然后从FIFO中取出首字节赋值到文件全局变量txData,并置位发送txFlag和清零发送位计数器txBitCount。在定时器中断事件中执行发送。示意代码如下所示:


if( txFlag )
{
        if( txBitCount == 0 ) //发送起始位
        {
                PIN_CLR( TX );
                txBitCount++;
        }
        else if( txBitCount < 9 ) //发送8个数据位
        {
                (txData & 0x01)? PIN_SET( TX ):PIN_CLR( TX );
                txData >>= 1;
                txBitCount++;
        }
        else if( txBitCount == 9 ) //发送1个停止位
        {
                PIN_SET( TX );
                txBitCount++;
        }
        else //检查FIFO中是否有未发送数据
        {
                if( txFifo.count )
                {
                        txData = txFifo.buf[txFifo.head];
                        txFifo.head++;
                        txFifo.head &= txFifo.mask;
                        txFifo.count--;
                        txBitCount = 0;
                }
                else
                {
                        txFlag = 0;
                }
        }
}


接收:
当产生外部中断事件时,置位接收标志rxFlag,并清零接收位计数器rxBitCount,然后在定时器中断事件中采样数据。将采样到的位数据暂存到文件全局变量rxData中,采样结束后将rxData存入接收FIFO中。示意代码如下所示:


if( rxFlag )
{
        if( rxBitCount < 9 ) //接收起始位和数据位
        {
                rxData >>= 1;
                if( PIN_READ( RX ) == SET )
                {
                        rxData |= 0x80;
                }
                rxBitCount++;
        }
        else //判断停止位
        {
                if( PIN_READ( RX ) == SET ) //有效停止位
                {
                        rxFifo.buf[rxFifo.tail] = rxData;
                        rxFifo.tail++;
                        rxFifo.tail &= rxFifl.mask;
                        rxFifo.count++;
                }
               
                rxFlag = 0;
                rxBitCount = 0;
        }
}


结尾:
经过测试,实现了非阻塞全双工通讯功能,但是接收数据不太稳定,尚需优化。如果对正确率要求不高(如本打字员,仅在生产时使用该串口配置下设备参数,一次不成,可以再来个2345下),那么还是可以凑合使用的。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分