1、12 位 ADC 是一种逐次逼近型模拟数字转换器。它有多达 18 个通道,可测量 16 个外部和 2 个内部信号源。
各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。 ADC 的结果可以左对齐或右对齐方式存储在
16 位数据寄存器中。
模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
ADC 的输入时钟不得超过 14MHz,它是由 PCLK2 经分频产生。
2、ADC 主要特征
● 12 位分辨率
● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断
● 单次和连续转换模式
● 从通道 0 到通道 n 的自动扫描模式
● 自校准
● 带内嵌数据一致性的数据对齐
● 采样间隔可以按通道分别编程
● 规则转换和注入转换均有外部触发选项
● 间断模式
● 双重模式(带 2 个或以上 ADC 的器件)
● ADC 转换时间:
─ STM32F103xx 增强型产品:时钟为 56MHz 时为 1μs(时钟为 72MHz 为 1.17μs)
─ STM32F101xx 基本型产品:时钟为 28MHz 时为 1μs(时钟为 36MHz 为 1.55μs)
─ STM32F102xxUSB 型产品:时钟为 48MHz 时为 1.2μs
─ STM32F105xx 和 STM32F107xx 产品:时钟为 56MHz 时为 1μs(时钟为 72MHz 为 1.17μs)
● ADC 供电要求: 2.4V 到 3.6V
● ADC 输入范围: VREF- ≤ VIN ≤ VREF+
● 规则通道转换期间有 DMA 请求产生。
● 转换范围:0~3.6V (3.6v---->当你需要将采集的数据用电压来显示的话:设你采集的数据为:x[0~4095],此时的计算公式就 为:(x / 4096) * 3.6))
●最多有18个通道:16个外部通道
2个内部通道:连接到温度传感器和内部参考电压(VREFINT = 1.2V)
3、ADC相关寄存器
① RCC_APB2ENR
使能ADC的时钟
② 时钟配置寄存器(RCC_CFGR)
设置预分频因子
③ ADC控制寄存器 1(ADC_CR1)
设置工作模式
④ ADC控制寄存器 2(ADC_CR2)
关于内部温度传感器参考中文手册
⑤ ADC规则序列寄存器 1(ADC_SQR1)
⑥ ADC采样时间寄存器 1(ADC_SMPR1)
对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降
低 ADC 的转换速率。 ADC 的转换时间可以由以下公式计算:
Tcovn=采样时间+12.5 个周期
其中: Tcovn 为总转换时间,采样时间是根据每个通道的 SMP 位的设置来决定的。例如,
当 ADCCLK=14Mhz 的时候,并设置 1.5 个周期的采样时间,则得到: TCONV = 1.5 + 12.5 = 14周期 = 14×(1 / (14 × 1000000)) = 1μs。
4、程序实现
① adc.c
#include "adc.h"
#include "delay.h"
/*
函数功能:ADC1规则通道初始化
说 明:初始化规则通道1 -->PA1
*/
void ADC1_Init(void)
{
//GPIO配置
RCC->APB2ENR |=1<<2;
GPIOA->CRL &=0xFFFFFF0F;
GPIOA->CRL |=0x00000000; //模拟输入
//ADC1时钟使能
RCC->APB2ENR |=1<<9;
RCC->APB2RSTR |=1<<9;
RCC->APB2RSTR &=~(1<<9);
//设置分频因子
RCC->CFGR &=~(3<<14);
RCC->CFGR |=2<<14; //12MHz
//设置工作模式
ADC1->CR1 &=~(0xF<<16);//清零,同时也是设置为独立模式 0000
//ADC1->CR1 &=~(0x7<<13);//一个通道
ADC1->CR1 &=~(1<<8);//非扫描模式
ADC1->CR2 |=1<<23;//启用温度传感器
ADC1->CR2 |=1<<20;//使用外部事件启动转换
ADC1->CR2 |=0x7<<17;//选择SWSTART触发
ADC1->CR2 &=~(1<<11);//右对齐
ADC1->CR2 &=~(1<<1);//单次转换模式
//设置ADC1规则通道序列的相关信息
ADC1->SQR1 &=~(0xF<<20);//一个转换
ADC1->SMPR1 |=7<<18; //通道16 239.5周期 采样时间
ADC1->SMPR2 |=7<<3; //通道1(PA1) 239.5周期
//开启AD转换器,并校准
ADC1->CR2 |=1<<0; //开启AD
ADC1->CR2 |=1<<3; //初始化校准寄存器
while(ADC1->CR2&1<<3);//等待初始化校准完成
ADC1->CR2 |=1<<2; //开始较准
while(ADC1->CR2&1<<2);//等待校准完成
}
/*
函数功能:获取通道的ADC转换值
参 数:
u8 ch ->通道号
返回值:ADC转换值
*/
u16 Get_Adc1(u8 ch)
{
ADC1->SQR3 &=0xFFFFFFE0;//将第1个转换位清零
ADC1->SQR3 |=ch<<0;
ADC1->CR2 |=1<<22;//开始转换规则通道
while(!(ADC1->SR&1<<1));//等待转换完成
return ADC1->DR;
}
/*
函数功能:获取通道ch的转换值,取times次,然后平均
参 数:
u8 ch 通道号
u8 times 次数
返回值:times次ch通道转换值的平均值
*/
u16 Get_AdcAve(u8 ch,u8 times)
{
u32 sum_val=0;
u8 i;
for(i=0;i<times;i++)
{
sum_val+=Get_Adc1(ch);
delay_MS(5);
}
return sum_val/times;
}
② main.c
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"
int main(void)
{
u16 adc_dat;
float temp;
Key_Init();
Led_Init();
Usart1_Init(115200);
ADC1_Init();
while(1)
{
adc_dat=Get_AdcAve(16,10);
temp=adc_dat*3.3/4095;
printf("ADC值:%d 电压:%0.2f 温度:%0.2f\r\n",adc_dat,temp,(1.43-temp)/0.0043+25);
delay_MS(1000);
}
}
写的不是很好,勿喷 O(∩_∩)O哈哈~
之前做了个心率监测系统,需要的可以下载