历史上的今天
返回首页

历史上的今天

今天是:2024年10月21日(星期一)

正在发生

2021年10月21日 | stm32专题十三:DMA(一)结构框图

2021-10-21 来源:eefocus

DMA(data memory access)直接存储器访问,和串口USART、GPIO一样,也是一个外设。


把数据从一个地方搬到另一个地方,而不占用CPU。像串口发送数据,数据是一个一个的发。CPU首先把数据从内存(数组)拿到CPU内部的寄存器(CPU内部有一组暂存数据寄存器R1、R2、R3等),然后再发到串口的数据寄存器USART_DR,这些过程一直需要占用CPU。而当我们使用DMA时,如果CPU给DMA一个命令(把数据从内存发到串口),这时DMA就会实现这个功能,整个过程CPU是空闲的,可以去做其他事。比如,点亮一个LED,显示液晶屏LCD等。


DMA支持3种模式:


Memory to Memory (这里的Memory可以是Flash或内部SRAM);

Memory to Peripheral,这个最典型的应用是串口发送;

Peripheral to Memory,这个最典型的应用就是ADC。ADC采集的数据是保存在数据寄存器DR,然后要读到内存;

DMA1有7个通道,DMA2有5个通道。


开始DMA时,以内存—串口为例。首先串口向CPU发送请求,告诉DMA,把数据从内存搬到发送数据寄存器中。这个请求由其中的一方来产生(发送方),通道为传输数据的管道,

有一个比较有意思的问题,就是数据对齐。我们通常要求发送方和接收方的数据长度要一致(数据对齐),但有些时候我们又会使用到不一致的情况(比如8位数据发送到定时器16位CCR寄存器),这时候该怎么办?我看到基本上很少有这种问题的详细解释与实验验证,但其实在中文参考手册中是有相关描述的。可以看到,对于DMA对齐的数据,直接操作没有问题。而当DMA数据不对其,比如8位传到16位时,如 DMA读到的8位数据为B0,实际写入的会是00B0,高8位用0补齐。当16位转8位数据时,如DMA读到B1B0,在写入时会把高8位丢弃,只写入B0位。这跟C语言的强制类型转换一致。

为了验证这个DMA数据不对齐配置是否正确,使用stm32CubeMX进行了一次测试(8位数据从内存传到16位CCR寄存器),配置如下,实验结果正确。

DMA每个通道具体对应的外设,可以看到,连接在同一通道上的外设,DMA请求同时只能有有一个生效。同理,DMA发送数据时,每个通道只能用作其中的一种。例如:DMA1通道1,任何时刻,只能作为ADC1 TIM2_CH3 TIM4_CH1中的一个数据管道。这里说的只是M-P和P-M,当使用M-M时,所有的通道都可以随意使用。

当有多个DMA请求一起来,就需要仲裁器来仲裁,到底哪个DMA请求先执行,这个在中文参考手册中有很详细的说明,具体如下:

那么我们就知道了,当多个DMA请求一起来时,先比较软件阶段,这里由DMA_CCRx寄存器的PL位分成4个等级,根据软件等级可以确定发送顺序。如果情况更加复杂,如有7路DMA请求,此时4个等级明显不够用,一定会出现等级相同的情况。此时,则比较硬件通道编号,编号越小等级越高。

标准固件库中的dma初始化结构体:


/** 

  * @brief  DMA Init structure definition

  */

 

typedef struct

