1.STM32ADC简介:
ADC(Analog to Digital Converter)即模数转换器,它可以将模拟信号转换成数字信号。按照其转换原理主要分为逐次逼近型、双积分型、电压频率转换型三种。
STM32 ADC主要特性:
- 12位分辨率;
- 转换结束、注入转换结束和发生模拟看门狗事件时产生中断;
- 单次和连续转换模式;
- 从通道0到通道n的自动扫描模式;
- 自校准;
1)STM32一般都有3个ADC,这些ADC可以独立的使用,可以使用双重或三重的模式,这种模式是为了提高ADC采样率;
2)STM32的ADC一般是12位的逐次逼近型的模拟转换器,多达18个复用通道可以测量16个外部的模拟通道和2个内部的信号源;
3)这些AD转换可以是单次连续扫描或间断模式执行,ADC结果可以左对齐或右对齐存放在16位的一个数据存储器中;
4)ADC还具有模拟看门狗的特性,运行应用程序来检测输入电压是否超出用户定义的阀值上限和下限,如果超过则触发模拟看门狗中断;
2.STM 32介绍:
- 带内嵌数据一致性的数据对齐;
- 采样间隔可以按通道分别编程;
- 规则转换和注入转换均有外部触发选项;
- 间断模式;
- 双重模式(带2个或以上ADC的器件);
- ADC转换时间;
- ADC供电要求:2.4V到3.6V;
- ADC输入范围:VREF-≤VIN≥VREF+;
- 规则通道转换期间有DMA请求产生;
STM ADC结构框图:
① 第一部分:电压输入引脚:
在设计电路中,将VEF+连接到基准电压源中,基准电压源实现的方法有很多种如TL431,将基准电压设置为固定的2.5V,实现高精度测量;
② 第二部分:输入通道(18个=16外+2内):
ADC2和ADC3不具有内部通道,ADC具有2个内部通道(内部温度传感器+内部参考电压VREF);
③ 第三部分:通道转换顺序(注入通道(最多4路)+规则通道(最多16路)):
- 如果在规则通道进行转换的时候,有注入通道插入进来,就要先执行注入通道转换等注入通道转换完成之后,再回到规则通道往下继续转换;
- 每组包含一个转换序列,序列可以按任意序列在任意的通道上进行完成,通过这个转换序列可以将要转换的通道进行排序;
- 规则通道组序列寄存器有3个(SQR3、SQR2、SQR1),SQR3(控制1到6的转换),SQR2(控制7到12的转换),SQR1(控制13到16的转换);
- 注入通道组序列寄存器只有1个,最多支持4个通道(JSQR(00->1次转换,01->2次转换,10->3次转换,11->4次转换));
- 如果在转换期间修改了SQR或JSQR寄存器中的值,将复位当前转换,并向ADC发送一次新的启动脉冲以转换新选择的通道;
④ 第四部分:触发源:
触发极性(4个):禁止触发检测、上升沿触发检测、下降沿触发检测、上升沿和下降沿触发检测;
⑤ 第五部分:ADC时钟(APB2最大支持14M):
- 72/6=12M;
- 采样的周期,可以通过ADC的采样时间寄存器来设置,ADC采样时间寄存器(SMPRE(10~17通道)+SMPR2(0~9通道));
- 每个通道可以分别用不同的采样时间,每个通道采样时间可以独立设置,采样周期最小是1.5个TCLK;
- Tcon(总的转换时间)=采样时间+12.5周期;
⑥ 第六部分:数据寄存器:
- ADC是12位,数据寄存器都是16位,因此存在左对齐和右对齐;
- 规则通道中(只有1个寄存器,容易出现数据覆盖),当转换完成之后,就立刻将数据取走,可以开启DMA将数据自动的搬到其他地方去;
⑦ 第七部分:中断:
只有在ADC1和ADC3中,才可以产生DMA请求;
3.ADC配置步骤:
ADC相关库函数在stm32f10x_adc.c和stm32f10x_adc.h文件中;
- 使能端口时钟和ADC时钟,设置引脚模式为模拟输入:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
- 设置ADC的分频因子:RCC_ADCCLKConfig(RCC_PCLK2_Div6);
- 初始化ADC参数,包括ADC工作模式、规则序列等:void ADC_Init();
- 使能ADC并校准:void ADC_Cmd()、ADC_ResetCalibration(ADC1) 复位校准、ADC_StartCalibrationStatus(ADC1) 开启校准;
- 读取ADC转换值:void ADC_RegularChannelConfig()、 void ADC_SoftwareStartConvCmd()、ADC_GetConversionValue()、ADC_GetFlagStatus()
4.ADC模数转换实验:
功能实现:通过ADC1通道1采样外部电压值,将采样的AD值和转换后的电压值通过串口打印出来,同时LED0指示灯闪烁,提示系统正常运行。
(1)原理图:
(2)主函数:
#include "delay.h"
#include "led.h"
#include "usart1.h"
#include "adc.h"
int main(){
u8 i=0;
u16 val=0;
float vol=0.0f;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置分组
delay_init(); //延时初始化
LED_Init();
usart1_Init(9600); //串口通信初始化
ADCx_Init(); //ADC1初始化
while(1)
{
i++;
if(i%20==0)
{
LED0=!LED0;
}
delay_ms(10);
if(i%100==0) //1s
{
val=Get_ADC_Value(ADC_Channel_1,20); //获取转换并且滤波后的值;通道1,20次
printf("检测的AD值=%d\r\n",val);
//AD值 0~4095,电压采集范围:0~3.3V
vol=(float)val*(3.3/4095);
printf("检测的电压值=%2.f V\r\n",vol);
printf("\r\n");
}
}
}
(3)头文件:
#ifndef __ADC_H
#define __ADC_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
void ADCx_Init(void); //ADC1初始化
u16 Get_ADC_Value(u8 ch,u8 times); //读取ADC转换值
#endif
(4)ADC模数转换功能函数:
#include "stm32f10x.h"
#include "delay.h"
#include "adc.h"
/*
功能:ADC1初始化->ADC1(PA1)
变量:无
返回值:无
*/
void ADCx_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
//1.使能端口时钟和ADC时钟,设置引脚模式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN; //模拟输入模式
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1; //PA1
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//2.设置ADC的分频因子
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ADC最大不超过16M,(72/6=12)<16
//3.初始化ADC参数,包括工作模式、规则序列等
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工作模式设置为独立模式
ADC_InitStruct.ADC_NbrOfChannel=1; //通道数
ADC_InitStruct.ADC_ScanConvMode=DISABLE; //不扫描
ADC_Init(ADC1,&ADC_InitStruct);
//4.使能ADC校准
ADC_Cmd(ADC1,ENABLE); //使能ADC1
ADC_ResetCalibration(ADC1); //复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //复位校准完成标志,完成后退出循环
ADC_StartCalibration(ADC1); //开启校准
while(ADC_GetCalibrationStatus(ADC1)); //开启复位校准完成标志,完成后退出循环
//5.开启软件触发方式
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
/*
功能:读取ADC转换的值
变量:ch:选择通道 times:读取的次数
返回值:返回平均值(进行滤波后的值)
*/
u16 Get_ADC_Value(u8 ch,u8 times)
{
u8 i=0;
u32 temp_val=0; //存储获取到的ADC转换值
//ADC规则通道配置
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5); //选择ADC、通道、通道数量、采样周期
//读取数据
for(i=0;i<times;i++)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //开启ADC转换,因为使用的是单次转换,所以每次转换都需要开启
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); //ADC_FLAG_EOC:规则组转换完成
temp_val+=ADC_GetConversionValue(ADC1); //获取转换的值
delay_ms(10);
}
return temp_val/times; //返回进过滤波后的数据
}
(5)实验结果: