STM32 ADC电压测试实验报告
AD采集测试报告
测试报告1 测试内容STM32 407单片机为核心板,配合AD7656读取差模信号的16位A/D采样值。
2 测试方法2.1整体方案使用串口调试助手(Baud 115200、数据位8、停止位1、效验位无)做为下位机接收数据,通过Stm32 407单片机采样的值发送给串口助手显示十进制的A/D采样值。
分别输入不同的信号进行观察数据变化是否成线性并进行数据统计。
整体方案如图1所示。
图1 方案原理图2.1方法原理硬件电路连接好之后,先给板子供电,用万能表测量板子供电电压是否正确,测试前保证硬件电路正常。
根据说明手册连接好外围电路以及供电电源,供电电压选择+15V—15V的模拟电压,AD7656板子选用ADC3通道(总共有6个通道,使用哪一个注释其他的观察即可),ADC3接信号发生器的正接线柱、AD7656板子GND接信号发生器的接地接线柱(下载程序之前先关闭信号发生器的CH1),分别让信号发生器输出正弦波、余弦波,通过AD7656板子进行采集并进行观察,如果AD7656板子采集的数据跟信号发生器给的信号相似或者呈线性,则观察结果和理论相吻合。
主程序流程图如图2所示图2 AD采集主程序流程图观察结束后,分别设置软件其他通道的参数并把采集的数据打印出来,与其它通道进行对比,看各个通道的采集情况,并导入到Excel表格中进行观察.3 测试结果让信号发生器输出一个频率:10KHz,高电平:1V,低电平:-1V,占空比:50%的方波信号.用串口助手观察数据并把这些数据导出到Excel表格中进行观察.观察结果如图3所示图3.1 测试结果观察结果显示的是一个与输出信号相吻合的方波信号,数据跳动厉害是信号发生器的精度不准确原因导致的,所以实际测量值与理论测量值呈线性相关.其它五个通道的采集情况与ADC3采集的情况基本相似.4.1 问题1调试AD采集程序的时候,AD采集的数据在串口上不显示, 测试硬件电路供电是否正常,当只给AD板子供电时候,测试引脚电压为3.3V.当外围接入数字电压+5V时,只能烧进去程序.4.1.1解决方案回看原理图,发现AD7656板子的供电电压只有在+15时才能带动板子正常工作,所以给AD7656板子外加一个+15V电源,观察AD采集数据和信号发生器输出的信号相吻合。
单片机STM32实验报告
实验报告课程名称:单片微机原理与车载系统学生姓名蒋昭立班级电科1601学号***********指导教师易吉良成绩2018年12 月17 日实验1 GPIO实验1.1 实验目的1)熟悉MDK开发环境;2)掌握STM32单片机的GPIO使用方法。
1.2 实验设备1)一台装有Keil和串口调试软件的计算机;2)一套STM32F103开发板;3)STlink硬件仿真器。
1.3 基本实验内容1)熟悉MDK开发环境,参考《STM32F1开发指南(精英版)-寄存器版本_V1.0》第3章,安装MDK 并新建test工程,运行例程,在串口窗宽观察结果,并记录如下:从图片可以看出,例程运行成功,没有错误。
2)按键输入实验,《STM32F1开发指南(精英版)-寄存器版本_V1.0》第8章。
实现功能:3 个按钮(KEY_UP、KEY0和KEY1),来控制板上的2 个LED(DS0 和DS1)和蜂鸣器,其中KEY_UP 控制蜂鸣器,按一次叫,再按一次停;KEY1 控制DS1,按一次亮,再按一次灭;KEY0 则同时控制DS0 和DS1,按一次,他们的状态就翻转一次。
理解连续按概念及其实现代码。
参数mode 为0 的时候,KEY_Scan 函数将不支持连续按,扫描某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。
当mode 为1 的时候,KEY_Scan 函数将支持连续按,如果某个按键一直按下,则会一直返回这个按键的键值,这样可以方便的实现长按检测。
寄存器方法实现不支持连续按的关键代码,以及程序运行后的效果。
由程序可知,给KEY_Scan函数输入的值为0,为不支持连按模式。
寄存器方法实现支持连续按的关键代码,以及程序运行后的效果。
由程序可知,给KEY_Scan函数输入的值为1,为支持连按模式。
3)采用库函数方法实现按键输入实验,参考《STM32F1开发指南(精英版)-库函数版本_V1.0》第8章。
48脚STM32内部基准电压校准ADC的一些心得记录
48脚STM32内部基准电压校准ADC的一些心得记录在进行STM32内部基准电压校准ADC的过程中,我积累了一些心得和经验。
在此记录下来,分享给大家。
首先,基准电压是ADC精度的关键,因此校准过程十分重要。
基准电压在STM32系列芯片中默认为3V,但实际上可能存在差异。
因此,我们需要通过校准过程来提高ADC的测量精度。
校准前,我们需要做一些准备工作。
首先,确定使用的电压参考源,常用的有外部参考电压和内部基准电压两种。
相比于外部参考电压,内部基准电压的供电更加稳定和可靠。
接下来,我们需要配置ADC的工作模式和精度。
根据实际应用情况,选择合适的采样速率和转换模式。
在校准过程中,一般选择单次转换模式。
校准的关键在于获取两组参考电压值:理论值和测量值。
理论值是指校准前,我们已知的基准电压值。
测量值是指通过ADC测量得到的实际电压值。
首先,我们需要获取理论值。
根据STM32芯片的技术手册,可以查找到基准电压的精确数值。
然后,我们需要通过参考电压源提供一个已知电压,并将其连接到芯片的ADC通道上。
接下来,我们需要获取测量值。
通过ADC测量参考电压源的输出电压,并将结果保存在寄存器中。
在单次转换模式下,可以直接通过读取ADC_DR寄存器来获取测量值。
获取了理论值和测量值后,我们就可以计算出校准系数。
校准系数是理论值与测量值之间的比例关系。
通过将测量值除以理论值,即可得到校准系数。
然后,我们可以在程序中使用这个校准系数来校准ADC转换结果。
通过上述步骤,我们可以提高ADC的精度和准确性。
但需要注意的是,校准系数是基于当前环境和条件下得到的。
如果环境和条件发生变化,可能会导致校准系数失效。
因此,我们需要定期进行校准,以保证ADC的准确性。
总结一下,进行STM32内部基准电压校准ADC需要做以下几个步骤:确定使用的电压参考源、配置ADC的工作模式和精度、获取理论值和测量值、计算校准系数和使用校准系数来校准ADC转换结果。
STM32双ADC通道测量电压
双ADC通道测量电压值说明书
一:原理图
电压测量等功能电路图
二:工作原理
根据PA0和PA1输入的电压,可转换成不同的AD值,通过获取寄存器中的AD值,再将其转变为电压值。
开发板使用了3.3V的外部参考电压。
ADC的使用请参考《STM32中文参考资料》。
三:实验现象及操作
程序下载到开发板,并运行后,可以观察到数码管的左边三位和右边三位点亮。
并显示有精确到小数点后2位的数值。
当PA0或PA1槽没有任何接入时,不同的开发板可能显示的值有所不同,但对电压的测量没有影响。
先取一个电压值小于3.3V的电池,将电池的负极接EXT的GND槽,电池的正极接EXT 的PA0槽或PA1槽,根据正极接入不同的插槽,是的电压值显示的位置不同。
●左边三位形成的十进制值为PA0槽测到的电压值,精确到小数点后2位。
●右边三位形成的十进制值为PA1槽测到的电压值,精确到小数点后2位。
基于STM32系统的ADC测试设计
偏移误 差 E =实际的转换 一 理 想的转换
ADC 采样过程其实是一个将连续的模拟信号量化成有限的数
E。= 8 Vl-7.63pV=0.37pV
字的过程,每个数 字代表一次采样所获得的信号。量化时,根 据数据
Eo 0:37pV/15.26pV=O.024LSB
2.1.2.1电源 噪 声
STM 3 2H7微控制器 自带的 16 位 ADC 是逐次逼近 型的
模拟 电源引脚是用于为转换 提供参考电压 ,因为 ADC输 出是模
模拟数 字转换器。有通道数 2O个,2 个可以测量内部信号。各通道 拟信号电压和模拟参考电压之间的比例数值 ,因此任何模拟 参考 电源
如果 VREF+=3.3V,理想情况下输入 7.63“V(O.5 LSB = O.5 当配置寄存器后即可实现过采样 。
x 15.26pV)时,产生数 字输出 1。然而实际上 ,这 时 ADC模块的读 数可能仍然为 0如 果在输入电压达 到 8pV时才 能得到数字输 出1则
5.1过 采样 原理 3.1.1 量化 噪 声 分 析
平均 值 方 法
在 STM32H7的数 据手册 中,给 出了不 同类型 的 ADC精度 误
平均值法是 一个简单的技 术,通过 对一 个模拟输入信号 的多次
差数值 。通常 ,精度误差是 以
采样和 软件计算取平均值 实现。这个技术有利于 消除 那些不频繁变
LSB为单位表示 。电压的分辨率与参考 电压相关。电压误差是按 化的模拟输入信号上的噪声。
综 合
基于 STM32系统的 ADC测试设计
叶敏 意法半导体 中国投资有限公司
随着科技 水平的提高 ,ARM 内核 的芯片,凭借强大的处理能力
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模块,所以在打印输出时需要转换⼀下。
单片机STM32实验报告
实验报告课程名称:单片微机原理与车载系统学生姓名蒋昭立班级电科1601学号16401700119指导教师易吉良成绩2018年12 月17 日实验1 GPIO实验1.1 实验目的1)熟悉MDK开发环境;2)掌握STM32单片机的GPIO使用方法。
1.2 实验设备1)一台装有Keil和串口调试软件的计算机;2)一套STM32F103开发板;3)STlink硬件仿真器。
1.3 基本实验内容1)熟悉MDK开发环境,参考《STM32F1开发指南(精英版)-寄存器版本_V1.0》第3章,安装MDK 并新建test工程,运行例程,在串口窗宽观察结果,并记录如下:从图片可以看出,例程运行成功,没有错误。
2)按键输入实验,《STM32F1开发指南(精英版)-寄存器版本_V1.0》第8章。
实现功能:3 个按钮(KEY_UP、KEY0和KEY1),来控制板上的2 个LED(DS0 和DS1)和蜂鸣器,其中KEY_UP 控制蜂鸣器,按一次叫,再按一次停;KEY1 控制DS1,按一次亮,再按一次灭;KEY0 则同时控制DS0 和DS1,按一次,他们的状态就翻转一次。
理解连续按概念及其实现代码。
参数mode 为0 的时候,KEY_Scan 函数将不支持连续按,扫描某个按键,该按键按下之后必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次触发,而坏处就是在需要长按的时候比较不合适。
当mode 为1 的时候,KEY_Scan 函数将支持连续按,如果某个按键一直按下,则会一直返回这个按键的键值,这样可以方便的实现长按检测。
寄存器方法实现不支持连续按的关键代码,以及程序运行后的效果。
由程序可知,给KEY_Scan函数输入的值为0,为不支持连按模式。
寄存器方法实现支持连续按的关键代码,以及程序运行后的效果。
由程序可知,给KEY_Scan函数输入的值为1,为支持连按模式。
3)采用库函数方法实现按键输入实验,参考《STM32F1开发指南(精英版)-库函数版本_V1.0》第8章。
STM32内部AD采样实现简易电压表(同时显示直流电压波形)
//内部AD可显示正确的电压值。
oh ye ah!调了我两天呀!总算调出来了yeah!//我第一个想到的就是与大家一起分享我的程序。
oh ye ah!还请各位大侠多多指教呀!大家一起学习交流。
/*********************************************************************** ********* F ile N ame :main.c* A uthor :Wuhan R&DCente r, Em best* Dat e Fir st Is sued : 08/08/2008* Desc ripti on : Mai n pro grambody************************************************************************ ********//* Incl udes------------------------------------------------------------------*/#inclu de "s tm32f10x_l ib.h"#inc lude"stdio.h"//#inc lude"moni tor.h"/************ 用于定义ITMViewe r相关的I TM激励寄存器端口************************//*#d efine ITM_Port8(n) (*((vola tileunsig ned c har *)(0xE0000000+4*n)))#defi ne IT M_Por t16(n) (*((vo latil e uns igned shor t*)(0xE0000000+4*n)))#de fineITM_P ort32(n) (*((volat ile u nsign ed lo ng *)(0xE0000000+4*n)))#defi ne DE MCR (*((vo latil e uns igned long *)(0xE000EDFC)))#d efine TRCE NA 0x01000000*//*用于定义是否使用ITMViewe r*///#def ine D BG_IT M /* P rivat e typ edef-----------------------------------------------------------*//*Priva te de fine------------------------------------------------------------*/#d efine ADC1_DR_A ddres s ((u32)0x4001244C)fl oat A D_val ue;i nt AD_valu e1;//stat ic un signe d lon g tic ks;//unsi gnedcharClock1s;u8 adc_1[10]={0};//用来存放经AD C转换后的电压值的每一位数值。
STM32-ARM-综合实验报告
STM32 与M25P80的IO 接口对应关系如表1所示。
图2 STM32 的SPI1 硬件框图1 STM32 与M25P80 的IO 接口对应关系1.3 Key 按键介绍通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。
按键的消抖,可用硬件或软件两种方法。
Key 硬件框图如图3 所示,按键输入与PG8 口连接。
当按键不按下时,PG8 口输入高电平;当按键按下时,PG8 口输入低电平。
图3 Key 硬件框图41.4 定时器图5 主程序的流程框图如图5 所示,对于该流程框图的分析如下:1) 对STM32的初始化,其中包括ADC 初始化、SPI串口初始化、LCD 初始化等,初始化过程在其相应的子程序中执行。
2) 显示组员的信息和时间,正如实验七所学的,运用函数LCD_ShowString() ,即可在LCD 上显示自己所需要的信息,其显示的位置可以根据设定的坐标来设置。
3) 设置Key 键,当Key 键被按下时,开始采集数据并将其显示,而数据采集和显示的编程及其分析过程在前面的实验七中已经有过比较详细的介绍了,所以这里不再赘述。
同时,采集到的数据及时的将其存储在Flash中,Flash的设置在其初始化中已经完成。
4) 设置Temper键,当Temper 键被按下的时候,开始对之前采集到的数据进行绘图7 数据绘制子程序四、实验结果和分析1、软件的调试结果将程序烧录到STM32 中进行调试,调试结果如图8~9所示,从图中可知,程序满足实验要求。
图8 显示日期及组员信息。
STM32 ADC电压测试实验报告
STM32 ADC电压测试实验报告一、实验目的1.了解STM32的基本工作原理2. 通过实践来加深对ARM芯片级程序开发的理解3.利用STM32的ADC1通道0来采样外部电压值值,并在TFTLCD模块上显示出来二、实验原理STM32拥有1~3个ADC,这些ADC可以独立使用,也可以使用双重模式(提高采样率)。
STM32的ADC是12位逐次逼近型的模拟数字转换器。
它有18个通道,可测量16个外部和2个内部信号源。
各通道的A/D转换可以单次、连续、扫描或间断模式执行。
ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中接下来,我们介绍一下执行规则通道的单次转换,需要用到的ADC寄存器。
第一个要介绍的是ADC控制寄存器(ADC_CR1和ADC_CR2)。
ADC_CR1的各位描述如下:ADC_CR1的SCAN位,该位用于设置扫描模式,由软件设置和清除,如果设置为1,则使用扫描模式,如果为0,则关闭扫描模式,ADC_CR1[19:16]用于设置ADC的操作模式我们要使用的是独立模式,所以设置这几位为0就可以了。
第二个寄存器ADC_CR2,该寄存器的各位描述如下:ADCON位用于开关AD转换器。
而CONT位用于设置是否进行连续转换,我们使用单次转换,所以CONT位必须为0。
CAL和RSTCAL用于AD校准。
ALIGN用于设置数据对齐,我们使用右对齐,该位设置为0。
EXTSEL[2:0]用于选择启动规则转换组转换的外部事件,我们这里使用的是软件触发(SWSTART),所以设置这3个位为111。
第三个要介绍的是ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2),这两个寄存器用于设置通道0~17的采样时间,每个通道占用3个位对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低ADC的转换速率。
ADC的转换时间可以由下式计算:Tcovn=采样时间+12.5个周期第四个要介绍的是ADC规则序列寄存器(ADC_SQR1~3),第五个要介绍的是ADC规则数据寄存器(ADC_DR)。
stm32电容测量仪实验报告
stm32电容测量仪实验报告实验目的:本实验旨在通过使用STM32单片机设计和制作一个电容测量仪,用于测量电路中的电容值。
实验原理:电容是电子元件中常见的一种被动电子元件,其主要功能是储存电荷。
在电容测量仪中,我们使用了STM32单片机的内部模拟数字转换器(ADC)来测量电容。
ADC将电容的电压信号转换为数字信号,然后通过计算可以得到电容的值。
实验器材:1. STM32F103C8T6开发板2. 电容3. 电阻4. 面包板5. 连接线实验步骤:1. 将STM32开发板插入面包板中,并连接相应的电源线。
2. 将电容和电阻连接在面包板上,组成一个简单的RC电路。
3. 使用连接线将RC电路与STM32开发板的ADC引脚相连。
4. 在STM32开发板上编写程序,配置ADC并进行电容测量。
5. 将程序下载到STM32开发板中,并进行实验测量。
6. 根据实验结果,计算并记录电容的测量值。
实验结果与分析:通过实验测量,我们得到了电容的测量值。
根据测量值和实际电容的理论值进行对比,可以评估测量的准确性和精度。
如果测量值与理论值相差较大,则可能存在测量误差或电路中存在其他因素影响测量结果。
实验结论:本实验成功设计和制作了一个基于STM32的电容测量仪。
通过该仪器可以准确测量电路中的电容值,并可以用于实际的电子电路设计和测试中。
实验结果的准确性和精度对于保证电路正常工作和性能的提升具有重要意义。
拓展:在实际应用中,电容测量仪可以用于故障诊断、质量控制和电路设计等领域。
通过测量电容值,可以判断电容的健康状况,避免因电容老化或损坏引起的电路故障。
此外,电容测量仪还可以用于电路的质量控制,确保电路的性能和可靠性。
在电路设计中,测量电容值可以用于验证设计参数的准确性,并为电路的优化和改进提供参考。
因此,电容测量仪在电子领域具有广泛的应用前景。
STM32之ADC(内部基准电压,参考电压)
STM32之ADC(内部基准电压,参考电压)
转 STM32内部参照电压VREFIN的使⽤ https:///uncle_guo/article/details/50625660
每个STM32芯⽚都有⼀个内部的参照电压,相当于⼀个标准电压测量点,在芯⽚内部连接到ADC1的通道17。
根据数据⼿册中的数据,这个参照电压的典型值是1.20V,最⼩值是1.16V,最⼤值是1.24V。
这个电压基本不随外部供电电压的变化⽽变化。
不少⼈把这个参照电压与ADC的参考电压混淆。
ADC的参考电压都是通过Vref+提供的。
100脚以上的型号,Vref+引到了⽚外,引脚名称为Vref+;64脚和⼩于64脚的型号,Vref+在芯⽚内部与VCC信号线相连,没有引到⽚外,这样AD的参考电压就是VCC上的电压。
在ADC的外部参考电压波动,或因为Vref+在芯⽚内部与VCC相连⽽VCC变化的情况下,如果对于ADC测量的准确性要求不⾼时,可以使⽤这个内部参照电压得到ADC测量的电压值。
具体⽅法是在测量某个通道的电压值之前,先读出参照电压的ADC测量数值,记为ADrefint;再读出要测量通道的ADC转换数值,记为ADchx;则要测量的电压为:
Vchx = Vrefint * (ADchx/ADrefint)
其中Vrefint为参照电压=1.20V(STM32F107)。
如何⽤VDDA作为ADC参考电压,当测量信号电压超过这个范围可以⽤精密电阻分压或者放⼤器分压,或者选择合适的外部电压基准芯⽚。
stm32单通道双ADC电压温度采集
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //设置了成员NVIC_IRQChannel中的从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定了在成员NVIC_IRQChannel中定义的IRQ通道被使能
ErrorStatus HSEStartUpStatus;
extern void Delay_xms(u32 nTime);
static vu32 TimingDelay;
vu16 adc_value;
vu16 temp_value;
/*******************************************************************************
GPIO_InitStruct.GPIO_Pin = (GPIO_Pin_3);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC,&GPIO_InitStruct);
关于ST M32开发版与adc知识的实验报告
关于ST M32开发版与adc知识的实验报告
一、实验准备
1.实验环境。
一块stm32开发板,以及数据线。
已经安装STM32CubeMX。
已经安装KeilMDK,并导入stm32开发板对应的芯片包(小熊派使用的是STM32L431RCT6)。
准备一个串口调试助手,我使用的是UartAssist(包含在附件中)。
一个土壤湿度传感器模块。
2.目标效果。
通过CubeMX创建工程并配置参数。
获取stm32以硬件IIC获取SHT20传感器值(通过SHT20数据手册转化)。
串口1重定向输出土壤湿度值。
二、通过CubeMX生产MDK工程
1、芯片选择。
打开CubeMX,进入芯片选择:选择自己的stm32芯片(即
STM32L431RCT6):B.时钟源RCC设置。
2、更改系统时钟源。
系统时钟默认使用内部的高速时钟(HSI),选择使用HSE,时钟更精确。
3、设置外部时钟对应的端口。
4、配置时钟树。
STM32L431RCT6系统时钟最大可以为80MHz,我们配置到最大即可。
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;}}程序烧写正确之后,给单片机供电,首先用可调试电源调试电压电流。
ADC实验山东交通学院
实验六ADC实验一、实验目的与要求1、了解STM32系列ADC转换原理;熟悉HAL固件库中ADC库函数的使用方法2、掌握HAL固件库轮训方式的ADC启动、转换数据获取方法,模拟值计算方法3、熟悉STM32系列CPU的通用同步异步收发器(USART),熟悉HAL固件库中USART库函数的使用方法4、了解printf函数通过串口输出信息方法及重定向的概念。
二、实验设备SUN ESMC01实验仪(含STM32F103模块)一套、ARM仿真器一套、PC机一台三、实验内容1、自选ADC及其任意输入通道,采集实验箱C2区的可调电压值,经轮询方式A/D转换后,将转换后的数字量和由该数字量对应计算获得的电压值通过串口助手显示出来。
2、编写程序:将printf函数重定位给串口,使用printf函数输出一串字符;再使用printf函数输出1个字节的16进制数串口配置:- BaudRate = 9600 baud- Word Length = 8 Bits- One Stop Bit- No parity- Software flow control- Receive and transmit enabled3、用万用表测量C2区的模拟电压输出值,与串口显示值比较,验证是否正确。
四、实验原理图CH340C是串口转USB接口芯片。
注意:(1)本例需使用STM32F103核心板上资源,确认USB-B座CN3附近JP4已用短路块短接;CN3使用USB线与微机连接。
(2)请确保微机已正确安装CH340C对应的驱动程序。
(3)需要利用B8的信号转接区将模拟电压输入到相应的ADC引脚。
五、使用STM32CubeMX分别配置ADC1和串口Usart1。
六、实验说明1、源文件组成stm32f1xx_hal_conf.h 库配置文件、HSE值定义stm32f1xx_it.c 中断处理文件stm32f1xx_it.h 中断处理头文件stm32f1xx_hal_msp.c 提供MSP初始化、中断初始化函数system_stm32f1xx.c HAL库提供,一般不作改动。
STM32F1ADC实验(HAL库版)
STM32F1ADC实验(HAL库版)ADC(Analog-to-Digital Converter)即模数转换器,输⼊模拟电压即可转换为数字量。
⼀、STM32的ADC STM32F1有三个ADC,分别是ADC1、ADC2、ADC3,根据STM32参考⼿册可知,ADC1和ADC2均有16个输⼊通道,ADC3有若⼲个输⼊通道(根据芯⽚类型不同有差异),还有有⼀个内部温度传感器通道和⼀个光敏传感器通道。
分布在各个引脚上,可根据STM32 芯⽚⼿册查询。
如ADC1 IN1 (通道1)在PA1上。
⼆、STM32 ADC的⼀些概念(单次转换、连续转换、扫描模式) 1、单次转换:⼀次转换结束后,需要⼿动开启才能进⾏下⼀次转换。
2、连续转换:⼀次转换结束后继续下⼀次转换。
3、扫描模式:对多通道的转换进⾏逐个转换。
若此时开启单次转换模式,扫描完所有通道后需要⼿动启动下⼀次扫描转换;若此时开启连续转换模式,扫描完成后⾃动进⼊下⼀次扫描转换,所以扫描模式需要配合DMA才能读取数据。
三、ADC的配置(HAL库版) 要使⽤ADC,必须先对其进⾏配置,HAL库提供了若⼲函数来对ADC进⾏配置。
1、配置ADC时钟,这个基本没有什么修改的余地RCC_PeriphCLKInitTypeDef ADC_CLKInit;ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC; //ADC外设时钟ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV6; //分频因⼦6时钟为72M/6=12MHzHAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit); //设置ADC时钟 2、配置ADC,使⽤到哪个ADC就配置哪个__HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟ADC1_Handler.Instance=ADC1;ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐ADC1_Handler.Init.ScanConvMode=DISABLE; //不扫描模式ADC1_Handler.Init.ContinuousConvMode=DISABLE; //不连续转换ADC1_Handler.Init.NbrOfConversion=1; //⼀个规则通道转换ADC1_Handler.Init.DiscontinuousConvMode=DISABLE; //禁⽌不连续采样模式ADC1_Handler.Init.NbrOfDiscConversion=0; //不连续采样通道数为0ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START; //软件触发HAL_ADC_Init(&ADC1_Handler); //初始化 其中扫描模式和连续转换模式根据需求改,规则转换通道数NbrOfConversion 为你要使⽤的ADC转换通道数。
电压精准测量实验报告(3篇)
第1篇一、实验目的本实验旨在研究STM32L476单片机在电池供电较低情况下,如何通过HAL库编程和DMA多通道采集ADC,实现对外部电池电压的精准测量。
实验重点在于解决电池供电低于外部校准电压时,ADC采集不准确的问题,并通过内部基准修正技术提高测量精度。
二、实验原理1. ADC原理:模数转换器(ADC)将模拟信号转换为数字信号,用于测量电压等物理量。
STM32L476单片机内置12位ADC,能够将模拟电压转换为数字值。
2. DMA多通道采集:直接内存访问(DMA)是一种高速数据传输技术,允许ADC在单个转换周期内连续采集多个通道的数据,提高采集效率。
3. 内部基准修正:STM32L476单片机内部具有基准电压源,可以通过调整内部基准电压,修正因电池供电低导致的ADC采集误差。
三、实验设备1. STM32L476G-DISCOVERY开发板2. 3.6V电池3. 7.2V通信电池4. LCD点阵液晶屏5. 二极管6. 稳压芯片7. 万用表四、实验步骤1. 搭建实验电路:将电池、二极管、稳压芯片和STM32L476开发板连接成电路,确保电路稳定可靠。
2. 编程:a. 使用HAL库编程,配置ADC为12位单次转换模式。
b. 设置DMA为多通道采集模式,连续采集多个通道的电压数据。
c. 使用内部基准修正功能,调整内部基准电压,修正采集误差。
3. 测试:a. 使用万用表测量电池电压,确保实验条件符合要求。
b. 在不同电池电压下,观察LCD点阵液晶屏显示的电压值,验证测量精度。
c. 比较开启背光灯和关闭背光灯时的电压采集结果,分析误差原因。
五、实验结果与分析1. 电压采集结果:在电池电压为3.2V时,ADC采集到的电压值约为3.2V,测量精度较高。
2. 误差分析:a. 开启背光灯时,电压采集结果偏高,原因是背光灯电流较大,导致接入板子的电压降低。
b. 电池供电低于外部校准电压时,ADC采集误差较大,通过内部基准修正功能,可以有效降低误差。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32 ADC电压测试实验报告
一、实验目的
1.了解STM32的基本工作原理
2. 通过实践来加深对ARM芯片级程序开发的理解
3.利用STM32的ADC1通道0来采样外部电压值值,并在TFTLCD模块上显示出
来
二、实验原理
STM32拥有1~3个ADC,这些ADC可以独立使用,也可以使用双重模式(提高采样率)。
STM32的ADC是12位逐次逼近型的模拟数字转换器。
它有18个通道,可测量16个外部和2个内部信号源。
各通道的A/D转换可以单次、连续、扫描或间断模式执行。
ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中
接下来,我们介绍一下执行规则通道的单次转换,需要用到的ADC寄存器。
第一个要介绍的是ADC控制寄存器(ADC_CR1和ADC_CR2)。
ADC_CR1的各位描述如下:
ADC_CR1的SCAN位,该位用于设置扫描模式,由软件设置和清除,如果设置为1,则使用扫描模式,如果为0,则关闭扫描模式,ADC_CR1[19:16]用于设置ADC的操作模式
我们要使用的是独立模式,所以设置这几位为0就可以了。
第二个寄存器ADC_CR2,该寄存器的各位描述如下:
ADCON位用于开关AD转换器。
而CONT位用于设置是否进行连续转换,我们使用单次转换,所以CONT位必须为0。
CAL和RSTCAL用于AD校准。
ALIGN用于设置数据对齐,我们使用右对齐,该位设置为0。
EXTSEL[2:0]用于选择启动规则转换组转换的外部事件,我们这里使用的是软件触发(SWSTART),所以设置这3个位为111。
第三个要介绍的是ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2),这两个寄存器用于设置通道0~17的采样时间,每个通道占用3个位
对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低ADC的转换速率。
ADC的转换时间可以由下式计算:
Tcovn=采样时间+12.5个周期
第四个要介绍的是ADC规则序列寄存器(ADC_SQR1~3),
第五个要介绍的是ADC规则数据寄存器(ADC_DR)。
换时的各种状态。
三.实验内容
一.实验步骤
1)开启PA口时钟,设置PA0为模拟输入。
STM32F103RBT6的ADC通道0在PA0上,所以,我们先要使能PORTA的时钟,然后设置PA0为模拟输入。
2)使能ADC1时钟,并设置分频因子。
要使用ADC1,第一步就是要使能ADC1的时钟,在使能完时钟之后,进行一次ADC1的复位。
接着我们就可以通过RCC_CFGR设置ADC1的分频因子。
分频因子要确保ADC1的时钟(ADCCLK)不要超过14Mhz。
3)设置ADC1的工作模式。
在设置完分频因子之后,我们就可以开始ADC1的模式配置了,设置单次转换模式、触发方式选择、数据对齐方式等都在这一步实现。
4)设置ADC1规则序列的相关信息。
接下来我们要设置规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为1,然后设置通道0的采样周期。
5)开启AD转换器,并校准。
在设置完了以上信息后,我们就开启AD转换器,执行复位校准和AD校准,注意这两步是必须的!不校准将导致结果很不准确。
6)读取ADC值。
在上面的校准完成之后,ADC就算准备好了。
接下来我们要做的就是设置规则序列0里
面的通道,然后启动ADC转换。
在转换结束后,读取ADC1_DR里面的值就是了。
通过以上几个步骤的设置,我们就可以正常的使用STM32的ADC1来执行AD转换操作了。
二,程序代码
void Adc_Init(void)
{
//先初始化IO口
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
GPIOA->CRL&=0XFFFF0000;//PA0 1 2 3 anolog输入
//通道10/11设置
RCC->APB2ENR|=1<<9; //ADC1时钟使能
RCC->APB2RSTR|=1<<9; //ADC1复位
RCC->APB2RSTR&=~(1<<9);//复位结束
RCC->CFGR&=~(3<<14); //分频因子清零
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降!
RCC->CFGR|=2<<14;
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16; //独立工作模式
ADC1->CR1&=~(1<<8); //非扫描模式
ADC1->CR2&=~(1<<1); //单次转换模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17; //软件控制转换
ADC1->CR2|=1<<20; //使用用外部触发(SWSTART) 必须使用一个事件来触发
ADC1->CR2&=~(1<<11); //右对齐
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1&=0<<20; //1个转换在规则序列中也就是只转换规则序列1
//设置通道0~3的采样时间
ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采样时间清空
ADC1->SMPR2|=7<<9; //通道3 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<6; //通道2 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<3; //通道1 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<0; //通道0 239.5周期,提高采样时间可以提高精确度
ADC1->CR2|=1<<0; //开启AD转换器
ADC1->CR2|=1<<3; //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件设置并由硬件清除。
在校准寄存器被初始化后该位将被清除。
ADC1->CR2|=1<<2; //开启AD校准
while(ADC1->CR2&1<<2); //等待校准结束
//该位由软件设置以开始校准,并在校准结束时由硬件清除
}
//获得ADC值
//ch:通道值0~3
u16 Get_Adc(u8 ch)
{
//设置转换序列
ADC1->SQR3&=0XFFFFF
ADC1->CR2|=1<<22; //启动规则转换通道
while(!(ADC1->SR&1<<1));//等待转换结束
return ADC1->DR; //返回adc值
}。
接下来在adc.h文件里面输入如下代码:
#ifndef __ADC_H
#define __ADC_H
//Mini STM32开发板
//ADC 驱动代码
//正点原子@ALIENTEK
#define ADC_CH0 0 //通道0
#define ADC_CH1 1 //通道1
#define ADC_CH2 2 //通道2
#define ADC_CH3 3 //通道3
void Adc_Init(void);
u16 Get_Adc(u8 ch);
#endif
该部分代码很简单,这里我们就不多说了,这里定义的4个通道的宏定义,我们在main 函数将会用到ADC_CH0。
接下来我们在test.c里面,修改main函数如下:
int main(void)
{
u16 adcx;
float temp;
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口1初始化
LED_Init();
LCD_Init();
Adc_Init();
POINT_COLOR=RED;//设置字体为红色
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,150,"ADC_CH0_VOL:0.000V");
while(1)
{
LCD_ShowNum(156,150,adcx,1,16);//显示电压值
temp-=adcx;
temp*=1000;
LCD_ShowNum(172,150,temp,3,16);
LED0=!LED0;
delay_ms(250);
}。