dha什么时间段吃最好| 澳门为什么叫澳门| 蚯蚓喜欢吃什么| ct什么意思| 乳核是什么| 祖师香是什么意思| 荔枝不能与什么一起吃| 压缩性骨折是什么意思| 原教旨主义是什么意思| 肺部有空洞是什么病症| 99年属什么| 王维字什么| 经变是什么意思| 大学毕业是什么学历| 下嫁是什么意思| 猪冲什么生肖| 一个口一个甫念什么| 小儿疳积是什么症状| 红鸾是什么意思| 女人吃什么补充胶原蛋白| 往来账是什么意思| 92年1月属什么生肖| lv是什么意思| 抽血前喝水有什么影响| 什么是阴历| 失眠吃什么药| 胰腺炎为什么不能同房| 小孩一到晚上就发烧是什么原因| 吃什么对头发有好处| 什么是肇事逃逸| 栋字五行属什么| cybex是什么牌子| 上梁不正下梁歪什么意思| 夏天什么时候结束| 吃什么补气养血最快| 冯巩什么军衔| 黄牛什么意思| 七夕送什么| 老想睡觉是什么原因| 乙肝抗体1000代表什么| 腐女什么意思| 女人喝劲酒有什么好处| 鼻子旁边有痣代表什么| 女朋友的弟弟叫什么| 小孩磨牙是什么原因| 肾主骨是什么意思| 三国演义是什么朝代| 唇钉是干什么用的| 指示是什么意思| 手指麻木什么原因| 溦是什么意思| 土家族是什么族| 印度阿三是什么意思| 上火了吃什么药好| 苦荞茶和什么搭配最好| 树根有什么作用| 湫是什么意思| 生蚝和牡蛎有什么区别| 梦见吃蜂蜜是什么预兆| 梦见怀孕是什么预兆| 酥油茶是什么做的| 海豚吃什么食物| 情感障碍是什么| 什么样的心情| 睡久了头疼是什么原因| 黎明是什么时间| 洋葱什么时候种| 华为最新款手机是什么型号| 率性是什么意思| 男性阴虱用什么药最好| 大姨妈期间吃什么好| rush是什么东西| 人为什么会怕鬼| 班禅是什么级别| 静待花开什么意思| 舌苔黄厚腻是什么原因| 徒刑是什么意思| 依云矿泉水为什么贵| 什么叫早教| 肝火旺吃什么药| 正在值机是什么意思| 珊瑚红是什么颜色| 天秤座是什么星座| 闰六月是什么意思| 清淡饮食吃什么| 天降横财什么意思| 胰腺检查挂什么科| 海底有什么动物| 梦见被蛇追是什么意思| 人为什么会说梦话| 张信哲为什么不结婚| 什么补血快| 古人的婚礼在什么时候举行| 复方血栓通片功效作用治疗什么病| 千里单骑是什么生肖| 梦见自己大肚子快生了是什么意思| 乙肝挂什么科| 胃胀胃不消化吃什么药| 58年属狗是什么命| 胃痛怎么办吃什么药| 不什么不什么| 烧火棍是什么意思| 825是什么意思| 澳大利亚人说什么语言| 化疗后白细胞低吃什么补得快| 黄姜长什么样图片| 一什么城市| 梦到被雷劈是什么意思| allin什么意思| 梦到门牙掉了是什么意思| 无聊的反义词是什么| 敞开心扉是什么意思| 来例假不能吃什么| 这次是我真的决定离开是什么歌| 变态什么意思| 艾草泡脚有什么功效| 肾结石是什么原因导致的| 抗坏血酸是什么| 长痘痘去医院挂什么科| 宫颈阳性是什么意思| 宿命是什么意思| 甲状腺看什么科| 转念是什么意思| 缩量十字星意味着什么| 送手镯的寓意是什么| 少尉是什么级别| 玖字五行属什么| 拉谷谷女装什么档次的| 钟鸣鼎食是什么意思| 什么是胸推| 惯犯是什么意思| 88.88红包代表什么意思| 吃什么对肺有好处| 真露酒属于什么酒| 11月7号是什么星座| 女生长胡子是什么原因| 秦朝为什么那么快灭亡| 2006属狗的五行缺什么| 士大夫是什么意思| 静脉炎吃什么药好得快| 店里来猫是什么兆头| 吃什么可以消除淋巴结| 金钱草有什么功效| hpf医学是什么意思| 浮肿是什么原因造成的| 孕酮低有什么影响| 黄疸是什么病| 3.3是什么星座| 双肺门不大是什么意思| 前纵韧带钙化是什么意思| 一什么心| 18k金是什么金| 再创佳绩是什么意思| 天上九头鸟地上湖北佬是什么意思| 心口痛是什么原因引起的| 阴道炎吃什么药好| 作壁上观什么意思| 拔罐颜色深浅代表什么| 适宜是什么意思| pe是什么意思| 舌尖起泡是什么原因| 威士忌是什么酿造的| 淋巴结有什么症状| 汉菜不能和什么一起吃| 夯实是什么意思| 山什么水什么| 亚洲没有什么气候| 什么丰富| 森林里有什么| 右脸长痘是什么原因| louis是什么意思| sherpa是什么面料| 左耳嗡嗡响吃什么药| 四史指的是什么| 脂浊是什么意思| 口苦是什么问题| 今年十八岁属什么生肖| 带状疱疹后遗神经痛挂什么科| 什么样的人容易得心梗| 额头青筋凸起是什么原因| 转呼啦圈有什么好处| 非无菌是什么意思| 中秋节吃什么| 腺样体挂什么科| 慧五行属什么| 夜间咳嗽是什么原因| 蜜獾为什么什么都不怕| 肠粉是用什么粉做的| 高血压吃什么水果| 舒化奶是什么意思| 分泌物是什么| 为什么会早产| 俱往矣是什么意思| 晕车吃什么能缓解| 牛筋面是用什么做的| 眼睛有血丝是什么原因| 飞机上不能带什么| 圣字五行属什么| 三观不合是什么意思| 吃钙片有什么副作用| 舌头根发麻是什么原因| nikon是什么牌子| 什么颜色加什么颜色等于白色| 嘴唇周围长痘痘是什么原因| o型血是什么血型| 胰腺炎吃什么| 鲭鱼是什么鱼| 无骨鱼是什么鱼| 1948年属鼠的是什么命| 什么人什么己| 黄牌是什么意思| 尿急尿频尿不尽吃什么药| 早晨起来口干舌燥是什么原因| 小孩贫血有什么症状| 青春痘长什么样| eps是什么意思| 四月什么星座| 紫薯不能和什么一起吃| 下嘴唇起泡是什么原因| 看不上是什么意思| 党内警告处分有什么影响| 什么医院才是正规医院| 黑枣是什么枣| 为什么拔罐肩膀最黑| 钢琴8级什么水平| 尿酸高吃什么降的快| 舌苔厚白应该吃什么| 经常生气会得什么病| 家里进鸟了是什么预兆| 小意思是什么意思| 泡脚有什么好处| 抗缪勒氏管激素是检查什么的| 1217是什么星座| 苹果a1661是什么型号| 喝红茶有什么效果| 吃中药忌口都忌什么| 什么水果养胃又治胃病| 深圳为什么叫鹏城| 6.24什么星座| 长方形脸适合什么发型| hpv是什么意思| ssa抗体阳性说明什么| 吃了火龙果小便红色是什么原因| 寒风吹起细雨迷离是什么歌| 心脏属于什么组织| 心肌缺血吃什么药| ab型血和o型血的孩子是什么血型| 什么的虫子| ghz是什么单位| 凌厉是什么意思| 腮腺炎什么症状| 尿隐血是什么问题| 灵芝泡水喝有什么功效| 舌苔白厚有齿痕是什么原因| 什么叫浪漫| 1964年出生属什么| 77年属什么| 噫是什么意思| 川崎病是什么| 物美价廉是什么意思| 手掌麻是什么原因引起的| 小鸟站在高压线上为什么不会触电| 总做梦是什么原因| 最长的河流是什么河| 百度
打印
[华山论剑]

