STM32学习笔记---ADC转换

目录

一、什么是ADC

二、如何配置ADC

1、ADC框图

2、功能说明

2.1 ADC转换开关

2.2 ADC时钟

2.3 通道选择

2.4 单次转换模式

2.5 连续转换模式

2.6 扫描模式

2.7 注入通道管理

2.8 不连续采样模式

2.9 数据对齐

2.10 预分频

2.11 外部触发转换和触发极性

3、程序设计

3.1 查询等待方式

3.2 中断方式

三、具体使用ADC

需求1:光敏传感器利用查询等待方式获取数据

需求2:毒气传感器利用查询等待方式获取数据

需求3:毒气传感器 & 光敏传感器在同一个ADC利用查询等待方式获取数据

需求4:毒气传感器 & 光敏传感器 &温度传感器在同一个ADC利用查询等待方式获取数据

 需求5:毒气传感器 & 光敏传感器 &温度传感器在同一个ADC利用中断方式获取数据


一、什么是ADC

        12 位 ADC 逐次近型模数转换器。它具有多达 19 个复用通道,可测量来自 16 个外部源、两个内部源和 VBAT 通道的信号这些通道的 A/D 转换可在单次、连续、扫描或不连续采样模式下进行 ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中

什么是12 位逐次近型ADC

CPU只能处理数字量,我们要处理模拟量,需要将模拟量转换成数字量,在处理此过程就是ADC转换;芯片中有一个转换器可以将模拟信号转换成数字信号,就是ADC控制器

12位:ADC的采样深度

什么是采样深度?

总结:ADC的采样深度越深,转换的结果越精细;采样深度是衡量ADC性能的重要指标

ADC转换分为两个过程:采样+转换

采样:采集模拟量

转换:将模拟量转换为数字量

采样的原理:逐次逼近型(曹冲称象)

 

主要参数:

1、参考电压  每一个ADC转换器都会有一个参考电压  -------STM32f407 3.3v

2、精度  8bit  10bit   12bit  14bit  16bit

STM32f407中集成的是12bit精度(如果芯片内部集成的精度不够,可以外接高精度ADC 转换芯片)

3、ADC的分辨率   指它能够产生的不同数字输出的数量,通常以位数来表示。对于一 个N位的ADC,其分辨率是2的N次方。因此,12位ADC的分辨率是2^12,即4096。分辨率也就是精度。

ADC的输入电压范围被均匀地划分为这些离散的步骤,每个步骤对应一个唯一的数字输出值。例如,如果ADC的参考电压是3.3V,那么每个步骤大约代表 3.3v / 4096份 (约0.805mv)的电压变化分辨率。

电压转换公式:Vx=(3.3/4096)*数字量

(数字量/4096)*100可得到转换后数字量所占分辨率的百分比,相比于电压,更直观的看出转换后的状态。

总结:通过ADC转换后的结果就是数字量(份数)

二、如何配置ADC

1、ADC框图

2、功能说明

2.1 ADC转换开关

ADC控制器使能的情况下,ADON 位置 1 时,会将 ADC 从掉电模式中唤醒 

SWSTART 位置 1 开始转换规则通道

JSWSTART 位置 1 开始转换,注入通道

相关寄存器:ADC_CR2

2.2 ADC时钟

提供ADC转换所需要的时钟脉冲----APB2

2.3 通道选择

通过寄存器配置转换个数和转换排序

规则组:

设置有几个转换

第一个转换的通道号

第二个转换的通道号

..............

注入组同理。

相关寄存器:ADC_SQRx/ADC_JSQRx

        规则:ADC_SQRx

L代表着有几个通道转换

SQx:第几个转换,写入的是通道号

若不写入通道号则无法对该通道进行转换

注入:ADC_JSQR

注入同理。

特殊说明:

测量内部温度   只能使用ADC1_IN16

内部参考电压  只能用ADC1_IN17 

测量VBT         只能用ADC1_IN18

2.4 单次转换模式

在单次转换模式下, ADC 执行一次转换 

CONT 位为 0 时,可通过以下方式启动此模式

ADC_CR2 寄存器中的 SWSTART 位置 1(仅适用于规则通道) 

JSWSTART 位置 1(适用于注入通道) 

外部触发(适用于规则通道或注入通道) 

完成所选通道的转换之后: 

如果转换了规则通道:

转换数据存储在 16 ADC_DR 寄存器中

