基于STM32CubeIDE HAL库利用基本定时器实现串口接收不定长数据
- ✨申明:本文章仅发表在
CSDN
网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创! - 🍁对于文中所提供的相关资源链接将作不定期更换。
- 📌相关参考《HAL库教程9:串口接收不定长数据》
🎉对于串口接收不定长数据的处理方案网上有很多,个人觉得采用定时器的方式最为简单,容易理解。
- 🎬串口数据收发演示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/e3ede8bddd34441e9b5d59269d26037c.gif#pic_center)
📑原理实现:就是利用串口接收中断,来开启对应的定时器计时,只要串口有数据进来就会进入串口接收中断函数里面执行相关内容,在接收中断函数里面,提供两种方式来处理计时方法,在一定时间内没有进入串口中断,那么定时器计时就会溢出,产生定时中断,来判断一次串口数据流的接收。
- ✨本示例基于
STM32G070RBT6
单片机,64MHz频率。如果匹配到不同型号的单片机需要注意在配置定时器分频参数需要根据选定的单片机主频时钟来配置。
![在这里插入图片描述](https://img-blog.csdnimg.cn/57ebe9f19aec45068cc027aa7695a2a3.png)
🛠在内置的STM32CubeMX配置
- 🌿基本定时器7配置如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/555626a182e048a5a9a57642a4f779a4.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/c881ecd21bf14137a0e464de5f2eec5a.png)
🍁间隔的时间常常与通信的波特率是相关的。在9600波特率下,一个字节的数据共 起始+8数据+结束=10位,一位是104us,所以一个字节的数据是1.04ms,3.5个字节,我们就认为是4ms。有时可能有校验位,稍微保险一点,5ms吧。假如使用115200的波特率,5ms已经算是非常“奢侈”了。本文使用定时器7来计时,配置的PSC为63,ARR为4999,即5ms的溢出时间。这是按传输每一位数据来设定数据超时时间的,当然你也可以将串口接收中断作为定时器开始计时起点,然后定一个固定的时长来中断串口数据流的接收,具体看使用场合。
- 🔰如果串口接收数据频率比较高(数据流传输间隔小于500ms),那么就选择第一种方式按传输数据位来设定时长。
- 🔰如果串口接收数据频率不是很高(大于500ms),那么就选择一个固定的时长来中断串口数据流的接收。
- 🌴串口1配置
![在这里插入图片描述](https://img-blog.csdnimg.cn/4dcf47c9ab904111b613edb46020243e.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/d825d1d907d044c6af86d47da34545dc.png)
📝主程序代码
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#define REC_LENGTH 20
uint8_t UART1_Rx_Buf[REC_LENGTH];
uint8_t UART1_Rx_flg=0;
uint8_t UART1_Rx_cnt=0;
uint8_t Rxbuff[1];
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM7_Init();
HAL_UART_Receive_IT(&huart1, (uint8_t *)Rxbuff,1);
while (1)
{
if(UART1_Rx_flg)
{
HAL_UART_Transmit(&huart1,UART1_Rx_Buf,UART1_Rx_cnt,0xffff);
for(int i = 0;i<UART1_Rx_cnt;i++)
UART1_Rx_Buf[i] = 0;
UART1_Rx_cnt = 0;
UART1_Rx_flg = 0;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 16;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(0 == UART1_Rx_cnt)
{
__HAL_TIM_CLEAR_FLAG(&htim7,TIM_FLAG_UPDATE);
HAL_TIM_Base_Start_IT(&htim7);
}
__HAL_TIM_SET_COUNTER(&htim7,0);
UART1_Rx_Buf[UART1_Rx_cnt] = Rxbuff[0];
UART1_Rx_cnt++;
HAL_UART_Receive_IT(&huart1,Rxbuff,1);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&htim7))
{
UART1_Rx_flg = 1;
HAL_TIM_Base_Stop_IT(&htim7);
}
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
📚程序源码
- ✨申明:本文章仅发表在
CSDN
网站,任何其他网见此内容均为盗链和爬取,请多多尊重和支持原创! - 🍁对于文中所提供的相关资源链接将作不定期更换。
链接: https:
提取码: rhrp
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)