俄方:乌女议员为俄特工的说法是“无稽之谈”

[复制链接]
6833|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2024-5-14 14:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DMA是一种在嵌入式实时任务处理中常用的功能。

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

简述DMA

DMA:Direct Memory Access,直接内存存取/访问。简单来说就是内存RAM直接和其他设备(外设)进行数据交互,而不需要CPU参与的一种控制器。



DMA它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的数据复制到缓存器,然后把它们再次写回到新的地方。在这个过程中,CPU不能做其他的工作。



DMA优点

DMA在系统中的角色好比一个公司的员工,CPU好比是公司的老板。

老板想要寄送一个快递到北京,只需要一个口令安排员工即可,具体填写快递单号、物流、派送等一系列工作老板不用关心。最后快递被对方收到,通知一声老板即可。
回到UART发送数据,同样的道理,CPU只需要简单的操作(“安排任务”),就可把一串数据包丢给DMA直接发送,最后发送完成,收到一个发送完成中断,通知CPU发送完成即可。

说到这里相信大部分人都明白了,老板可以亲自开车或者坐飞机送快递,完成这件事情,但会耽搁老板很多时间。

同样,如果我们使用UART自己发送,CPU就会不停仲裁发送结果,占据CPU大量资源。

在RTOS中,特别是有大量任务需要处理的时候,UART使用DMA发送就会带来很大方便。使用裸机运行的相同,尤为突出。