EOC(转换结束)标志置 1   

EOCIE 位置 1产生中断

如果转换了注入通道:

转换数据存储在 16 ADC_JDR1 寄存器中

JEOC(注入转换结束)标志置 1

JEOCIE 位置 1 时将产生中断

然后, ADC 停止。 

单次:CONT位  0  

连续:CONT位  1

2.5 连续转换模式

在连续转换模式下, ADC 结束一个转换后立即启动一个新的转换 

CONT 位为 1 时,可通过以下方式启动此模式

ADC_CR2 寄存器中的 SWSTART 位置 1(仅适用于规则通道) 

JSWSTART 位置 1(适用于注入通道) 

外部触发(适用于规则通道或注入通道)

完成所选通道的转换之后:同单次转换

单次与连续的区别:单次转换只执行一次,而连续转换就是会循环转换

2.6 扫描模式

此模式用于扫描一组模拟通道 

当只有一个转换的时候,应该用非扫描模式。

当有多于1个转换的时候,就要用扫描模式。

可以和单次转换、连续转换进行组合:

单次扫描模式     

连续扫描模式

2.7 注入通道管理

触发注入

要使用触发注入,必须将 ADC_CR1 寄存器中的 JAUTO 位清零。 

自动注入

如果将 JAUTO 位置 1,则注入组中的通道会在规则组通道之后自动转换

说明:

2.8 不连续采样模式

此模式适用于分组转换

相关寄存器:ADC_CR1

规则组

可将 ADC_CR1 寄存器中的 DISCEN 位置 1 来使能此模式 

注入组

可将 ADC_CR1 寄存器中的 JDISCEN 位置 1 来使能此模式

2.9 数据对齐

右对齐

相关寄存器:ADC_CR2

2.10 预分频

一般选择2分频,如果数据偏差过大就选定在所在的频率范围内

相关寄存器:ADC_CCR

2.11 外部触发转换和触发极性

可以通过外部事件(例如,定时器捕获、 EXTI 中断线)触发转换 ----- 少用

相关寄存器:ADC_CR2

规则组:


注入组:

3、程序设计

3.1 查询等待方式

总体思路

ADC通道初始化配置函数

{

        /*IO控制器配置*/

        /*ADC控制器配置*/

}

获取数据转换函数

{

        //开始转换

        //等待转换完成

        //获取转换数据

        //返回数字量

}

详细思路

ADC通道初始化配置函数

{

        /*IO控制器配置*/

        //端口时钟使能

        //端口模式选择----模拟模式

        /*ADC控制器配置*/

        //ADC控制器时钟使能

        //CR1

        //CR2

        //SMPRx

        //SQRx

        //CCR

}

u16获取数据转换函数

{

        //开始转换

        //等待转换完成

        //获取转换数据   把数据寄存器的值赋给一个变量

        //返回数字量

}

3.2 中断方式

总体思路

ADC通道初始化配置函数

{

        /*IO控制器配置*/

        /*ADC控制器配置*/

        /*NVIC控制器配置*/

}

中断服务函数

{

        //判断是否为转换完成信号

        //清除中断标志位

        //获取转换数据   把数据寄存器的值赋给一个变量

}

详细思路

ADC通道初始化配置函数

{

        /*IO控制器配置*/

        //端口时钟使能

        //端口模式选择----模拟模式

        /*ADC控制器配置*/

        //ADC控制器时钟使能

        //CR1

        //CR2

        //SMPRx

        //SQRx

        //CCR

        /*NVIC控制器配置*/

}

中断服务函数

{

        //判断是否为转换完成信号

        //清除中断标志位

        //获取转换数据   把数据寄存器的值赋给一个变量

}

        定时中断--->开始转换

三、具体使用ADC

需求1:光敏传感器利用查询等待方式获取数据

每100毫秒转换一次,通过串口打印转换数据(ADC1)

分析:

光敏----------PC2---------adc1_ch12

光敏电阻通常具有四个接口:AO(模拟信号输出)、DO(开关信号输出)、‌GND(接地)、‌VCC(电源正极)。接线时,需要将AO接口连接到单片机的AD转换模块,用于读取光线强度的模拟信号;DO接口则用于输出开关信号,当光线超过设定的阈值时,DO接口输出低电平(或高电平,具体取决于电路设计)。电源VCC通常接3.3V电源,GND接电源负极。

光敏电阻所用ADC初始化配置函数:

