ADC实验采集电压

 

ADC实验

STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。

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

STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。举个例子,在室内和室外都有监控,平常都检查室外监控,这个时候想看一下室内监控,就按住一个按键跳转到室内监控,看完后松手继续进行室外监控的检查。

STM32F4 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组最多包含 4 个通道。STM32F4 的 ADC 可以进行很多种不同的转换模式,我们本章仅介绍如何使用规则通道的单次转换模式。

ADC相关寄存器

1. ADC 控制寄存器(ADC_CR1 和 ADC_CR2)。

 

ADC_CR1 的 SCAN 位,该位用于设置扫描模式,由软件设置和清除,如果设置为 1,则使用扫描模式,如果为 0,则关闭扫描模式。这里我们不用扫描模式。RES[25:24]用来设置ADC的分辨率。采用00位12bit分辨率,01——10bit,10——8bit,11——6bit。ADC_CR2的ADON用来开关AD转换器,ALIGN选择对齐模式:左对齐和右对齐;CONT用来设置转换模式,这里是单次转换模式,设置位0。不采用外部触发模式。

2. 第二个是 ADC 通用控制寄存器(ADC_CCR)

设置ADCCLK = PCLK2 / 4 =84/4 =21MHz。即设置ADCPRE位01,分频系数位4。MULTI[4:0]用于多重ADC 模式选择,这里我们选择独立模式,置0即可。

3. 第三个是 ADC 采样时间寄存器(ADC_SMPR1 和 ADC_SMPR2)。这两个寄存器用于设置通道 0~18 的采样时间,每个通道占用 3 个位。

对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低ADC的转换速率。ADC 的转换时间可以由以下公式计算:Tcovn=采样时间+12 个周期。

例如:当 ADCCLK=21Mhz 的时候,并设置 480 个周期的采样时间,则得到:Tcovn=480+12=492个周期=23.43us。

4. 第四个是 ADC 规则数据寄存器(ADC_DR)。规则序列中的 AD 转化结果都将被存在这个寄存器里面。

5. 最后一个ADC 寄存器为 ADC 状态寄存器(ADC_SR),该寄存器保存了 ADC 转换时的各种状态。

这里我们仅介绍将要用到的是 EOC 位,我们通过判断该位来决定是否此次规则通道的 AD转换已经完成,如果该位位 1,则表示转换完成了,就可以从 ADC_DR 中读取转换结果,否则等待转换完成。

实现ADC的步骤

接下来我们通过ADC1的通道5来进行AD转换,根据数据手册

PA5可以作为AD的模拟输入。

实现步骤

  1. 构建GPIO结构体,ADC通用控制寄存器结构体,ADC初始化结构体
  2. 设置时钟。ADC挂在总线APB2上,首先要开启AHB1。
  3. 配置GPIO初始化,主要是PA5的mode位模拟输入AN
  4. 配置ADC_CommonInitStructure 初始化
  5. 配置ADC_InitStructure 初始化
  6. 开启AD转换器, ADC_Cmd(ADC1,ENABLE)
  7. 读取ADC的值,并多次取得ADC的值作平均处理,或者使用一阶低通滤波器的算法。

代码部分

#include "adc.h"
#include "delay.h"
void Adc_Init()
{ //1.定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;

//2.开启时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

//3.设置GPIO引脚为AN
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
//GPIO_InitStructure.GPIO_OType=
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
//GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
GPIO_Init(GPIOA,&GPIO_InitStructure);

//4.设置ADC通用控制寄存器
ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4;
//ADCCLK=PCLK2/4=84/4=21MHz ADC时钟不要超过36Mhz
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);

//5.设置ADC寄存器
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
//ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_NbrOfConversion=1;
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//12位模式
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_Init(ADC1,&ADC_InitStructure);

//6.开启ADC转换器
ADC_Cmd(ADC1,ENABLE);
}

//7.获取ADC的值
u16 Get_ADCvalue(u8 channel)
{
ADC_RegularChannelConfig(ADC1,channel,1,ADC_SampleTime_480Cycles);
ADC_SoftwareStartConv(ADC1);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));

return ADC_GetConversionValue(ADC1);
}
//8.获取ADC的平均值
u16 Get_Average_ADCvalue(u8 ch,u16 times)
{
u32 temp = 0;u8 t;
for(t=0;t<times;t++)
{
temp+=Get_ADCvalue(ch); 
delay_ms(5);//如何一次一次的取得Get_ADCvalue的值呢?一次次的调用就可以不断取得新的value了。
}
return temp/times;
}

//第2种算法 低通滤波器
float Get_Low_filter_ADCvalue(u8 ch)
{
static float a;
static float prevalue;
a = 0.65;
float fil_value = a*Get_ADCvalue(ch) + (1-a)*prevalue;
prevalue = fil_value;
return fil_value;
}
#ifndef __ADC_H__
#define __ADC_H__
#include "sys.h"

void Adc_Init(void);
u16 Get_ADCvalue(u8 channel);
u16 Get_Average_ADCvalue(u8 ch,u16 times);
float Get_Low_filter_ADCvalue(u8 ch);
#endif
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "adc.h"

extern float Get_Low_filter_ADCvalue(u8 ch);

int main(void)
{ 

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168);      //初始化延时函数
uart_init(115200);//初始化串口波特率为115200

LED_Init();  //初始化LED
 LCD_Init();           //初始化LCD FSMC接口
POINT_COLOR=BLUE;     //画笔颜色:红色
Adc_Init();//Adc初始化
u16 ADC_VALUE;//ADC的值
u16 adcx;
float ADC_VALUE_VOLTAGE;//ADC所测电压值

LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VAL: ");
LCD_ShowString(30,170,200,16,16,"ADC1_CH5_VOL:0.000V"); //这里显示了小数点

 while(1) 
{  
//需要将 ADC_value转化成 3.3V为最大值的电压,然后通过LCD显示出来
ADC_VALUE = Get_Low_filter_ADCvalue(ADC_Channel_5);//获取ADC初始值
LCD_ShowNum(134,150,ADC_VALUE,4,16);//显示ADC初始值
ADC_VALUE_VOLTAGE = ADC_VALUE*3.3 / 4096;
adcx = (int)(ADC_VALUE_VOLTAGE);
//这里需要注意,LCD无法直接显示小数。要显示小数就得先显示整数,再显示小数。
LCD_ShowNum(134,170,adcx,1,16);//显示整数部分
ADC_VALUE_VOLTAGE-=adcx;
ADC_VALUE_VOLTAGE*=1000;
LCD_ShowxNum(150,170,ADC_VALUE_VOLTAGE,3,16,0X80);

LED0=!LED0; 
delay_ms(250);
} 
}

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值