STM32使用GPIO模拟UART来打印log

注:本文模拟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!

猜你喜欢

转载自my.oschina.net/igiantpanda/blog/1618138
今日推荐