STM32L051电阻分压ADC电量采集

合集下载

stm32 adc例程

stm32 adc例程

stm32 adc例程STM32 ADC例程是指在STM32微控制器上使用ADC(模拟数字转换器)进行电压检测的实例程序。

这个例程是非常有用的,因为它可以帮助开发人员更好地理解和掌握STM32微控制器的ADC功能。

要运行STM32 ADC例程,您需要掌握以下一些基本概念:1. ADC初始化:首先要初始化ADC接口,以便将其配置为所需的状态。

2. ADC输入通道选择:ADC能够接收多个不同的输入通道,因此需要选择要使用的通道。

3. ADC采样时间:ADC采样时间会影响输出结果的准确性。

采样时间越短,准确性越高。

4. ADC转换速率:ADC转换速率指的是系统每秒钟执行的转换次数。

通常,较快的转换速率可能会影响ADC准确性。

在运行STM32 ADC例程之前,您需要确认您的硬件环境已经全部搭建完毕。

接下来,您可以按照如下步骤进行操作:1. 配置ADC:首先,您需要选择要使用的ADC以及所希望的采样时间和转换速率。

此外,还需要配置其他参数,例如参考电压和校准方式。

2. 配置输入通道:然后,您需要选择要使用的输入通道。

通道的选择应基于测量需求。

例如,如果您需要测量电池电压,则需要选择与电池相关的通道。

选择通道后,还需要配置其他通道参数,例如增益和偏置。

3. 启动ADC:当您完成ADC配置和通道选择后,就可以启动ADC并开始转换电压信号。

转换结果将以数字格式保存在数据寄存器中。

4. 处理数据: 在ADC执行完转换之后,您将需要处理所获得的数据。

如果您想要可视化或记录数据,您可以使用串口或者其他通信接口将数据输出到计算机或者其他处理设备上。

如果您想要对数据进行实时处理,则可以使用GPIO控制器或其他外设对数据进行处理。

5. 停止ADC: 当您完成所需测量或转换后,您可以停止ADC并将其配置回最初的状态。

综上,STM32 ADC例程作为一款非常实用的程序,可以帮助开发者更好地掌握STM32的ADC功能。

通过了解和应用该例程,开发人员可以更加准确地测量电压波形,有利于设计和优化各种电子系统。

stm32 adc工作原理

stm32 adc工作原理

stm32 adc工作原理
STM32 ADC工作原理
STM32微控制器的ADC(模拟数字转换器)模块可以将模拟
信号转换为数字信号。

ADC是一种重要的外设,用于从外部
传感器或其他模拟源获取数据。

ADC模块的工作包括采样、保持、量化和序列转换等过程。

首先,ADC模块会接收来自外部模拟信号的输入。

这些信号
可以是来自温度传感器、光敏电阻或其他传感器的模拟信号。

接下来,ADC模块会将输入信号通过采样和保持电路进行采样。

采样是指将模拟信号转换为相应的电压值。

保持电路将输入信号的电压保持在一个稳定的水平上,以便进行后续的处理。

然后,ADC模块将采样和保持的电压值进行量化。

量化是指
将连续的模拟信号转换为离散的数字信息。

ADC模块使用一
定的分辨率来表示模拟信号,例如12位或16位。

最后,ADC模块将量化后的数字信息通过序列转换器进行处理。

序列转换器将多个信道的数字信息按照一定的顺序进行转换和存储。

转换的结果可以存储在寄存器中供CPU读取,或
者被DMA直接传输到内存中。

总结来说,STM32 ADC工作原理包括采样、保持、量化和序
列转换等步骤,将外部模拟信号转换为数字信息,以供微控制器进行进一步处理和分析。

单片机adc 内部电压校准

单片机adc 内部电压校准

单片机adc 内部电压校准
单片机ADC内部电压校准主要是为了消除由于制造工艺、温度、电源电压等因素的影响,导致ADC转换精度降低的问题。

一般来说,STM32的ADC校准分为参考电压校准和增益校准。

参考电压校准的过程通常如下:首先测量ADC参考电压的实际值,然后将该值与预设的参考电压进行比较,得到参考电压的偏差,最终通过校准将其校正。

例如,对于STM32L051单片机,内部基准电压存放在0x1FF80078这个地址。

可以通过读取这个地址的值来获取内部基准电压的实际采样值,然后与标准3v的基准电压进行比较,从而进行校准。

如果ADC具有集成PGA,则内部产生的电压通常是ADC的基准电压除以PGA的选定增益,以避免ADC过量程。

这允许器件在每个增益设置下支持内部满量程校准。

具有校准功能的ADC通常重复一定次数(例如16次)的零电平和满量程测量,并平均转换结果以计算校准。

总的来说,单片机ADC内部电压校准是一个重要步骤,它能确保ADC转换的准确性,从而提高整个单片机系统的性能和稳定性。

STM32系列ADC采样频率及相应时间的确定

STM32系列ADC采样频率及相应时间的确定

STM32系列ADC采样频率及相应时间的确定一、采样频率的确定1.首先确定ADC 的时钟,这里需要看你的RCC的设置。

在采用固件库的基础上,设定ADC的采样频率相对来说是很容易的。

(1)由时钟控制器提供的ADCCLK 时钟和PCLK2(APB2 时钟)同步。

CLK 控制器为ADC 时钟提供一个专用的可编程预分频器。

(2) 一般情况下在程序中将 PCLK2 时钟设为与系统时钟相同RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK2Config(RCC_HCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);(3)在时钟配置寄存器(RCC_CFGR) 中有为ADC 时钟提供一个专用的可编程预分器位15:14 ADCPRE:ADC预分频由软件设置来确定ADC时钟频率00:PCLK2 2分频后作为ADC时钟01:PCLK2 4分频后作为ADC时钟10:PCLK2 6分频后作为ADC时钟11:PCLK2 8分频后作为ADC时钟我们可对其进行设置例如:RCC_ADCCLKConfig(RCC_PCLK2_Div4);另外还有 ADC 时钟使能设置RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |RCC_APB2Periph_GPIOC, ENABLE);(4)采样时间和转换时间ADC 使用若干个ADC_CLK 周期对输入电压采样,采样周期数目可以通过ADC_SMPR1 和ADC_SMPR2 寄存器中的SMP[2:0]位而更改。

每个通道可以以不同的时间采样。

总转换时间如下计算:TCONV = 采样时间+ 12.5 个周期例如:当ADCCLK=36MHz 和239.5 周期的采样时间TCONV = 239.5 + 12.5 = 252周期= 7μs若你采样的是1KHz的正弦波信号,采样了10000个点,则其中就有70个周期。

实验六ADC数据采集实验

实验六ADC数据采集实验

实验六 ADC数据采集实验一、实验目的了解AD转换的基础知识,学习了基于DMA专递方式的ADC采集软件的编制及控制流程。

二、实验内容板子加电后,通过串口1延时间隔显示ADC1的通道11的测量结果。

三、实验仪器、设备计算机、开发板、keil软件四、应用知识用到的几处需要关注的知识:DMA:在这个例程用到了ADC转换结果采用DMA传递方式。

