是Analog-to-Digital Converter的缩写。指的是模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。AD转换就是模数转换,也可以是整流。顾名思义,就是把模拟信号转换成数字信号。
模拟量可以是电压、电流等电信号,也可以是压力、温度、湿度等非电信号。
A/D转换后,输出的数字信号可有8位、10位、12位、14位和16位等。
一般分为四个步骤进行,即取样、保持、量化和编码。而且前两个步骤(取样和保持)在电路中完成,后两个步骤(量化和编码)在ADC中完成。
积分型、逐次逼近型、并行比较型/串并行型、调制型和电容阵列逐次比较型及压频变换型。
(1)规则通道组:相当正常运行的程序。最多16个通道。规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则组转换的总数应写入ADC_SQR1寄存器的L[3:0]中;
(2)注入通道组:相当于中断。最多4个通道。 注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转化的总数应写入ADC_JSQR寄存器的L[1:0]中;
(3)通道组流程图如下:
(1)单次转换内容如下图:
(2)多次转换内容如下图:
(3)多次转换中涉及的自动注入内容如下图:
(1)单次扫描:触发一次,把设定的转换通道依次转换一次;
(2)单次不扫描:触发一次,把设定的第一个通道转换一次;
(3)连续扫描:触发一次,把设定的通道转换依次转换一次,然后又回到第一个转换重新启动一轮转换,如此循环;
(4)连续不扫描:触发一次,不停的对第一个通道进行转换。
(1)ADC1初始化函数:
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
(2)开启GPIOC/ADC1时钟代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使能GPIOC时钟
(3)IO口初始化代码:
GPIO_InitTypeDef GPIO_ADC1_Init; //定义GPIOC结构体变量
GPIO_ADC1_Init.GPIO_Mode = GPIO_Mode_AN; //模拟输入
GPIO_ADC1_Init.GPIO_Pin = GPIO_Pin_0; //0引脚
GPIO_ADC1_Init.GPIO_Speed = GPIO_Fast_Speed; //50MH翻转速度(数据的速度)
GPIO_ADC1_Init.GPIO_PuPd = GPIO_PuPd_NOPULL; //无上下拉(浮空)
GPIO_Init(GPIOC,&GPIO_ADC1_Init);
(4)ADC1初始化代码配置
ADC_InitTypeDef ADC1_vol_Init;
ADC1_vol_Init.ADC_ContinuousConvMode = DISABLE; //单次转换
ADC1_vol_Init.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
// ADC1_vol_Init.ADC_ExternalTrigConv = ; //外部线触发
ADC1_vol_Init.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //无触发源选择
ADC1_vol_Init.ADC_NbrOfConversion = 1; //通道数选择
ADC1_vol_Init.ADC_Resolution = ADC_Resolution_12b;//精度选择12位
ADC1_vol_Init.ADC_ScanConvMode = DISABLE; //失能扫描
ADC_Init(ADC1, &ADC1_vol_Init);
(5)ADC通用寄存器初始化配置
ADC_CommonInitTypeDef ADC1_CommonInit;
ADC1_CommonInit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//DMA是否使能
ADC1_CommonInit.ADC_Mode =ADC_Mode_Independent;//单个ADC工作,ADC模式选择(独立、协同等)
ADC1_CommonInit.ADC_Prescaler =ADC_Prescaler_Div4;//预分频,84MHZ/4=21MHZ <= 36MHZ
ADC1_CommonInit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;//两次采样间隔时间(一般最大)
ADC_CommonInit(&ADC1_CommonInit);
(6)使能ADC1和设置通道和采样时间代码
ADC_Cmd( ADC1, ENABLE); //使能ADC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); //设置通道和采样时间(规则组通道)1:序列号
(7)编写获取光照影响电压值函数
u16 ADC1_SY(void){
//规则组设置通道及转换顺序,转换时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); //设置通道和采样时间(规则组通道)1:序列号
ADC_SoftwareStartConv(ADC1); //软件触发
//判断规则组测量转换是否完成
while( ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC) != SET ){;} //读取SoftwareStart位是否置1
ADC_ClearFlag(ADC1,ADC_FLAG_EOC); //清规则组转换完成标志位
return ADC_GetConversionValue( ADC1);//读取AD值
}
(8)编写获取ADC平均值函数
u16 GetAverageADCValue(void){
u16 adcValue[10]; // 存储10次ADC转换结果的数组
u16 averageValue = 0; // 平均值
ADC1_Init(); // 调用ADC1初始化
// 进行10次采样
for (int i = 0; i < 10; i++) {
adcValue[i] = ADC1_SY(); // 获取ADC转换结果
}
// 取中间两次转换结果,计算平均值
averageValue = (adcValue[4] + adcValue[5]) / 2;
return averageValue;
}
#include "adc1.h"
void ADC1_Init(void){
//使能GPIOC/ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 使能GPIOC时钟
//IO口初始化
GPIO_InitTypeDef GPIO_ADC1_Init; //定义GPIOC结构体变量
GPIO_ADC1_Init.GPIO_Mode = GPIO_Mode_AN; //模拟输入
GPIO_ADC1_Init.GPIO_Pin = GPIO_Pin_0; //0引脚
GPIO_ADC1_Init.GPIO_Speed = GPIO_Fast_Speed; //50MH翻转速度(数据的速度)
GPIO_ADC1_Init.GPIO_PuPd = GPIO_PuPd_NOPULL; //无上下拉(浮空)
GPIO_Init(GPIOC,&GPIO_ADC1_Init);
//ADC1初始化
ADC_InitTypeDef ADC1_vol_Init;
ADC1_vol_Init.ADC_ContinuousConvMode = DISABLE; //单次转换
ADC1_vol_Init.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
// ADC1_vol_Init.ADC_ExternalTrigConv = ; //外部线触发
ADC1_vol_Init.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //无触发源选择
ADC1_vol_Init.ADC_NbrOfConversion = 1; //通道数
ADC1_vol_Init.ADC_Resolution = ADC_Resolution_12b;//精度选择12位
ADC1_vol_Init.ADC_ScanConvMode = DISABLE; //失能能扫描
ADC_Init(ADC1, &ADC1_vol_Init);
//ADC通用寄存器初始化配置
ADC_CommonInitTypeDef ADC1_CommonInit;
ADC1_CommonInit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//DMA是否使能
ADC1_CommonInit.ADC_Mode =ADC_Mode_Independent;//单个ADC工作,ADC模式选择(独立、协同等)
ADC1_CommonInit.ADC_Prescaler =ADC_Prescaler_Div4;//预分频,84MHZ/4=21MHZ <= 36MHZ
ADC1_CommonInit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;//两次采样间隔时间(一般最大)
ADC_CommonInit(&ADC1_CommonInit);
//启动ADC
ADC_Cmd( ADC1, ENABLE); //使能ADC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); //设置通道和采样时间(规则组通道)1:序列号
}
u16 ADC1_SY(void){
//规则组设置通道及转换顺序,转换时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); //设置通道和采样时间(规则组通道)1:序列号
ADC_SoftwareStartConv(ADC1); //软件触发
//判断规则组测量转换是否完成
while( ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC) != SET ){;} //读取SoftwareStart位是否置1
ADC_ClearFlag(ADC1,ADC_FLAG_EOC); //清规则组转换完成标志位
return ADC_GetConversionValue( ADC1);//读取AD值
}
u16 GetAverageADCValue(void){
u16 adcValue[10]; // 存储10次ADC转换结果的数组
u16 averageValue = 0; // 平均值
// 初始化ADC1
ADC1_Init();
// 进行10次采样
for (int i = 0; i < 10; i++) {
adcValue[i] = ADC1_SY(); // 获取ADC转换结果
}
// 取中间两次转换结果,计算平均值
averageValue = (adcValue[4] + adcValue[5]) / 2;
return averageValue;
}
#ifndef _ADC1_H_
#define _ADC1_H_
#include "stm32f4xx.h"
void ADC1_Init(void);
u16 ADC1_SY(void);
u16 GetAverageADCValue(void);
#endif
#include "delay.h"
#include "usart1.h"
#include "adc1.h"
int main{
Delay_Init(168);
Usart1_Init(115200);//波特率、频率
ADC1_Init();
printf("程序已启动\r\n"); //验证串口是否可行
while(1){
//光照影响电压值
float V = ADC1_SY()*3.3/4096; //计算并打印电压值的浮点型结果
printf("V = %.2f\r\n",V);
u16 B = ADC1_SY();
printf("B = %u\r\n",B);
Delay_ms(500);
}
}