精华内容
下载资源
问答
  • Stm32 DMA

    千次阅读 2013-05-12 20:49:03
    两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。 在同一个DMA模块上,多个请求间的优先权可以...

    两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。

    在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)

    独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。

    每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。

    闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。

    可编程的数据传输数目:最大为65535

    每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。DMA传输的数据量是可编程的,最大达到65535。包含要传输的数据项数量的寄存器,在每次传输后递减。

    通过设置DMA_CCRx寄存器中的PINC和MINC标志位,外设和存储器的指针在每次传输后可以有选择地完成自动增量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值,增量值取决与所选的数据宽度为1、2或4。第一个传输的地址是存放在DMA_CPARx /DMA_CMARx寄存器中地址。在传输过程中,这些寄存器保持它们初始的数值,软件不能改变和读出当前正在传输的地址(它在内部的当前外设/存储器地址寄存器中)。当通道配置为非循环模式时,传输结束后(即传输计数变为0)将不再产生DMA操作。要开始新的DMA传输,需要在关闭DMA通道的情况下,在DMA_CNDTRx寄存器中重新写入传输数目。在循环模式下,最后一次传输结束时,DMA_CNDTRx寄存器的内容会自动地被重新加载为其初始数值,内部的当前外设/存储器地址寄存器也被重新加载为DMA_CPARx/DMA_CMARx寄存器设定的初始基地址。

    通道配置过程下面是配置DMA通道x的过程(x代表通道号):1. 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将是数据传输的源或目标。2. 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数据将从这个地址读出或写入这个地址。3. 在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。4. 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。5. 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。6. 设置DMA_CCRx寄存器的ENABLE位,启动该通道。一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。

    循环模式

    循环模式用于处理循环缓冲区和连续的数据传输(如ADC的扫描模式)。在DMA_CCRx寄存器中的CIRC位用于开启这一功能。当启动了循环模式,数据传输的数目变为0时,将会自动地被恢复成配置通道时设置的初值,DMA操作将会继续进行。

    存储器到存储器模式

    DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时,DMA传输结束。存储器到存储器模式不能与循环模式同时使用。

     

    操作一个不支持字节或半字写的AHB设备

    当DMA模块开始一个AHB的字节或半字写操作时,数据将在HWDATA[31:0]总线中未使用的部分重复。因此,如果DMA以字节或半字写入不支持字节或半字写操作的AHB设备时(即HSIZE不适于该模块),不会发生错误,DMA将按照下面两个例子写入32位HWDATA数据:●当HSIZE=半字时,写入半字’0xABCD’,DMA将设置HWDATA总线为’0xABCDABCD’。●当HSIZE=字节时,写入字节’0xAB’,DMA将设置HWDATA总线为’0xABABABAB’。假定AHB/APB桥是一个AHB的32位从设备,它不处理HSIZE参数,它将按照下述方式把任何AHB上的字节或半字按32位传送到APB上:●一个AHB上对地址0x0(或0x1、0x2或0x3)的写字节数据’0xB0’操作,将转换到APB上对地址0x0的写字数据’0xB0B0B0B0’操作。●一个AHB上对地址0x0(或0x2)的写半字数据’0xB1B0’操作,将转换到APB上对地址0x0的写字数据’0xB1B0B1B0’操作。例如,如果要写入APB后备寄存器(与32位地址对齐的16位寄存器),需要配置存储器数据源宽度(MSIZE)为’16位’,外设目标数据宽度(PSIZE)为’32位’。

    DMA请求映像

    DMA1控制器

    从外设(TIMx[x=1234]ADC1SPI1SPI/I2S2I2Cx[x=12]USARTx[x=123])产生的7个请求,通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。参见下图的DMA1请求映像。

     

    外设

    通道1

    通道2

    通道3

    通道4

    通道5

    通道6

    通道7

     

    ADC1

    ADC1

     

     

     

     

     

    SPI/I2S

     

    SPI1_RX

    SPI1_TX

    SPI/I2S2_RX

    SPI/I2S2_TX

     

     

    USART

     

    USART3_TX

    USART3_RX

    USART1_TX

    USART1_RX

    USART2_RX

    USART2_TX

    I2C

     

     

     

    I2C2_TX

    I2C2_RX

    I2C1_TX

    I2C1_RX

    TIM1

     

    TIM1_CH1

    TIM1_CH2

    TIM1_TX4

    TIM1_TRIG

    TIM1_COM

     

    TIM1_UP

    TIM1_CH3

     

    TIM2

    TIM2_CH3

    TIM2_UP

     

     

    TIM2_CH1

     

    TIM2_CH2

    TIM2_CH4

    TIM3

     

    TIM3_CH3

    TIM3_CH4 TIM3_UP

     

     

    TIM3_CH1

    TIM3_TRIG

     

    TIM4

    TIM4_CH1

     

     

    TIM4_CH2

    TIM4_CH3

     

    TIM4_UP

     

    DMA2控制器从外设(TIMx[5678]ADC3SPI/I2S3UART4DAC通道12SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,这意味着同时只能有一个请求有效。参见下图的DMA2请求映像。

     

    外设

    通道1

    通道2

    通道3

    通道4

    通道5

    ADC3(1)

     

     

     

     

    ADC3

    SPI/I2S3

    SPI/I2S3_RX

    SPI/I2S3_TX

     

     

     

    UART4

     

     

    UART4_RX

     

    UART4_TX

    SDIO(1)

     

     

     

    SDIO

     

    TIM5

    TIM5_CH4 TIM5_TRIG

    TIM5_CH3 TIM5_UP

     

    TIM5_CH2

    TIM5_CH1

    TIM6/ DAC通道1

     

     

    TIM6_UP/ DAC通道1

     

     

    TIM7/ DAC通道2

     

     

     

    TIM7_UP/DAC通道2

     

    TIM8(1)

    TIM8_CH3 TIM8_UP

    TIM8_CH4 TIM8_TRIG TIM8_COM

    TIM8_CH1

     

    TIM8_CH2

     

    展开全文
  • DMA介绍 STM32 DMA介绍 STM32 DMA库函数使用 项目实践;DMA概念;STM32 DMA介绍;DMA工作模式;外设到存储器模式;存储器到外设模式;存储器到存储器模式;DMA中断;DMA中断;STM32 DMA库函数使用;STM32 DMA库函数使用;STM32 ...
  • STM32 DMA串口接收不定长数据

    千次阅读 2020-03-15 12:23:03
    STM32 DMA串口接收不定长数据

    串口通信(UART)在通信当中尤其是在低速率占用很重要的地位 通信 速度虽然比不上SPI通信但是由于其简单,对通信双方的时钟要求不是很高,受到很广泛的使用,很多嵌入式程序猿(媛) 都倾向于串口通信。

    1. 串口发送

    串口发送函数非常简单,直接调用串口的API函数
    void USART_SendData(USART_TypeDef USARTx, uint16_t Data);*
    即可发送出去,举个简单的实例:

    void Usart1_SendData(u8 *Str)     //Str存储发送的数据
    {
      u8 i=0;
      while(Str[i]!=0)
      {
        USART_SendData(USART1,Str[i]);
        while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE));
        i++;
      }
    }
    

      上面的函数存在一个问题,当数据当中有0x00字节 时,就会跳出while循环,停止发送数据,所以存在bug,需要进行改良。

      很多朋友会问无缘无故为啥会发0x00字节呢?这是因为在项目中,尤其是一些协议通讯,经常会遇到0x00 ,代表数据正常 或者一定的含义 ,如果还是调用上面的函数,就会出现发送不完整的情况。

      所以要发送完全,就要加上数据的长度dateLength ,这样就万无一失了。

    void Usart3_SendData(u8 *Str,u8 Datalength)
    {
      u8 i=0;
      while(i<Datalength)
      {
        USART_SendData(USART3,Str[i]);
        while(!USART_GetFlagStatus(USART3,USART_FLAG_TXE));
        i++;
      }
    }
    

      当然如果为了减少CPU的压力,可以使用DMA去发送数据。
      思路是:首先设置DMA的Counter值=数据长度,然后启动DMA流,就开始发送了。可以设置DMA发送完成中断,也可以无需设置,最后判断一下串口是否发送完成即可。

    void UART1_SentMsgL(unsigned char *data, u16 cnt)
    {
      u16 i;
      USART_ClearFlag(USART1, USART_FLAG_TC);       //清除UART1发送完成标志位
      for(i=0;i<cnt;i++)
        USART_TX_BUF[i]=data[i];
      DMA_SetCurrDataCounter(DMA2_Stream7, cnt);
      DMA_ITConfig(DMA2_Stream7 , DMA_IT_TC , ENABLE);
      DMA_Cmd(DMA2_Stream7, ENABLE);
      while(USART_GetFlagStatus(USART1, USART_FLAG_TC)!=1);  //发送完成退出
    }
    

    2. 串口接收

      串口接收,个人觉得比发送要难,因为涉及到中断,还要判断什么时候接收完成,相当于处于被动的地位,无法掌控对数据的操作。

      最基本的接收方式就是:串口接收中断置位,USART_GetITStatus(USART1, USART_IT_RXNE)=SET
      则利用串口接收函数接收字符,
    Res =USART_ReceiveData(USART1);
      然后就可以存储到字符串当中,关键的方式就是,如何判断接收完成。然后进行处理。

      最常见的串口接收函数应该就是正点原子的接收函数,很经典,也很方便,直接拿来就用,是根据最后的结束标志位(0x0D 0x0A) 来判断一帧数据接收完成的。

    void USART1_IRQHandler(void)                	//串口1中断服务程序
    {
    	u8 Res;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    	{
    		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
    		
    		if((USART_RX_STA&0x8000)==0)//接收未完成
    		{
    			if(USART_RX_STA&0x4000)//接收到了0x0d
    			{
    				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    				else USART_RX_STA|=0x8000;	//接收完成了 
    			}
    			else //还没收到0X0D
    			{	
    				if(Res==0x0d)USART_RX_STA|=0x4000;
    				else
    				{
    					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
    					USART_RX_STA++;
    					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
    				}		 
    			}
    		}   		 
      } 
    

      我自己也写过一个简单版的,附在下面,也比较清晰一点。(使用0x0A做结尾或者接收达到上限

    void USART2_IRQHandler()
    {
    	u8 TempData;
    	if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
    	{
    		TempData = USART_ReceiveData(USART2);
    		if((TempData == 0X0A)||(RX_Index == RX_Num))
    		{
    			ReceiveFlag = 1;
    		}
    		else
    		{
    			RX_Buffer[RX_Index++] = TempData;
    		}
    		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
    	}
    }
    

      上面的函数存在一个问题是(正点原子例程),通信的帧数据必须以0x0D 0x0A为结尾,否则会出现无法判断接收完成的情况。

      所以这样就引出一个问题,如何接收任意的数据呢?即不定长而且不以任何特定的字符为结尾的数据。

      在数据通信完成之后,串口就会出现空闲的状态是否可以根据这样的状态来判断数据接收完成呢,答案当然是可以的。

      串口中提供了一个可以获取串口是否空闲的函数:
    USART_GetITStatus(USART3,USART_IT_IDLE);
    根据这样的一个函数就可以判断串口是否空闲,从而来判断数据帧是否结束。

      当然如果直接采用中断的话,对CPU的占用率比较大,采用DMA接收串口的数据的话,可以有效缓解CPU的压力。

      设计思路是:先开启串口接收中断,当接收开始时,这是开启DMA接收,当接收完成之后,进入空闲中断,此时判断帧结束,数据接收完成。

      所以这样一个串口接收函数就新鲜出炉了:

    void USART3_IRQHandler(void)                	//串口3中断服务程序
    {
    	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //通过接收中断来开启DMA接收
    	{
          USART_ClearITPendingBit(USART3,USART_IT_RXNE);
          USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);
    	  USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);
    	  DMA_Cmd(DMA1_Stream1,ENABLE);
      }
      else if(USART_GetITStatus(USART3,USART_IT_IDLE)!=RESET)//再通过空闲中断来判断数据帧结束。
      {
           USART_ClearITPendingBit(USART3,USART_IT_IDLE);
    	   Usart3_DataLength=RXNum-DMA_GetCurrDataCounter(DMA1_Stream1);   //DMA  Counter可以判断接收到多少个字节。
    	   DMA_Cmd(DMA1_Stream1,DISABLE);
    	   USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
    	   USART_ITConfig(USART3,USART_IT_IDLE,DISABLE);
           Usart_RecFlag=1;                     //接收完成标志位
      }
    } 
    

      还有一种思路是,不使用串口空闲来判断,而是通过定时器来实现,如果一定时间内没有数据接收,则认为接收完成,通常时间设置的是5ms。

      同样使用DMA来接收,DMA是循环模式通过DMACounter的值来判断是否开始接收和接收完成。
      DMAcounter值指示的待发送或者接收到的数据量,如果完成,则Counter值变为0。

    oid UART1Poll()
    {
      unsigned short dmacnt;
      dmacnt=DMA_GetCurrDataCounter(DMA2_Stream5);
      if(USARTRecStartFlag==0)
      {
        if(dmacnt==USART_LEN);   //如果发生变化,则数据通信开始,
        else 
        {
          USARTRecStartFlag=1;
          TIM_Cmd(TIM5,ENABLE);
          USARTDataInTime = Systemtime;     // 记下时间
        }
      }
      else                           //开始接收数据,
      {
        if(dmacnt==DMALastCnt)
        {
          USARTCurrTime = Systemtime;   
          if(USARTCurrTime-USARTDataInTime>5)//时间片5*1ms   超过一定时间,则认为接收完成
          {
            USART_FrameFlag=1;
            DMALastCnt=USART_LEN;
            USART_Len = USART_LEN - DMA_GetCurrDataCounter(DMA2_Stream5);
            USARTRecStartFlag=0;  
            DMA_Cmd(DMA2_Stream5,DISABLE); //停止使能 才能修改计数器 
            DMA_SetCurrDataCounter(DMA2_Stream5, USART_LEN);
            DMA_Cmd(DMA2_Stream5,ENABLE); //停止使能 才能修改计数器 
            TIM_Cmd(TIM5,DISABLE);
            TIM_SetCounter(TIM5,0); 
          }    
        }
        else 
        {
           DMALastCnt=dmacnt;
          USARTDataInTime = Systemtime;     //GetSystemtime();        // Systemtime;
        }   
      } 
    }
    
    void TIM5_IRQHandler(void)  //1000HZ     定时器计时。
    {
      if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
      {
        Systemtime++;
        // led output
        if(Systemtime == 1000)
        {  
           Systemtime = 0;  
        }
      }
      TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
    }
    
    如有雷同,纯属我抄你,有问题可以直接联系邮箱,在个人资料里面。
    展开全文
  • 关于STM32 DMA传输的理解

    千次阅读 2020-07-21 22:02:28
    参考了网上一些教程总结的STM32 DMA笔记,从原理到实例运用,希望对你有帮助!


    1. DMA是什么

      DMA (Direct Memory Access),直接存储器存取,是一种不经过CPU而直接从内存存取数据的数据交换模式,因而被广泛地使用。早在 8086 的应用中,就已经有 Intel 的 8237 这种典型的 DMA 控制器。而 STM32 的 DMA 则是以类似外设的形式,添加到 Cortex 内核之外的。
      DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。
      DMA由硬件实现,从共用系统数据总线的角度看,DMA和CPU是竞争对手的关系,在实现DMA传输时,是由DMA控制器直接掌管总线,在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU

    系统总线包括:

    • 数据总线:用于CPU与主存储器、CPU与I/O接口之间传送数据
    • 地址总线:用于CPU访问主存储器或外部设备时,传送相关的地址
    • 控制总线:用于传送CPU对主存储器和外部设备的控制信号
      即任何一个部件只要按照标准挂接到总线上,就进入了系统,就可以在CPU统一控制下进行工作

    2. CPU如何传输数据

      在DMA出现之前,CPU与外设之间的数据传送方式有程序传送方式、中断传送方式,均由软件实现。CPU是通过系统总线与其他部件连接并进行数据传输。

    ① 程序控制方式
      1) 无条件传送方式
      也叫做同步传送方式,微机系统中的一些简单的外设,如开关、继电器、数码管、发光二极管等,在它们工作时,可以认为输入设备已随时准备好向CPU提供数据,而输出设备也随时准备好接收CPU送来的数据,这样,在CPU需要同外设交换信息时,就能够用IN或OUT指令直接对这些外设进行输入/输出操作。由于在这种方式下CPU对外设进行输入/输出操作时无需考虑外设的状态,故称之为无条件传送方式。可以简单理解为CPU直接读取某个引脚的状态。
      2) 条件传送
      也叫做查询式传送方式,在开始传送数据前,必须要确认外设是否已经准备好接受数据的状态。
      是指在执行输入指令(IN)或输出指令(OUT)前,要先查询相应设备的状态,当输入设备处于准备好状态、输出设备处于空闲状态时,CPU才执行输入/输出指令与外设交换信息。为此,接口电路中既要有数据端口,还要有状态端口。比如iic传输中,读取数据前需要先等待设备响应后才能读取。

    ② 中断传送方式
      用查询方式,CPU要不断的查询外设的状态,很浪费时间,CPU工作效率很低。采用中断方式之后,CPU不需要查询外设的状态,而是执行主程序时,当外设数据准备好之后向CPU发出中断申请,因此CPU工作效率大大提高。但是CPU处理中断请求时需要进行断点和现场的保护和恢复,浪费了很多CPU的时间,适合少量数据的传送。

      软件方式实现数据传输的过程:
      在硬件系统中,主要由 CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常要在内存与外设之间转移,或从外设 A 转移到外设 B。
      例如:当 CPU 需要处理由 ADC 外设采集回来的数据时,CPU 首先要把数据从 ADC 外设的寄存器读取到内存中(变量),然后进行运算处理,这是一般的处理方法。

      其过程是内核通过 DCode 经过总线矩阵协调,使用 AHB 把外设 ADC 采集的数据读取到内核,暂时存放在内核的内存中(作为临时数据),然后内核通过 DCode 、再通过总线矩阵协调,把数据存放到内存 SRAM 中,最后再由CPU的运算器读取内存中的数据进行处理运算。

       ③ DMA传输
      DMA 正好可以取代上述的工作,其由硬件完成。即由 DMA 控制器的DMA 总线与总线矩阵协调,使用 AHB 把外设 ADC 的数据经由 DMA 通道存放到内存 SRAM,是点到点的数据转移,而不是使用 DMA 的方式还要以内核来作为中转站。在这个数据传输的过程中,不需要内核的全程参与。
      在DMA方式下,CPU连到这些总线上的线处于第三态(高阻状态),而由DMA控制器接管,控制传送的字节数,判断DMA是否结束,以及发出DMA结束信号。

    3. DMA的传输过程

      一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。
    ① 请求
      CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。

    DMA中断和普通中断的区别
      两者最大的不同表现为对CPU的干扰程度不同:DMA 传送方式的优先级高于程序中断,两者的区别主要表现在对CPU的干扰程度不同。中断请求不但使CPU停下来,而且要CPU执行中断服务程序为中断请求服务,这个请求包括了对断点和现场的处理以及CPU与外设的传送,所以CPU付出了很多的代价;DMA请求仅仅使CPU暂停一下,不需要对断点和现场的处理,并且是由DMA控制外设与主存之间的数据传送,无需CPU的干预,DMA只是借用了一点CPU的时间而已。
      还有一个区别就是,CPU对这两个请求的响应时间不同,对中断请求一般都在执行完一条指令的时钟周期末尾响应,而对DMA的请求,由于考虑它的高效性,CPU在每条指令执行的各个阶段之中都可以让给DMA使用,是立即响应。

    ② 响应
      DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。
    ③ 传输
      DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。
      在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过程中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。
    ④ 结束
      当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。

      由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。

    4. DMA一些特性

      STM32 最多有 2 个 DMA 控制器(DMA2 仅存在大容量产品中),DMA1 有 7 个通道。DMA2 有 5个通道。每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁起来协调各个 DMA 请求的优先权。

    ● 每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
    ● 在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相等优先权时由硬件决定(请求 0 优先于请求 1,依此类推) 。
    ● 独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
    ● 支持循环的缓冲器管理
    ● 每个通道都有 3 个事件标志(DMA 半传输,DMA 传输完成和 DMA 传输出错), 3 个事件标志逻辑或成为一个单独的中断请求。
    存储器和存储器间,外设和存储器,存储器和外设的传输
    ● 闪存、SRAM、外设的 SRAM、APB1 APB2 和 AHB 外设均可作为访问的源和目标。
    ● 可编程的数据传输数目:最大为 65536

    5. DMA各通道对应外设

    DMA1

    DMA2

    6. DMA 实例之串口通信

      以 DMA 的方式使用串口发送数据,实际上是利用 DMA 把数据(数组)从内存转移到外设(串口)。我们知道外设工作的时候,除了转移数据,实质是不需要内核干预的,而数据转移的工作现在交给了 DMA,所以在串口发送数据的时候,内核同时还可以进行其它操作,例如点亮 LED灯。使用的是串口 1 的 DMA1 传送,也就是要用到通道 4。

    6.1 传输过程的分析

      在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果有更多的请求时,外设可以启动下一个周期。总之,每次DMA传送由3个操作组成:

    • 从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
    • 存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
    • 执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

    6.1.1 DMA_CCRx寄存器

    ① 由位4[DIR]设置数据传输方向,该位由软件设置和清除。
      0:从外设读  1:从存储器读

    ② 由位13:12[PL]设置通道优先级
      软件方面:00:低  01:中  10:高  11:最高
      硬件方面:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。举个例子,通道2优先于通道4。 注意: 在大容量产品和互联型/产品中DMA1控制器拥有高FDMA2控制器的优先级

    ③ 由位11:10[MSIZE]设置存储器数据宽度
      00:8位(字节)  01:16位(半字)  10:32位(字)  11:保留

    ④ 由位9:8[PSIZE]设置外设数据宽度
      00:8位(字节)  01:16位(半字)  10:32位(字)  11:保留

    指针增量
    当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值,增量值取决与所选的数据宽度为1、2或4。第一个传输的地址是存放在DMA_CPARx/DMA_CMARx寄存器中地址。在传输过程中,这些寄存器保持它们初始的数值,软件不能改变和读出当前正在传输的地址(它在内部的当前外设/存储器地址寄存器中)。

    ⑤ 由位7[MINC]设置存储器地址增量模式
      0:不执行存储器地址增量模式操作1:执行存储器地址增量模式操作

    ⑥ 由位6[PINC]设置外设地址增量模式
      0:不执行外设地址增量模式操作1:执行外设地址增量模式操作

    ⑦ 由位5[CIRC]设置循环模式
      0:不执行循环模式操作1:执行循环模式操作

    6.1.2 通道传输数据量

    6.1.3 通道传输中断

    6.2 通道配置过程

    • DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将是数据传输的源或目标。
    • DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数据将从这个地址读出或写入这个地址。
    • 在DMA_ CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
    • 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。
    • 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。
    • 设置DMA_CCRx寄存器的ENABLE位,启动该通道。
    • 一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。
    • 当传输一半的数据后,半传输标志(HTIF)被置1,当设置了允许半传输中断位(HTIE)时,将产生一个中断请求。在数据传输结束后,传输完成标志(TCIF)被置1,当设置了允许传输完成中断位(TCIE)时,将产生一个中断请求。

    6.3 代码配置过程

      将利用外部按键 KEY0 来控制 DMA 的传送,每按一次 KEY0,DMA 就传送一次数据到USART1,然后在串口助手上显示进度等信息,同时在DMA数据传输过程进行点亮LED的操作。
      
    dma.c文件

    #include "dma.h"
    DMA_InitTypeDef DMA_InitStructure;
    u16 DMA1_MEM_LEN;//保存 DMA 每次数据传送的长度 
    //DMA1 的各通道配置
    //这里的传输形式是固定的,这点要根据不同的情况来修改
    //从存储器->外设模式 /8位数据宽度 /存储器增量模式
    //DMA_CHx:DMA 通道 CHx
    //cpar:外设地址
    //cmar:存储器地址
    //cndtr:数据传输量
    void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
    {
    	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
    	DMA_DeInit(DMA_CHx); //将 DMA 的通道 1 寄存器重设为缺省值
    	DMA1_MEM_LEN = cndtr;
    	DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA 外设 ADC 基地址
    	DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA 内存基地址
    	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向内存到外设
    	DMA_InitStructure.DMA_BufferSize = cndtr; //DMA 通道的 DMA 缓存的大小
    	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不变
    	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器递增
    	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为 8 位
    	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度//为 8 位
    	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式
    	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DM 通道拥有中优先级
    	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非内存到内存传输
    	DMA_Init(DMA_CHx, &DMA_InitStructure); //初始化 DMA 的通道
    } 
    
    //开启一次 DMA 传输
    void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
    { 
    	DMA_Cmd(DMA_CHx, DISABLE); //关闭 USART1 TX DMA1 所指示的通道 
    	DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//设置 DMA 缓存的大小
    	DMA_Cmd(DMA_CHx, ENABLE); //使能 USART1 TX DMA1 所指示的通道
    }
    

      
    main.c文件

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"	 
    #include "dma.h"
    
    #define SEND_BUF_SIZE 8200	//发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍
    
    u8 SendBuff[SEND_BUF_SIZE];	//发送数据缓冲区
    const u8 TEXT_TO_SEND[]={"测试:WarShip STM32F1 DMA 串口实验"};
    int main(void)
    {	 
    	u16 i;
    	u8 t=0;
    	u8 j,mask=0;
    	float pro=0;//进度
    
    	delay_init();	    	 //延时函数初始化	  
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
    	uart_init(115200);	 	//串口初始化为115200
    	LED_Init();		  		//初始化与LED连接的硬件接口
    	KEY_Init();				//按键初始化		 	
     	MYDMA_Config(DMA1_Channel4,(u32)&USART1->DR,(u32)SendBuff,SEND_BUF_SIZE);//DMA1通道4,外设为串口1,存储器为SendBuff,长度SEND_BUF_SIZE.
    
    	//显示提示信息	
    	j = sizeof(TEXT_TO_SEND);
    	for(i=0;i<SEND_BUF_SIZE;i++)//填充数据到SendBuff
      {
    		if(t>=j)//加入换行符
    		{
    			if(mask)
    			{
    				SendBuff[i]=0x0a;
    				t=0;
    			}else 
    			{
    				SendBuff[i]=0x0d;
    				mask++;
    			}	
    		}else//复制TEXT_TO_SEND语句
    		{
    			mask=0;
    			SendBuff[i]=TEXT_TO_SEND[t];
    			t++;
    		}    	   
      }		  
    	i=0;
    	while(1)
    	{
    		t=KEY_Scan(0);
    		if(t==KEY0_PRES)//KEY0按下
    		{
    		  USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送      
    			MYDMA_Enable(DMA1_Channel4);//开始一次DMA传输!	  
    		    //等待DMA传输完成,此时我们来做另外一些事,点灯
    		    //实际应用中,传输数据期间,可以执行另外的任务
    		  while(1)
    		  {
    				if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)	//判断通道4传输完成
    				{
    					DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志
    					break; 
    				}
    				pro=DMA_GetCurrDataCounter(DMA1_Channel4);//得到当前还剩余多少个数据
    				pro=1-pro/SEND_BUF_SIZE;//得到百分比	  
    				pro*=100;      //扩大100倍
    				LED1 = 0;
    				//printf("正在传输……\t%.2f%%\r\n",pro);
    		  }
    			LED1 = 1;
    			//printf("传输完成!\t%.2f%%\r\n",100.00);			
    		}
    		i++;
    		delay_ms(10);
    		if(i==20)
    		{
    			LED0=!LED0;//提示系统正在运行	
    			i=0;
    		}		   
    	}
    }
    
    

    运行结果

    6.3.1 部分代码理解

      将存储器中的数组发送至串口,因此设置外设为非增量模式,而存储器为增量模式,因此存储器中发送数据后,指针增量会自动增加。

    typedef struct
    {
    	uint32_t DMA_PeripheralBaseAddr; //外设基地址
    	uint32_t DMA_MemoryBaseAddr; //存储器基地址
    	uint32_t DMA_DIR; //数据传输方向
    	uint32_t DMA_BufferSize; //通道传输数据量
    	uint32_t DMA_Peripherallnc;//外设增量模式
    	uint32_t DMA_MemoryInc; //存储器增量模式
    	uint32_t DMA_PeripheralDataSize; //外设数据宽度
    	uint32_t DMA_MemoryDataSize; //存储器数据宽度
    	uint32_t DMA_Mode; //模式:是否循环
    	uint32_t DMA_Priority; //优先级
    	uint32_tDMA_M2M; //是否存储器到存储器方式
    }DMA_ InitTypeDef;
    
    
    //本实例中使用的是非循环模式
    #define DMA_Mode_Circular                  ((uint32_t)0x00000020)
    #define DMA_Mode_Normal                    ((uint32_t)0x00000000)
    #define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Circular) || ((MODE) == DMA_Mode_Normal))
    
    //当通道配置为非循环模式时,传输结束后(即传输计数变为0)将不再产生DMA操作
    //要开始新的DMA传输,需要在关闭DMA通道的情况下,在DMA_CNDTRx寄存器中重新写入传输数目。
    //因此有main函数里以下两行
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送      
    MYDMA_Enable(DMA1_Channel4);//开始一次DMA传输!(重新写入传输数目)	
    
    

      执行MYDMA_Enable(DMA1_Channel4);之后,由DMA控制系统总线进行数据传输,此时CPU会继续执行接下来的代码,即在DMA数据传输的过程进行读取数据的剩余量、点亮LED等操作。




    引用参考:
    正点原子教程
    https://blog.csdn.net/zhejfl/article/details/82555634
    https://www.cnblogs.com/cposture/p/4278801.html
    https://baike.baidu.com/item/DMA/2385376?fr=aladdin


      谢谢观看,如有错误还望指正!😁
      (疑问:DMA方式下,CPU是被挂起不工作,还是还能执行其他代码?)

    展开全文
  • 个人学习stm32 DMA_AD采集温度

    千次阅读 2016-10-26 17:19:11
    个人学习stm32 DMA_AD采集
    #include "advalue.h"
    #include "gpioconfig.h"
    #include "stm32f10x_dac.h"
    #include  "variable.h"




    extern  struct Flag flag;
    u32 getADValue[100]={0};
    u16 getdata [3]  ={1,2,3};
    static DMA_InitTypeDef DMA_InitStructure;
    static ADC_InitTypeDef ADC_InitStructure;




    void adc_init()
    {
        GPIO_InitTypeDef GPIO_InitStructure;  
       NVIC_InitTypeDef NVIC_InitStructure;  


     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // positive rotate signal input
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOC, &GPIO_InitStructure);  //in put
      

        //---------------------??AD???--------------------  
        //DMA1??1??  
        DMA_DeInit(DMA1_Channel1);  
        //????  
        DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)( &(ADC1->DR));  
        //????  
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)getADValue;  
        //dma??????  
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  
        //??DMA??????????  
        DMA_InitStructure.DMA_BufferSize = 20;  
        //??DMA???????,????  
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
        //??DMA???????  
        DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;   //    DMA_MemoryInc_Enable;  
        //??????  
        DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_Word;  
        //??????  
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 
        //??DMA?????:?????????  
        DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;          //DMA_Mode_Circular;  
        //??DMA?????  
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
        //??DMA?2?memory????????  
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);  
          
    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
        //????1  
        DMA_Cmd(DMA1_Channel1, ENABLE);  
      
        //ADC1??  
        //??????  
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  
        //????  
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;  
        //???? 
        ADC_InitStructure.ADC_ContinuousConvMode =ENABLE;  
        //??????  
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;  
        //?????  
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  
        //????????  
        ADC_InitStructure.ADC_NbrOfChannel = 1;  
        ADC_Init(ADC1, &ADC_InitStructure);  
       
        //????????  
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_71Cycles5);
        
          
        //??ADC1?DMA  
        ADC_DMACmd(ADC1, ENABLE);  
          
        //??ADC1  
        ADC_Cmd(ADC1, ENABLE);  
          
        //??ADC1???????    
        ADC_ResetCalibration(ADC1);  
        //?????????????  
        while(ADC_GetResetCalibrationStatus(ADC1));  
          
        //????  
        ADC_StartCalibration(ADC1);  
        //????????  
        while(ADC_GetCalibrationStatus(ADC1));  
           
        //??ADC1?????  
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);  


     /* Configure one bit for preemption priority */
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
      /* Enable DMA channel1 IRQ Channel */
     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
     


     

    }


    void DMA1_Channel1_IRQHandler(void)
    {
    if(DMA_GetITStatus(DMA1_IT_TC1))//??1??????
     {  
      DMA_ClearITPendingBit(DMA1_IT_GL1); //????????
    flag.DMA_GetOver=1;    
     }

    }


    展开全文
  • stm32 DMA初始化选项研究 DMA比较好用,也比较简单,今天在做多通道ADC“连续”“扫描”采样时,对DMA有了更深一点的认识,今天给大家分享下: #define ADC1_DR_Address ((uint32_t)0x4001244C) unsigned short ...
  • STM32 DMA详解

    千次阅读 2020-08-04 22:57:32
    本文根据STM32F207用户手册DMA章节翻译总结的DMA知识点
  • STM32DMA实验

    千次阅读 2018-09-18 22:34:02
    1.1STM32F4 DMA简介 DMA,全称Direct Memory Access ,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送的同类,能使...
  • 本程序实现STM32 DMA中断模式下ADC多通道数据采集,并经过简单的均值滤波,亲测可用。 若有错误之处,希望读者指出,大家共同学习,一起进步!
  • DMA寄存器版本DMA简介STM32DMA介绍DMA框图1.DMA请求2.通道3.仲裁器4.主要特性DMA通道配置过程DMA寄存器ending... DMA简介 1.DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬...
  • STM32 DMA使用详解

    万次阅读 多人点赞 2017-12-08 09:17:19
    DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧。下面用问答的形式表达我的思路。 DMA的定义直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许...
  • DMA是把一个地址的数据搬运到另外一个地址,所以它需要控制地址,这些地址在处理器内部是AHB和APB总线矩阵管理的,所以DMA必须要挂到AHB和APB上面,下图是ATMEL ARM9的DMA的框图: 下图是STM32F4XX的DMA内部的框图:...
  • STM32 DMA 学习笔记(一)

    千次阅读 2018-08-03 10:58:20
    一、功能介绍 DMA 传输将数据从一个地址空间复制到另外一个地址空间。...二、STM32DMA 含有两个通道,DMA1有7个通道,DMA2有5个通道。每一一个通道都可以连接一个外设。那么就有一个仲裁器,...
  • STM32 DMA配置

    千次阅读 2019-04-28 17:24:49
    大容量STM32产品集成了两个DMA,分别是DMA1和DMA2,。其中DMA1有7个通道,DMA2有5个通道,具体每个通道连接的外设可以参考STM32芯片的数据手册。 ②:通过DMA可以将数据在两个不同的地址之间进行传递,如存储器到...
  • 使用stm32 库文件通过DMA联立ADC实现三通道电压的连续采样和转换
  • STM32 DMA1 DMA2冲突???

    千次阅读 2020-02-15 17:14:14
    使用stm32F4的SPI2 DMA1更新LCD显示; 同时通过USART1 DMA2将显示数据发给上位机。 从stm32F4 总线矩阵看两者并无交叉(下图);但实际测试发现DMA2发送的串口数据乱码较多。 从图中标记看DMA2 DMA1 分别访问USART1...
  • STM32 DMA介绍

    2019-10-29 20:18:14
    DMA功能简介 DMA:Direct Memory Access,直接存储器存取,是一种大大减少CPU工作量的数据存取方式,被广泛的使用。 在硬件系统中,主要由CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常在内存和与外设...
  • STM32 DMA加串口空闲中断接收数据

    千次阅读 2019-12-27 10:42:47
    STM32使用DMA加串口空闲中断接收数据 STM32中,需要用串口接收数据,是使用串口中断来接收数据。但是用这种方法的话,就要频繁进入串口中断,然后处理,效率就比较低。于是就想到用DMA来接收串口数据,这个STM32...
  • STM32 DMA flag definitions 的含义

    千次阅读 2018-10-11 17:08:58
    STM32F429使用HAL库实现DMA发送UART串口数据时的代码如下: MYDMA_USART_Transmit(&amp;UART1_Handler,(uint8_t*)tx,i);//启动DMA传输方式 while(!__HAL_DMA_GET_FLAG(&amp;UART1TxDMA_Ha...
  • STM32 DMA 自我学习 简单总结

    千次阅读 2014-11-03 22:00:45
    简单记录一下STM32DMA
  • stm32 DMA步进电机控制

    千次阅读 2017-07-28 15:44:40
    刚好stm32的定时器的DMA不占用cpu资源,可以克服这个缺点。 步进电机控制原理 给步进电机发一个脉冲(一个高电平,一个低电平),步进电机走一个步距角。步进电机的控制的基本需求:运行速度。运行速度取决于电机...
  • STM32 DMA通道一览及其配置

    千次阅读 2019-10-12 17:04:21
    DMA通道一览 DMA1通道 DMA2通道 DMA内容详解 DMA的定义 直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统...
  • STM32 DMA->内存到内存

    千次阅读 2016-02-03 15:22:28
    基于STM32 F401 Discovery板: DMA2在AHB1总线上 步骤一:使能DMA #define DMA_STREAM_CLOCK RCC_AHB1Periph_DMA2 RCC_AHB1PeriphClockCmd(DMA_STREAM_CLOCK, ENABLE);步骤二:reset DMA Stream ...
  • STM32 DMA 疑问解答

    千次阅读 2016-08-24 10:22:57
    1 DMA怎么知道外设接收缓冲区有新的数据到来?  也就是外设怎么通知DMA接收缓冲区有新的数据了?  比如SPI接收的数据,通过DMA搬运到内存里面,DMA怎么知道SPI的缓冲区里面有新的数据到来 解答:在SPI的寄存器...
  • STM32 DMA正常模式等待传输完成和开始下一次传输 2017-07-01 12:01 461人阅读 评论(0) 收藏 举报  分类: stm32&stm8(42)  版权声明:本文为博主原创文章,未经博主允许不得转载。 ...
  • STM32 DMA工作原理

    千次阅读 2019-08-01 16:03:54
    DMA工作原理 DMA介绍 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个DMA控制器有12个...
  • STM32 DMA的特性

    2017-06-10 21:42:51
    STM32DMA特性:  ·每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通多软件来配置。  ·在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相等...
  • 1.打开STM32cubemx,我的版本号是4.27.0,新建工程,选择芯片,例如STM32F103R8T6 2.左侧使能串口1,sys那里选择serial wire,否则导致后面无法下载程序,配置时钟 3.在configuration页面配置DMA,如下所示 4.点击生成...
  • STM32 DMA buffersize理解

    万次阅读 多人点赞 2017-02-22 23:24:58
    DMA buffersize理解

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,335
精华内容 6,534
关键字:

stm32dma