直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

无须CPU任何干预,通过DMA 数据可以快速地移动。

这就节省了CPU的资源来做其他操作。

ADC规则组:STM32的ADC通道选择有两种方式,一种是规则组,一种是注入组,简单来讲就是规则组设置后,可以按照设置的通道顺序对各通道进行依次采集。

方便于对多路ADC通道的自动采集。

注入组最多设置4个通道,简单来讲就是需要触发才能采集设置的通道ADC值。

本实验选择了采用规则组,设置了一个通道进行自动采集。

五、程序设计根据任务要求,程序内容主要包括:1. 初始化串口1,用于ADC1通道11采集值的输出显示。

2. ADC1通道11的初始化配置。

3. 间隔时间将采集到的ADC值通过串口1发送出去。

整个工程包含4类源文件:FWLIB--stm32f10x_gpio.c ST公司的标准库,包含了关于对通用IO口设置的函数。

stm32f10x_rcc.c ST公司的标准库,包含了关于对系统时钟设置的函数。

stm32f10x_dma.c ST公司的标准库,包含了关于对于DMA设置的函数。

stm32f10x_adc.c ST公司的标准库,包含了和ADC有关的函数。

stm32f10x_USART.c ST公司的标准库,包含了关于对USART设置的函数。

Misc.c ST公司的标准库,包含了关于中断设置的函数。

CMSYS—是关于CORETEX-M3平台的系统函数及定义USER—main.c 例程的主函数。

主函数如下:RCC_Configuration(void)用于配置系统时钟设置,及外设时钟使能。

STM32实现双通道ADC采集电压电流值

STM32实现双通道ADC采集电压电流值

STM32实现双通道ADC采集电压电流值本次的实验是通过配置DMA来获取ADC采集到的数据的。

软件实现如下: adc.c⽂件#include "adc.h"#define ADC1_DR_Address ((u32)0x40012400+0x4c) //定义ADC1地址volatile uint16_t ADCConvertedValue[2]; //定义内存地址数组float AD_Value[2];static void ADC1_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStructure;/* Enable ADC1 and GPIOC clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);/* Configure PC.01 as analog input */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOB, &GPIO_InitStructure); // PB0,PB1 ,输⼊时不⽤设置速率}static void ADC1_DMA_Config(void){DMA_InitTypeDef DMA_InitStructure;/* DMA channel1 configuration */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA传输DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR); //ADC地址DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADCConvertedValue; //内存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = 2;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址不固定DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环传输DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel1, &DMA_InitStructure);}static void ADC1_Config(void){/* ADC1 configuration */ADC_InitTypeDef ADC_InitStructure;ADC_DeInit(ADC1);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //使能ADC1时钟ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独⽴ADC模式ADC_InitStructure.ADC_ScanConvMode = ENABLE; //启动扫描模式,扫描模式⽤于多通道采集ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式,即不停地进⾏ADC转换ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使⽤外部触发转换ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 2; //要转换的通道数⽬2ADC_Init(ADC1, &ADC_InitStructure);/*配置ADC时钟,为PCLK2的6分频,即12Hz*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);/*配置ADC1的通道8,9为239.5个采样周期,序列为1,2*/ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1 , ADC_SampleTime_239Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 2 , ADC_SampleTime_239Cycles5);/* Enable ADC1 DMA */ADC_DMACmd(ADC1, ENABLE);/* Enable ADC1 */ADC_Cmd(ADC1, ENABLE);/*复位校准寄存器 */ADC_ResetCalibration(ADC1);/*等待校准寄存器复位完成 */while(ADC_GetResetCalibrationStatus(ADC1));/* ADC校准 */ADC_StartCalibration(ADC1);/* 等待校准完成*/while(ADC_GetCalibrationStatus(ADC1));}void adc1_start(void){ADC_SoftwareStartConvCmd(ADC1, ENABLE); //ADC1软计启动DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道1}void ADC1_Init(void){ADC1_GPIO_Config();ADC1_DMA_Config();ADC1_Config();}adc.h⽂件#ifndef __ADC_H#define __ADC_H#include <stm32f10x.h>void ADC1_Init(void);void adc1_start(void);#endif /*ADC_H*/main.c⽂件#include "adc.h"extern volatile uint16_t ADCConvertedValue[2]; //定义内存地址数组extern float AD_Value[2];int main(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级组为组2,2位抢占优先级,2位响应优先级 USART1_Int(); //串⼝初始化ADC1_Init(); //ADC1初始化adc1_start();SysTick_Init(); //系统时钟初始化while(1){ AD_Value[0]=(float)ADCConvertedValue[0]/4096*3.3; //获取电压值 AD_Value[1]=(float)ADCConvertedValue[1]/4096*3.3; //获取电流值 printf("\r\n电压值为:%f V\r\n",AD_Value[0]); printf("\r\n电流值为:%f A\r\n",(AD_Value[1]-2.5)/0.185);}}本次实验的电流采集模块⽤的是ACS712模块,所以在打印输出时需要转换⼀下。

stm32adc原理

stm32adc原理

stm32adc原理STM32 ADC(Analog-to-Digital Converter)是一种用于将模拟信号转换为数字信号的设备。

它是STM32微控制器中的一个重要模块,可用于采集外部传感器的模拟信号。

STM32 ADC的原理如下:1. 采样保持电路(Sample and Hold Circuit):首先,ADC需要将输入的模拟信号进行采样并保持住。

采样保持电路可以将模拟信号的瞬时值转换为一个稳定的电压。

在采样期间,采样保持电路将输入信号与一个电容器连接,然后在保持期间将电容器的电压保持在一个恒定值。

这样可以确保输入信号的瞬时值不会受到输入电阻或电容的影响。

2. 输入选择器(Channel Selector):ADC在每次转换之前需要选择要采集的输入信号通道。

选择器通常是一个多路选择器,可以从多个输入通道中选择一个。

3. 模数转换器(Analog-to-Digital Converter):模数转换器将采样和保持电路中保持的模拟信号转换为数字信号。

STM32 ADC通常使用逐次逼近型模数转换器(Successive Approximation Converter),它采用逼近算法来逼近输入信号的模拟值。

逐次逼近型模数转换器通过逐位逼近的方式进行转换,从最高有效位开始,逐渐逼近到最低位。

4. 校准电路(Calibration Circuit):为了确保转换精度,ADC需要进行校准。

校准电路可以通过测量和校正不同的误差源,如偏移误差和增益误差,来提高转换精度。

5. 控制和配置单元(Control and Configuration Unit):ADC还包含一个控制和配置单元,用于配置ADC的采样率、输入范围、转换分辨率等参数。

控制和配置单元还负责控制ADC的转换开始和结束,并生成转换完成的中断。

总的来说,STM32 ADC利用采样保持电路对输入信号进行采样保持,然后使用模数转换器将保持的模拟信号转换为数字信号。

stm32adc采样频率计算

stm32adc采样频率计算

