原文章:【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_Z小旋的博客-CSDN博客_hal dma
#include <string.h>
memset(rx_buffer,0,rx_len);//清空数组rx_buffer,长度是rx_len
通过DMA发送,串口号、发啥数据、多长的数据:
HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);
判断一下是不是发完了:“DMA1_Channel4”在DMA.C文件最后面可以看到,
或者是从CUBE的dma配置界面看到TX的通道号:
while(DMA1_Channel4->CNDTR !=0);
c文件定义:定义你这数据多长,中断中接收完了的标志位,你接收数据用的数组
volatile uint8_t rx_len = 0; //接收一帧数据的长度 main和中断函数使用
volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志 main和中断函数使用
uint8_t rx_buffer[100] = {0}; //接收数据缓存数组 数据寸这里
h文件声明:声明一下上面的东西,方便别人用
#define BUFFER_SIZE 100 //计数用,判断数组长度和下面那个一样要
extern volatile uint8_t rx_len; //接收一帧数据的长度
extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志
extern uint8_t rx_buffer[BUFFER_SIZE]; //接收数据缓存数组
中断函数:看一下数据接收完了,清除标志位停止DMA然后判断数据长度,立中断中接收完了的标志位FLAG
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除IDLE标志位
HAL_UART_DMAStop(&huart1); //停止DMA传输,防止叠加数据 在main处理函数之后在给他打开
rx_len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
recv_end_flag = 1;//中断中接收完了的标志位挂起
}
if(recv_end_flag == 1) //中断中接收完了的标志位在main函数中的while函数中检测到了
{//执行串口数据处理函数
HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len); //串口1发送这个数组,发送长度rx_len是中断函数中计算出来的
recv_end_flag = 0;//清除中断接收完了的标志位
while(DMA1_Channel4->CNDTR !=0); //看看是不是发完了
memset(rx_buffer,0,rx_len);//发完了数据再清空数组
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
自动生成的main.c文件中添加如下代码:
因为下面用到了memset函数,所以在头文件处添加:#include <string.h>,然后填写下面代码段:
while (1)
{
if(recv_end_flag == 1) //接收完成标志
{
HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len); //串口发送
recv_end_flag = 0; //清除接收结束标志位
while(DMA1_Channel4->CNDTR !=0); //从CUBEMX里面找 串口发送完成
memset(rx_buffer,0,rx_len); //清空
rx_len = 0; //清除计数
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
}
自动生成的usart.c文件中添加如下代码:
/* USER CODE BEGIN 0 */
volatile uint8_t rx_len = 0; //接收一帧数据的长度 main和中断函数使用
volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志 main和中断函数使用
uint8_t rx_buffer[100] = {0}; //接收数据缓存数组 数据寸这里
/* USER CODE END 0 */
void MX_USART1_UART_Init(void)//该函数中添加下面这俩代码
{
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//使能IDLE中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//开启DMA接收
}
自动生成的usart.h文件中添加如下代码:
/* USER CODE BEGIN Private defines */
#define BUFFER_SIZE 100 //计数用,判断数组长度和下面那个一样要
extern volatile uint8_t rx_len; //接收一帧数据的长度
extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志
extern uint8_t rx_buffer[BUFFER_SIZE]; //接收数据缓存数组
/* USER CODE END Private defines */
//usart.c和.ch文件中很容易看出来,仅仅是添加了几个变量而已,至于为啥放到usart文件中,是为了分类管理,你可以自己建自己的文件放进去。
自动生成的stm32f1xx_it.c文件中添加如下代码:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)) //idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除IDLE标志位
HAL_UART_DMAStop(&huart1); //停止DMA传输,防止叠加数据
rx_len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //求存了多少数
recv_end_flag = 1;//接收了数据
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}