STM32微项目08:ADC单通道/多通道模式采集详解
huo
一、微项目实现目标:
1,利用STM32内置的ADC模块,将外部模拟量信号(0-3.3v)转化成12位有效(16位数据)的数字量(0-4095),在将采集的数字除4095,就会得到对应采集的模拟量信号;
二、微项目硬件配置需求:
stm32F103C8T6核心板一块;
0.96寸OLED显示,用于显示计数;
模拟量输入(滑动电阻、光线传感器、温度传感器等),接线时刻,需要接AO输出口;
三、前置知识:
1,逐次逼近型ADC的处理逻辑
在外部有模拟量输入时,DAC设置参数并输出模拟量,对比模拟量数据和输入的模拟量相近或相等时刻,则配置输出的DAC的数字量参数,就是输入模拟量的对应转化后的数字量;
2,ADC整体控制逻辑框图
①数据流:外部GPIO模拟量—–AD转换器(注入组和规则组)—–触发转化 —-转化数值存放到AD数据寄存器中
②ADC关键模块解析
图中2:表示外部模拟量的输入端口,有18个通道入口其中0-15是外部接口
图中1:表示启动ADC启动
图中3:表示ADC的时钟,ADC1最大接受时钟14MHZ的,外部接入72MHZ,需要配置分频处理;
图中4:具体转化执行模块
图中5:注入通道和规则通道寄存器,转化后数据存放在这。其中规则通道只有一个,所有转化后,需要立即取走,否则后续转化数据会覆盖掉;
图中6:DMA请求,ADC转化后,配合DMA模式进行数据转移;
③输入通道及转化模式
1-ADC1通道情况
1)单次模式和连续模式:数据转化时,是否连续转化。单次模式,仅转化一次;连续模式时,转换一次 后再从头开始重新转化;
2)扫描模式和非扫描模式:扫描模式,就是将序列中数据从头到尾全部转化;非扫描模式,仅转化序列中的第一个;
3)几种数据转化模式:
单次转换,非扫描模式
连续转换,非扫描模式
、
单次转换,扫描模式
连续转换,扫描模式
④触发转化,一般选用软件触发
⑤转化后,寄存器数据对齐方式,一般选用靠右侧对齐
⑥转化校准,具体代码中执行
四、代码逻辑分析:
①开启GPIO和ADC的时钟,并且对输入ADC通道进行分频处理;
②配置GPIO模式,模拟输入
③配置AD输入通道,即配置输入通道和所在处理序列;
④初始化AD模块,并配置AD模式\数据对齐\扫描模式\连续模式等
⑤打开ADC使能开关(并非开启后ADC就会工作,需要软件触发源触发执行)
⑥执行AD校准模块
⑦开启软件触发ADC执行工作
五、代码示例:
①开启GPIO和ADC的时钟,并且对输入ADC通道进行分频处理;
//打开ADC1时钟 和GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//配置ADC1的分频,ADC最高支持14mhz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
②配置GPIO模式,模拟输入
//初始化GPIO模块,模拟输入模式
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
③配置AD输入通道,即配置输入通道和所在处理序列;
第二个参数:通道接入的端口
第三个参数:规则序列的位置
第四个参数:采样时间
//配置ad输入通道
ADC_RegularChannelConfig( ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
④初始化AD模块,并配置AD模式\数据对齐\扫描模式\连续模式等
//初始化AD模块
ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//单次模式
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right ;//转化后在寄存器内右对齐
ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None ;//软件触发,不使用硬件触发转化
ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//独立模式
ADC_InitStruct.ADC_NbrOfChannel=1;
ADC_InitStruct.ADC_ScanConvMode=DISABLE;//扫描模式
ADC_Init( ADC1, & ADC_InitStruct);
⑤打开ADC使能开关(并非开启后ADC就会工作,需要软件触发源触发执行)
//开启adc电源
ADC_Cmd(ADC1,ENABLE);
⑥执行AD校准模块
//ADC校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1)==SET);//完成后会被硬件置为reset
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1)==SET);
⑦获取转化后的寄存器数值
注意是先进行软件触发,之后等待标志位E0C,再返回数据
uint16_t AD_getvalue(void)
{
ADC_SoftwareStartConvCmd( ADC1, ENABLE);//软件触发转换
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
//转化完成后,返回的是reset.读完后,对应寄存器会自动变为reset
return ADC_GetConversionValue(ADC1);
}
最后在主函数中,简答配置
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "OLED.H"
#include "ad.H"
uint16_t advalue=0;
float voltage=0.0;
int main()
{
OLED_Init();
ADC_init();
OLED_ShowString(1,1,"ADvalue:");
OLED_ShowString(2,1,"voltage:0.00v");
while(1)
{
advalue= AD_getvalue();
voltage=(float)advalue/4095*3.3;//输出电压
OLED_ShowNum(1,9,advalue,4);
OLED_ShowNum(2,9,voltage,1);
OLED_ShowNum(2,11,(uint16_t)(voltage*100)%100,2);
Delay_ms(1000);
}
}