STM32的ADC DMA USART综合学习

发布者:chunying最新更新时间:2016-10-08 来源: eefocus关键字:STM32  ADC  DMA  USART 手机看文章 扫描二维码
随时随地手机看文章
学习STM32的ADC转换,在开发板上写程序调试。

四个任务:

1.AD以中断方式(单次)采集一路

2.AD以中断方式连续采集四路

3.AD以DMA方式采集一路,DMA深度为一级

4.AD以DMA方式采集四路,每路DMA深度为28级,并滤波,说明滤波原理。

总结:

第一个任务:ADC以中断方式采集一路ADC,通过配置ADC_InitStructure结构体中的ADC_ScanConvMode,它规定模数转换工作在扫描模式(多通道)还是单次模式(单通道),

ADC_InitStructure.ADC_ScanConvMode=DISABLE,为单通道单次模式。

ADC_ContinuousConvMode,定转换是连续还是单次,ADC_ContinuousConvMode=DISABLE

为单次,ADC_NbrOfChangnel规定ADC规则转换的通道数。ADC_NbrOfChannel=1;//开启1个通道数。

ADC_RegularChannelConfig(ADC1,ADC_Channel_13, 1,ADC_SampleTime_55Cycles5);设置指定规则组的通道的采样顺序和转换时间。这里以为只有一路通道,采用的是PC3引脚,对应的通道数是13通道,采样顺序也就是1,。

ADC_Cmd(ADC1,ENABLE);使能ADC

ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);开启ADC转换结束中断。

ADC_ResetCalibration(ADC1);//重置校验寄存器

while(ADC_GetResetCalibrationStatus(ADC1));  //等待重置校验成功

ADC_StartCalibration(ADC1);//开始ADC校验

while(ADC_GetCalibrationStatus(ADC1));//等待ADC校验好

ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发开始转换

因为ADC有一个16位的规则组数据寄存器(ADC_DR),采用一路转换时可以不用通过DMA传输。这里就没有配置DMA。

void ADC_IRQHandler(void)

{

       ADCConvertedValue=ADC_GetConversionValue(ADC1); 

       ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);            

}

当一次转换结束,DAC产生中断,在中断函数里,读取ADC_DR寄存器中的值,一定清除中断标志位。

采集出来的数据是16进制数,要经过处理,变成10进制数,具体如下:

(value*100/4096)*33,value是从寄存器读出来的十六进制的数据,经过此变换后就变成10进制数,是个整数,我们通过串口显示的时候要把小树部分也要显示出来则有:((value*100/4096)*33)/1000,整数部分。

((value*100/4096)*33)%1000/100,((value*100/4096)*33)%100/10),小数部分,

串口配置,我是通过STM32上的串口1与PC机通讯的,具体配置如下:

void USART_Configuration(void)

{

       USART_InitTypeDef USART_InitStructure;

       USART_InitStructure.USART_BaudRate=9600;波特率9600

      USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位数据位

      USART_InitStructure.USART_StopBits=USART_StopBits_1;1个停止位

      USART_InitStructure.USART_Parity=USART_Parity_No;无奇偶校验

      USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

       USART_Init(USART1,&USART_InitStructure);初始化串口配置

       USART_Cmd(USART1,ENABLE);使能串口

}

int fputc(int ch,FILE *f)

{

       USART_SendData(USART1, (u8)ch);

       while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)//检查发送是否完成

       {

       }

       return ch;

}此函数,是把printf输出函数定向到USART。

第一个任务大概就是这个过程,在后面的任务有相同之处,就不重复叙述了。

第二个任务:ADC以中断方式连续采集四路。

首先配置4路模拟输入,我配置的是PC0、PC1、PC2、PC3四个IO口,输入方式为模拟输入,速度采用2M,它们对应的ADC通道分别是10、11、12、13通道。

在第一个任务说了,ADC规则转换多路采样时,ADC的数据寄存器只有一个16位寄存器,所以必须采用DMA来传输数据,DMA配置如下:

DMA_InitStructure.DMA_PeripheralBaseAddr=DR_ADDRESS; //DMA对应的外设基地址

DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&Buf; //内存存储基地址,定义的一个数组

DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //DMA转换模式为SRC模式,由外设搬移到内存

DMA_InitStructure.DMA_BufferSize=4; // DMA缓存大小,4个(设置DMA在传输时缓冲区的长度)

DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移(设置DMA的外设递增模式)

DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //关闭接收一次数据后,目标内存地址后移(设置DMA的内存递增模式)

DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//定义外设数据长度

DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;

//循环模式开启,Buf写满后,自动回到初始地址开始传输

DMA_InitStructure.DMA_Priority=DMA_Priority_High;//优先级高

DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;

ADC配置:

//ADC配置

       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外部开关,关闭状态

      ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//对齐方式,右对齐方式

      ADC_InitStructure.ADC_NbrOfChannel=4;//开启通道数,4个

       ADC_Init(ADC1,&ADC_InitStructure);//初始化ADC

       ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5);

       ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_55Cycles5);

       ADC_RegularChannelConfig(ADC1, ADC_Channel_12,3,ADC_SampleTime_55Cycles5);

       ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_55Cycles5);;

       //ADC通道组,第10、11、12、13个通道,采样顺序分别是1,2,3,4转换时间55.5个周期

       ADC_DMACmd(ADC1, ENABLE);//使能ADC1模块DMA

       ADC_Cmd(ADC1, ENABLE);//打开ADC1

       ADC_ResetCalibration(ADC1);//重置ADC1校准寄存器

       while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校准重置完成

       ADC_StartCalibration(ADC1);//开始ADC1校准

       while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校准完成

       ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1软件开始转换

中断是采用DMA中断,当DMA第一轮传输结束时,设一个标志位,当标志位为1时,表明第一轮转化和传输完成,此时就可以读取数组中的数据,经过处理就可以通过串口显示出来。

void DMAChannel1_IRQHandler(void)

{          

              ADC_DMA_OK=1;

              DMA_ClearITPendingBit(DMA1_IT_TC1);              

}中断函数。

第二个任务大概就这样子。

第三个任务:AD以DMA方式采集一路,DMA深度为一级。

这个任务不难,关键要理解到DMA深度,用自己的语言来理解哈DMA深度吧,当ADC以一路采集时,ADC转换完成就自动把转换结果通过DMA传给目的地址,如果传输一次结束DMA就产生中断的话,DMA的深度就为一级,如果连续传输N次,DMA的深度就位N级,当然这个N是又范围的,因为受目的地址的内存大小控制和数据宽度,这个大家应该豆明白的。

这个任务在第一个任务的基础上我通过DMA传输,意思是AD配置没什么区别。DMA配置和第二个任务的区别就是DMA_BufferSize的宽度不同。

#define  DR_ADDRESS   (u32)0x4001244c  ADC的地址

#define  DMA_Count    1   DMA深度,也就是连续传输的次数

#define  ADC_Channle  1  ADC通道

数据处理和串口通讯这里不重复叙述。DMA中断和任务二的类似。

第四个任务:AD以DMA方式采集四路,每路DMA深度为128级,并滤波,说明滤波原理。

这个任务和是个综合性任务,只要弄懂前面三个任务,难点是再如何滤波,开始的时候我也不知道怎么滤波,同事提醒我才知道怎么滤波的,我大概说哈我的理解,把四路通道采集的数据分别放到四个数组中,然后给他来个排序,降序,升序都行,把首位两个数丢掉,然后加起来求平均值。但是我这里因为DMA的深度为128级,也就是四个通道分别采样了128次,大家都知道,数据越多,求平均值就越准确,所以我就没有采用什么排序法了,直接给他们分别求平均值,具体如下:

#define  DR_ADDRESS   (u32)0x4001244c  ADC的地址

#define  DMA_Count    128   DMA深度,也就是连续传输的次数

