STM32-ADC

ADC(模拟-数字转化器)

  • ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁;
  • AD转换步骤:采样、保持、量化、编码;
  • 12位逐次逼近型ADC,1us转换时间;
  • 输入电压范围:0~3.3V,转换结果范围:0~4095;
  • 18个输入通道,可以测量16个外部和2个内部信号源(整个系列);
  • 有规则组和注册组两个转换单位;
  • 模拟看门狗自动监测输入电压范围;
  • 总转换时间:T = 采样时间 + 12.5个ADC周期;
  • STM32F1003C8T6 ADC资源:ADC1、ADC2、10个外部输入通道。

整个ADC的基本结构图如下:

一、ADC单通道测量

本实验用PA0连接一个简易继电器对模拟信号进行转换。

先对ADC模块进行编写,ADC.c文件:

复制代码
#include "stm32f10x.h"                  // Device header

void ADC_init(void)
{
    //打开ADC1时钟
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1 ,ENABLE);
	//打开GPIOA时钟
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE);
	
    //对ADC时钟进行分频配置,ADC频率不能超过14MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
    //对PA0进行初始化配置,这里使用模拟输入模式(ADC专属模式)
	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);
	
	//"点菜"对规则组的通道进行配置
	ADC_RegularChannelConfig(ADC1 ,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	
    //对ADC进行初始化配置
	ADC_InitTypeDef ADC_InitStructer;
	ADC_InitStructer.ADC_Mode =ADC_Mode_Independent;//使用的是ADC单通道模式
	ADC_InitStructer.ADC_DataAlign =ADC_DataAlign_Right;//选择右对齐方式
	ADC_InitStructer.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None;
    //软件触发,这里不需要外部触发
	ADC_InitStructer.ADC_ContinuousConvMode =DISABLE;//单次转换模式
	ADC_InitStructer.ADC_ScanConvMode =DISABLE;//非扫描模式
	ADC_InitStructer.ADC_NbrOfChannel =1;//需要转换的通道数量
	ADC_Init(ADC1 ,&ADC_InitStructer);
	
    //打开ADC1
	ADC_Cmd(ADC1 ,ENABLE);
	
    //对ADC进行校正,标志位是独立的,完成了某个操作才会将对应的标志位SET
	ADC_ResetCalibration(ADC1 );//复位校正
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//检测是否复位校正
	ADC_StartCalibration(ADC1);//进行校正
	while(ADC_GetCalibrationStatus(ADC1) == SET);//检测是否进行校正
	
}

//读值函数:将ADC转换后的值读取出来
uint16_t Get_Value(void)
{
	ADC_SoftwareStartConvCmd(ADC1 ,ENABLE );//选择软件触发方式
	while(ADC_GetFlagStatus(ADC1 ,ADC_FLAG_EOC) == RESET);//判断是否完成转换
	uint16_t value = ADC_GetConversionValue(ADC1);//将DR中的值读出来
	ADC_ClearFlag(ADC1 ,ADC_FLAG_EOC);//清除标志位
	return value;//返回读取值
}

ADC.h文件:

复制代码
#ifndef _ADC_H
#define _ADC_H
void ADC_init(void);
uint16_t Get_Value(void);

#endif

再在主函数中对各模块函数进行调用,main.c文件:

复制代码
#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "OLED.h"
#include "ADC.h"

uint16_t Value;//创建变量用于存储转换后直接读取值
float Voltage;//创建变量用于存储电压值
int main(void)
{	
	OLED_Init();
	ADC_init ();//各模块初始化值
	OLED_ShowString (1,1,"Value:");//显示提示字符串
	OLED_ShowString (2,1,"Voltage:0.000");//显示提示字符串
	while(1)
	{
		Value = Get_Value();//实时读取值
		Voltage = (float)Get_Value() / 4095 * 3.3;//对电压进行转换
		OLED_ShowNum (1,7,Value,4);//实时显示直接读取值
		OLED_ShowNum (2,9,Voltage,1);
        //实时显示电压值,由于函数的局限性,将其分为整数、小数两部分进行显示
		OLED_ShowNum (2,11,(uint16_t)(Voltage *1000) % 1000,3);
		Delay_ms (500);//延时500ms,让ADC转换效果更加明显
	}
}

二、ADC多通道

本实验分别用PA0~PA3连接继电器、光敏传感器、热敏传感器、发射式红外传感器,将使用ADC1的0~3四个通道接收各模块的模拟量,并将其转换为数字量。(由于ADC规则组,只有一个寄存器用于寄存数据,这里还是选择使用单次转换、非扫描模式进行转换)

先对ADC模块进行编写,ADC.c文件:

复制代码
#include "stm32f10x.h"                  // Device header


