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

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

3天内不再提示

单片机DMA驱动串口过程

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-12-03 14:23 次阅读

先上代码:

#define COMM_COM                  USART2
#define COMM_COM_CLK              RCC_APB1Periph_USART2
#define COMM_COM_TX_GPIO_CLK      RCC_AHB1Periph_GPIOD     //UART TX
#define COMM_COM_TX_PIN           GPIO_Pin_5
#define COMM_COM_TX_GPIO_PORT     GPIOD
#define COMM_COM_TX_SOURCE        GPIO_PinSource5
#define COMM_COM_TX_AF            GPIO_AF_USART2
#define COMM_COM_RX_GPIO_CLK      RCC_AHB1Periph_GPIOD     //UART RX
#define COMM_COM_RX_PIN           GPIO_Pin_6
#define COMM_COM_RX_GPIO_PORT     GPIOD
#define COMM_COM_RX_SOURCE        GPIO_PinSource6
#define COMM_COM_RX_AF            GPIO_AF_USART2
#define COMM_COM_IRQn             USART2_IRQn
#define COMM_COM_Priority         9                        //优先级
#define COMM_COM_BaudRate         115200                   //波特率
#define COMM_COM_IRQHandler       USART2_IRQHandler        //中断函数接口(见stm32f4xx_it.c)


USART配置:



/************************************************
函数名称 :USART_COMM_Configuration
功    能 :通信串口配置
参    数 :无
返 回 值 :无
作    者 :strongerHuang
*************************************************/
void USART_COMM_Configuration(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;  

  /* 时钟配置 */
  RCC_AHB1PeriphClockCmd(COMM_COM_TX_GPIO_CLK | COMM_COM_RX_GPIO_CLK, ENABLE);  
  if((USART1 == COMM_COM) || (USART6 == COMM_COM))
    RCC_APB2PeriphClockCmd(COMM_COM_CLK, ENABLE);
  else
    RCC_APB1PeriphClockCmd(COMM_COM_CLK, ENABLE);  

  /* 复用配置 */
  GPIO_PinAFConfig(COMM_COM_TX_GPIO_PORT, COMM_COM_TX_SOURCE, COMM_COM_TX_AF);
  GPIO_PinAFConfig(COMM_COM_RX_GPIO_PORT, COMM_COM_RX_SOURCE, COMM_COM_RX_AF);  

  /* 引脚配置 */
  GPIO_InitStructure.GPIO_Pin = COMM_COM_TX_PIN;                     //USART Tx
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                       //复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(COMM_COM_TX_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = COMM_COM_RX_PIN;                     //USART Rx
  GPIO_Init(COMM_COM_RX_GPIO_PORT, &GPIO_InitStructure);  

  /* NVIC配置 */
  NVIC_InitStructure.NVIC_IRQChannel = COMM_COM_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_COM_Priority;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  

  /* USART配置 */
  USART_InitStructure.USART_BaudRate = COMM_COM_BaudRate;            //波特率
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;        //传输位数
  USART_InitStructure.USART_StopBits = USART_StopBits_1;             //停止位
  USART_InitStructure.USART_Parity = USART_Parity_No ;               //校验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发功能
  USART_Init(COMM_COM, &USART_InitStructure);

  USART_ClearFlag(COMM_COM, USART_FLAG_RXNE | USART_FLAG_TC);
  USART_ITConfig(COMM_COM, USART_IT_RXNE, ENABLE);                   //接收中断

  USART_DMACmd(COMM_COM, USART_DMAReq_Tx, ENABLE);                   //使能DMA

  USART_Cmd(COMM_COM, ENABLE);                                       //使能USART
}

DMA配置中的宏定义:

#define COMM_DR_ADDRESS           ((uint32_t)USART2 + 0x04)
#define COMM_DMA                  DMA1
#define COMM_DMA_CLK              RCC_AHB1Periph_DMA1
#define COMM_TX_DMA_CHANNEL       DMA_Channel_4
#define COMM_TX_DMA_STREAM        DMA1_Stream6
#define COMM_TX_DMA_FLAG_TCIF     DMA_FLAG_TCIF6
#define COMM_TX_DMA_IRQn          DMA1_Stream6_IRQn
#define COMM_TX_DMA_Priority      8                        //优先级
#define COMM_TX_DMA_IRQHandler    DMA1_Stream6_IRQHandler  //中断函数接口(见stm32f4xx_it.c)
#define COMM_TX_DMA_IT_TCIF       DMA_IT_TCIF6

