1.电压输入管脚(VREF-到VREF+),VREF-和VSS届地,VREF+和VDDA届正,0-3.3V
2.16个可以采集的通道,对应不同的IO脚
3.16个通道可分为两组,规则通道可以被注入通道打断
4.进入通道触发源
5.ADC时钟,有APB2提供,最大14Mhz采样周期最小是1.5个ADCCLK(1us),通常用12M,最小1.7us
规则通道使用多通道则一个通道传输玩就输出再接下一个
7.触发中断
1开启时钟
2设置ADC分频系数
3初始化ADC
4使能并校验
5*读取转换值
ADC1的通道1引脚是PA1,连接在滑动变阻器上,这个实验就是利用AD转换来读取滑动变阻器电压
adc.c
#include "adc.h"
void ADCx_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
//1*时钟开启并配置ADC分频系数
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频,72/6=12Mhz,函数在rcc.h中
//2*GPIO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模式是模拟输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
//3*ADC初始化并使能
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC模式:单通道模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //关闭连续转换,变单次转换
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数是1
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //禁止外部触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采样数据在寄存器中右对齐
ADC_Init(ADC1,&ADC_InitStructure); //初始化
ADC_Cmd(ADC1,ENABLE); //开启ADC
//4*重置校验寄存器并开始校验
ADC_ResetCalibration(ADC1); //重置校验寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //等待重置完成
ADC_StartCalibration(ADC1); //开始校验
while(ADC_GetCalibrationStatus(ADC1));//等待校验完成
//5*开始AD转换
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
/*******************************************************************************
* 函 数 名 : Get_ADC_Value
* 函数功能 : 获取通道ch的转换值,取times次,然后平均,以提高数据的可靠性
* 输 入 : ch:通道编号
times:获取次数
* 输 出 : 通道ch的times次转换结果平均值
*******************************************************************************/
//6*获得转换后数字
u16 Get_ADC_Value(u8 ch,u8 times)
{
u8 t=0;
u32 temp_val=0;
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); //ADC1,ADC 通道,239.5 个周期,提高采样时间 可以提高精确度
for(t=0;t<times;t++) //10次
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //开始转换
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); //等待转换完成
temp_val += ADC_GetConversionValue(ADC1); //times次值累加
}
return temp_val/times; //返回转换后数字,ADC1 最大为 12 位精度, 所以返回值类型为 u16 即可
}
adc.h
#ifndef _adc_H
#define _adc_H
#include "system.h"
void ADCx_Init(void);
u16 Get_ADC_Value(u8 ch,u8 times);
#endif
main.c
#include "systick.h"
#include "led.h"
#include "system.h"
#include "key.h"
#include "usart.h"
#include "adc.h"
int main()
{
u8 i=0;
u16 Value; //得到的AD的值
float Vol; //滑动百变阻器点压
SysTick_Init(72); //系统时钟初始
LED_INIT();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART1_Init(9600);
ADCx_Init();
while(1)
{
i++;
if(i%20==0) //200ms变换一次
{
led1=!led1;
}
if(i%50==0) //500ms采集一次
{
Value = Get_ADC_Value(ADC_Channel_1,10);
printf("检测到的AD值为%d\r\n",Value);
Vol = (float)Value*(3.3/4096);/*我们使用的 ADC1 为 12 位转换精度,最大值为 2^12 即 4096,
而 ADC 的参考电压 VREF+为 3.3V,所以知道 AD 转换值就可以计算对应的电压值*/
printf("变阻器电压值为%.2f\r\n",Vol);
}
delay_ms(10);
}
}
网友评论