/*
函数名:adc1_ch12_light_sensor
函数功能:ADC1通道12转换初始化
返回值:void
形参:void
函数说明:
光敏----------PC2---------adc1_ch12

*/
void adc1_ch12_lightsensor_init(void)
{
	/*IO控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1 << 2);
	//端口模式选择----模拟模式
	GPIOC->MODER &= ~(3 << 4);
	GPIOC->MODER |=  (3 << 4);
	/*ADC控制器配置*/
	//ADC控制器时钟使能
	RCC->APB2ENR |= (1 << 8);
	//CR1
	ADC1->CR1 &= ~(1 << 8);//扫描模式  单个通道使用
	ADC1->CR1 &= ~(3 << 24);//分辨率---12位精度
	
	//CR2
	ADC1->CR2 &= ~(1 << 1);//单次转换模式
	ADC1->CR2 |=  (1 << 10);//结束转换选择
	ADC1->CR2 &= ~(1 << 11);//右对齐
	
	//SMPRx
	ADC1->SMPR1 &= ~(7 << 6);
	ADC1->SMPR1 |=  (7 << 6);//采样时间
	
	//SQRx
	ADC1->SQR1 &= ~(0xf << 20);//规则通道序列长度---共1个转换
	ADC1->SQR1 &= ~(0x1f << 0);
	ADC1->SQR3 |= (12 << 0);//写入通道12
	//CCR
	ADC->CCR &= ~(3 << 16);
	ADC->CCR |=  (1 << 16);//预分频  4分频
	//使能ADC转换
	ADC1->CR2 |= (1 << 0);
	
	
}

获取数据函数:

/*
函数名:get_lightsensor_data
函数功能:光敏传感器获取数据函数
返回值:void
形参:void
函数说明:
在环境光线亮度达不到设定阈值时, DO 端输出高电平, 
当外界环境光线亮度超过设定阈值时, DO 端输出低电平
*/

u16 get_lightsensor_data(void)
{
	u16 adc1_data = 0;
	//开始转换
	ADC1->CR2 |= (1 << 30);//开始转换规则通道
	//等待转换完成
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	adc1_data = ADC1->DR;
	//返回数字量
	return adc1_data;
	
}

二次封装关敏传感器初始化配置函数:

/*
函数名:lightsensor_init
函数功能:光敏传感器初始化
返回值:void
形参:void
函数说明:
在环境光线亮度达不到设定阈值时, DO 端输出高电平, 
当外界环境光线亮度超过设定阈值时, DO 端输出低电平
*/

void lightsensor_init(void)
{
		adc1_ch12_lightsensor_init();

}

需求2:毒气传感器利用查询等待方式获取数据

每100毫秒转换一次,通过串口打印转换数据(ADC2)

分析:

毒气----------PC0---------adc2_ch10

毒气传感器通常具有四个接口:AO(模拟信号输出)、DO(开关信号输出)、‌GND(接地)、‌VCC(电源正极)。接线时,需要将AO接口连接到单片机的AD转换模块,用于读取毒气浓度的模拟信号;DO接口则用于输出开关信号,当毒气浓度超过设定的阈值时,DO接口输出高电平(或低电平,具体取决于电路设计)。电源VCC通常接3.3V电源,GND接电源负极。

光敏电阻所用ADC初始化配置函数:

/*
函数名:adc1_ch10_gassensor
函数功能:ADC1通道10转换初始化
返回值:void
形参:void
函数说明:
毒气----------PC0---------adc2_ch10

*/
void adc2_ch10_gassensor_init(void)
{
	/*IO控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1 << 2);
	//端口模式选择----模拟模式
	GPIOC->MODER &= ~(3 << 0);
	GPIOC->MODER |=  (3 << 0);
	/*ADC控制器配置*/
	//ADC控制器时钟使能
	RCC->APB2ENR |= (1 << 9);
	//CR1
	ADC2->CR1 &= ~(1 << 8);//扫描模式  单个通道使用
	ADC2->CR1 &= ~(3 << 24);//分辨率
	
	
	//CR2
	ADC2->CR2 &= ~(1 << 1);//单次转换模式
	ADC2->CR2 |=  (1 << 10);//结束转换选择
	ADC2->CR2 &= ~(1 << 11);//右对齐
	
	
	//SMPRx
	ADC2->SMPR1 &= ~(7 << 6);
	ADC2->SMPR1 |=  (7 << 6);//采样时间
	
	//SQRx
	ADC2->SQR1 &= ~(0xf << 20);//规则通道序列长度
	ADC2->SQR1 |=  (10 << 0);//写入通道10
	//CCR
	ADC->CCR &= ~(3 << 16);
	ADC->CCR |=  (1 << 16);//预分频  4分频
	//使能ADC转换
	ADC2->CR2 |= (1 << 0);
	
	
}