通讯串口的配置

/************************************************
函数名称 :USART_COMM_DMA_Configuration
功    能 :通信串口的DMA配置
参    数 :无
返 回 值 :无
作    者 :strongerHuang
*************************************************/
void USART_COMM_DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;  

  /* 使能时钟 */
  RCC_AHB1PeriphClockCmd(COMM_DMA_CLK, ENABLE);  

  /* NVIC配置 */
  NVIC_InitStructure.NVIC_IRQChannel = COMM_TX_DMA_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_TX_DMA_Priority;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  

  /* DMA配置 */
  DMA_DeInit(COMM_TX_DMA_STREAM);
  DMA_InitStructure.DMA_Channel = COMM_TX_DMA_CHANNEL;               //DMA通道
  DMA_InitStructure.DMA_PeripheralBaseAddr = COMM_DR_ADDRESS;        //外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;               //内存地址(待传入参数)
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;            //传输方向
  DMA_InitStructure.DMA_BufferSize = 0;                              //传输长度(待传入参数)
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;   //外设递增
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;            //内存递增
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;    //数据宽度
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                      //循环模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;              //优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(COMM_TX_DMA_STREAM, &DMA_InitStructure);

  DMA_ClearFlag(COMM_TX_DMA_STREAM, COMM_TX_DMA_FLAG_TCIF);
  DMA_ITConfig(COMM_TX_DMA_STREAM, DMA_IT_TC, ENABLE);               //使能DMA传输完成中断

  DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE);                              //初始化禁止
}

j接下来实现数据发送与接收

/************************************************
函数名称 :COMM_SendBufByDMA
功    能 :通信串口通过DMA发送数据
参    数 :Buf ------ 数据(地址)
            Length --- 数据长度(字节)
返 回 值 :无
作    者 :strongerHuang
*************************************************/
void COMM_SendBufByDMA(uint8_t *Buf, uint16_t Length)
{
  DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE);                              //关闭DMA
                                                                     //内存地址
  DMA_MemoryTargetConfig(COMM_TX_DMA_STREAM, (uint32_t)Buf, DMA_Memory_0);
  DMA_SetCurrDataCounter(COMM_TX_DMA_STREAM, Length);                //设置DMA传输长度
  DMA_Cmd(COMM_TX_DMA_STREAM, ENABLE);                               //使能DMA
}

DMA是一种在嵌入式实时任务处理中常用的功能。

pYYBAGOJ9qaAPcf0AAEKOSVJNBQ774.png


而UART发送数据包,使用DMA方式能大量减轻CPU处理的时间,使其CPU资源不被大量浪费,尤其在UART收发大量数据包(如高频率收发指令)时具有明显优势。

审核编辑:汤梓红

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

    关注

    6001

    文章

    43971

    浏览量

    620797
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348725
  • 串口
    +关注

    关注

    14

    文章

    1483

    浏览量

    74506
  • dma
    dma
    +关注

    关注

    3

    文章

    535

    浏览量

    99016
