0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32CUBEMX(6)--移植雅特力AT32F403AVGT7,双串口通过DMA方式接收不定长数据

嵌入式单片机MCU开发 来源:嵌入式单片机MCU开发 作者:嵌入式单片机MCU开 2022-11-14 16:20 次阅读

概述

本篇文章主要介绍如何使用STM32CubeMX移植到雅特力AT32F403AVGT7,并通过双串口输出打印。

直接存储器访问(DMA)用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何CPU操作的情况下通过DMA快速传输传输。这样节省的CPU资源可供其它操作使用。

DMA允许在后台执行数据传输,无需Cortex-M3处理器干预。在此操作过程中,主处理器可以执行其它任务,仅当整个数据块需要处理时,才会中断主处理器。这样即使传输大量数据也不会对系统性能造成太大影响。

DMA主要用于为不同的外设模块实现集中数据缓冲存储(通常在系统SRAM中)。与分布式解决方案(其中每个外设都需要实现自己的本地数据存储)相比,DMA解决方案在硅片成本和功耗方面的成本较低。

根据使用的产品型号的不同,有一个或两个DMA模块。

本篇文章主要介绍如何使用STM32CubeMX实现串口DMA读取,并且打印出去。

在这里插入图片描述

硬件准备

首先需要准备一个开发板,这里我准备的是雅特力AT32F403AVGT7的开发板:

在这里插入图片描述

选择芯片型号

雅特力AT32F403AVGT7兼容STM32F103系列,故选取STM32f103VG进行开发。

在这里插入图片描述

配置时钟

HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:在这里插入图片描述

配置时钟树

雅特力AT32F403AVGT7最高频率到240M,但是STM32F1的最高主频到72M,同时使用不使用外部晶振时候,最高速度只能到64M,所以配置64即可:

在这里插入图片描述

串口配置

本次实验使用的串口2,串口3进行串口通信,波特率配置为115200。

在这里插入图片描述

在这里插入图片描述

配置DMA

在DMA 设置中,Mode有两种模式,一种是普通模式(Normal),使用一次发送语句就发一次,另一种是循环模式(Circula),使用一次发送会一直发送。这里接收选择循环模式。

在这里插入图片描述

在这里插入图片描述

中断

在中断设置里打开串口2,3的中断。

在这里插入图片描述

生成工程设置

注意在生产工程设置中不能出现中文,不然会报错。

在这里插入图片描述

代码生成设置

最后设置生成独立的初始化文件

在这里插入图片描述

生成代码

在这里插入图片描述

代码编写

在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

变量定义 ,在main.c中添加。

/* USER CODE BEGIN PV */
#define BUFFERSIZE_usart2 1000           //可以接收的最大字符个数       
uint8_t ReceiveBuff_usart2[BUFFERSIZE_usart2]; //接收缓冲区
uint8_t recv_end_flag_usart2 = 0,Rx_len_usart2;//接收完成中断标志,接收到字符长度

#define BUFFERSIZE_usart3 1000           //可以接收的最大字符个数       
uint8_t ReceiveBuff_usart3[BUFFERSIZE_usart3]; //接收缓冲区
uint8_t recv_end_flag_usart3 = 0,Rx_len_usart3;//接收完成中断标志,接收到字符长度
int f1_u1 = 0;
/* USER CODE END PV */

函数声明和串口重定向,这里使用串口3进行打印,在main.c中添加。

/* USER CODE BEGIN PFP */
void uart2_data(void);                    //接收函数
void uart3_data(void);                    //接收函数
#ifdef __GNUC__                                    //串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif 
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}
/* USER CODE END PFP */

开启串口IDLE中断,在main.c中添加。