#define  ADC_Channle  4  ADC通道

       for(i=0;i<(ADC_Channle*DMA_Count);i+=4)

                     {                  

                            Value1[j]=Buf[i+0];

                            Sum1+=Value1[j];                      

                            Value2[j]=Buf[i+1];

                            Sum2+=Value2[j];                      

                            Value3[j]=Buf[i+2];

                            Sum3+=Value3[j];

                            Value4[j]=Buf[i+3];

                            Sum4+=Value4[j];

                            j++;

                     }           

              Valu1=Sum1/DMA_Count;

              Valu2=Sum2/DMA_Count;

              Valu3=Sum3/DMA_Count;

              Valu4=Sum4/DMA_Count;

              Delay(100000);     

              printf("\r\n当前AD_0值:0x%x,电压值:%d.%d%dV\n\r",

              Valu1,((Valu1*100/4096)*33)/1000,((Valu1*100/4096)*33)%1000/100,((Valu1*100/4096)*33)%100/10);

              Delay(100000);

              printf("\r\n当前AD_1值:0x%x,电压值:%d.%d%dV\n\r",

              Valu2,((Valu2*100/4096)*33)/1000,((Valu2*100/4096)*33)%1000/100,((Valu2*100/4096)*33)%100/10);

              Delay(100000);

              printf("\r\n当前AD_2值:0x%x,电压值:%d.%d%dV\n\r",

              Valu3,((Valu3*100/4096)*33)/1000,((Valu3*100/4096)*33)%1000/100,((Valu3*100/4096)*33)%100/10);

              Delay(100000);

              printf("\r\n当前AD_3值:0x%x,电压值:%d.%d%dV\n\r",

              Valu4,((Valu4*100/4096)*33)/1000,((Valu4*100/4096)*33)%1000/100,((Valu4*100/4096)*33)%100/10);

              Delay(100000);

关于ADC配置和DMA配置这里不重复叙述了。

关键字:STM32  ADC  DMA  USART 引用地址:STM32的ADC DMA USART综合学习

上一篇:S3C2440外部中断详解
下一篇:STM32 定时器产生PWM彻底应用

推荐阅读最新更新时间:2024-03-16 15:14

stm32 库文件_line 函数
定义   内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是否能形成内联函数,需要看编译器对该函数定义的具体处理。 动机   内联扩展是用来消除函数调用时的时间开销。它通常用于频繁执行的函数。 一个小内存空间的函数非常受益。 如果没有内联函数,编译器可以决定哪些函数内联 。 程序员很少或没有控制哪些职能是内联的,哪些不是。 给这种控制程度,作用是程序员可以选择内联的特定应用 。 函数内联问题   除了相关的问题, 内联扩展一般,语言功能作为一个内联函数可能不被视为有价值的,因为它们出现的原因,对于一个数字:
[单片机]
美信推出推出MAX11102系列系列低功耗ADC
Maxim最新推出的ADC系列产品功耗仅为9.9mW,工作电压可低至2.2V,提供突发工作模式,可最大程度地降低功耗。 该系列ADC可降低32%的功耗,有效延长电池使用寿命 SUNNYVALE,CA,2010年6月28日。Maxim Integrated Products (NASDAQ:MXIM)扩展业内领先的12/10/8位ADC产品线,推出 MAX11102 系列低功耗ADC。该系列产品共包含9款器件,分别具有不同的分辨率(12/10/8位)、通道数(2/1)和转换速率(3/2Msps)。器件的最大功耗仅为9.9mW,比竞争方案低32%,可有效延长便携式电子产品的电池使用寿命。此外,该系列ADC也是同类产品中仅有的能
[模拟电子]
STM32 TIM触发ADC 定时采样-笔记
用TIM3的update触发adc,只需勾选Internal clock就可以了 ADC设置,关键是选TIM3 TRIGGER OUT TIM3 设置时间间隔然后关键选Update event 程序代码 记得开启TIM3 HAL_ADCEx_Calibration_Start(&hadc1); //STM32F1 HAL_TIM_Base_Start(&htim3); HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_Value,1024); 然后重写callback 函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* h
[单片机]
<font color='red'>STM32</font> TIM触发<font color='red'>ADC</font> 定时采样-笔记
利用高速信号链提高医学成像质量的研究
  与所有非常依赖科技进步的行业一样,医学成像设备厂商不得不持续改进他们的产品——主要是改进系统的成像质量。无论是超声波反射声波、核磁共振成像 (MRI) 磁场扰动还是正电子发射断层成像 (PET) 的正电子发射,大多数医学成像技术均需要患者信号接收传感器阵列。提高成像质量的最直接方法就是扩大传感器阵列规模。但是由于为设备添加了更多的传感器,因此将信号传输至处理引擎的信号链就必须增加电子器件。   与此同时,厂商还必须提高其系统标准,包括特定电子组件的尺寸、功耗以及性能。系统某一方面的性能增强也许会给其他方面带来挑战。仅仅增加传感器和信号链,可能会引发包括系统尺寸及功耗增大在内的不利影响。但是,用于医学成像系统的最新一代信号链组
