使用CubeMX新建USART1不定长接收工程
目录
1、新建板级支持包
2、修改中断服务函数
3、修改main.c文件
4、程序流程
新建工程的基本操作步骤参考这里:STM32CubeMX学习笔记(6)——USART串口使用_unused(huart)-CSDN博客
1、新建板级支持包
在本地保存新建工程的文件夹中新建User文件夹,再在User文件夹中新建USRT1文件夹。
Keil打开使用CubeMX创建的工程模板,新建bsp_debuge_usart.c和bsp_debuge_usart.h文件保存在干菜新建的USRT1文件夹中。
将bsp_debuge_usart.c添加到工程文件夹Core中,将bsp_debuge_usart.h的头文件路径添加到工程中。
bsp_debuge_usart.c代码:可以把自动生成的USART1配置初始化代码复制过来然后修改一下,定义了一个数组,一个接收数据长度变量Rxlen ,一个接收完成中断变量用来表示产生了接收完成中断。还有一些发送字符串函数。
#include "./USART1/bsp_debug_usart.h"UART_HandleTypeDef huart1;char RxBuff[BUFFSIZE];
uint32_t Rxlen = 0;
uint8_t Rxflag;/* USART1 init function */void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspInit 0 *//* USER CODE END USART1_MspInit 0 *//* USART1 clock enable */__HAL_RCC_USART1_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**USART1 GPIO ConfigurationPA9 ------> USART1_TXPA10 ------> USART1_RX*/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_AF_INPUT; //模式要设置为复用输入模式! HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);HAL_NVIC_EnableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspInit 1 *//* USER CODE END USART1_MspInit 1 */}
}void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{if(uartHandle->Instance==USART1){/* USER CODE BEGIN USART1_MspDeInit 0 *//* USER CODE END USART1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_USART1_CLK_DISABLE();/**USART1 GPIO ConfigurationPA9 ------> USART1_TXPA10 ------> USART1_RX*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);/* USART1 interrupt Deinit */HAL_NVIC_DisableIRQ(USART1_IRQn);/* USER CODE BEGIN USART1_MspDeInit 1 *//* USER CODE END USART1_MspDeInit 1 */}
}/*********************发送字符串*******************************/
void Usart_SendString(uint8_t *str)
{unsigned int k = 0;do{HAL_UART_Transmit(&huart1,(uint8_t *)(str + k),1,1000);k++;}while(*(str + k) != '\0');}//重定向c库函数printf到串口USART1,重定向后可使用函数printf
int fputc(int ch,FILE *f)
{//发送一个字节数据到串口USART1,重写后可使用scanf、getchar等函数HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000); return (ch);}//重定向c库函数scanf到串口USART1,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{ int ch;HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000); return (ch);
}
bsp_debuge_usart.h代码
#ifndef __DEBUG_USART_H
#define __DEBUG_USART_H#ifdef __cplusplus
extern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx.h"
#include <stdio.h>//串口波特率/* USER CODE BEGIN Includes *//* USER CODE END Includes */extern UART_HandleTypeDef huart1;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_USART1_UART_Init(void);/* USER CODE BEGIN Prototypes */
void Usart_SendString(uint8_t *str);
int fputc(int ch, FILE *f);
int fgetc(FILE *f);extern UART_HandleTypeDef huart1;#define BUFFSIZE 100extern char RxBuff[BUFFSIZE];
extern uint32_t Rxlen;
extern uint8_t Rxflag;
#define BUFFSIZE 100/* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __USART_H__ */
2、修改中断服务函数
在中断服务函数中添加接收完成中断后的处理程序代码,
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE ) != RESET) //判断产生了空闲中断标志位,认为一轮结束{ Rxflag = 1;Rxlen += BUFFSIZE - huart1.RxXferCount; //累计达不到BUFFSIZE个数的部分__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除串口空闲中断标志位HAL_UART_AbortReceive_IT(&huart1); //关闭接受使能位 return ;} /* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}
回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){ /*例程演示从简,当一轮接收超过了RxBuff,继续使用同一个RxBuff接收,接收字节数仍然累计,接收内容从头覆盖。根据实际的项目编写多份Rxbuff,类似循环队列切换到另一个Buff和及时处理已接收部分,*/Rxlen += huart1.RxXferSize; HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuff,BUFFSIZE); }
}
3、修改main.c文件
在main.c文件中添加#include "./USART1/bsp_debug_usart.h"
在main函数中添加代码
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_USART1_UART_Init();/* USER CODE BEGIN 2 *//*调用printf函数,因为重定向了fputc,printf的内容会输出到串口*/printf("欢迎使用野火开发板\n"); /*自定义函数方式*/Usart_SendString( (uint8_t *)"串口接收不定长字节,请查看程序内注释\r\n" );/*开启第一次接收状态*/HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuff,BUFFSIZE);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */if(Rxflag == 1) { printf("总共接受到 %d 字节\r\n",Rxlen); /*例程演示从简,只打印一份RxBuff内容*/Rxlen = (Rxlen > BUFFSIZE) ? BUFFSIZE : Rxlen; // 确保发送的数据长度不超过缓冲区大小 HAL_UART_Transmit(&huart1,(uint8_t*)RxBuff,Rxlen,1000);memset(RxBuff,0,Rxlen);//C 标准库函数,用于将一段内存区域设置为指定的值。清空缓冲区/*一轮接收数据以上的自定义处理完后重启接收*/HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuff,BUFFSIZE); Rxflag = 0;Rxlen = 0;}/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
4、程序流程
初始化串口,开启第一次接收状态,当接收到数据时触发中断,跳转到中断服务函数中判断是否产生空闲中断标志位,设置接收变量和接收长度变量,清除串口空闲中断标志位,关闭接收使能位。然后再跳转到中断回调函数判断是否接受的数据长度超出设定的数组大小结束中断回到主函数执行主循环,判断是否产生了接收中断,打印接收到的字节长度,然后开启发送中断函数,发送完后重启接收。