void ADC_init(void)
{
    //打开ADC1和GPIOA
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1 ,ENABLE);
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE);
	
    //对ADC时钟进行分频配置
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
    //对PA0~PA3四个引脚进行初始化配置,这里均配置为:模拟输入模式
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init (GPIOA ,&GPIO_InitStruct);

    //不在这里对ADC规则组通道进行配置
	
	//对ADC单元进行初始化配置
	ADC_InitTypeDef ADC_InitStructer;
	ADC_InitStructer.ADC_Mode =ADC_Mode_Independent;
	ADC_InitStructer.ADC_DataAlign =ADC_DataAlign_Right;
	ADC_InitStructer.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None;
	ADC_InitStructer.ADC_ContinuousConvMode =DISABLE;
	ADC_InitStructer.ADC_ScanConvMode =DISABLE;
	ADC_InitStructer.ADC_NbrOfChannel =1;
	ADC_Init(ADC1 ,&ADC_InitStructer);
	
    //打开ADC1
	ADC_Cmd(ADC1 ,ENABLE);
	
    //对ADC进行校正
	ADC_ResetCalibration(ADC1 );
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1) == SET);
	
}

//对ADC规则组进行灵活配置,对转换后的数值进行读取
uint16_t Get_Value(uint8_t ADC_Channel)//将具体通道作为函数参数
{
    //对ADC规则组进行灵活配置
	ADC_RegularChannelConfig(ADC1 ,ADC_Channel,1,ADC_SampleTime_55Cycles5);
	ADC_SoftwareStartConvCmd(ADC1 ,ENABLE );//选择软件触发ADC转换
	while(ADC_GetFlagStatus(ADC1 ,ADC_FLAG_EOC) == RESET);//判断数据是否转换完成
	uint16_t value = ADC_GetConversionValue(ADC1);//读取转换值
	ADC_ClearFlag(ADC1 ,ADC_FLAG_EOC);//清除标志位
	return value;//返回读取值
}

ADC.h文件:

复制代码
#ifndef _ADC_H
#define _ADC_H
void ADC_init();
uint16_t Get_Value(uint8_t ADC_Channel);

#endif

最后在主函数中调用ADC模块函数实现ADC多通道转换,mian.c文件:

复制代码
#include "stm32f10x.h"    // Device header
#include "Delay.h"
#include "OLED.h"
#include "ADC.h"

uint16_t Value0;
uint16_t Value1;
uint16_t Value2;
uint16_t Value3;//创建四个变量,用于存储四个通道的读取值

int main(void)
{	
	OLED_Init();
	ADC_init();//各模块初始化
	OLED_ShowString (1,1,"Value0:");
	OLED_ShowString (2,1,"Value1:");
	OLED_ShowString (3,1,"Value2:");
	OLED_ShowString (4,1,"Value3:");//四个通道对应的提示字符串
	while(1)
	{
		Value0 = Get_Value(ADC_Channel_0);
		Value1 = Get_Value(ADC_Channel_1);
		Value2 = Get_Value(ADC_Channel_2);
		Value3 = Get_Value(ADC_Channel_3);//对四个通道实时读取值进行存储,函数要进行传参
		OLED_ShowNum (1,8,Value0,4);
		OLED_ShowNum (2,8,Value1,4);
		OLED_ShowNum (3,8,Value2,4);
		OLED_ShowNum (4,8,Value3,4);//对四个通道读取值进行实时显示
		Delay_ms (100);//延时增强观感
	}
}

最终效果:四个通道均能实时将模拟量转换为数字量,并在OLED屏幕上显示出来。

注意事项:

  • ADC的规则组只有一个寄存器,注入组有四个寄存器;
  • 在使用扫描模式进行转换时,转换完一个值需要将ADC中DR的值用DMA进行转运;
  • OLED_ShowNum()函数无法直接显示浮点数,需要使用取巧的方法进行显示。
相关推荐
Messy create3 小时前
【储能系统三大核心】
网络·stm32·单片机·算法·能源
Nomarsgo3 小时前
生产车间产线巡检解决方案:基于联控 Lionconit PTC-1006 工业手持平板电脑打造移动化、数字化车间巡检终端
单片机·嵌入式硬件·电脑
IT实战课堂之秋老师3 小时前
基于IOT技术的太阳能板表面清洁程度检测系统设计
单片机
智购科技无人售货机厂家3 小时前
2026自动售货机出货口防夹手设计:从红外检测到电机反转的工程实践~YH
大数据·linux·单片机·嵌入式硬件·微信
2601_966799043 小时前
酷嗨米J300:多平台同步直播的硬件级解法,一台相机三路输出不卡顿
嵌入式硬件
CHENKONG_CK4 小时前
晨控CK-FR08系列与欧姆龙NX系列PLC配置MODBUSTCP例程使用手册
网络·单片机·嵌入式硬件
XiHongShi20164 小时前
51基础学习视频分享(2),三极管,点亮LED灯
单片机·学习
youshi66686 小时前
stm32-看门狗
stm32·单片机·嵌入式硬件
M158227690556 小时前
三格串口服务器:RS232/485 设备联网解决方案
运维·服务器·单片机