STM32f103的数电采集电路的DMA设计和使用优化程序

2017-09-12 15:34:35编辑:什么鱼 关键字:STM32f103  数电采集  DMA

DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。

DMA设置的一般步骤可以总结为如下几个步骤:

1.DMA时钟使能

2.DMA设置复位

3.设置DMA基地址,内存地址,输出方向参数

4.设置DMA数据大小,优先级,使用通道参数

5.DMA工作方式初始化

6.使能DMA

7.编写中断处理函数

 

前端采集模块的DMA使用主要用于ADC采集结果的传输和USART串口的数据发送传输。根据《stm32中文参考手册》的DMA请求一览表,选用了DMA1的通道1作为ADC1的数据传输通道,以及DMA1通道4作为和USART串口的数据发送传输通道。此处采用了单个DMA复用多通道的设计,是因为DMA速度足以完成这些任务,而且留下其他DMA资源以便项目以后可以扩展,达到节省资源的目的。


USART使用DMA发送数据配置和使能代码


  1. //DMA1的各通道配置  

  2. //这里的传输形式是固定的,这点要根据不同的情况来修改  

  3. //从存储器->外设模式/8位数据宽度/存储器增量模式  

  4. //DMA_CHx:DMA通道CHx  

  5. //cpar:外设地址  

  6. //cmar:存储器地址  

  7. //cndtr:数据传输量   

  8. void DMA_USART_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)  

  9. {  

  10.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输  

  11.       

  12.   DMA_DeInit(DMA_CHx);   //将DMA的通道1寄存器重设为缺省值  

  13.     DMA1_MEM_LEN=cndtr;  

  14.     DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //DMA外设ADC基地址  

  15.     DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //DMA内存基地址  

  16.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设  

  17.     DMA_InitStructure.DMA_BufferSize = cndtr;  //DMA通道的DMA缓存的大小  

  18.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变  

  19.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增  

  20.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位  

  21.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位  

  22.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式  

  23.     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级   

  24.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输  

  25.     DMA_Init(DMA_CHx, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器  

  26.           

  27. }   

  28. //开启一次DMA传输  

  29. void DMA_USART_Enable(DMA_Channel_TypeDef*DMA_CHx)  

  30. {   

  31.     DMA_Cmd(DMA_CHx, DISABLE );  //关闭USART1 TX DMA1 所指示的通道        

  32.     DMA_SetCurrDataCounter(DMA_CHx, DMA1_MEM_LEN);//DMA通道的DMA缓存的大小  

  33.     DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1 所指示的通道   

  34. }       


ADC使用DMA传送多通道数据配置和使能代码

  1. //DMA1的各通道配置  

  2. //这里的传输形式是固定的,这点要根据不同的情况来修改  

  3. //从存储器->外设模式/8位数据宽度/存储器增量模式  

  4. //DMA_CHx:DMA通道CHx  

  5. //cpar:外设地址  

  6. //cmar:存储器地址  

  7. //cndtr:数据传输量   

  8. void DMA_ADC_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)  

  9. {  

  10.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输  

  11.       

  12.     DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值  

  13.     DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址  

  14.     DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址  

  15.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地  

  16.     DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小  

  17.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变  

  18.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增  

  19.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位  

  20.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位  

  21.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式  

  22.     DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级  

  23.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输  

  24.     DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道  

  25.   

  26. }  

  27.   

  28. //开启一次DMA传输  

  29. void DMA_ADC_Enable(DMA_Channel_TypeDef*DMA_CHx)  

  30. {   

  31.     DMA_Cmd(DMA_CHx, DISABLE );  //关闭USART1 TX DMA1 所指示的通道  

  32.     DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1 所指示的通道   

  33. }  


这里需要注意的是USART使用DMA发送数据需要每一次都重新使能,即每发送一次数据使能一下。


而ADC使用DMA传送多通道数据则只需要使能一次就可以自动循环工作,只需从数组空间读取ADC数据。


关键字:STM32f103  数电采集  DMA

来源: eefocus 引用地址:http://www.eeworld.com.cn/mcu/article_2017091234390.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32f103的数电采集电路的USART的使用与蓝牙的连接的程序
下一篇:STM32f103的数电采集电路的ADC多通道采集程序

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32F407学习笔记——GPIO_按键控制LED亮灭

#include <stm32f4xx.h>#include "stm32f4xx_conf.h"#include "delay.h" GPIO_TypeDef* io_led=GPIOC;//定义一个指向结构体GPIO_TypeDef的io_led  const u16 pin_led=GPIO_Pin_1;//引脚GPIO_TypeDef* io_key=GPIOC;const u16 pin_key=GPIO_Pin_0; void Led_Init(){ GPIO_InitTypeDef GPIO_init_l;//用于初始化的结构体
发表于 2018-07-21 11:07:23

【stm32f407】外部中断实现按键中断方式

一.外部中断STM32F4的每个IO都可以作为外部中断的中断输入口,这点也是STM32F4的强大之处。STM32F407的中断控制器支持22个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F407的22个外部中断为:EXTI线0~15:对应外部IO口的输入中断。EXTI线16:连接到PVD输出。EXTI线17:连接到RTC闹钟事件。EXTI线18:连接到USB OTG FS唤醒事件。EXTI线19:连接到以太网唤醒事件。EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。EXTI线21:连接到RTC入侵和时间戳事件。EXTI线22:连接到RTC唤醒事件。从上面可以看出
发表于 2018-07-20 21:14:56

STM32F103的SysTick使用方法

写下来,方便以后用。void SysTick_Configuration(void){  /* Setup SysTick Timer for 10 msec interrupts  */  if (SysTick_Config(SystemCoreClock / 100))                //SysTick配置函数  {     /* Capture error */ 
发表于 2018-07-20 21:06:43

STM32F407ZGT6使用Systic定时器实现延时

预备知识        STM32F4的系统滴答计时器的介绍及其说明。时间有限,这里点到为止,详情自行百度。        延时的原理:                        因为在 ucos 下 systick 不能再被随意更改,如果我们还想利用 systick 来做
发表于 2018-07-20 20:21:48

STM32F072在8M下的软件延时

    使用定时器产生的延时精度确实是高,但是也相对麻烦,软件延时虽然精度不高,但也相对简单,使用方便,在精度要求不高的情况的可以使用。                使用的是STM32F032 Nucleo开发板,为内部8M晶振。    以下延时函数用示波器测得,精度小于1us。//STM32F072RB Nucleo//在内部晶振为8M的情况下 void delay3us()//3us{ int i; for(i=0;i<1;i++);} void delay10us()//10us
发表于 2018-07-20 20:21:10

Stm32f01x_SysTick定时器_延时功能

;stm32f10x.h>#include <sys.h>//配置systick 寄存器void SysTick_Configuration(void) { SysTick->VAL = 0;  SysTick->LOAD = (72000000/8000000)*1000;//´ú±íÿ¸ömsÐèÒªµÄ9000¸ösystickʱÖÓÊý SysTick->CTRL |= 0x06;  } //中断处理函数void SysTick_Handler(void) //???? { extern unsigned
发表于 2018-07-20 20:01:49

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved