2019独角兽企业重金招聘Python工程师标准>>>
注:本文模拟UART部分参考了STM32 IO口模拟串口通讯,在此表示感谢!
由于芯片自带的3个UART都被用完了,所以只得用GPIO来模拟UART来打印log了。
使用TIM3来用作延时使用,STM32CubeMX上的配置如下:
计数周期配置位65535,这也是能配置的最大值。
然后在tim.c中添加:
void Delay_us(uint32_t us)
{
__HAL_TIM_SET_COUNTER(&htim3, 0);
HAL_TIM_Base_Start(&htim3);
while (__HAL_TIM_GET_COUNTER(&htim3) < (72 * us)) ;
HAL_TIM_Base_Stop(&htim3);
}
由于timer的时钟为72MHz,所以1us就是72个时钟周期,因此,上面的延时时间要乘以72。此外,由于计数周期最大为65535,所以此函数最大延时时间为65535/72=910us。我们也可以通过修改Prescaler的值来降低timer的输入时钟,从而增加延时函数的最大延时时间,但这却会降低一些延时精度。
接下来就是模拟UART输出了,下面是用GPIO模拟UART输出一个字节,波特率9600,所以周期约为104us。
void sendByte(uint8_t val)
{
HAL_GPIO_WritePin(IO_TX_GPIO_Port, IO_TX_Pin, GPIO_PIN_RESET);
Delay_us(104);
for (int i = 0; i < 8; i++)
{
if (val & 0x01)
{
HAL_GPIO_WritePin(IO_TX_GPIO_Port, IO_TX_Pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(IO_TX_GPIO_Port, IO_TX_Pin, GPIO_PIN_RESET);
}
Delay_us(104);
val >>= 1;
}
HAL_GPIO_WritePin(IO_TX_GPIO_Port, IO_TX_Pin, GPIO_PIN_SET);
Delay_us(104);
}
经实测,波特率为9600时可稳定运行(测试了12万字节无误码),而19200的波特率存在小于千分之一的误码率。
接下来再修改prinf的重定向,以前是重定向到UART1的,现在要改为模拟的UART。
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART2 and Loop until the end of transmission */
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
+ sendByte(ch);
return ch;
}
It's over!