/* USER CODE BEGIN 2 */
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);//使能串口2 IDLE中断 
    __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);//使能串口2 IDLE中断 
        printf("双串口DMA接收例程
");
  /* USER CODE END 2 *

串口DMA获取,在main.c中添加。

void uart2_data(void)
{
    if(recv_end_flag_usart2 ==1)//接收完成标志
    {
        printf("串口2数据长度=%d
",Rx_len_usart2);//打印接收到的数据长度 
        printf("串口2数据内容:");
        for(int i=0;iprintf("%c",ReceiveBuff_usart2[i]);//向串口打印接收到的数据
            }
    printf("
");          
    for(int i = 0; i < Rx_len_usart2 ; i++) //清空接收缓存区
    ReceiveBuff_usart2[i]=0;//置0
    Rx_len_usart2=0;//接收数据长度清零
    recv_end_flag_usart2=0;//接收标志位清零
    }
                //开启下一次接收
    HAL_UART_Receive_DMA(&huart2,(uint8_t*)ReceiveBuff_usart2,BUFFERSIZE_usart2);
}
void uart3_data(void)
{
    if(recv_end_flag_usart3 ==1)//接收完成标志
    {
        printf("串口3数据长度=%d
",Rx_len_usart3);//打印接收到的数据长度 
        printf("串口3数据内容:");
        for(int i=0;iprintf("%c",ReceiveBuff_usart3[i]);//向串口打印接收到的数据
            }
    printf("
");          
    for(int i = 0; i < Rx_len_usart3 ; i++) //清空接收缓存区
    ReceiveBuff_usart3[i]=0;//置0
    Rx_len_usart3=0;//接收数据长度清零
    recv_end_flag_usart3=0;//接收标志位清零
    }
                //开启下一次接收
    HAL_UART_Receive_DMA(&huart3,(uint8_t*)ReceiveBuff_usart3,BUFFERSIZE_usart3);
}

主循环,在main.c中添加。

/* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        uart2_data();
        uart3_data();
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 *

中断外部变量引用,在stm32f0xx_it.c中添加。

/* USER CODE BEGIN 0 */
#define BUFFERSIZE_usart2 255    //可接收的最大数据量
extern uint8_t recv_end_flag_usart2,Rx_len_usart2;


#define BUFFERSIZE_usart3 255    //可接收的最大数据量
extern uint8_t recv_end_flag_usart3,Rx_len_usart3;
/* USER CODE END 0 */

串口2,3中断函数,在stm32f0xx_it.c中添加。

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
        uint32_t temp_usart2;
    if(USART2 == huart2.Instance)//判断是否为串口2中断

    {      
        if(RESET != __HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))//如果为串口2
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中断标志
      HAL_UART_DMAStop(&huart2);//停止DMA接收
             temp_usart2  = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//获取DMA当前还有多少未填充
              Rx_len_usart2 =  BUFFERSIZE_usart2 - temp_usart2; //计算串口接收到的数据个数
              recv_end_flag_usart2 = 1;
         }
        }
  /* USER CODE END USART2_IRQn 1 */
}

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
    uint32_t temp_usart3;
    if(USART3 == huart3.Instance)//判断是否为串口3中断

    {      
        if(RESET != __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))//如果为串口3
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除中断标志
      HAL_UART_DMAStop(&huart3);//停止DMA接收
             temp_usart3  = __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);//获取DMA当前还有多少未填充
              Rx_len_usart3 =  BUFFERSIZE_usart3 - temp_usart3; //计算串口接收到的数据个数
              recv_end_flag_usart3 = 1;
         }
        }
  /* USER CODE END USART3_IRQn 1 */
}

结果演示

开机会显示双串口DMA接收例程。

串口2发送数据会在串口3中打印,但是会显示接收的是串口2。

串口3发送数据会在串口3中打印,但是会显示接收的是串口3。

在这里插入图片描述

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • dma
    dma
    +关注

    关注

    3

    文章

    535

    浏览量

    99021
  • stm32cubemx
    +关注

    关注

    5

    文章

    260

    浏览量

    14447
  • 雅特力
    +关注

    关注

    0

    文章

    135

    浏览量

    7768