stm32adc采样频率计算摘要:1.STM32 ADC 简介2.采样频率与采样定理3.STM32 ADC 采样频率计算方法4.具体应用场景下的采样频率设置5.总结正文:一、STM32 ADC 简介STM32 ADC(模拟数字转换器)是一种12位精度、逐次逼近型模拟数字转换器。

它有多达18个通道,可测量16个外部和2个内部信号源。

各通道的A/D转换可以单次、连续、扫描或间断模式执行。

ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。

值得注意的是,ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。

转换时最快为1us,当ADC的输入时钟超过14MHz时,其会损失一些精度。

二、采样频率与采样定理采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。

采样频率的倒数是采样周期或者叫作采样时间,它是采样之间的时间间隔。

通俗的讲,采样频率是指计算机每秒钟采集多少个声音样本,是描述声音文件的音质、音调,衡量声卡、声音文件的质量标准。

在进行模拟/数字信号的转换过程中,当采样频率fs大于信号中最高频率fmax的2倍(fs > 2fmax),采样之后的数字信号完整地保留了原始信号中的信息。

一般实际应用中保证采样频率为信号最高频率的5~10倍;采样定理又称奈奎斯特定理。

三、STM32 ADC 采样频率计算方法1.确定ADC的时钟:首先了解由时钟控制器提供的ADCCLK。

2.计算采样频率:根据ADC的时钟和采样定理,计算合适的采样频率。

3.计算采样时间:采样时间等于采样频率的倒数。

四、具体应用场景下的采样频率设置在不同应用场景下,根据实际需求和信号特性,合理设置采样频率。

例如,在语音处理、图像处理等领域,需要较高的采样频率以保证信号质量;在某些传感器数据采集场景下,可根据传感器特性和精度要求调整采样频率。

五、总结STM32 ADC 采样频率计算是实际应用中关键环节,合适的采样频率有助于保证信号质量和提高系统性能。

谈谈STM32ADC采集原理

谈谈STM32ADC采集原理

谈谈STM32ADC采集原理ADC概念:它是把连续的模拟信号转变为离散的数字信号的器件。

转换器的分类:积分型、逐次逼近型、并⾏⽐较型/串并⾏⽐较型、Σ-Δ调制型、电容阵列逐次⽐较型及压频变换型。

1).积分型:AD⼯作原理是将输⼊电压转换成时间(脉冲宽度信号)或频率(脉冲频率),然后由定时器/计数获得数字值。

2).逐次⽐较型 SAR :AD由⼀个⽐较器和DA转换器通过逐次⽐较逻辑构成,从MSB开始,顺序地对每⼀位将输⼊电压与内置DA转换器输出进⾏⽐较,经n次⽐较⽽输出数字值。

3).并⾏⽐较型 /串并⾏⽐较型:AD采⽤多个⽐较器,仅作⼀次⽐较⽽实⾏转换,⼜称FLash(快速)型。

由于转换速率极⾼,n位的转换需要2n-1个⽐较器,因此电路规模也极⼤,价格也⾼,只适⽤于视频AD转换器等速度特⾼的领域,串并⾏⽐较型AD结构上介于并⾏型和逐次⽐较型之间,最典型的是由2个n/2位的并⾏AD转换器配合DA转换器组成,⽤两次⽐较实⾏转换,所以称为 Half flash(半快速)型。

还有分成三步或多部实现AD转换的叫做分级(Multistep/Subrangling)型AD,⽽从转换时序⾓度⼜可称为流⽔线(Pipelined)型AD。

4). Σ-Δ (Sigma delta) 调制型 (如 AD7705) :Σ-Δ型AD由积分器、⽐较器、1位DA转换器和数字滤波器等组成。

原理上近似于积分型,将输⼊电压转换成时间(脉冲宽度)信号,⽤数字滤波器处理后得到数字值。

5).电容阵列逐次⽐较型:AD在内置DA转换器中采⽤电容矩阵⽅式,也可称为电荷再分配型。

6).压频变换型 (如 AD650) :(Voltage-Frequency Converter)是通过间接转换⽅式实现模数转换的。

其原理是⾸先将输⼊的模拟信号转换成频率,然后⽤计数器将频率转换成数字量。

下⾯说⼀下我在⽹络看到对逐次逼近法较为通俗的理解:如图1图1逐次逼近转换过程和⽤天平称物重⾮常相似。

stm32寄存器版学习笔记ADC采集

stm32寄存器版学习笔记ADC采集

stm32寄存器版学习笔记ADC采集⼀:ADC1通道0来采样外部电压值配置步骤①开启PA⼝时钟,设置PA0为模拟输⼊由数据⼿册(不是参考⼿册)可知,ADC123的通道0皆为PA0⼝由参考⼿册可知,ADC引脚GPIO配置为模拟输⼊APB2外设时钟使能寄存器(RCC_APB2ENR)Eg:RCC->APB2ENR| = 1 << 2; //使能PORTA时钟Eg:GPIOA->CRL&=0XFFFFFFF0;//PA0 模拟输⼊②使能ADC1时钟,并设置分频因⼦要使⽤ADC1,第⼀步使能ADC1时钟,之后进⾏⼀次ADC1复位。

通过RCC_CFGR设置ADC1的分频因⼦。

ADC1时钟不能超过14MHz。

APB2外设复位寄存器 (RCC_APB2RSTR) Eg:RCC->APB2ENR|=1<<9; //ADC1时钟使能 RCC->APB2RSTR|=1<<9; //ADC1复位 RCC->APB2RSTR&=~(1<<9);//复位结束 RCC->CFGR&=~(3<<14); //分频因⼦清零 RCC->CFGR|=2<<14; //SYSCLK/DIV2 = 72M / 6=12M (不得超过14MHz、否则准度下降)③设置ADC1的⼯作模式设置单次转换模式、触发⽅式选择、数据对齐⽅式等。

ADC控制寄存器1(ADC_CR1) Eg:ADC1->CR1&=0XF0FFFF; //⼯作模式清零 ADC1->CR1|=0<<16; //独⽴⼯作模式 ADC1->CR1&=~(1<<8); //⾮扫描模式ADC控制寄存器2(ADC_CR2)Eg: ADC1->CR2&=~(1<<1); //单次转换模式 ADC1->CR2&=~(7<<17); //清0 ADC1->CR2|=7<<17; //软件控制转换 ADC1->CR2|=1<<20; //使⽤⽤外部触发(SWSTART) 必须使⽤⼀个事件来触发 ADC1->CR2&=~(1<<11); //右对齐④设置ADC1规则序列的相关信息这⾥只有⼀个通道,并且单次转换,所以设置规则序列中通道数为1(ADC_SQR1[23:20]=0000)。

32单片机adc采样电路设计

32单片机adc采样电路设计

32单片机adc采样电路设计
32单片机ADC采样电路设计需要考虑以下几个步骤:
1.选择ADC:选择一个适合您需求的ADC。

需要考虑输入通道数、分辨率、采样速率、参考电压、电源电压等参数。

2.选择采样电路:根据您的需求选择合适的采样电路。

如果需要采样模拟信号,可以使用电阻、电容等元件组成采样电路;如果需要采样数字信号,可以使用逻辑电路等元件。

