• 【STM32+HAL+Proteus】系列学习教程---串口USART(DMA 方式)定长,不定长收发。


    实现目标

    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、定义一个数组

    1. /* USER CODE BEGIN PM */
    2. uint8_t Txbuf[] = "好好学习STM32+HAL+PROTUES 系列教程\r\n";
    3. unsigned char rx[16];
    4. /* USER CODE END PM */

    2、开机串口DMA发送Txbuf[]数据

    1. /* USER CODE BEGIN 2 */
    2. HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Txbuf, sizeof(Txbuf));
    3. HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
    4. HAL_Delay(500);
    5. /* USER CODE END 2 */

    3、接收回调函数,将接收到的数据反发回到上位机

    1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    2. {
    3. if(huart == &huart1){ // 将上位机发来的数据完整的返回回去
    4. HAL_UART_Transmit_DMA(&huart1,rx,sizeof(rx));
    5. HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
    6. }
    7. }

    4、实验现象

    说明:由于用16进制显示模式,开机汉字全部显示为16进制。功能:上位机输入定长度(16个字节)的 数字,都能正确的返回显示。

    五、程序设计2(串口不定长收发数据通信

    1、定义一个数组

    1. /* USER CODE BEGIN PM */
    2. uint8_t Txbuf[] = "好好学习STM32+HAL+PROTUES 系列教程\r\n";
    3. unsigned char rx[16];
    4. /* USER CODE END PM */

    2、开机串口DMA发送Txbuf[]数据

    1. /* USER CODE BEGIN 2 */
    2. HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Txbuf, sizeof(Txbuf));
    3. HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
    4. HAL_Delay(500);
    5. /* USER CODE END 2 */

    3、在usart.h中,添加extern DMA_HandleTypeDef hdma_usart1_rx;

    1. //在usart.h中
    2. /* USER CODE BEGIN Includes */
    3. extern DMA_HandleTypeDef hdma_usart1_rx;
    4. /* USER CODE END Includes */

    4、接收回调函数,将接收到的数据反发回到上位机

    1. void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
    2. {
    3. if(huart == &huart1) // 将上位机发来的数据完整的返回回去
    4. {
    5. HAL_UART_Transmit_DMA(&huart1,rx,Size);
    6. HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
    7. __HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
    8. }
    9. }

    5、实验现象

    说明:由于用16进制显示模式,开机汉字全部显示为16进制。功能:上位机输入不定长度的 数字,都能正确的返回显示。

  • 相关阅读:
    C语言运算符优先级一览表
    Android~RxJava实现newSingleThreadExecutor()同等效果
    LVS+Keepalived群集
    实验篇(7.2) 10. 扩充物理实验环境 ❀ 远程访问
    DCU上如何运行大模型以及用到的docker命令
    每日一题:web常见的攻击方式有哪些?如何防御?
    @enableeurekaserver 无法引入
    基于MRF和CNN的图像生成
    go语言学习
    【15-项目中服务的远程调用之OpenFeign&订单模块与商品模块集成使用OpenFeign的案例】
  • 原文地址:https://blog.csdn.net/luojuan198780/article/details/137833713