STM32-ADC

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哈哈~

之前做了个心率监测系统,需要的可以下载

https://download.csdn.net/download/zdw6868/10643057

猜你喜欢

转载自blog.csdn.net/zdw6868/article/details/82349025