获取数据函数:

/*
函数名:get_gassensor_data
函数功能:毒气传感器获取数据函数
返回值:void
形参:void
函数说明:

*/

u16 get_gassensor_data(void)
{
	 u16 adc2_data = 0;
	//开始转换
	ADC2->CR2 |= (1 << 30);//开始转换规则通道
	//等待转换完成
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	adc2_data = ADC2->DR;
	//返回数字量
	return adc2_data;
	
}

二次封装关敏传感器初始化配置函数:

/*
函数名:gassensor_init
函数功能:毒气传感器初始化
返回值:void
形参:void
函数说明:

*/
void gassensor_init(void)
{
		adc2_ch10_gassensor_init();
	
}

需求3:毒气传感器 & 光敏传感器在同一个ADC利用查询等待方式获取数据

敏和毒气都进行转换.同一个ADC要有两个转换

分析:

光敏----------PC2---------adc1_ch12

毒气----------PC0---------adc1_ch10

扫描模式,通道排序

光敏电阻和毒气传感器所用ADC初始化配置函数(两个通道):

/*
函数名:adc1_ch12_light_sensor
函数功能:ADC1通道10和12转换初始化
返回值:void
形参:void
函数说明:
光敏和毒气都进行转换.同一个ADC要有两个转换 
光敏----------PC2---------adc1_ch12
毒气----------PC0---------adc1_ch10

*/
void adc1_sensor_init(void)
{
	/*IO控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1 << 2);
	
	//端口模式选择----模拟模式
	GPIOC->MODER &= ~(3 << 4);
	GPIOC->MODER |=  (3 << 4);
	GPIOC->MODER &= ~(3 << 0);
	GPIOC->MODER |=  (3 << 0);
	
	/*ADC控制器配置*/
	//ADC控制器时钟使能
	RCC->APB2ENR |= (1 << 8);
	//CR1
	ADC1->CR1 |=  (1 << 8);//扫描模式  多个通道使用
	ADC1->CR1 &= ~(3 << 24);//分辨率
	
	//CR2
	ADC1->CR2 &= ~(1 << 1);//单次转换模式
	ADC1->CR2 |=  (1 << 10);//结束转换选择
	ADC1->CR2 &= ~(1 << 11);//右对齐
	
	
	//SMPRx
	ADC1->SMPR1 &= ~(7 << 6);
	ADC1->SMPR1 |=  (7 << 6);//通道12光敏采样时间
	
	ADC1->SMPR1 &= ~(7 << 0);
	ADC1->SMPR1 |=  (7 << 0);//通道10毒气采样时间
	//SQRx
	ADC1->SQR1 &= ~(0xf << 20);//规则通道序列长度
	ADC1->SQR1 |=  (1 << 20);//两个通道两次转换
	
	ADC1->SQR3 |= (12 << 0) | (10 << 5);//写入通道10、12
	//CCR
	ADC->CCR &= ~(3 << 16);
	ADC->CCR |=  (1 << 16);//预分频  4分频
	//使能ADC转换
	ADC1->CR2 |= (1 << 0);
	
}

获取数据函数:

/*
函数名:get_light_or_gassensor_data
函数功能:光敏&毒气传感器获取数据函数
返回值:void
形参:void
函数说明:
*/
ADC_t get_light_or_gassensor_data(void)
{
	 ADC_t data;
	
	
	//开始转换
	ADC1->CR2 |= (1 << 30);//开始转换规则通道
	//等待转换完成
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	data.adc_light  = ADC1->DR;
	//等待转换完成
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	data.adc_gas   = ADC1->DR;
	
	return data;
	
	
}

二次封装光敏和毒气传感器初始化配置函数:

/*
函数名:gas_light_sensor_init
函数功能:毒气&光敏传感器初始化
返回值:void
形参:void
函数说明:

*/
void gas_light_sensor_init(void)
{
	adc1_sensor_init();
	
	
}

需求4:毒气传感器 & 光敏传感器 &温度传感器在同一个ADC利用查询等待方式获取数据

光敏、毒气和芯片内部温度都进行转换,ADC1要有三个转换

分析:

芯片内部温度必须用ADC1_IN16   不涉及IO口

温度使能配置

光敏电阻、毒气传感器和芯片内部传感器所用ADC初始化配置函数(三个通道):

/*
函数名:adc1_3sensor_init
函数功能:ADC1通道10、12和16转换初始化
返回值:void
形参:void
函数说明:
光敏和毒气都进行转换.同一个ADC要有两个转换 
光敏----------PC2---------adc1_ch12
毒气----------PC0---------adc1_ch10
温度----------------------adc1_IN16 
*/
void adc1_3sensor_init(void)
{
	/*IO控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1 << 2);
	
	//端口模式选择----模拟模式
	GPIOC->MODER &= ~(3 << 4);
	GPIOC->MODER |=  (3 << 4);
	GPIOC->MODER &= ~(3 << 0);
	GPIOC->MODER |=  (3 << 0);
	
	/*ADC控制器配置*/
	//ADC控制器时钟使能
	RCC->APB2ENR |= (1 << 8);
	//CR1
	ADC1->CR1 |=  (1 << 8);//扫描模式  多个通道使用
	ADC1->CR1 &= ~(3 << 24);//分辨率
	
	//CR2
	ADC1->CR2 &= ~(1 << 1);//单次转换模式
	ADC1->CR2 |=  (1 << 10);//结束转换选择
	ADC1->CR2 &= ~(1 << 11);//右对齐
	
	
	//SMPRx
	ADC1->SMPR1 &= ~(7 << 6);
	ADC1->SMPR1 |=  (7 << 6);//通道12光敏采样时间
	
	ADC1->SMPR1 &= ~(7 << 0);
	ADC1->SMPR1 |=  (7 << 0);//通道10毒气采样时间
	
	ADC1->SMPR1 &= ~(7 << 18);
	ADC1->SMPR1 |=  (7 << 18);//通道16毒气采样时间
	//SQRx
	ADC1->SQR1 &= ~(0xf << 20);//规则通道序列长度
	ADC1->SQR1 |=  (2 << 20);//三个通道三次转换
	
	ADC1->SQR3 |= (12 << 0) | (10 << 5) | (16 << 10);//写入通道10、12、16
	//CCR
	ADC->CCR &= ~(3 << 16);
	ADC->CCR |=  (1 << 16);//预分频  4分频
	ADC->CCR |= (1<<23);//使能温度传感器
	//使能ADC转换
	ADC1->CR2 |= (1 << 0);
	
}

光敏&毒气&温度传感器获取数据函数:

/*
函数名:get_3sensor_data
函数功能:光敏&毒气&温度传感器获取数据函数
返回值:void
形参:void
函数说明:
*/
ADC_t get_3sensor_data(void)
{
	 ADC_t data;
	 u16 temp;
	
	//开始转换
	ADC1->CR2 |= (1 << 30);//开始转换规则通道
	//等待转换完成  光敏
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	data.adc_light  = ADC1->DR;
	
	//等待转换完成   毒气
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	data.adc_gas   = ADC1->DR;
	
	//等待转换完成   温度
	while(!(ADC1->SR & (1 << 1)));
	//获取转换数据
	temp = ADC1->DR;
	
	data.adc_temp = (temp * (3.3/4096)*1000 - 760) / 2.5 + 25;
	
	return data;
}

芯片内部温度的计算公式:

Vsense指的是ADC转换后的电压值

 需求5:毒气传感器 & 光敏传感器 &温度传感器在同一个ADC利用中断方式获取数据

光敏电阻、毒气传感器和芯片内部传感器所用ADC中断初始化配置函数(三个通道):