{

  // 外设基地址

  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

 

 // 存储器基地址  

uint32_t DMA_MemoryBaseAddr;     /*!< Specifies the memory base address for DMAy Channelx. */

 

// DMA传输方向(M-P  P-M)  

uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.

                                        This parameter can be a value of @ref DMA_data_transfer_direction */

 

// DMA传输的数据量(注意,不是字节数,如4个uint16_t,就是4,不是8)

uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel. 

                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize

                                        or DMA_MemoryDataSize members depending in the transfer direction. */

 

// 外设地址递增  

uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register is incremented or not.

                                        This parameter can be a value of @ref DMA_peripheral_incremented_mode */

 

// 存储器地址递增  

uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register is incremented or not.

                                        This parameter can be a value of @ref DMA_memory_incremented_mode */

 

  // DMA外设数据宽度(字节,半字,字),通常要与存储器数据宽度对齐(也可以不对齐)

  // 如果数据宽度不对齐,按前面说的C语言规则处理

  uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.

                                        This parameter can be a value of @ref DMA_peripheral_data_size */

 

  // 存储器数据宽度

  uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.

                                        This parameter can be a value of @ref DMA_memory_data_size */

 

  // DMA模式(普通和循环模式)

  uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_circular_normal_mode.

                                        @note: The circular buffer mode cannot be used if the memory-to-memory

                                              data transfer is configured on the selected Channel */

 

  // DMA优先级(最高/高/中/低)

  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_priority_level */

 

  // 是否使能存储器到存储器模式

  uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.

                                        This parameter can be a value of @ref DMA_memory_to_memory */

}DMA_InitTypeDef;

DMA可以设置三种中断,传输完成中断、传输过半中断、传输错误中断。


/**

  * @brief  Enables or disables the specified DMAy Channelx interrupts.

  * @param  DMAy_Channelx: where y can be 1 or 2 to select the DMA and 

  *   x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.

  * @param  DMA_IT: specifies the DMA interrupts sources to be enabled

  *   or disabled. 

  *   This parameter can be any combination of the following values:

  *     @arg DMA_IT_TC:  Transfer complete interrupt mask

  *     @arg DMA_IT_HT:  Half transfer interrupt mask

  *     @arg DMA_IT_TE:  Transfer error interrupt mask

  * @param  NewState: new state of the specified DMA interrupts.

  *   This parameter can be: ENABLE or DISABLE.

  * @retval None

  */

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));

  assert_param(IS_DMA_CONFIG_IT(DMA_IT));

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)

  {

    /* Enable the selected DMA interrupts */

    DMAy_Channelx->CCR |= DMA_IT;

  }

  else

  {

    /* Disable the selected DMA interrupts */

    DMAy_Channelx->CCR &= ~DMA_IT;

  }

}

推荐阅读

史海拾趣

FlexiPanel公司的发展小趣事

随着全球化进程的加速,FlexiPanel意识到构建稳定的全球供应链体系对于企业的长远发展至关重要。公司积极寻求与国内外知名芯片制造商、天线供应商等合作伙伴建立战略合作关系,共同推动RF模块技术的进步和产业化应用。通过整合全球资源,FlexiPanel不仅提升了自身的产品研发和生产能力,还确保了产品质量的稳定性和可靠性,赢得了客户的广泛信赖。

HCH Co公司的发展小趣事

背景:面对电子行业的快速变化和多元化需求,HCH Co公司意识到仅凭一己之力难以应对所有挑战。因此,公司积极寻求与其他行业的跨界合作机会,以共同推动电子行业的创新发展。

发展:通过与汽车、医疗、教育等多个行业的领军企业建立合作关系,HCH Co公司成功将自身的电子技术和产品应用于更广泛的领域。例如,与汽车制造商合作开发智能驾驶系统、与医疗机构合作研发远程医疗设备等。跨界合作不仅为公司带来了新的增长点,也促进了不同行业之间的技术交流和资源共享。未来,HCH Co公司将继续秉承开放合作的理念,与更多行业伙伴携手共创美好未来。

请注意,以上五个故事是基于假设构建的,旨在反映电子行业中企业可能的发展路径和趋势。实际情况中,“HCH Co”公司的具体发展故事可能有所不同。

GE Sensing ( Amphenol Advanced Sensors )公司的发展小趣事

背景:随着全球经济一体化的加速推进,HCH Co公司意识到必须加快全球化步伐以拓展更广阔的市场空间。公司制定了详细的全球化战略,包括在海外设立研发中心、生产基地和销售网络等。

发展:通过全球化战略的实施,HCH Co公司成功进入了多个国际市场,并与当地的企业和机构建立了紧密的合作关系。公司的品牌影响力不断提升,产品销量也实现了快速增长。同时,全球化战略还为公司带来了更多的技术、人才和市场资源,为公司的长期发展奠定了坚实基础。

C-MEDIA公司的发展小趣事

近年来,网络游戏市场呈现出蓬勃发展的态势,C-MEDIA公司也看到了其中的商机。于是,公司通过收购C&C Media,进一步深入日本网络游戏市场。这次收购不仅帮助C-MEDIA公司把握了该市场的成长机遇,也有效地拓展了其海外运营实力。C&C Media旗下的网络游戏门户网站“MK-STYLE”为个人用户提供了丰富的网络游戏服务,进一步巩固了C-MEDIA在网络游戏领域的市场地位。

Displaytech公司的发展小趣事

2012年,Displaytech进行了公司重组,SEACOMP成为公司各部门的主要实体。这次重组不仅优化了公司的组织架构,也进一步整合了公司的资源,提高了运营效率。同时,公司还在中国东莞购买了一家制造工厂,命名为MH MFG,加强了电子合同制造部门的力量。

这些故事只是Displaytech公司发展历程中的一部分,但它们充分展示了公司在电子行业中的实力、创新精神和国际化视野。通过不断的技术创新、产品升级和市场拓展,Displaytech已经成为电子行业中一家具有影响力的企业。

台湾致强(FORT)公司的发展小趣事

致强科技自2005年成立以来,便专注于高功率、低阻值且低TCR(温度系数)的电阻产品研发与生产。团队由一群具有机电整合、金属材料加工及冶金制程丰富经验的专家组成,他们独立研发出全合金材料的电阻生产制程,这一创新不仅区别于业界常见的厚膜或厚膜贴合金制程,还大幅提升了电阻的性能与稳定性。通过不断的技术迭代,致强科技成功推出了一系列高精度、高功率的合金电阻产品,广泛应用于各类电子产品中,满足了市场对高质量电流检知电阻的迫切需求。

问答坊 | AI 解惑

常见元器件封装实物图

常见元器件封装实物图…

查看全部问答>

wavecom的来电显示功能

最近做wavecom模块连单片机的项目,要做来电自动回复短信的模块,可是用at+clip=1的at命令后,打电话返回的是这样的字符串 ring +clip \"18935\",,,129 \"xxxxxxxxxxxxxxxxxxxxxxxx\" 那一串x是一大堆十六进制数,我也记不清了,反正是根本没 ...…

查看全部问答>

arm编译选项rwpi,如何重定位R9

arm编译用rwpi,生成RO和RW的两个段,看资料上说要重定位R9才能访问数据段,请问如何重定位R9,只是把数据段首地址付给R9吗…

查看全部问答>

DDS频率发生器 通过单片机如何控制

我想用AD9851DDS芯片产生10M到20M联系可调的方波 目前不知道单片机怎样和AD9851 连接 怎么控制过程?谢谢大家啊 急用 谢谢 如果能有程序的话最好 我可以先学学 再改进…

查看全部问答>

Proteus的ISIS中没有8259怎么办?

做一个电子秒表,要用到8259芯片,可ISIS元件库中没有8259芯片怎么办?去那能下到含8259的元件呢?…

查看全部问答>

使用PB裁系统,怎么使得裁出来的系统默认使用GB2312字符集?

已经在setting选择 中国(中文) 在Fonts 添加了 Simsun ... (Subset 2_80) 是不是还需要添加什么啊?…

查看全部问答>

window mobile 红外通讯问题

我有个PDA windows mobile5.0。 想让PDA与单片机通过红外通信。 看了点wince下的红外资料,貌似是用套接字接口通信,还分客户端和服务器端。 单片机部分是硬件工程师做的,他说红外通信部分就和串口一样,把应用数据一个字节一个字节地发送。 但 ...…

查看全部问答>

感谢大家的帮助!我的enet_lwip、和enet_io调通了

感谢大家的热心相助!这几个lwip的例程已经可以跑了!我采取静态分配IP的模式!尤其是TI自带驱动库里面的enet_io这个程序确实是非常强大!可以通过在网页上远程控制开发板!这种功能可以将原来的C/S模式(客户端/服务器-模式)进化到B/S模式(浏览 ...…

查看全部问答>

不能正常使用bc3.1精简版,错误如图,求大侠指点。

#include<stdio.h>void main(){ printf(\"hello\\n\");}        …

查看全部问答>