STM32ADC模数转换器(STM32笔记)
目录
ADC
简介:
ADC(Analog-Digital Converter)模拟-数字转换器
ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
12位逐次逼近型ADC,1us转换时间
输入电压范围:0~3.3V,转换结果范围:0~4095
18个输入通道,可测量16个外部和2个内部信号源
规则组和注入组两个转换单元
模拟看门狗自动监测输入电压范围
STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
逐次逼近型ADC

1.通道选择开关,有八路模拟电压输入,由下方的地址锁存和译码控制。
例如:地址锁存输入011,那就是IN3号通道输入
2.比较器:把输入电压跟DAC的输出电压进行比较
3.DAC把SAR里面的数字量转换成模拟量跟输入电压进行比较。采用二分法
4.二分法:如果DAC输出量大于输入电压,那么DAC的输出量就会取一半再跟输入量进行比较,最多比较八次
5.当他们近似相等时,就会把结果输出到8位三态锁存缓冲器中,等到OE输出使能有效时,才会输出结果到总线中
6.定时和控制逻辑:输入START和CLOCK信号,是一个开工指令。当转换完成后,会置EOC标志位提醒转换完成
ADC框图:

GPIO端口控制模拟输入,进入多路开关。
软件配置通道选择,多路开关选通你指定的那一路信号。
选中的信号被送入 “注入通道” 或 “规则通道”,再进入 “模拟至数字转换器”,转换成数字量。
转换结果存入对应的寄存器,供 CPU 或 DMA 读取
注入通道数据寄存器可以同时存储四条通路的数据,但是规则通路数据寄存器只能存储最新的一个通道的数据。
上方注入和规则数据寄存器会引出一条导线通向一个或门,最后通向EOC标志位。(即注入和规则任意通路完成发出的完成信号都会通向EOC标志位)
注入通道数据寄存器转换结束后,也会输出一个注入转换结束的信号置JEOC标志位。
另外还可以设置一个模拟看门狗,对输出结果进行一个操作,只输出阈值内的量
(为什么要单独把注入数据寄存器单独引出一条信号通路呢?因为注入和规则一起连接了一个或门,当这条通路被规则单独使用时,注入组则可以使用另外一条路)
上方的EOC,JEOC和AWD都是中断标志位,后面的是中断使能信号。这里不做中断说明
下面的注入组和规则组的开始触发信号是START信号。
触发源有两种:
- 软件触发:调用一条代码
- 硬件触发:就是图中的部分
这些通道通过一个多路选择器来触发注入/规则数据寄存器的开始信号
触发控制:

ADC基本结构

输入通道:

转换模式:
- 单次转换,非扫描模式
- 多次转换,非扫描模式
- 单次转换,扫描模式
- 多次转换,扫描模式
1.
2.
3.
4.
注意:扫描模式下只能储存最后一个通道的数据。其他数据要通过DMA转运
对齐方式:

转换时间:

校准:
这一步直接被封装好了,不用理解原理。直接调用几个函数就行了
硬件电路:

程序源码:
配置步骤:
- 开启RCC时钟,包括ADC和GPIO的时钟。ADCCLK的分频器也要配置
- 配置GPIO为模拟输入模式
- 配置多路开关,把左边的通道接入右边的规则组里面(点菜)
- 配置ADC转换器
- 中断和看门狗,需要的自行配置
- 校准
AD.h模块:
#ifndef __AD__H
#define __AD__H
void AD_Init(void);
uint16_t ADC_GetValue(void);
#endif
main.c模块:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Oled.h"
#include "AD.h"
uint16_t ADValue;
float Voltage;
int main(void)
{
OLED_Init();
AD_Init();
OLED_ShowString(1,1,"ADValue:");
OLED_ShowString(2,1,"Voltage:0.00V");
while(1)
{
ADValue = ADC_GetValue();
Voltage = (float)ADValue / 4095 * 3.3;
OLED_ShowNum(1,9,ADValue,5);
OLED_ShowNum(2,9,Voltage,1);
OLED_ShowNum(2,11,(uint16_t)(Voltage * 100) % 100, 2);
Delay_ms(100);
}
}
AD.c模块:
#include "stm32f10x.h" // Device header
/*
*
* 1.开启RCC时钟,包括ADC和GPIO的时钟。ADCCLK的分频器也要配置
* 2.配置GPIO为模拟输入模式
* 3.配置多路开关,把左边的通道接入右边的规则组里面(点菜)
* 4.配置ADC转换器
* (中断和看门狗,需要的自行配置)
* 5.校准
*/
void AD_Init(void)
{
//1.开启RCC时钟,包括ADC和GPIO的时钟。ADCCLK的分频器也要配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ADCCLK时钟最大14MHz 6分频后是12MHz
//2.配置GPIO为模拟输入模式
GPIO_InitTypeDef GPIOA_InitStructure;
/*这里的模拟输入模式是ADC的专属模式,让GPIO的输入输出失效,信号直接进入板子里面的ADC外设*/
GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIOA_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIOA_InitStructure);
//3.配置多路开关,把左边的通道接入右边的规则组里面(点菜)
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
/*ADC1的菜单里,菜品:通道0,排在第一位,采样时间是55.5个ADC周期*/
//还想再点几个菜的话,就多调用计次这个函数
//ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
//4.配置ADC转换器
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //配置ADC的工作模式(独立模式/双ADC模式)
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //设置右对齐还是左对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发转换选择
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //选择 连续/单次 转换模式 ENABLE(连续)/DISABLE(单次)
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //选择扫描模式(ENABLE)还是非扫描模式(DISABLE)
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数目:在扫描模式下,总共会用到几个通道
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
//5.对ADC进行校准
ADC_ResetCalibration(ADC1); //复位校准
/*软件置1,开启复位校准,复位校准完成后,硬件自动清零*/
while(ADC_GetResetCalibrationStatus(ADC1) == SET); //等待复位校准完成(未完成则一直开始等待)
ADC_StartCalibration(ADC1); //开始校准
/*软件置1,开启校准,校准完成后,硬件自动清零*/
while(ADC_GetCalibrationStatus(ADC1) == SET); //等待校准完成
}
uint16_t ADC_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件开启转换命令
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}
ADC配置代码:
//4.配置ADC转换器
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
/*配置ADC的工作模式(独立模式/双ADC模式)*/
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
/*设置右对齐还是左对齐*/
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
/*外部触发转换选择*/
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
/*选择 连续/单次 转换模式 ENABLE(连续)/DISABLE(单次)*/
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
/*选择扫描模式(ENABLE)还是非扫描模式(DISABLE)*/
ADC_InitStructure.ADC_NbrOfChannel = 1;
/*通道数目:在扫描模式下,总共会用到几个通道*/
ADC_Init(ADC1, &ADC_InitStructure);
更多推荐

所有评论(0)