3.选择参考电压:ADC需要一个参考电压来确定输入信号的幅度范围。

您需要根据您的输入信号范围选择一个合适的参考电压。

4.设计电源电路:为ADC和采样电路提供稳定的电源是保证采样准确性的关键。

您需要设计一个稳定的电源电路,并考虑电源噪声和干扰等问题。

5.设计接口电路:根据您的需求,设计一个与ADC和采样电路相匹配的接口电路。

例如,如果需要将采样数据传输到计算机中,您需要设计一个USB接口电路或者RS-232接口电路等。

6.调试和测试:完成电路设计后,需要进行调试和测试。

您可以使用示波器等工具来观察采样信号和ADC输出信号,并调整采样电路和ADC的参数以达到最佳的采样效果。

需要注意的是,ADC采样电路的设计需要考虑多个因素,包括采样精度、采样速率、电源稳定性、接口类型等。

因此,建议在进行电路设计前进行充分的调研和论证。

stm32adc连续采样库函数

stm32adc连续采样库函数

stm32adc连续采样库函数在STM32系列的微控制器中,使用库函数进行ADC(模数转换器)的连续采样是非常常见的。

在HAL库中,连续采样可以通过以下步骤实现:1. 配置ADC外设,首先,需要初始化ADC外设,设置采样时间、分辨率等参数。

这可以通过调用HAL_ADC_Init函数来实现。

2. 配置ADC通道,接下来,需要配置ADC通道,选择要进行采样的通道。

这可以通过调用HAL_ADC_ConfigChannel函数来实现。

3. 配置DMA,为了实现连续采样,通常会使用DMA(直接存储器访问)来自动将采样数据传输到内存中。

需要配置DMA通道和缓冲区。

4. 启动ADC转换,一旦配置完成,可以调用HAL_ADC_Start_DMA函数来启动ADC转换并使用DMA进行数据传输。

5. 数据处理,一旦DMA传输完成,可以在DMA传输完成中断中处理采样数据。

以下是一个简单的示例代码,演示了如何使用HAL库函数进行ADC的连续采样:c.#include "stm32f4xx_hal.h"ADC_HandleTypeDef hadc;DMA_HandleTypeDef hdma_adc;void ADC_Init()。