收藏 人收藏

    评论

    相关推荐

    stm32串口怎么用DMA接收不定长数据?

    stm32串口怎么用DMA接收不定长数据,求大神点播1. 网上查到,空闲中断+
    发表于 08-21 09:21

    STM32CUBEMX移植

    STM32CUBEMX移植AT32F403AVGT7[兼容
    发表于 07-23 09:21

    如何使用STM32CubeMX移植AT32F403AVGT7

    如何使用STM32CubeMX移植AT32F403AVGT7,并
    发表于 08-05 07:01

    不定长数据接收的原理IDLE空闲中断介绍

    1_V1.8.0(STM32Cube MCU Package for STM32F1xx Series)本文内容:不定长数据接收的原理IDL
    发表于 08-16 07:42

    STM32 HAL库中串口空闲中断+DMA 实现串口数据不定长接收 精选资料分享

    for STM32F0 Series)本文内容:不定长数据接收的原理串口接收中断的配置
    发表于 08-16 08:02

    如何使用STM32CubeMX移植AT32F403AVGT7

    如何使用STM32CubeMX移植AT32F403AVGT7呢?并通过串口输出打印?
    发表于 10-25 08:36

    STM32HAL库串口空闲中断+DMA是如何去实现串口接收不定长数据

    STM32HAL库串口空闲中断+DMA是如何去实现串口接收不定长
    发表于 11-16 09:01

    STM32CubeMX串口+DMA接收不定长数据的函数分享

    STM32CubeMX串口+DMA接收不定长数据的函数分享
    发表于 12-07 07:23

    STM32 HAL库中串口空闲中断+DMA 实现串口数据不定长接收

    Package for STM32F0 Series)本文内容:不定长数据接收的原理串口接收
    发表于 12-06 18:36 20次下载
    <b class='flag-5'>STM32</b> HAL库中<b class='flag-5'>串口</b>空闲中断+<b class='flag-5'>DMA</b> 实现<b class='flag-5'>串口</b><b class='flag-5'>数据</b>的<b class='flag-5'>不定长</b><b class='flag-5'>接收</b>

    STM32CubeMX HAL库串口+DMA+IDLE空闲中断不定长度数据接收和发送

    Cube_FW_F1_V1.8.0(STM32Cube MCU Package for STM32F1xx Series)本文内容:不定长数据接收
    发表于 12-07 11:36 23次下载
    <b class='flag-5'>STM32CubeMX</b> HAL库<b class='flag-5'>串口</b>+<b class='flag-5'>DMA</b>+IDLE空闲中断<b class='flag-5'>不定长度数据</b><b class='flag-5'>接收</b>和发送

    STM32 DMA串口接收不定长数据

    STM32 DMA串口接收不定长数据
    发表于 12-24 18:50 40次下载
    <b class='flag-5'>STM32</b>  <b class='flag-5'>DMA</b><b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    STM32串口DMA接收不定长数据

    目录STM32串口DMA接收不定长数据引言DMA
    发表于 12-24 19:03 30次下载
    <b class='flag-5'>STM32</b>之<b class='flag-5'>串口</b><b class='flag-5'>DMA</b><b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    STM32CUBEMX(7)--移植雅特力AT32F403AVGT(兼容STM32F103VGT6),DAC输出电压

    本篇文章主要介绍如何使用STM32CubeMX移植到雅特力AT32F403AVGT7,并通过DAC输出电压,在芯片中有2个12位的DAC口可以供选择。
    的头像 发表于 11-14 16:23 2369次阅读
    <b class='flag-5'>STM32CUBEMX</b>(7)--<b class='flag-5'>移植</b>雅特力AT32F<b class='flag-5'>403AVGT</b>(兼容<b class='flag-5'>STM32</b>F103VGT6),DAC输出电压

    STM32CUBEMX(8)--USART通过定时器中断方式接收不定长数据

    本文利用中断实现串口不定长接收(非DMA),使用HAL库,将接收数据打印出去。
    的头像 发表于 11-14 16:31 990次阅读
    <b class='flag-5'>STM32CUBEMX</b>(8)--USART<b class='flag-5'>通过</b>定时器中断<b class='flag-5'>方式</b><b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    STM32CubeMX串口接收不定长数据

    基本串口通信通常只能接收定长数据,无法稳定接收不定长数据
    的头像 发表于 05-11 09:59 2258次阅读
    <b class='flag-5'>STM32CubeMX</b>之<b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>