一、背景
最近做一个项目,需要用STM32F407来做7路串口通信,由于芯片最多只有6路,所以只能用IO口来模拟串口通信。在网上查找了很多模拟串口的资料,决定串口发送采用延时的方式,串口接收采用外部中断+定时器中断来实现。外部中断检测第一次检测下降沿表明接收到了起始位,通过定时器中断定时检测接收IO口上的电平,从而判断接收的是0还是1.
二、正文
1)、串口发送:
由于串口发送的函数比较简单,所以先从发送开始做起,首先咱们来熟悉一下串口协议,1位起始位+8位数据位+1位奇偶校验位+1位停止位(其中停止位可能为0.5位,1位,1.5位或2位,可以选择)。串口异步传输在空闲状态时都必须是高电平。
由于现在是模拟串口,暂时不考虑复杂的奇偶校验位,所以采用的格式为:1位起始位+8位数据位+1位奇偶校验位+1位停止位。项目需要采用的波特率为115200,所以每发送1bit数据需要的时间:1/115200=8.68us.
模拟串口发送发送函数:
1 #define COM1_TX_PORT GPIOA 2 3 #define COM1_TX_PIN GPIO_Pin_9 4 5 void Virtual_Uart_Bytesend(u8 val) 6 7 { 8 9 u8 i=0; 10 11 COM1_TX_DATA_LOW(); // 起始位,低电平,IO口初始化时应该置为高电平 12 13 delay_us(baudRate); 14 15 for(i = 0;i<8;i++) // 8位数据位 16 17 { 18 19 if (val & 0x01) 20 21 { 22 23 COM1_TX_DATA_HIGH(); 24 25 } 26 27 else 28 29 { 30 31 COM1_TX_DATA_LOW(); 32 33 } 34 35 delay_us(baudRate); 36 37 val >>= 1; 38 39 } 40 41 COM1_TX_DATA_HIGH(); // 停止位 高电平 42 43 delay_us(baudRate); 44 45 }
以上代码完全是根据协议的格式来写的,思路很简单,里面最重要的一个参数是这个baundRate;这个参数根据不同的波特率而不同,并且实际值和理论值算出来的时间可能有些差别,调试发现STM32F4的误差比较小,基本上理论值和实际值一样就可以正常通信。波特率为115200,延时理论上为8.68us。但是问题就来了,STM32F407例程delay.c里给的延时函数最小单位为us,设置baundRate=8或者9通信偶尔能够正常接收,但是很多时候是乱码,如下图:
如何解决这一问题呢,首先想到是设计一个延时0.1us