首先 打开cube 选择芯片 略。。。
以F1系列为例
SYSTEM CORE选择外部高速晶振↓
dubug选择 SW↑
时钟树配好↑
选择一个串口打开 ↑,参数不用管 波特率115200就行↓
把中断打开,功能少的话 优先级不用管 0 0就行↓
项目名称 路径 ide version选好↓
直接生成代码就可以了
USART.C(修改后)
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
#include <string.h>//调用了 size of 和 memset
uint8_t RecieveBuffer[1] = {0}; // U3接收数据缓冲区
char RXBuffer[256]; // 串口数据暂时储存区
uint8_t USART_RX_LEN = 0; // 用于存储每个USART接收数据的长度
//重定义printf
#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__*/
/******************************************************************
*@brief Retargets the C library printf function to the USART.
*@param None
*@retval None
******************************************************************/
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1,0xFFFF);
return ch;
}
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* 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 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);//U1开启接收中断
/* 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 Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
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);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
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 Configuration
PA9 ------> USART1_TX
PA10 ------> 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 */
}
}
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//阻塞接收 循环callback 主函数
{
RXBuffer[USART_RX_LEN++] = RecieveBuffer[0]; // 接收数据转存
if(RXBuffer[USART_RX_LEN-1] == 0x0A && RXBuffer[USART_RX_LEN-2] == 0x0D )
{
printf("test\r\n");
USART_RX_LEN = 0;//LEN重新置零
memset(RXBuffer,0x00,sizeof(RXBuffer));//清空buffer
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);//调用回调函数之后,重新开启U1接收中断等待下一次接收
}
/* USER CODE END 1 */
其中有几处是需要自行添加的
首先
/* USER CODE BEGIN 0 */
#include <string.h>//调用了 size of 和 memset
uint8_t RecieveBuffer[1] = {0}; // U3接收数据缓冲区
char RXBuffer[256]; // 串口数据暂时储存区
uint8_t USART_RX_LEN = 0; // 用于存储每个USART接收数据的长度 //重定义printf
#include <stdio.h>
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__*/
/******************************************************************
*@brief Retargets the C library printf function to the USART.
*@param None
*@retval None
******************************************************************/
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1,0xFFFF);
return ch;
}/* USER CODE END 0 */
上述部分可以分为三部分
1. include string 方便调用 memset和sizeof
2.定义了缓冲区以及长度标志
3.重定义printf使得串口发送可以直接用printf代替HAL_Transmit。。。。。
其次
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 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);//U1开启接收中断
/* USER CODE END USART1_Init 2 */}
这一部分重点在于开启接收中断,也是唯一需要自行添加的代码 (倒数第三行)
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);//U1开启接收中断
Mspinit里边的东西看看就行(包括NVIC,GPIO时钟),之前在cubemx已经配置过了,不用管。
最后,重新定义一下 HAL_UART_RxCpltCallback
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//阻塞接收 循环callback 主函数
{
RXBuffer[USART_RX_LEN++] = RecieveBuffer[0]; // 接收数据转存
if(RXBuffer[USART_RX_LEN-1] == 0x0A && RXBuffer[USART_RX_LEN-2] == 0x0D )//判断结束位
{
printf("test\r\n");
USART_RX_LEN = 0;//LEN重新置零
memset(RXBuffer,0x00,sizeof(RXBuffer));//清空buffer
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)RecieveBuffer, 1);//调用回调函数之后,重新开启U1接收中断等待下一次接收
}
/* USER CODE END 1 */
这里边比较重要的是
1.接收数据的转存。
RXBuffer[USART_RX_LEN++] = RecieveBuffer[0]; // 接收数据转存到RXBuffer
2.串口数据可以有个结束位,一般以\r\n结尾,即0x0D,0x0A,
if(RXBuffer[USART_RX_LEN-1] == 0x0A && RXBuffer[USART_RX_LEN-2] == 0x0D )
3.判断收到结束位之后,就可以执行相应的功能,比如说RXBuffer内的数据处理,如SPI发送RXBuffer内的数据,或者执行其他功能如ADC,GPIO iic发送数据之类的。本代码以printf打印数据为例。
4.最后一定要把RXBuffer清零,RX LEN重新置零,然后再一次开启接收中断,方便下一次接收。
之后把代码烧录到单片机中,在单片机串口接收到数据的时候会自动从while循环中跳入串口中断,执行callback函数内的相应功能。