嵌入式笔记系列(1) 基于RT_Thread 进行串口动态切换的方法

嵌入式的通讯类型有很多种,最先接触到的就是串口这类工具,本身以为串口会很简单,初始化后直接使用就好,在工作当中遇到了通过RT_Thread要求进行串口的重新初始化及切换,刚好再次进行一下串口基础知识的学习和记录,基于的芯片是STM32F103,和STM32F407。本人对串口的认识不是很深刻,有错误的地方欢迎指正,也希望能对大家有一些帮助。

RTTHREAD对串口进行了默认的初始化,使用的时候,只需要在board.h里面开启对应的串口宏定义并指定引脚就好(复用引脚也可以直接指定),除了控制台串口由系统进行初始化,其余的串口需要我们自己对其进行设备的查找,设置工作模式,及接受回调函数,在这个阶段可手动更改串口的相关配置,详情可参考官方文档[https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README]

我们这里要实现的是在RTTHREAD运行过程中,切换相同的串口下复用不同的引脚,并更改相应的波特率,此处使用了两个芯片,F103和F407,对于国产芯片的GDF103和GDF407都是适用的。实现的方法是调用HAL库来实现。

首先需要关闭当前串口调用rt_device_close,关闭当前串口,再使用HAL库对串口重新进行初始化。

int serial_change(void)
{
    serial_mspdeinit(&huart1);

    if (0x01 == g_hlw_serial_af_enable)
    {
        huart1.Instance = USART1;
        huart1.Init.BaudRate = 4800;
        huart1.Init.WordLength = UART_WORDLENGTH_9B;
        huart1.Init.StopBits = UART_STOPBITS_1;
        huart1.Init.Parity = UART_PARITY_EVEN;
        huart1.Init.Mode = UART_MODE_TX_RX;
        huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    }
    else
    {
        huart1.Instance = USART1;
        huart1.Init.BaudRate = 2400;
        huart1.Init.WordLength = UART_WORDLENGTH_9B;
        huart1.Init.StopBits = UART_STOPBITS_1;
        huart1.Init.Parity = UART_PARITY_EVEN;
        huart1.Init.Mode = UART_MODE_TX_RX;
        huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
        huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    }

    if (HAL_OK != uart_init(&huart1))
    {
        return -1;
    }

    return 0;
}
void serial_mspdeinit(UART_HandleTypeDef* uartHandle)
{
    if (0x01 == g_hlw_serial_af_enable)  //g_hlw_serial_af_enable 为标志选择不同引脚
    {
        __HAL_RCC_USART1_CLK_DISABLE();
        HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);

    }
    else
    {
        __HAL_RCC_USART1_CLK_DISABLE();
        HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6 | GPIO_PIN_7);

    }
    HAL_NVIC_DisableIRQ(USART1_IRQn);
}
huart->gState = HAL_UART_STATE_BUSY;

    __HAL_UART_DISABLE(huart);

    hlw_serial_setconfig(huart);

    CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
    CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));

    __HAL_UART_ENABLE(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->gState = HAL_UART_STATE_RESET;      //使能问题,修改为 HAL_UART_STATE_RESET
    huart->RxState = HAL_UART_STATE_READY;
void serial_mspinit(UART_HandleTypeDef* uartHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    if (0x01 == g_hlw_serial_af_enable)
    {
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_6;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;

        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        __HAL_AFIO_REMAP_USART1_ENABLE();
        HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
    }
    else
    {
        __HAL_RCC_USART1_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();

        GPIO_InitStruct.Pin = GPIO_PIN_9;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;

        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        GPIO_InitStruct.Pin = GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;

        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        __HAL_AFIO_REMAP_USART1_DISABLE();     //F103有此函数
        HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);

    }
}

配置完成后rt_device_open打开串口即可,此处需要注意的是,设备的关闭和打开函数要对应,此细节在文档函数里面的说明也有所提及,切换完之后,串口的中断回调函数可以使用同一个,也可以重新指定新的串口中断函数,此操作在打开串口前进行即可。
总之,实现这个的方式大体的思路就是,完全关闭串口引脚的中断绑定及初始化,重新配置串口参数,再次使能串口中断及对应的引脚配置,调用系统函数来再次打开串口。

posted @ 2022-11-02 21:46  noodle_extra  阅读(953)  评论(0)    收藏  举报