实现目标
1、利用UART实现上位机PC与下位机开发板之间的数据通信
2、学会STM32CubeMX软件关于UART的DMA模式配置
3、具体目标:1、实现串口定长收发数据通信;2、串口不定长收发数据通信。
一、DMA简介
1、什么是DMA?
DMA(Direct Memory Access)直接内存访问,是一种数据传输方法。利用DMA控制器,将数据直接从一个地址空间复制到另一个地址空间。。
优点:在创建完DMA通道后,它会在合适的时机自动将数据转移,不占用CPU进行转移,且在转移完成后触发一次中断表明转移完成。
2、STM32F103的DMA
STM32F1系列的MCU有两个DMA控制器(DMA2只存在于大容量产品中),DMA1有7个通道,DMA2有5个通道,每个通道专门用来管理来自于一个或者多个外设对存储器的访问请求。还有一个仲裁器来协调各个DMA请求的优先权。
二、原理图设计
三、STM32CubeMX 配置
1.USART1 DMA模式配置
USART1的参数配置如下,波特率115200,传输数据长度为8 Bit,奇偶检验无,停止位1.其他参数默认
使能USART1中断,串口使用DMA方式必须开启中断,否则程序发送一次数据后,不能判断DMA传输是否完成,串口会一直处于busy状态。
点击Add, 增加USART1_RX和USART1_TX,参数默认。
DMA参数配置:
(1)发送选择 DMA1 Stream 4通道,方向从存储器到外设,优先级为低。
(2)接收选择 DMA1 Stream 5通道,方向从外设到存储器。
(3)mode设置:Normal: 表单次传输,传输一次后终止传输; Circular:表示循环传输,传输完成后又重新开始继续传输,不断循环永不停止。
(4)Data Width:串口数据发送寄存器只能存储8bit,每次发送一个字节,所以数据长度选择Byte。
四、程序设计1(串口定长收发数据通信)
1、定义一个数组
/* USER CODE BEGIN PM */
uint8_t Txbuf[] = "好好学习STM32+HAL+PROTUES 系列教程\r\n";
unsigned char rx[16];
/* USER CODE END PM */
2、开机串口DMA发送Txbuf[]数据
/* USER CODE BEGIN 2 */
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Txbuf, sizeof(Txbuf));
HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
HAL_Delay(500);
/* USER CODE END 2 */
3、接收回调函数,将接收到的数据反发回到上位机
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1){ // 将上位机发来的数据完整的返回回去
HAL_UART_Transmit_DMA(&huart1,rx,sizeof(rx));
HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
}
}
4、实验现象
说明:由于用16进制显示模式,开机汉字全部显示为16进制。功能:上位机输入定长度(16个字节)的 数字,都能正确的返回显示。
五、程序设计2(串口不定长收发数据通信)
1、定义一个数组
/* USER CODE BEGIN PM */
uint8_t Txbuf[] = "好好学习STM32+HAL+PROTUES 系列教程\r\n";
unsigned char rx[16];
/* USER CODE END PM */
2、开机串口DMA发送Txbuf[]数据
/* USER CODE BEGIN 2 */
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Txbuf, sizeof(Txbuf));
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
HAL_Delay(500);
/* USER CODE END 2 */
3、在usart.h中,添加extern DMA_HandleTypeDef hdma_usart1_rx;
//在usart.h中
/* USER CODE BEGIN Includes */
extern DMA_HandleTypeDef hdma_usart1_rx;
/* USER CODE END Includes */
4、接收回调函数,将接收到的数据反发回到上位机
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &huart1) // 将上位机发来的数据完整的返回回去
{
HAL_UART_Transmit_DMA(&huart1,rx,Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
}
}
5、实验现象
说明:由于用16进制显示模式,开机汉字全部显示为16进制。功能:上位机输入不定长度的 数字,都能正确的返回显示。