[医疗电子]
STM32外设寄存器简介及简单用法
STM32外设有哪些? 外设指的是单片机外部的外围功能模块,比如键盘控制芯片,液晶,A/D转换芯片,等等。外设可通过单片机的I/O,SPI,I2C等总线控制。 Smt32外设有以下几类寄存器: 1. 控制寄存器CR:配置、控制相应外设工作方式 2. 数据寄存器DR:存储外设进行输入输出的数据 3. 状态寄存器SR:存储当前外设的运行状态(标准位,状态位) 控制寄存器CR结构体初始化代码: 1. GPIO_initTypedef用来配置GPIO 2. NVIC_InitTypedef配置NVIC 3. EXTI_InitTypede配置EXTI 4. USART_InitTypede配置USART 控制寄存器使用库初始化外设
[单片机]
理解STM32的中断优先级
STM32提供68个中断通道,每一个中断通道对应一个中断源,这里的中断源是指引发中断的外设(例如,I2C,UART,EXTI等等)。每一个中断源又可以包括多种中断发生情况,例如UART发送数据完毕,接收到数据等情况均可能引起UART中断源向STM32内核提出中断处理请求。 STM32的中断优先级可以分为抢占式优先级和非抢占式优先级控制两部分。 为了符合COTEX-M3标准,STM32的中断源优先级寄存器采用8位的方式存储,但是只是用了高4位,低4位保留未用。高4位又被分为了两段:抢占式优先级控制段和非抢占式优先级控制段。STM32提供了一个函数 NVIC_PriorityGroupConfig(NVIC_PriorityGrou
[单片机]
基于ARM处理器的HDLC通信的DMA实现
    摘要: 以ARM7TDMI为内核的Samsung公司S3C4510B网络微控制器(Networking MCU)为基础,重点论述如何通过DMA(直接内存访问)方式实现HDLC通信。对软件设计中缓冲描述符、DMA状态配置和控制、ISR服务程序设计以及相关的硬件配置进行详细的描述,并讨论如何编写在操作系统下的驱动程序。     关键词: HDLC 缓冲描述符 循环链表 中断服务程序 DMA 目前在嵌入式产品开发设计中,通常是在OS(Operating System)厂商提供的BSP基础上进行开发工作;对于底层硬件的操作,程序设计人员很少关注或只是少量的修改。实际上很多产品,我们完全可以
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • Linux内核移植
    实验步骤:(1)准备工作(2)修改顶层Makefile(3)修改falsh 分区(4)配置编译内核下面以Linux2 6 30 4内核移植到gec2440为例:一、准备 ...
  • S5PV210 PWM定时器
    第一节 S5PV210的PWM定时器S5PV210共有5个32bit的PWM定时器,其中定时器0、1、2、3有PWM功能,定时器4没有输出引脚。PWM定时器使用PCLK_PS ...
  • S5PV210 NAND Flash
    NAND Flash关于NAND FlashS5PV210的NAND Flash控制器有如下特点:1) 支持512byte,2k,4k,8k的页大小2) 通过各种软件模式来进行NAND Fl ...
  • S5PV210串口
    串口设置之输入输出字符S5PV210 UART相关说明 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它用来 ...
  • S5PV210按键控制LED
    原理图如图所示:查询用户手册得到:程序例子:(完整代码见“代码下载链接”)1、轮询的方式查询按键事件 *main c* 核心代码如下:while(1 ...
  • S5PV210控制蜂鸣器
  • S5PV210的启动过程
  • S5PV210点亮LED
  • S5PV210启动过程详解
何立民专栏 单片机及嵌入式宝典

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

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