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

浙公网安备 33010602011771号