{。

// 初始化ADC外设。

HAL_ADC_Init(&hadc);// 配置ADC通道。

ADC_ChannelConfTypeDef sConfig = {0};sConfig.Channel = ADC_CHANNEL_0;sConfig.Rank = 1;sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; HAL_ADC_ConfigChannel(&hadc, &sConfig);// 配置DMA.hdma_adc.Instance = DMA2_Stream0;hdma_adc.Init.Channel = DMA_CHANNEL_0;hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;hdma_adc.Init.MemInc = DMA_MINC_ENABLE;hdma_adc.Init.PeriphDataAlignment =DMA_PDATAALIGN_HALFWORD;hdma_adc.Init.MemDataAlignment =DMA_MDATAALIGN_HALFWORD;hdma_adc.Init.Mode = DMA_CIRCULAR;hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;HAL_DMA_Init(&hdma_adc);__HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc);// 启动ADC转换。

一文带你看懂Stm32定时器+ADC+DMA进行AD采样的实现

一文带你看懂Stm32定时器+ADC+DMA进行AD采样的实现

一文带你看懂Stm32定时器+ADC+DMA进行AD采样的实现一文带你看懂Stm32定时器+ADC+DMA进行AD采样的实现此STM32单片机为STM32F103系列的STM32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法:1、使用定时器中断每隔一定时间进行ADC转换,这样每次都必须读ADC的数据寄存器,非常浪费时间!2、把ADC设置成连续转换模式,同时对应的DMA通道开启循环模式,这样ADC就一直在进行数据采集然后通过DMA把数据搬运至内存。

但是这样做的话还得加一个定时中断,用来定时读取内存中的数据!3、使用ADC的定时器触发ADC转换的功能,然后使用DMA进行数据的搬运!这样只要设置好定时器的触发间隔,就能实现ADC定时采样转换的功能,然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断,我是采用第二种方法。

下面上代码:我这里使用的单通道//定时器初始化voidTIM2_ConfiguraTIon(void){TIM_TImeBaseInitTypeDefTIM_TimeBaseStructure;TIM_OCInitTypeDefTIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);TIM_TimeBaseStructure.TIM_Period=1999;//设置2ms一次TIM2比较的周期TIM_TimeBaseStructure.TIM_Prescaler=71;//系统主频72M,这里分频71,相当于1000K 的定时器2时钟TIM_TimeBaseStructure.TIM_ClockDivision=0x0;。

STM32基本外设应用-任务5ADC采集获取电压值

STM32基本外设应用-任务5ADC采集获取电压值

任务5 电池电量监测应用开发2.6.1 任务要求本任务要求设计一个可对电池电压进行监测的应用程序,电路图如图2- 1所示。

图2- 1 电池电量监测电路原理图在图2- 1中,供电电池的电压为12.6V,通过“PIN”端接入。

电池电压经过分压后,通过“VM_ADC”与微控制器的PA1引脚相连,作为ADC采集输入。

要求每隔1秒钟对电池电压进行采集,采集到的电压值通过串行通信的方式发送至上位机显示。

电压显示样例:3.25V,数值精确到小数点后两位数。

2.6.3 任务实施1. 建立STM32CubeMX工程并生成初始C代码(1)建立工程存放的文件夹在“STM32_WorkSpace”文件夹下新建文件夹“task5_Battery_ADC”用于保存本任务工程。

(2)新建STM32CubeMX工程参考2.2节相关内容。

(3)选择MCU型号参考2.2节相关内容,选择型号为STM32F103VE的微控制器。

(4)配置调试端口参考2.2节相关内容,将“PA13”引脚配置为SWDIO功能,“PA14”引脚配置为SWCLK功能。

(5)配置MCU时钟树参考2.2节相关内容,将HCLK配置为72MHz,PCLK1配置为36MHz,PCLK2配置为72MHz。

(6)配置ADC外设的工作参数切换到“Clock Configuration(时钟配置)”标签,进行ADC时钟配置,如图2- 2所示。

将“ADC Prescaler(ADC分频系数)”配置为“6”(图2- 2的标号①处),则ADC的输入时钟为12MHz(图2- 2的标号②处)。

图2- 2 ADC时钟配置本任务使用PA1引脚作为ADC1的输入端口,展开“Pinout & Configuration”标签页左侧的“Analog”选项,选择“ADC1”选项,勾选“IN1”复选框(如图2- 3中标号①所示)。

标号②:将ADC工作模式配置为“Independent mode(独立模式)”。

单片机adc采样原理

单片机adc采样原理

单片机adc采样原理单片机(Microcontroller)是一种集成了微处理器(Microprocessor)、存储器(Memory)和外设接口(Peripheral Interface)等功能于一体的集成电路芯片。

其中,ADC(Analog-to-Digital Converter)是单片机常用的外设之一,用于将模拟信号转换为数字信号。

ADC采样原理是指将模拟信号转换为数字信号的过程。

在采样时,模拟信号会按照一定的时间间隔进行离散化处理,将连续的模拟信号转换为一系列离散的数字信号。

采样原理涉及到采样定理、采样速率、量化精度等概念。

采样定理是指在进行模拟信号采样时,采样频率必须大于等于被采样信号最高频率的两倍。

这是为了避免采样时出现混叠现象,即采样频率低于被采样信号频率时,无法准确还原原始信号。

所以,在进行ADC采样时,需要根据被采样信号的频率确定合适的采样频率。

采样速率是指每秒采样的次数,通常用赫兹(Hz)表示。

采样速率越高,表示单片机对模拟信号进行离散化的频率越快,可以更准确地还原原始信号。

但是,采样速率过高也会导致数据量增大,对存储器和处理器的要求更高。

然后,量化精度是指将模拟信号离散化为数字信号时,数字信号的表示精度。

量化精度通常用位数表示,比如8位、10位、12位等。

位数越高,表示单片机对模拟信号的离散化精度越高,可以更准确地表示模拟信号的幅值。

但是,位数越高也会导致数据量增大,对存储器和处理器的要求更高。

在ADC采样过程中,还有一个重要的参数是参考电压(Reference Voltage)。

参考电压是用来确定模拟信号的量化范围的,它将模拟信号映射到数字量化范围内。

通常,单片机的参考电压可以通过外部电压源或内部参考电压源来提供。

实际上,ADC采样原理可以分为两个步骤:采样和量化。

首先是采样步骤。

单片机通过采样模块对模拟信号进行采样。

采样模块会在每个采样周期内对模拟信号进行采样,将其离散化为一系列的采样值。

STM32L051电阻分压ADC电量采集

STM32L051电阻分压ADC电量采集

电阻分压ADC电量采集STM32的ADC特点:※STM32L051单片机具有12位ADC(逐次逼近型ADC);※ADC具有四中工作模式:单次、连续、扫描、不连续;※ADC采集的结果具有左对齐和右对齐两种方式的16位寄存器;※ADC模拟看门狗功能允许开发人员监测ADC的电压输入是否超过设置上下门限;※一个高效的低功耗模式允许ADC采集在极低的功耗下运行;※ADC具有多点连续采集模式,该模式通过硬件完成多点采集减少了CPU的占用率提高采样效率;STM32的ADC功能描述:ADC具有内部独立的电压调节器,调节器必须在使用ADC前使能并且等待调节器稳定后才能使用ADC;调节器的稳定时间由硬件自己决定,开发人员无需关注;校准:ADC具有自动校准功能,开发人员在校准ADC之后才能使用ADC,校准能够消除芯片和芯片之间的差异以及其他硬件偏移;ADC时钟:ADC具有双时钟模式,ADC有一个独立的内部时钟源;1 初始化:Linki2u产品的ADC采集通过STM32的ADC单次采样模式进行;电量检测通过电阻分压的方式进行,ADC的初始化配置:AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;//初始化ADC的时钟,这个参数只能在ADC停止工作的时候更改****AdcHandle.Init.Resolution = ADC_RESOLUTION12b;//初始化ADC的分辨率****AdcHandle.Init.ScanDirection = ADC_SCAN_DIRECTION_UPWARD;//采样方向AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIG_EDGE_NONE;//触发方式AdcHandle.Init.EOCSelection = EOC_SINGLE_CONV;//采样完成EOC标志位置位AdcHandle.Init.DMAContinuousRequests = DISABLE;//DMA连续模式关闭AdcHandle.Init.DiscontinuousConvMode = DISABLE;//非连续模式关闭AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;//右对齐AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;//采样周期设置AdcHandle.Init.OversamplingMode = DISABLE;//过量采集模式禁止AdcHandle.Init.LowPowerAutoOff = ENABLE;//使能单次采集模式AdcHandle.Init.LowPowerFrequencyMode = DISABLE;//AdcHandle.Init.LowPowerAutoWait = DISABLE;//AdcHandle.Init.ContinuousConvMode = DISABLE;//HAL_ADC_Init(&AdcHandle);//初始化ADC参数2ADC校准HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);//开启ADC校准3设置ADC通道sConfig.Channel = ADC_CHANNEL_7;//ADC采样通道HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);//设置ADC采样通道4使能ADC功能HAL_ADC_Start(&AdcHandle);单次采集流程:电池电量通过电阻分压ADC采样的方式获取;1)程序中定义了一个电池电量的结构体:typedef uint16_t (* ARRAYAVRAGE ) (uint16_t buf[],uint8_t len);typedef uint16_t (* PARAMEMPTYFUN) (void);typedef struct Tag_Framet_Battery{uint8_t lnvalue; //电池电量的线性系数uint8_t adcnt; //电池电量ADC采样次数uint8_t delay_cnt; //延时次数uint16_t *ptr; //电池电量采样指针uint16_t ADCValue[10]; //电池电量采样数据数组float bat_value; //电池电量ARRAYAVRAGE AvgFun; //电池电量数据处理函数PARAMEMPTYFUN ValueFun; //电池电量采样函数}Framet_Battery;2 初始化电池电量采集的参数void BatTest_funInit(Framet_Battery *bat){bat->lnvalue=0;bat->adcnt=0;bat->delay_cnt=0;bat->bat_value=0;bat->ValueFun=(PARAMEMPTYFUN)Get_singleADCValue;//单次采样模式bat->ptr=bat->ADCValue;bat->AvgFun=(ARRAYAVRAGE) StrBubble_Sort; //数据求均值}3 ADC采集主循环中进行数据采集;#define FILTERCOUNTER 10 //¶¨ÒåÊý¾ÝÂ˲¨¸öÊý#define VDD_ADCREF (3.3)#define MAX_ADCSAMPLE (4096.0)#define ADCRESOLUTION (VDD_ADCREF/MAX_ADCSAMPLE)#define RES_UP (133000.0)#define RES_DOWN (100000.0)#define RES_SUM (RES_UP+RES_DOWN)#define BAT_MAXVALUE (4.1)//ΪÁËÂú×ã﮵ç³ØÌØÐÔ½«ÉÏÏÞ¼õС#define BAT_MINVALUE (3.0)#define BAT_ABSOLUTE (BAT_MAXVALUE-BAT_MINVALUE)#define PERCENTAGE (100.0)uint16_t Get_singleADCValue(){uint16_t ADCvalue;ADC1->CR |= ADC_CR_ADSTART;HAL_ADC_PollForConversion(&AdcHandle,5000);ADCvalue=HAL_ADC_GetValue(&AdcHandle);return ADCvalue;}void Get_BatLinValue(Framet_Battery *bat){bat->delay_cnt++;if(bat->delay_cnt==100){bat->delay_cnt=0;bat->ADCValue[bat->adcnt++]=bat->ValueFun();if(bat->adcnt==10){bat->adcnt=0;bat->bat_value=bat->AvgFun(bat->ptr,FILTERCOUNTER)*ADCRESOLUTION*RES_SUM/RES_DOWN;bat->lnvalue=(uint8_t)((bat->bat_value-BAT_MINVALUE)*PERCENTAGE/BAT_ABSOLUTE);if(bat->lnvalue>100) bat->lnvalue=100;}}}。

STM32—ADC多通道采集电压

STM32—ADC多通道采集电压

STM32—ADC多通道采集电压⽂章⽬录ADC详解前⾯的博客中详细介绍了STM32中ADC的相关信息,这篇博客是对ADC内容的⼀个总结提升,ADC的详细介绍:程序说明为了使这次代码阅读⽅便,博主没有在头⽂件中宏定义变量,都是直接采样库函数中的规定形参。

此次采⽤多通道采集电压,使⽤ADC1的通道10、11、12、13、14、15⼀共六个通道,采⽤DMA将转换结果传输⾄内存。

函数主体引脚配置引脚配置的时候,将所有引脚⼀次性配置好,过于简单,不作详细说明。

void ADC_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN ;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;GPIO_Init(GPIOC , &GPIO_InitStruct);}ADC和DMA配置此函数中主要配置了ADC的相关信息和DMA的信息。