收藏 人收藏

    评论

    相关推荐

    单片机串口驱动问题

    我的电脑win8.1系统,现在51单片机串口驱动装不了,显示事件错误代码43,又提示是最新驱动,请大神们指教
    发表于 05-12 10:53

    单片机并性行总线驱动串口驱动

    摘要;武汉谷鑫科技有限公司(www.mcutech.cn)专业致力于单片机并口、串口驱动TFTLCD彩色液晶屏模块1.单片机并性行总线驱动T
    发表于 07-19 00:59

    蓝牙串口+DMA接收单片机经常跑飞

    手机蓝牙和单片机蓝牙连接,手机APP检测到的数据会定时通过蓝牙传回给单片机,每次传21字节(如果没有出错)。本人刚开始是直接串口中断接收的,但是由于单次发送的数据量有点大(21字节),而且手机的发送
    发表于 04-25 23:28

    如何去设计单片机串口dma模式呢

    如何去设计单片机串口dma模式呢?
    发表于 02-18 07:04

    如果单片机不支持串口空闲中断和DMA怎么办

    如果单片机不支持串口空闲中断和DMA,可以参考之前写的,串口只用接收中断,完成不定长的分包。这里以stm32L4的单片机举例,思路可拓展到G
    发表于 02-22 07:32

    散列DMA设计的高速串口驱动技术

    散列DMA设计的高速串口驱动技术 1  概  述由于串口在电报通信、工控和数据采集等领域有着广泛的应用,绝大多数嵌入式处理器
    发表于 05-26 16:45 656次阅读
    散列<b class='flag-5'>DMA</b>设计的高速<b class='flag-5'>串口</b><b class='flag-5'>驱动</b>技术

    单片机USB串口驱动软件CH340下载

    单片机USB串口驱动软件CH340下载
    发表于 04-25 09:16 28次下载

    PIC单片机DMA和ADC

    PIC单片机DMA和ADC
    发表于 11-16 11:21 32次下载
    PIC<b class='flag-5'>单片机</b>的<b class='flag-5'>DMA</b>和ADC

    单片机串口调试丢包验证过程记录 已解决

    单片机串口调试丢包验证过程记录 已解决
    发表于 11-16 15:36 80次下载
    <b class='flag-5'>单片机</b><b class='flag-5'>串口</b>调试丢包验证<b class='flag-5'>过程</b>记录 已解决

    C语言条件编译语句and单片机DMA的介绍

    C语言条件编译语句and单片机DMA的介绍C语言条件编译:这里面介绍的很详细,也有历程。DMA的介绍:介绍了单片机中为什么要使用DMA,以及
    发表于 11-29 10:36 3次下载
    C语言条件编译语句and<b class='flag-5'>单片机</b><b class='flag-5'>DMA</b>的介绍

    stm32F4 配置串口+DMA 接收不定长数据 串口空闲中断

    串口是一种很常见的通讯接口,通过串口回传数据是很多智能型的传感器都拥有的特点。 很多智能型传感器内置单片机 通过单片机将原始的数据处理,然后以串口
    发表于 12-24 18:56 10次下载
    stm32F4 配置<b class='flag-5'>串口</b>+<b class='flag-5'>DMA</b> 接收不定长数据  <b class='flag-5'>串口</b>空闲中断

    STM32单片机串口空闲中断+DMA接收不定长数据

    在上一篇文章STM32单片机串口空闲中断接收不定长数据中介绍了利用串口空闲中断接收不定长数据,这种方式有一个问题就是串口每接收到一个字节就会进入一次中断,如果发送的数据比较频繁,那么
    发表于 12-27 19:24 18次下载
    STM32<b class='flag-5'>单片机</b><b class='flag-5'>串口</b>空闲中断+<b class='flag-5'>DMA</b>接收不定长数据

    STM32单片机实现DMA+ADC+UART功能

    。于是想到了ADC采样的数据用DMA功能存储,并通过串口打印。但是串口打印依然要占用单片机时间,那能不能串口数据的输出也采用
    发表于 12-28 19:25 32次下载
    STM32<b class='flag-5'>单片机</b>实现<b class='flag-5'>DMA</b>+ADC+UART功能

    单片机接收不定长的数据,最优解是DMA+串口空闲中断

    如果单片机不支持串口空闲中断和DMA,可以参考之前写的,串口只用接收中断,完成不定长的分包。这里以stm32L4的单片机举例,思路可拓展到G
    发表于 12-28 19:26 19次下载
    <b class='flag-5'>单片机</b>接收不定长的数据,最优解是<b class='flag-5'>DMA</b>+<b class='flag-5'>串口</b>空闲中断

    基于STM32单片机DMA使用库文件设计源代码

    基于STM32单片机DMA使用库文件设计源代码)
    发表于 04-26 15:03 1次下载