实例代码:DMA发送配置

本文使用STM32F4 MCU、标准外设库为例给大家简单讲述一下配置。


1、USART配置



USART(COM)宏定义:



/* COMM通信 */
#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
}

2、DMA配置

DMA宏定义:

/* COMM_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

DMA配置:

/************************************************
函数名称 :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);                              //初始化禁止
}

3、DMA发送UART数据包
DMA发送函数:

/************************************************
函数名称 :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
}

细心的朋友会发现,这个发送函数其实很简单。当然,这里是使用STM32F4芯片,其他芯片也差不多,原理类似。HAL库同样可以完成。



关于DMA发送完成中断,可根据实际情况,如果使用RTOS,一般发送数据是一个任务,这个任务会OS等待(检测)发送完成信号(即DMA发送完成中断)。

沙发
tpgf| | 2024-6-3 13:07 | 只看该作者
我觉得任何应用都是可以考虑使用dma来实现的
板凳
heimaojingzhang| | 2024-6-3 13:54 | 只看该作者
如果使用dma能减少cpu处理的时间 这个优势体现在外在表现是什么呢
地板
wakayi| | 2024-6-3 14:39 | 只看该作者
如果使用dma方式的话 能不能将数据发送的时候每包的数据量加大呢
5
caigang13| | 2024-6-3 19:25 | 只看该作者
这个不一定,关键还是看应用,用DMA只是效率更高。
6
renzheshengui| | 2024-6-3 21:20 | 只看该作者
如果觉得并不影响使用并且不会导致速度的下降 我觉得用不用都无所谓的
7
paotangsan| | 2024-6-3 21:51 | 只看该作者
个人认为dma并不是必须的 但是在数据量比较大的时候 还是有非常明显优势的
8
keaibukelian| | 2024-6-3 22:22 | 只看该作者
如果使用dma会对单片机有额外的要求吗
9
chenjun89| | 2024-6-4 08:08 | 只看该作者
用DMA处理发送和接收数据,CPU的利用率更高。
10
旧年胶片| | 2025-7-25 16:31 | 只看该作者
[color=rgba(0, 0, 0, 0.85)]UART 串口是否用 DMA 发送取决于需求,高频大量数据时用 DMA 可解放 CPU,低频少量则直接发送。
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1296

主题

6229

帖子

15

粉丝
n0是什么意思 温饱是什么意思 孕妇零食可以吃什么 下巴长痘痘是什么原因 月经过后有褐色分泌物是什么原因
机制是什么 大连有什么好吃的 吃枸杞有什么好处 饺子什么馅好吃 天无二日指什么生肖
人类什么时候出现的 干咳嗽是什么原因 性感染有什么症状 世界上最高的高原是什么 gummy是什么意思
去美容院洗脸有什么好处 美国有什么特产 序曲是什么意思 wonderflower是什么牌子 阴阳代表什么数字
面部神经吃什么药hcv7jop9ns9r.cn 微信加入黑名单和删除有什么区别hcv8jop7ns3r.cn 花指什么生肖hcv8jop1ns6r.cn 六月十一是什么星座jinxinzhichuang.com 三伏天要注意什么xinjiangjialails.com
梦见打牌是什么意思hcv8jop2ns3r.cn 1111是什么意思hcv7jop4ns6r.cn 疝是什么意思hcv9jop2ns4r.cn 尿酸高是什么意思hcv9jop4ns8r.cn 三唑酮主治什么病害hcv9jop3ns5r.cn
脚磨破了涂什么药hcv8jop2ns4r.cn 番茄是什么时候传入中国的hcv8jop0ns7r.cn 扎马步有什么好处hcv8jop6ns6r.cn 谷草谷丙低是什么原因hcv9jop3ns7r.cn 饮食清淡的标准是什么hcv7jop6ns3r.cn
maggie是什么意思hcv8jop8ns2r.cn 日文是什么字hcv8jop5ns0r.cn hyq什么意思hcv9jop0ns5r.cn 小孩脚后跟疼是什么原因dajiketang.com 支气管炎吃什么药效果最好96micro.com
百度