uint16_t result[6]={0,0,0,0,0,0};void ADC_DMA_COnfig(void){ADC_InitTypeDef ADC_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* 复位DMA1的通道1 */DMA_DeInit(DMA1_Channel1);// 配置 DMA 初始化结构体// 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr = ( u32 ) ( ADC1_BASE+0x4c);// 存储器地址DMA_InitStructure.DMA_MemoryBaseAddr = (u32)result;// 数据源来⾃外设DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 缓冲区⼤⼩,应该等于数据⽬的地的⼤⼩DMA_InitStructure.DMA_BufferSize = 6;// 外设寄存器只有⼀个,地址不⽤递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 外设数据⼤⼩为半字,即两个字节DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;// 内存数据⼤⼩也为半字,跟外设数据⼤⼩相同DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;// 循环传输模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// DMA 传输通道优先级为⾼,当使⽤⼀个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁⽌存储器到存储器模式,因为是从外设到存储器DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 初始化DMADMA_Init(DMA1_Channel1, &DMA_InitStructure);// 使能 DMA 通道DMA_Cmd(DMA1_Channel1 , ENABLE);// 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_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;// 转换通道个数ADC_InitStructure.ADC_NbrOfChannel = 6;// 初始化ADCADC_Init(ADC1, &ADC_InitStructure);// 配置ADC时钟为PCLK2的8分频,即9MHzRCC_ADCCLKConfig(RCC_PCLK2_Div8);// 配置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_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_55Cycles5);// 使能ADC DMA 请求ADC_DMACmd(ADC1, ENABLE);// 开启ADC ,并开始转换ADC_Cmd(ADC1, ENABLE);// 初始化ADC 校准寄存器ADC_ResetCalibration(ADC1);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC1));// ADC开始校准ADC_StartCalibration(ADC1);// 等待校准完成while(ADC_GetCalibrationStatus(ADC1));// 由于没有采⽤外部触发,所以使⽤软件触发ADC转换ADC_SoftwareStartConvCmd(ADC1, ENABLE);函数开头定义了ADC和DMA的结构体变量,并且打开了俩个外设的时钟(DMA挂载在AHB总线上)。

ADC基于stm32的电压电流采集

ADC基于stm32的电压电流采集

ADC基于stm32的电压电流采集,用数码管显示首先组装硬件,如下图所示:如上图连接数码管与单片机,然后再按下图做两路电压采集电路,运用op07对电流进行30倍放大即可测得相对精准的电压,如下图所示:以上步骤完成即可编写程序,程序如下:*//* Includes ------------------------------------------------------------------*/#include "stm32f10x.h"#include <stdio.h>#include "LED8.h"#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printfset to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ */#define ADC1_DR_Address ((u32)0x4001244C)/* Private function prototypes -----------------------------------------------*/void GPIO_Configuration(void);void NVIC_Configuration(void);void TIM_Configuration(void);void ADC_Configuration(void);void numdisplay(uint16_t num);void numdisplay1(uint16_t num);void delay(void);void delay(){int i,j;for (i=0; i<0xfffff; i++) j++;}vu16 ADC_ConvertedValue[3];/******************************************************************** ************ Function Name : main* Description : Main program* Input : None* Output : None* Return : None* Attention : None*********************************************************************** ********/int main(void){int i=0;GPIO_Configuration();NVIC_Configuration();TIM_Configuration();ADC_Configuration();/* Infinite loop */for(i=0;i<10;i++){numb[i]=i;}numb[10]=1;numb[11]=2;numb[12]=3;numb[13]=4;numb[14]=5;numb[15]=6;;while (1){ delay();numdisplay((ADC_ConvertedValue[1]/4.096)*10.79); //显示电流值numdisplay1((ADC_ConvertedValue[2]/4.096)*11.755);//显示电压值}}/******************************************************************** ************ Function Name : GPIO_Configuration* Description : Configure GPIO Pin* Input : None* Output : None* Return : None* Attention : None********************************************************************* **********/void numdisplay(uint16_t num) //电流的{uint16_t temp1=0;uint16_t temp2=0;uint16_t temp3=0;uint16_t temp4=0;if((num<10000)&&(num>=1000)){temp1=num/1000;temp2=(num-temp1*1000)/100;temp3=(num-temp1*1000-temp2*100)/10;temp4=num-temp1*1000-temp2*100-temp3*10;}else if((num<1000)&&(num>=100)){temp2=num/100;temp3=(num-temp2*100)/10;temp4=num-temp2*100-temp3*10;}else if((100>num)&&(num>=10)){temp3=num/10;temp4=num-temp3*10;}else if(num<10){temp4=num;}else{}numb[12]=temp1;numb[13]=temp2;numb[14]=temp3;numb[15]=temp4;}void numdisplay1(uint16_t num) //电压的{uint16_t temp5=0;uint16_t temp6=0;uint16_t temp7=0;uint16_t temp8=0;if((num<10000)&&(num>=1000)){temp5=num/1000;temp6=(num-temp5*1000)/100;temp7=(num-temp5*1000-temp6*100)/10;temp8=num-temp5*1000-temp6*100-temp7*10;}else if((num<1000)&&(num>=100)){temp6=num/100;temp7=(num-temp6*100)/10;temp8=num-temp6*100-temp7*10;}else if((100>num)&&(num>=10)){temp5=10;temp7=num/10;temp8=num-temp7*10;}else if(num<10){temp5=10;temp8=num;}else{}numb[8]=temp5;numb[9]=temp6;numb[10]=temp7;numb[11]=temp8;}void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIO B|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE , ENABLE);/*** LED1 -> PD8 , LED2 -> PD9 , LED3 -> PD10 , LED4 -> PD11*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 |GPIO_Pin_5 |GPIO_Pin_7 |GPIO_Pin_8 | GPIO_Pin_9| GPIO_Pin_10 | GPIO_Pin_11| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8 |GPIO_Pin_11|GPIO_Pin_7 | GPIO_Pin_10 |GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ;GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11|GPIO_Pin_8 | GPIO_Pin_10| GPIO_Pin_12 ;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_15 ;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ;GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 |GPIO_Pin_11|GPIO_Pin_13 |GPIO_Pin_15 ;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; ;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure PA.05.06.07 (ADC Channel 5.6.7) as analog input -------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStructure);}void ADC_Configuration(void){ADC_InitTypeDef ADC_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO, ENABLE);/* DMA channel1 configuration ----------------------------------------------*/DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = 3;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel1, &DMA_InitStructure);/* Enable DMA1 channel1 */DMA_Cmd(DMA1_Channel1, ENABLE);/* ADC1 configuration ------------------------------------------------------*/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 = 3;ADC_Init(ADC1, &ADC_InitStructure);/* ADC1 regular channel15 configuration */ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 2, ADC_SampleTime_239Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 3, ADC_SampleTime_239Cycles5);/* Enable ADC1 DMA */ADC_DMACmd(ADC1, ENABLE);/* Enable ADC1 */ADC_Cmd(ADC1, ENABLE);/* Enable ADC1 reset calibaration register */ADC_ResetCalibration(ADC1);/* Check the end of ADC1 reset calibration register */while(ADC_GetResetCalibrationStatus(ADC1));/* Start ADC1 calibaration */ADC_StartCalibration(ADC1);/* Check the end of ADC1 calibration */while(ADC_GetCalibrationStatus(ADC1));/* Start ADC1 Software Conversion */ADC_SoftwareStartConvCmd(ADC1, ENABLE);}/******************************************************************** ************ Function Name : TIM_Configuration* Description : TIM_Configuration program.* Input : None* Output : None* Reswitch(count2)turn : None* Attention : None********************************************************************* **********/void TIM_Configuration(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);TIM_DeInit(TIM3);TIM_TimeBaseStructure.TIM_Period=200; /* 自动重装载寄存器周期的值(计数值) *//* 累计TIM_Period个频率后产生一个更新或者中断*/TIM_TimeBaseStructure.TIM_Prescaler= (100 - 1); /* 时钟预分频数例如:时钟频率=72MHZ/(时钟预分频+1) */TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; /* 采样分频*/TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; /* 向上计数模式*/TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);TIM_ClearFlag(TIM3, TIM_FLAG_Update); /* 清除溢出中断标志*/TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);TIM_Cmd(TIM3, ENABLE); /* 开启时钟*/}/******************************************************************** ************ Function Name : NVIC_Configuration* Description : Configuration the nested vectored interrupt controller.* Input : None* Output : None* Return : None* Attention : None********************************************************************* **********/void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t* file, uint32_t line){/* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* Infinite loop */while (1){}}#endif/******************************************************************** *************************************END FILE********************************************************************* ************************************/#include "LED8.h"unsigned char num[16]={0};unsigned char numb[16]={0};unsigned int count2=0;void LED8_Fresh(void){count2++;if(count2>16)count2=0;LED8_SetCH(count2);LED8_SetChar(numb[count2-1]);}void LED8_SetBuff(unsigned char num){}void LED8_SetChar(unsigned char num){switch(num){case 0:GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_11);GPIO_SetBits(GPIOE , GPIO_Pin_11);// GPIO_SetBits(GPIOA , GPIO_Pin_12);break;case 1:GPIO_SetBits(GPIOD , GPIO_Pin_14);GPIO_SetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8);GPIO_SetBits(GPIOE , GPIO_Pin_11);GPIO_SetBits(GPIOA , GPIO_Pin_8);GPIO_ResetBits(GPIOC , GPIO_Pin_11);GPIO_ResetBits(GPIOA , GPIO_Pin_10);break;case 2:GPIO_SetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_11);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOC , GPIO_Pin_8);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 3:GPIO_SetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOC , GPIO_Pin_11);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 4:GPIO_SetBits(GPIOD , GPIO_Pin_14);GPIO_SetBits(GPIOA , GPIO_Pin_8);GPIO_SetBits(GPIOC , GPIO_Pin_8);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_11);GPIO_ResetBits(GPIOA , GPIO_Pin_10);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 5:GPIO_SetBits(GPIOA , GPIO_Pin_10);GPIO_SetBits(GPIOC , GPIO_Pin_8);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_11);GPIO_ResetBits(GPIOE , GPIO_Pin_11);GPIO_ResetBits(GPIOA , GPIO_Pin_8);GPIO_ResetBits(GPIOD , GPIO_Pin_14);break;case 6:GPIO_SetBits(GPIOA , GPIO_Pin_10);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOA , GPIO_Pin_8);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_11);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 7:GPIO_SetBits(GPIOA , GPIO_Pin_8);GPIO_SetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8);GPIO_SetBits(GPIOE , GPIO_Pin_11);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOA , GPIO_Pin_10);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOC , GPIO_Pin_11);break;case 8://GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_11);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 9:GPIO_SetBits(GPIOC , GPIO_Pin_8);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_ResetBits(GPIOD , GPIO_Pin_14);GPIO_ResetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_ResetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_11);GPIO_ResetBits(GPIOE , GPIO_Pin_11);break;case 10:GPIO_SetBits(GPIOC , GPIO_Pin_8);// GPIO_SetBits(GPIOA , GPIO_Pin_12);GPIO_SetBits(GPIOD , GPIO_Pin_14);GPIO_SetBits(GPIOA , GPIO_Pin_8|GPIO_Pin_10);GPIO_SetBits(GPIOC , GPIO_Pin_6|GPIO_Pin_11);GPIO_SetBits(GPIOE , GPIO_Pin_11);break;}}void LED8_SetCH(unsigned char ch){GPIO_SetBits(GPIOC , GPIO_Pin_12);GPIO_SetBits(GPIOC , GPIO_Pin_10);GPIO_SetBits(GPIOA , GPIO_Pin_11);GPIO_SetBits(GPIOA , GPIO_Pin_9);GPIO_SetBits(GPIOB , GPIO_Pin_8);GPIO_SetBits(GPIOD , GPIO_Pin_7);GPIO_SetBits(GPIOD , GPIO_Pin_5);GPIO_SetBits(GPIOD , GPIO_Pin_3);GPIO_SetBits(GPIOC , GPIO_Pin_7);GPIO_SetBits(GPIOD , GPIO_Pin_15);GPIO_SetBits(GPIOD , GPIO_Pin_13);GPIO_SetBits(GPIOD , GPIO_Pin_11);GPIO_SetBits(GPIOB , GPIO_Pin_15);GPIO_SetBits(GPIOB , GPIO_Pin_13);GPIO_SetBits(GPIOB , GPIO_Pin_11);GPIO_SetBits(GPIOE , GPIO_Pin_15);GPIO_SetBits(GPIOA , GPIO_Pin_12);switch(ch){case 1: GPIO_ResetBits(GPIOC , GPIO_Pin_12); break;case 2: GPIO_ResetBits(GPIOC , GPIO_Pin_10); break;case 3: GPIO_ResetBits(GPIOA , GPIO_Pin_11); break;case 4: GPIO_ResetBits(GPIOA , GPIO_Pin_9); break;case 5: GPIO_ResetBits(GPIOB , GPIO_Pin_8); break;case 6: GPIO_ResetBits(GPIOD , GPIO_Pin_7); break;case 7: GPIO_ResetBits(GPIOD , GPIO_Pin_5); break;case 8: GPIO_ResetBits(GPIOD , GPIO_Pin_3); break;case 9: GPIO_ResetBits(GPIOC , GPIO_Pin_7); break;case 10: GPIO_ResetBits(GPIOD , GPIO_Pin_15); GPIO_ResetBits(GPIOA , GPIO_Pin_12);break;case 11: GPIO_ResetBits(GPIOD , GPIO_Pin_13); break;case 12: GPIO_ResetBits(GPIOD , GPIO_Pin_11); break;case 13: GPIO_ResetBits(GPIOB , GPIO_Pin_15);GPIO_ResetBits(GPIOA , GPIO_Pin_12); break;case 14: GPIO_ResetBits(GPIOB , GPIO_Pin_13);break;case 15: GPIO_ResetBits(GPIOB , GPIO_Pin_11); break;case 16: GPIO_ResetBits(GPIOE , GPIO_Pin_15); break;}}程序烧写正确之后,给单片机供电,首先用可调试电源调试电压电流。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

电阻分压ADC电量采集
STM32的ADC特点:
※STM32L051单片机具有12位ADC(逐次逼近型ADC);
※ADC具有四中工作模式:单次、连续、扫描、不连续;
※ADC采集的结果具有左对齐和右对齐两种方式的16位寄存器;
※ADC模拟看门狗功能允许开发人员监测ADC的电压输入是否超过设置上下门限;
※一个高效的低功耗模式允许ADC采集在极低的功耗下运行;
※ADC具有多点连续采集模式,该模式通过硬件完成多点采集减少了CPU的占用率提高采样效率;
STM32的ADC功能描述:
ADC具有内部独立的电压调节器,调节器必须在使用ADC前使能并且等待调节器稳定后才能使用ADC;调节器的稳定时间由硬件自己决定,开发人员无需关注;
校准:ADC具有自动校准功能,开发人员在校准ADC之后才能使用ADC,校准能够消除芯片和芯片之间的差异以及其他硬件偏移;
ADC时钟:ADC具有双时钟模式,ADC有一个独立的内部时钟源;
1 初始化:
Linki2u产品的ADC采集通过STM32的ADC单次采样模式进行;电量检测通过电阻分压的方式进行,ADC的初始化配置:
AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
//初始化ADC的时钟,这个参数只能在ADC停止工作的时候更改****
AdcHandle.Init.Resolution = ADC_RESOLUTION12b;
//初始化ADC的分辨率****
AdcHandle.Init.ScanDirection = ADC_SCAN_DIRECTION_UPWARD;
//采样方向
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIG_EDGE_NONE;
//触发方式
AdcHandle.Init.EOCSelection = EOC_SINGLE_CONV;
//采样完成EOC标志位置位
AdcHandle.Init.DMAContinuousRequests = DISABLE;
//DMA连续模式关闭
AdcHandle.Init.DiscontinuousConvMode = DISABLE;
//非连续模式关闭
AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
//右对齐
AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
//采样周期设置
AdcHandle.Init.OversamplingMode = DISABLE;
//过量采集模式禁止
AdcHandle.Init.LowPowerAutoOff = ENABLE;
//使能单次采集模式
AdcHandle.Init.LowPowerFrequencyMode = DISABLE;
//
AdcHandle.Init.LowPowerAutoWait = DISABLE;
//
AdcHandle.Init.ContinuousConvMode = DISABLE;
//
HAL_ADC_Init(&AdcHandle);
//初始化ADC参数
2ADC校准
HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);
//开启ADC校准
3设置ADC通道
sConfig.Channel = ADC_CHANNEL_7;
//ADC采样通道
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
//设置ADC采样通道
4使能ADC功能
HAL_ADC_Start(&AdcHandle);
单次采集流程:
电池电量通过电阻分压ADC采样的方式获取;
1)程序中定义了一个电池电量的结构体:
typedef uint16_t (* ARRAYAVRAGE ) (uint16_t buf[],uint8_t len);
typedef uint16_t (* PARAMEMPTYFUN) (void);
typedef struct Tag_Framet_Battery
{
uint8_t lnvalue; //电池电量的线性系数
uint8_t adcnt; //电池电量ADC采样次数
uint8_t delay_cnt; //延时次数
uint16_t *ptr; //电池电量采样指针
uint16_t ADCValue[10]; //电池电量采样数据数组
float bat_value; //电池电量
ARRAYAVRAGE AvgFun; //电池电量数据处理函数
PARAMEMPTYFUN ValueFun; //电池电量采样函数
}Framet_Battery;
2 初始化电池电量采集的参数
void BatTest_funInit(Framet_Battery *bat)
{
bat->lnvalue=0;
bat->adcnt=0;
bat->delay_cnt=0;
bat->bat_value=0;
bat->ValueFun=(PARAMEMPTYFUN)Get_singleADCValue;//单次采样模式bat->ptr=bat->ADCValue;
bat->AvgFun=(ARRAYAVRAGE) StrBubble_Sort; //数据求均值
}
3 ADC采集
主循环中进行数据采集;
#define FILTERCOUNTER 10 //¶¨ÒåÊý¾ÝÂ˲¨¸öÊý
#define VDD_ADCREF (3.3)
#define MAX_ADCSAMPLE (4096.0)
#define ADCRESOLUTION (VDD_ADCREF/MAX_ADCSAMPLE)
#define RES_UP (133000.0)
#define RES_DOWN (100000.0)
#define RES_SUM (RES_UP+RES_DOWN)
#define BAT_MAXVALUE (4.1)//ΪÁËÂú×ã﮵ç³ØÌØÐÔ½«ÉÏÏÞ¼õС
#define BAT_MINVALUE (3.0)
#define BAT_ABSOLUTE (BAT_MAXVALUE-BAT_MINVALUE)
#define PERCENTAGE (100.0)
uint16_t Get_singleADCValue()
{
uint16_t ADCvalue;
ADC1->CR |= ADC_CR_ADSTART;
HAL_ADC_PollForConversion(&AdcHandle,5000);
ADCvalue=HAL_ADC_GetValue(&AdcHandle);
return ADCvalue;
}
void Get_BatLinValue(Framet_Battery *bat)
{
bat->delay_cnt++;
if(bat->delay_cnt==100)
{
bat->delay_cnt=0;
bat->ADCValue[bat->adcnt++]=bat->ValueFun();
if(bat->adcnt==10)
{
bat->adcnt=0;
bat->bat_value=
bat->AvgFun(bat->ptr,FILTERCOUNTER)*ADCRESOLUTION*RES_SUM/RES_DOWN;
bat->lnvalue=(uint8_t)((bat->bat_value-BAT_MINVALUE)*PERCENTAGE/BAT_ABSOLUTE);
if(bat->lnvalue>100) bat->lnvalue=100;
}
}
}。

相关文档
最新文档