环境
STM32L476G-DISCO 开发板
STM32CubeIDE 1.1.0
STM32CubeMX 5.4.0
说明:由于STM32L476G-DISCO 开发板将UART4串口的RX(PA1)和TX(PA0)两个引脚分别用于JoyStick的按键输入,和地相连,所以如果同样使用STM32L476G-DISCO开发板的UART4引脚做测试,需要根据原理图,将威廉希尔官方网站
板的C43C42R59断开(硬件小白,不知道不断可不可以)。
STM32CubeMX配置
UART4配置
打开UART4,选择Asynchronous异步通信模式。参数设置默认。
中断(NVIC)设置,打开串口总中断。
DMA设置,打开接收Rx的DMA通道。
GPIO设置,选择Rx和Tx的GPIO引脚。默认打开即可。
整体的引脚视图
时钟配置,选择自动生成的配置即可。
之后生成工程文件即可。实际用的是STM32CubeIDE创建的工程,直接生成代码。
相关代码(只贴出修改的代码)
usart.c
/* UART4 init function */
void MX_UART4_Init(void) {
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK) {
Error_Handler();
}
//在这里添加__HAL_UART_ENABLE_IT(),打开huart4的空闲中断
__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
}
stm32l4xx_it.c
//从其他文件中找到定义的相关变量
/* USER CODE BEGIN EV */
extern uint8_t rxData[100];
extern uint8_t tempData[100];
extern uint8_t receiveFlag;
/* USER CODE END EV */
/**
* @brief This function handles UART4 global interrupt.
*/
void UART4_IRQHandler(void) {
/* USER CODE BEGIN UART4_IRQn 0 */
uint8_t temp;
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE) != RESET) {
//空闲中断
//temp = huart4.Instance-》ISR;
//清除空闲中断标志位
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
//清除数据读寄存器
temp = huart4.Instance-》RDR;
temp = temp;
//关闭DMA传输通道,防止在处理数据过程中有新的数据被DMA导入
HAL_UART_DMAStop(&huart4);
//对传输的数据进行转存处理,把rxData暂存区空闲出来,用来接收新的数据。
if (strlen(rxData) != 0) {
memcpy(tempData, rxData, strlen(rxData));
memset(rxData, 0x00, strlen(rxData));
}
//再次清楚空闲中断标志位。打开空闲中断,重新启动串口DMA传输。
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart4, rxData, 100);
//接收标志位置位。通知在主函数中处理数据。
receiveFlag = SET;
}
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
/* USER CODE END UART4_IRQn 1 */
}
main.c
/* USER CODE BEGIN Includes */
#include “string.h”
/* USER CODE END Includes */
//定义一些需要用到的全局变量。这些变量可能在其他文件中用到
/* USER CODE BEGIN PV */
uint8_t rxData[100] = { 0 };
uint8_t tempData[100] = { 0 };
uint8_t receiveFlag = RESET;
/* USER CODE END PV */
/* USER CODE BEGIN 4 */
//定义UART错误回调函数,用来处理串口的各种错误。注意,如果是用多个串口同时工作,需要简单修改本函数中的判断逻辑,实现更好的兼容和代码的简洁。
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_ErrorCallback can be implemented in the user file.
*/
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_ORE) != RESET) {
__HAL_UART_CLEAR_OREFLAG(&huart4);
HAL_UART_Receive_DMA(&huart4, rxData, 100);
}
}
//主函数
/**
* @brief The application entry point.
* @retval int
*/
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_GPIO_Init();
MX_DMA_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
//在最开始开启串口的DMA传输
/*
经过测试、如果这里的数据长度BUFFERSIZE设为10的话,在第一次接收到的数据超过10位数据时,只能收到前10位数据,
之后就无法继续接收数据了。断点了一下,并没有进入ORE的错误处理回调函数。还需要进一步调试。如果有
哪位大佬看出来问题,不吝赐教。
*/
HAL_UART_Receive_DMA(&huart4, rxData, BUFFERSIZE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
//当空闲中断一帧数据接收完成后,receiveFlag这个变量在中断函数中被置位。我们在主函数将接收到的数据再通过串口发送给上位机。
if (receiveFlag != RESET){
receiveFlag = RESET;
HAL_UART_Transmit(&huart4, tempData, strlen(tempData), 1000);
memset(tempData, 0x00, strlen(tempData));
}
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE END 4 */
结果
将BUFFERSIZE设置为1024后,牺牲了一些空间,但是保证串口接收到的数据不会丢失是正确的。具体的结果图就不贴了。
环境
STM32L476G-DISCO 开发板
STM32CubeIDE 1.1.0
STM32CubeMX 5.4.0
说明:由于STM32L476G-DISCO 开发板将UART4串口的RX(PA1)和TX(PA0)两个引脚分别用于JoyStick的按键输入,和地相连,所以如果同样使用STM32L476G-DISCO开发板的UART4引脚做测试,需要根据原理图,将威廉希尔官方网站
板的C43C42R59断开(硬件小白,不知道不断可不可以)。
STM32CubeMX配置
UART4配置
打开UART4,选择Asynchronous异步通信模式。参数设置默认。
中断(NVIC)设置,打开串口总中断。
DMA设置,打开接收Rx的DMA通道。
GPIO设置,选择Rx和Tx的GPIO引脚。默认打开即可。
整体的引脚视图
时钟配置,选择自动生成的配置即可。
之后生成工程文件即可。实际用的是STM32CubeIDE创建的工程,直接生成代码。
相关代码(只贴出修改的代码)
usart.c
/* UART4 init function */
void MX_UART4_Init(void) {
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK) {
Error_Handler();
}
//在这里添加__HAL_UART_ENABLE_IT(),打开huart4的空闲中断
__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
}
stm32l4xx_it.c
//从其他文件中找到定义的相关变量
/* USER CODE BEGIN EV */
extern uint8_t rxData[100];
extern uint8_t tempData[100];
extern uint8_t receiveFlag;
/* USER CODE END EV */
/**
* @brief This function handles UART4 global interrupt.
*/
void UART4_IRQHandler(void) {
/* USER CODE BEGIN UART4_IRQn 0 */
uint8_t temp;
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE) != RESET) {
//空闲中断
//temp = huart4.Instance-》ISR;
//清除空闲中断标志位
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
//清除数据读寄存器
temp = huart4.Instance-》RDR;
temp = temp;
//关闭DMA传输通道,防止在处理数据过程中有新的数据被DMA导入
HAL_UART_DMAStop(&huart4);
//对传输的数据进行转存处理,把rxData暂存区空闲出来,用来接收新的数据。
if (strlen(rxData) != 0) {
memcpy(tempData, rxData, strlen(rxData));
memset(rxData, 0x00, strlen(rxData));
}
//再次清楚空闲中断标志位。打开空闲中断,重新启动串口DMA传输。
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart4, rxData, 100);
//接收标志位置位。通知在主函数中处理数据。
receiveFlag = SET;
}
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
/* USER CODE END UART4_IRQn 1 */
}
main.c
/* USER CODE BEGIN Includes */
#include “string.h”
/* USER CODE END Includes */
//定义一些需要用到的全局变量。这些变量可能在其他文件中用到
/* USER CODE BEGIN PV */
uint8_t rxData[100] = { 0 };
uint8_t tempData[100] = { 0 };
uint8_t receiveFlag = RESET;
/* USER CODE END PV */
/* USER CODE BEGIN 4 */
//定义UART错误回调函数,用来处理串口的各种错误。注意,如果是用多个串口同时工作,需要简单修改本函数中的判断逻辑,实现更好的兼容和代码的简洁。
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_UART_ErrorCallback can be implemented in the user file.
*/
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_ORE) != RESET) {
__HAL_UART_CLEAR_OREFLAG(&huart4);
HAL_UART_Receive_DMA(&huart4, rxData, 100);
}
}
//主函数
/**
* @brief The application entry point.
* @retval int
*/
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_GPIO_Init();
MX_DMA_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
//在最开始开启串口的DMA传输
/*
经过测试、如果这里的数据长度BUFFERSIZE设为10的话,在第一次接收到的数据超过10位数据时,只能收到前10位数据,
之后就无法继续接收数据了。断点了一下,并没有进入ORE的错误处理回调函数。还需要进一步调试。如果有
哪位大佬看出来问题,不吝赐教。
*/
HAL_UART_Receive_DMA(&huart4, rxData, BUFFERSIZE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
//当空闲中断一帧数据接收完成后,receiveFlag这个变量在中断函数中被置位。我们在主函数将接收到的数据再通过串口发送给上位机。
if (receiveFlag != RESET){
receiveFlag = RESET;
HAL_UART_Transmit(&huart4, tempData, strlen(tempData), 1000);
memset(tempData, 0x00, strlen(tempData));
}
HAL_Delay(500);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE END 4 */
结果
将BUFFERSIZE设置为1024后,牺牲了一些空间,但是保证串口接收到的数据不会丢失是正确的。具体的结果图就不贴了。
举报