前阵子,调项目时需要用到低波特率串口通讯(300的波特率),才发下发现在正常情况下(PCLK1时钟频率为72M,PCLK2时钟频率为36M):STM32的USART0的最低波特率只能设置到1200,;而USART1最低波特率只能设置到600。怎么设置STM32的600或以下的波特率呢?有两种方法:一种是改变外设时钟频率,而另一种方法就是使用IO口模拟串口通讯。今天就来讲讲,用IO口模拟串口通信!
1、串口传输协议
首先,必须要知道串口通讯时数据是怎样传输的?这里以异步传输字符为例子,如下图所示:
一般字符传输都采用:1位起始位,8位数据位,1位停止位,没有校验位 的形式传输,其他形式的这里不讲。串口异步传输在空闲状态时都必须是高电平。第一位传输的是起始位,起始位会将原来空闲时的高电平拉成低电平,起始位用来来标识数据开始传输,提示接收方准备开始接收数据;当接收方第一次检测到一个下降沿时,就表示接收到了起始位。起始位后就是8位的数据位,接收方在接收每一位数据的时候会采集几十次,如果结果都是低电平,则接收到的数据位0,如果结果都是高电平,则棘手到的数据位是1。1位停止位会将电平拉成高电平,以为接收下一个数据做准备。
2、IO模拟串口发送程序
IO口模拟串口发送数据,必须严格按照上面的异步传输协议。我们用伪代码实现这一过程:
void VirtualCOM_ByteSend(u8 val)
{
u8 i;
IO_LOW(); //起始位,拉低电平
Delay(sometime);
for(i = 0; i < 8; i++) //8位数据位
{
if(val & 0x01)
IO_HIGH();
else
IO_LOW();
Dealy(sometime);
val >>= 1;
}
IO_HIGH(); //停止位,拉高电平
Delay(sometime);
}
代码很简单,思路也很清晰,完全是按照异步传输的过程写的。这里最重要的是Delay(sometime),sometime的延时时间就决定了传输的速度,sometime去取某些值才可以设置程序标准的串口波特率(1200、2400、9600、38400、115200等等)。
下面,我采用STM32开发板实现IO模拟串口发送。
(1)选择IO引脚设置为虚拟串口TX引脚
我选择PA4引脚来模拟串口的TX引脚,所以需要配置下PA4这个引脚为推挽输出:
#define COM_TX_PORT GPIOA
#define COM_TX_PIN GPIO_Pin_4
void VirtualCOM_TX_GPIOConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* PA4最为数据输出口,模拟TX */
GPIO_InitStructure.GPIO_Pin = COM_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(COM_TX_PORT, &GPIO_InitStructure);
GPIO_SetBits(COM_TX_PORT, COM_TX_PIN);
}
这里需要说明的是,在配置完引脚后,需要将PA4引脚拉高,这样做是为了防止在发送数据起始位时,由于原来引脚是低电平而导致没有产生一个下降沿信号。
(2)IO模拟串口发送一个字节
遵循串口异步传输协议,编写了STM32上面的相应代码:
#define COM_TX_PORT GPIOA
#define COM_TX_PIN GPIO_Pin_4
#define COM_DATA_HIGH() GPIO_SetBits(COM_TX_PORT, COM_TX_PIN) //高电平
#define COM_DATA_LOW() GPIO_ResetBits(COM_TX_PORT, COM_TX_PIN) //低电平
u32 delayTime;
void VirtualCOM_