前言:
本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用
所用工具:
1、芯片: STM32G431RBT6
2、STM32CubeMx软件
3、IDE: MDK-Keil软件
4、STM32G4xxHAL库
知识概括:
通过本篇博客您将学到:
DMA工作原理
STM32CubeMX创建DMA例程
HAL库定时器DMA函数库
首先:串口配置
先找到引脚PA9,PA10,打开串口1接收。
然后在打开串口1。
如果顺序弄错,串口1的引脚就会是PC4,PC5;
然后左边找到串口1,选择异步通信,波特率看实际情况,我改为9600
点进DMA
点击ADD添加两个DMA,分别是RX和TX的。其它参数保持默认
进入中断控制,打开中断其它的配置时钟配置,工程配置,调试配置就不赘述了。
生成代码,打开工程
串口DMA发送
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size);
参数描述
HAL_StatusTypeDef返回值:函数是否执行成功,成功:HAL_OK,失败:HAL_ERROR
huart :指定串口地址;
pData:发送数据缓存的地址;
Size:发送数据的长度;
使用:
直接调用即可发送:
cpp
while (1)
{
HAL_UART_Transmit_DMA(&huart1,"Hello2\r\n",strlen("Hello2\r\n"));
HAL_Delay(1000);
}
现象:
DMA接收:
首先,在main.h中定义好结构体
cpp
#define BUFFER_SIZE 256
typedef struct USART_STRUCT
{
unsigned char rx_len; //接收一帧数据的长度
unsigned char recv_end_flag; //一帧数据接收完成标志
char rx_buffer[BUFFER_SIZE];//接收缓存数组
}USART_STRUCT;
然后在main.c中
头部声明结构体变量
cpp
USART_STRUCT usart1Struct;
再进入stm32g4xx_it.c中
继承上面的变量
cpp
extern USART_STRUCT usart1Struct;
再找到USART1_IRQHandler()函数,将里面改为下面的代码
cpp
/**
* @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint32_t temp;
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
HAL_UART_DMAStop(&huart1); //
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数
//这句和上面那句等效
usart1Struct.rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
usart1Struct.recv_end_flag = 1; // 接受完成标志位置1
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
这个函数会进行空闲中断的处理
回到主函数
在while循环中改为下面代码:
cpp
if(usart1Struct.recv_end_flag == 1) //接收完成标志
{
HAL_UART_Transmit_DMA(&huart1,(uint8_t*)usart1Struct.rx_buffer,usart1Struct.rx_len);//将接收的数据发回去
usart1Struct.rx_len = 0;//清除计数
usart1Struct.recv_end_flag = 0;//清除接收结束标志位
memset(usart1Struct.rx_buffer,0,usart1Struct.rx_len);
HAL_UART_Receive_DMA(&huart1,(uint8_t*)usart1Struct.rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
改完,编译运行
有什么问题可以在评论区问我