/*
函数名:adc1_ch12_Interrupt_init
函数功能:ADC1通道10、12、16转换中断初始化
返回值:void
形参:void
函数说明:
光敏----------PC2---------adc1_ch12
毒气----------PC0---------adc1_ch10
温度----------------------adc1_IN16 

*/
void adc1_ch12_10_16_Interrupt_init(void)
{
	/*IO口控制器配置*/
	//端口时钟使能
	RCC->AHB1ENR |= (1<<2);
	//端口模式配置 --- 模拟模式
	GPIOC->MODER &= ~((3<<4)|(3<<0));
	GPIOC->MODER |= ((3<<4)|(3<<0));		
	
	/*ADC控制器配置*/
	//ADC时钟使能
	RCC->APB2ENR |= (1<<8);
	//CR1
	ADC1->CR1 &= ~(3<<24);				//12位分辨率
	ADC1->CR1 |= (1<<8);					//扫描模式

	ADC1->CR1 |= (1<<5);					//EOC中断使能
	//CR2
	ADC1->CR2 &= ~(1<<11);				//数据右对齐
	ADC1->CR2 &= ~(1<<1);				//单次转换模式
	ADC1->CR2 |= (1<<10);				//EOCS位,每个通道转换完成EOC都会置1
	//SMPRx
	ADC1->SMPR1 |= (7<<6);				//通道12	480个周期的采样时间
	ADC1->SMPR1 |= (7<<0);				//通道10	480个周期的采样时间
	ADC1->SMPR1 |= (7<<18);				//通道16	480个周期的采样时间
	//SQRx
	ADC1->SQR1 &= ~(0xf<<20);
	//ADC1->SQR1 |= (2<<20);				//3个转换通道		
	ADC1->SQR1 |= (2<<20);				//3个转换通道	
	
	ADC1->SQR3 &= ~(0x1f<<0);			
	ADC1->SQR3 |= (12<<0);				//第一个转换	通道12
	
	ADC1->SQR3 &= ~(0x1f<<5);			
	ADC1->SQR3 |= (10<<5);				//第二个转换	通道10
	
	ADC1->SQR3 &= ~(0x1f<<10);			
	ADC1->SQR3 |= (16<<10);				//第三个转换	通道16
	
	//CCR
	ADC->CCR &= ~(3<<16);					//2分频ADC 42MHz
  ADC->CCR |= (1<<23);					//使能温度传感器
	/*NVIC*控制器配置*/
	//优先级分组		----在主函数
	//计算优先级编码值
	u32 pri= NVIC_EncodePriority (5,0,2);
	//设置具体中断源
	NVIC_SetPriority(ADC_IRQn, pri);
	//使能NVIC响应通道
	NVIC_EnableIRQ(ADC_IRQn);
	
	//使能ADC1
	ADC1->CR2 |= (1<<0);
}

中断服务函数:

一开始的想法

看似逻辑没问题但是还是卡住,为什么?

因为在同一个ADC多个通道转换的过程中,每一个通道都是用同一个中断服务函数的,并且只要开启转换,ADC控制器就会依次进行转换(转换时间不固定);ADC控制器转换完成(EOC置1),然后又去执行下一次转换(每100ms),导致内核执行打印(约需要100ms)时被卡死了,所以可以在全部转换完成后再统一打印

那为什么能打印前两个?

因为第一个ADC转换的时间长了,到第二个转换触发中断后内核进行打印的时候,又触发了第三个转换的中断,当内核到达第三个中断时,ADC转换又触发了中断,依次进行,进而导致内核卡死

优化后的程序

/*
函数名:ADC_IRQHandler
函数功能:ADC转换中断服务函数
返回值:void
形参:void
函数说明:
*/
ADC_t data;
u8 ADC_cnt = 0;
void ADC_IRQHandler(void)
{
	//判断是否为转换完成信号
	if(ADC1->SR & (1 << 1))
	{
		ADC_cnt ++;
		//清除中断标志位
		ADC1->SR &= ~(1 << 1);
		if(ADC_cnt == 1)//光敏
		{
			data.adc_light = 100 - ADC1->DR / 4096.0 * 100;//获取转换数据   把数据寄存器的值赋给一个变量
		}
		else if(ADC_cnt == 2)//毒气
		{
			data.adc_gas = ADC1->DR / 4096.0 * 100;
		}
		else if(ADC_cnt == 3)
		{
			data.adc_temp = (ADC1->DR * (3.3/4096)*1000 - 760) / 2.5 + 25;
			printf("光敏数据:%d%%\r\n",data.adc_light);
			printf("毒气数据:%d%%\r\n",data.adc_gas);
			printf("芯片内部温度:%.2f℃\r\n",data.adc_temp);
			ADC_cnt = 0;
		}
		
	}
	
	
}

定时中断:

    if(Tim7_cnt[4] >= 100)
	{
		ADC1->CR2 |= (1 << 30);//开始转换规则通道
		Tim7_cnt[4] = 0;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值