零死角玩转stm32中级篇4-ADC和DAC

这篇具有很好参考价值的文章主要介绍了零死角玩转stm32中级篇4-ADC和DAC。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.ADC的基础概念

1.什么是ADC

① ADC全称为Analog-to-Digital Converter,中文名称为模数转换器。ADC是一种将模拟信号转换为数字信号的电路设备,它在电子系统中扮演着非常重要的角色。
② 模拟信号是以连续的方式变化的信号,例如声音、温度等,而数字信号是以离散的方式表示的信号,它是由“0”和“1”两种状态组成。ADC将模拟信号的大小和时间上的连续性转化为数字信号来进行处理,因此在很多电子系统中都需要使用ADC。
③ ADC通常由四个主要部分组成:采样、量化、编码和输出缓冲。采样部分将连续的模拟信号转换成离散的信号,量化部分将离散的信号转换成具有固定间隔的数字化电信号,编码部分将固定间隔的数字化电信号转化为可存储、传输和处理的二进制形式,输出缓冲区将数字信号放大并存储在输出端口,便于外部电路读取。
④ ADC的精度通常通过量化位数来表示。量化位数越高,ADC的精度和分辨率会越好,但相应的芯片价格和功耗也会越高。不同的电子系统需要使用不同精度的ADC来满足需要。
⑤ 总之,ADC是电子系统中重要的基础组成部分,它将模拟信号转化为对数字信号,实现了从现实世界到数字世界的转换,为数字电路的应用提供了可能。

作用:将模拟信号转换为数字信息
转换过程:采样–>量化–>编码–>输出缓冲

2.在单片机中我们一般使用ADC技术来做什么?

① 在单片机中,我们使用ADC技术来实现模拟量的数字化采集。
② 单片机内部集成有ADC模块,我们可以通过配置单片机的寄存器操作,将外部的模拟信号输入到ADC输入端口,ADC会将其转换成数字信号,并将结果保存在特定的寄存器中。通过读取这些寄存器的值,我们就可以得到正在测量的模拟量的数字化值。
③ 单片机中常使用ADC技术的应用包括温度和湿度测量、光强度检测、电压和电流测量、电池电量测量等。在这些应用中,ADC会将模拟量信号转换为数字信号,然后通过单片机内部的处理器进行处理、分析、存储等操作,实现各种不同的智能化应用。

3.怎么查看单片机的某一个引脚是否具有ADC功能

单片机的某一个引脚是否具有该ADC功能,需要结合数据手册进行查询,一般查询芯片数据手册中的Table 5. Medium-density STM32F103xx pin definitions 表格,下图是STM32F103xx芯片的引脚信息表截图。

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

4.ADC采集和引脚数据的读取有什么区别

ADC采集和引脚数据的读取有以下几个不同之处:
① 采集方式不同:ADC采集是通过ADC模块对模拟信号的采样和转换,而引脚数据的读取是通过直接读取引脚的电平状态来获取数字信号。
② 数据类型不同:ADC采集的结果是模拟信号的数字化结果,通常是一个整型数值(例如10位的ADC采集结果就是一个0-1023的整数),而引脚数据的读取是数字信号(高电平和低电平)。
③ 精度不同:ADC采集的精度和分辨率通常比引脚数据的读取要高。ADC的精度和分辨率通常是通过芯片的参数来限定的,在一定的参考电压下,可以实现更高的精度和分辨率。而引脚数据的读取通常只能读取到高电平和低电平两种状态,精度比ADC低。
④ 用途不同:ADC主要用于模拟信号的数字化处理,通常用于传感器采集、电压测量等场景。而引脚数据的读取通常用于控制IO设备、读取开关状态、读取数字信号等场景。
⑤ 需要注意的是,在某些场景下,ADC采集和引脚数据的读取是有联系的。例如,通过ADC采集对某个传感器的模拟信号进行数字转换后,将数字量作为引脚输出,用于控制其他设备的开关状态。在这种情况下,ADC采集和引脚数据的读取就是相互关联的。

5.单片机内部采用的是数字信号,为什么还要采用ADC进行转换
  • 比如采集内部的电源电压

① 如果是单片机内部信号,一般情况下是不需要通过ADC进行转换的。对于CPU内部的数字信号,我们可以直接使用单片机提供的IO口进行读取,这些IO口所输入的数字信号是可以直接被单片机内部电路所处理的。
② 例如,单片机内部包含一个计时器,可以通过IO口读取计时器内部的计数值,这个计数值就是单片机内部的数字信号,我们可以直接使用IO口进行读取。
③ 至于电源电压,它虽然也在单片机内部,但由于它是一个模拟信号,需要通过ADC模块进行转换后才能被单片机识别和处理。注意,这里需要测量的是单片机内部电源电压,而不是单片机外部电源电压。对于单片机外部电源电压,需要借助外部的模拟信号采集电路,通过ADC模块进行转换。
④ 对于单片机内部的电源电压,可以通过单片机内部的ADC模块进行采集,但是采集到的数据也需要进行转换才能得到实际电压值。因为单片机内部的ADC模块采集到的是数值结果,而不是电压值。
⑤ 一般来说,需要通过额外的硬件电路,如光电耦合器或电压传感器等,将电源电压转换成模拟信号进行采集,然后再经过ADC模块进行数字化处理。这样可以得到实际的电压值,以便进行后续的计算和控制。

  • 电压采集采样电路设计

你可以通过这篇博文(https://blog.csdn.net/weixin_42090940/article/details/102615898) 进行学习。

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

6.ADC的分类
  • ADC的分类

ADC根据不同的工作原理和使用场景,可以分为以下几类:

1.逐次逼近型ADC:

逐次逼近型ADC是一种常见的、精度较高的ADC。它从最高位开始逼近,逐一比较,并根据比较结果不断逼近所测量的数字量。这种ADC常用于需要高精度的应用,如仪器、传感器和电路控制等领域。

2.积分型ADC:

积分型ADC利用了信号积分的特性,将模拟信号分别积分和放电,并根据放电时间和模拟电压之间的关系,计算出模拟信号的值。这种ADC通常用于需要高速且精确的应用领域,如高速数据采集和声音处理等。

3.单比较器型ADC:

单比较器型ADC具有简单设计和低功耗的优点。它通过对参考电压和输入信号的比较,确定比较器的输出来得到模拟信号的值。它通常应用于低精度的电路,如电池电压检测等。

4.脉冲编码型ADC:

脉冲编码型ADC将模拟信号编码成脉冲信号,并通过对脉冲信号的计数得到数字信号的值。这种ADC通常用于高速和低功耗的应用领域,如视频和图像处理,还可以用于移动设备和智能手表等小型电子产品的应用。

以上是ADC的一些常见分类,不同类型的ADC适用于不同的应用场景,同时,不同类型的ADC在精度、功耗、速度和价格等方面也有差异。

  • 在单片机中ADC一般采用哪一种类型

① 在单片机中,ADC一般采用逐次逼近型ADC或单比较器型ADC。逐次逼近型ADC可以提供较高的精度,而单比较器型ADC则具有简单和低功耗的优点。
② 其中,逐次逼近型ADC通常比较精确,通过比较ADC的输出和参考电压大小,确定位值输出。由于逐次逼近算法每次只确定一位比特,所以需要多次多次逼进,速度较慢。但由于现有的MCU一般都有硬件支持,因此程序也比较容易实现。
③ 单比较器型ADC是一种常见的低精度ADC,它采用单个比较器对参考电压和输入信号进行比较。它通常具有低功耗、体积小、成本低等优点,能够满足一些功耗要求较低、精度要求不高的应用场景。然而,由于单比较器型ADC的输出是一个开关量,其精度不如逐次逼近型ADC,不过它在一些应用中也显得更加实用,如电池电压检测等。
④ 综上所述,单片机的ADC根据不同的应用场景而选择逐次逼近型ADC或单比较器型ADC,以满足不同的精度、速度、功耗和成本要求。

  • STM32F103系列的单片机的ADC采用什么类型的ADC

STM32F103系列的单片机内置了12位逐次逼近型模数转换器(ADC),可采用单独或多路扩展模式进行采样转换。该ADC采用的是逐次逼近型ADC。该型号的ADC最大采样速率为1Msps,具有多通道采样功能和多种触发方式,可满足不同的应用要求。此外,STM32F103系列单片机的ADC支持内部参考电压和外部参考电压,以及DMA和中断方式进行数据传输。因此在使用STM32F103系列单片机进行模拟量采集时,可以采用其内置的逐次逼近型ADC来实现对模拟信号的高精度采样。

  • 怎么查询ADC的类型

在STM32参考手册中,模拟、数字转换(ADC)章节中有介绍,如下:

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

7.ADC的工作原理

ADC(Analog-to-Digital Converter)是模拟信号转换为数字信号的电子元件,其工作原理可简单概括为:将模拟信号经过采样、量化和编码等步骤转换成数字信号。

  • 采样

将模拟信号按照一定的时间间隔进行采样,根据采样定理,采样频率要大于2倍的信号最大频率。

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

  • 量化

采样得到的模拟信号数值是连续的,为了转换成数字信号,需要将其离散化。量化过程会将连续的模拟信号转换成离散的数字信号,通常使用ADC内部的比较器,将输入的模拟信号与一些固定电压进行比较,并据此确定该信号在固定时刻内的大小区间。上图和这部分的知识可以参照这篇知乎文章:https://www.zhihu.com/tardis/zm/art/462841831?source_id=1005

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

  • 编码

编码是将量化后的数字信号转换成二进制数。通常使用的是逐次逼近法,即将每个定时段后,两个可能的数字中选其中的一个,将数字信号由连续变量转化为离散变量。 ADC根据输入模拟量信号的量化值大小,通过电路控制二进制加法器的级数来实现逐次逼近法。

你可以通过B站上的https://www.bilibili.com/video/BV1LN4y1g7yt/ 这个视频了解什么是逐次逼近法:

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

  • 输出

经过采样、量化和编码后,ADC输出的是一串二进制代码,该代码代表着输入模拟信号的数字化结果。这些数字化结果可以通过接口(如SPI、I2C、USART等)输出到其他外设进行进一步处理和存储。

需要注意的是,ADC的转换精度与采样率有关,通常转换精度越高(比如12位、16位),采样率越高,ADC的精度和灵敏度也就越高,但相应的功耗和转换时间也会增加。

8.ADC的参数

ADC是一个重要的电子元器件,通常需要考虑以下几个参数:

分辨率:ADC转换的数字值的位数,常用的有8位、10位、12位、16位等,分辨率越高,精度越高,但转换速度会受到影响。
采样率:ADC采样的频率,指ADC每秒可以对输入信号进行多少次采样,采样率越高,转换出来的信息将更接近原始信号,但转换时间也会增加。
灵敏度:指在不同电平的输入下,ADC在输出端所能够分辨的最小量化单位,也称为LSB(最小可测量值),其值取决于ADC的分辨率。
输入电压范围:ADC能够转换的模拟信号的电压范围,超出输入电压范围的模拟信号将导致ADC失真。
信噪比(SNR)和总谐波失真(THD):反映ADC在转换过程中的精度和噪声抗干扰能力,SNR越高,转换精度越高,THD越低,输出信号越干净。
功耗:ADC在工作时所消耗的电功率,功耗越低,对于需要长时间运行的应用更为适用。
模式:有单次采样模式、均值模式、峰值模式等,不同模式适用于不同的应用场景。
综上所述,选择ADC时需要根据不同的应用场景和要求选取适当的分辨率、采样率、输入电压范围、信噪比等参数。

二.DAC的基础知识

1.什么是DAC

① DAC是数字模拟转换器(Digital-to-Analog Converter)的缩写,是一种电子元件或集成电路,用于将数字信号转换为对应的模拟电压或电流输出。它将数字信号中每一个离散的数值转换为对应的连续的模拟信号,以便于驱动模拟电路或外设等。
② 通常情况下,数字信号是由微处理器、单片机、DSP等数字电路产生的,其信号取值范围是固定的、离散的、量化的,在某些应用中需要将这些数字信号转换为模拟信号,如音频信号处理、温度控制等领域。因此,DAC作为一种重要的数字与模拟接口,广泛应用于各种电子产品中,包括音频设备、仪表、通信设备、工业控制系统和汽车电子等。

2.在单片机中我们一般使用DAC技术来做什么?

在单片机中,DAC技术主要用于将数字信号转换成模拟信号,以驱动各种需要模拟输入信号的电路或设备。常见的应用包括:
1.音频处理:DAC被广泛应用于音频领域,如音效处理、音量控制、音频合成等。单片机通过DAC输出模拟信号,驱动扬声器或耳机等音频输出设备。
2.电压输出:DAC也可以被用来控制电源以及其它需要模拟输入电压的设备,如电机驱动、热敏电阻温度采集、LED亮度调节控制等。
3.模拟信号控制:例如模拟表盘、电流表、电压表等。单片机通过DAC输出模拟信号,驱动模拟表头指针。
总之,DAC是单片机中重要的模拟输出方式之一,可以提供准确、稳定的模拟输出信号,使单片机能够与模拟电路或外设连贯无缝地进行数据交互。

3.怎么看单片机的某一个引脚是否具有ADC功能

下图以STM32F103的数据手册为例,在Full compatibility throughout the family中就列出了相关DAC情况。其中STM32F103xx系列中,低密度型号设备和中低密度型号设备都不具备DAC功能。

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

4.PWM和DAC的区别

① PWM代表脉冲宽度调制,DAC代表数字到模拟转换。这两种技术在控制电路中常被用于产生模拟信号。
② PWM是一种数字信号,它通过不同占空比的脉冲信号来模拟产生一个模拟信号。PWM的输出信号包含一个高电平时间和一个低电平时间,通过这两个时间的比例来控制输出电压的大小。由于PWM信号是数字信号,所以它通常需要通过低通滤波器来去除高频噪声,生成一个平滑的模拟信号。
③ DAC是将数字信号转换为模拟信号的过程。它将数字信号的离散取值转化为连续的模拟信号。DAC通常具有比较高的精度和分辨率,可以产生高质量的模拟信号。
④ 因此,PWM和DAC都可以产生模拟信号,但它们的原理和应用场景略有不同。PWM通常用于控制设备,例如马达或LED灯的亮度调节。而DAC通常用于音频、视频和其他需要高质量模拟信号的应用中。

5.DAC的工作原理

DAC(数字模拟转换器)的作用是将数字信号转换成相应的模拟信号,它是数字信号处理中最常用的模拟输出设备之一。DAC的工作原理可以简单地描述为以下几个步骤:

  1. 输入数字信号:首先,将一个数字信号(如二进制代码)输入到DAC芯片中。
  2. 数字到模拟转换:通过DAC芯片内部的电路,在数字信号和模拟信号之间建立了一个映射关系,将数字信号转换成相应的模拟信号。这个过程主要涉及到DAC芯片内部的参考电压、比较器和开关电路等模块,以实现模拟信号输出的稳定性和准确性。
  3. 输出模拟信号:最后,DAC芯片将模拟信号输出到DAC的输出端口上,供外部电路使用。

需要注意的是,DAC的转换速度和精度取决于DAC芯片的设计和工作电路的特性。因此,在实际应用中,需要根据具体需求选择合适的DAC芯片,并正确设计和使用电路,以保证模拟信号输出的准确性和可靠性。

6.DAC的参数

DAC(数字模拟转换器)的参数包括以下几个方面:

  1. 分辨率(Resolution):分辨率是指DAC可以输出的模拟电压值的细节程度,通常用比特数(bits)表示,也就是能够将数字信号精确转换为多少级的模拟电压。例如,一个12位的DAC可以将数字信号精确转换为2^12=4096个模拟电压级别。

  2. 采样速率(Sampling Rate):采样速率是指DAC每秒钟可以进行多少次数字到模拟的转换,通常用赫兹(Hz)表示。采样速率越高,输出的模拟信号就越精确。

  3. 转换精度(Accuracy):转换精度是指DAC将数字信号转换为模拟信号时的精确度。通常用百分比的形式来表示,例如0.1%。转换精度越高,输出的模拟信号就越准确。

  4. DNL(差分非线性度):DNL是描述DAC输出非线性误差的指标,它反映了DAC相邻码之间的偏差是否均匀。如果DNL小于1 LSB(最低有效位),则认为DAC的性能较好。

  5. INL(积分非线性度):INL是一种衡量DAC非线性误差的指标,它反映了所有码之间的偏差是否均匀。如果INL小于1 LSB,也认为DAC的性能较好。

  6. 输出电压范围(Output Voltage Range):输出电压范围是指DAC可以输出的模拟电压的最大值和最小值之间的差值。通常用伏特(V)表示。

  7. 供电电源(Power Supply):DAC需要一个合适的供电电源来工作,需要在应用中选择合适的供电电源。

  8. 功耗(Power Consumption):DAC的功耗越低,对于应用来说就越省电。

  9. 封装类型(Package Type):DAC的封装类型有多种,选择合适的封装类型可以方便应用的设计和安装。

以上几个参数可以帮助用户选择合适的DAC芯片,并满足应用需求。

三.代码实例

下面的实例代码是我写的某个项目中ADC部分的代码,该项目使用了DMA来实现同步数据采集,至于怎么通过STM32来编写ADC采集代码就不做讲解了,你可以通过这篇博文进行了解https://blog.csdn.net/weixin_44636409/article/details/118678500。

  • 原理图

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集

dac模块,stm32(标准库),stm32,单片机,嵌入式硬件,ADC采集文章来源地址https://www.toymoban.com/news/detail-542895.html

  • adc.h
#ifndef __ADC_H
#define __ADC_H	
#include "sys.h"


void Adc_Init(void);
u16 Get_Adc_SoilMoisture();
u16 Get_Adc_WaterDepth();
#endif 

  • adc.c
#include "adc.h"
#include "delay.h"
#include "usart.h"
#include "math.h"
__IO uint32_t ADC_convered[1]={0}; // ADC2不存在DMA,所以只需要一个1空间即可;ADC2采用高16位,土壤湿度;ADC1采用低16位,水位深度


static void ADC_GPIO_CONFIG(void)// IO口的初始化
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE );	  //使能GPIOB通道时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE );	  //使能GPIOA通道时钟
	// PA0的GPIO配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	// PB1的GPIO配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

}


static void ADC_MODE_CONFIG(void)// 配置ADC的模式
{ 	
	// 开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// DMA1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE);// ADC1和ADC2时钟
	
	
	// ADC和DMA的结构体
	ADC_InitTypeDef ADC_InitStruct;	
	DMA_InitTypeDef DMA_InitStructure;

	
	// 配置DMA
	DMA_DeInit(DMA1_Channel1);// 重置DMA1(复位)
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));// 外设地址(数据源地址)
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_convered;// 存储器地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 外设到存储器
	DMA_InitStructure.DMA_BufferSize = 1;// 缓存区大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 外设地址是否递增(否)
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 存储器地址是否递增(否)
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;    // 外设大小(1字=32位)
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;            // 存储器大小(1字=32位)
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	// 循环传输模式
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;// DMA传输优先级(高)
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 禁止存储器到存储器
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);// 初始化DMA
	DMA_Cmd(DMA1_Channel1, ENABLE);// 使能DMA通道

  // 配置ADC1
	ADC_InitStruct.ADC_Mode = ADC_Mode_RegSimult;           // 采用规则同步模式
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;       // 不启用扫描模式(只有一个不需要扫描)
	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;	// 启用连续转换
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 启动方式不采用中断方式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;// 数据对齐方式采用右对齐
	ADC_InitStruct.ADC_NbrOfChannel = 1;	// 转换通道数量:1
	ADC_Init(ADC1,&ADC_InitStruct);// 初始化ADC
	
	// 配置ADC时钟N狿CLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);	
	// 配置ADC 通道的转换顺序和采样时间
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
  // 使能ADC DMA请求
	ADC_DMACmd(ADC1, ENABLE);


  // 配置ADC2
	ADC_InitStruct.ADC_Mode = ADC_Mode_RegSimult;           // 采用规则同步模式
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;       // 不启用扫描模式(只有一个不需要扫描)
	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;	// 启用连续转换
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 启动方式不采用中断方式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;// 数据对齐方式采用右对齐
	ADC_InitStruct.ADC_NbrOfChannel = 1;	// 转换通道数量:1
	ADC_Init(ADC2,&ADC_InitStruct);// 初始化ADC
	
	// 配置ADC时钟N狿CLK2的8分频,即9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);	
	// 配置ADC 通道的转换顺序和采样时间
	ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_239Cycles5);
  /* 使能ADCx_2的外部触发转换 */
  ADC_ExternalTrigConvCmd(ADC2, ENABLE);


	/**** ADC1校验 ****/
	// 开启ADC ,并开始转换
	ADC_Cmd(ADC1, ENABLE);	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADC1);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADC1));	
	// ADC开始校准
	ADC_StartCalibration(ADC1);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADC1));

	/**** ADC2校验 ****/
	// 开启ADC ,并开始转换
	ADC_Cmd(ADC2, ENABLE);	
	// 初始化ADC 校准寄存器  
	ADC_ResetCalibration(ADC2);
	// 等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADC2));	
	// ADC开始校准
	ADC_StartCalibration(ADC2);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADC2));

	// 由于没有采用外部触发,所以使用软件触发ADC转换 (ADC2采用的外部触发)
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}				  


void Adc_Init()// 初始化Adc
{
   ADC_GPIO_CONFIG();
   ADC_MODE_CONFIG();
}




u16 Get_Adc_SoilMoisture()  //获取土壤湿度的数据并返回给主函数
{
	
	  uint16_t temp = (ADC_convered[0] & 0xFFFF0000) >> 16;     // 高16位数据,这是ADC2的转换数据
    UsartPrintf(USART1,"adc1=%d",((ADC_convered[0] & 0xFFFF0000) >> 16)); 
	  float result = (4095-(float)temp)/(4095-1948)*100;
	
	return result >=100? 100:result;//(M_max-adcx)/(M_max-M_min)*100
}


u16 Get_Adc_WaterDepth(){   //获取水位传感器的数据并返回给主函数
  uint16_t temp = (ADC_convered[0] & 0xFFFF);   
	if(temp<= 3){
		return 0;
	}else{
			// 说明有值
	float tempValue = (float)temp/3.5;//GetAdc=2300/x = 250 ;250x=2300;x=2300/661
	u16 temp2 = (exp(0.0056*tempValue));//0.0056*tempValue = 3.7;tempValue=3.7/0.0056=661
	  UsartPrintf(USART1,"waterdepth=%d;GetAdc(0)=%d;tempValue=%.1f",temp2,temp,tempValue);
		return temp2;
	}
}

  • main.c
#include "adc.h"
int waterDepth = 0; //光照度
int soilMoisture = 0;// 土壤湿度

int main(){
// 初始化ADC
Adc_Init();

while(1){
	 // 获取土壤湿度
	 soilMoisture = Get_Adc_SoilMoisture();
		
	 // 获取水位
	 waterDepth = Get_Adc_WaterDepth(); 
	 // 延时...
}
return 0;
}

到了这里,关于零死角玩转stm32中级篇4-ADC和DAC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32学习】ADC(一)—— STM32 内置 AD 模块框图

    现在我们大致知道,ADC 的大致转换流程就是输入模拟信号,经由采样、保持、量化、编码等过程,最终转换成数字信号。下面将通过ADC模块框图了解ADC模块正常运作需要做哪些事。 准备阶段: 配置分频数(控制ADC周期) ADC 的输入范围控制(需要让输入信号在ADC转换范围内

    2024年02月05日
    浏览(44)
  • Stm32_标准库_11_ADC_光敏&热敏传感器_测数值

    在测量光敏传感器数值得基础上手动将通道改成热敏传感器通道即可 由于温度传感器的测量范围是-20 ~ 105摄氏度,所以输出温度得考虑带上符号这就需要在原有输出光照强度代码的基础上新添加几个函数 函数1: 在获取模拟电压函数最开始写入通道函数方便接入GPIO_1或GPIO_

    2024年02月19日
    浏览(46)
  • Stm32_标准库_8_ADC_光敏传感器_测量具体光照强度

    ADC简介 测量方式 采用二分法比较数据 IO通道 ADC基本结构及配置路线 获取数字变量需要用到用到光敏电阻的AO口,AO端口接在PA0引脚即可 测得的模拟数据与实际光照强度之间的关系为 代码: 完整朴素代码: 效果: 此代码的不足之处在于每次写入数字都会提前占据固定位置,

    2024年02月04日
    浏览(47)
  • 用STM32单片机ADC+NTC热敏电阻采集温度的设计思路 | 附参考电路

    目录 前言 一、热敏电阻NTC 二、参考电路  三、激励电压选择 记录一些我在工作和学习过程中遇到的问题 NTC:在淘宝随便买的 单片机型号:STM32G030C8T6 目的:用单片机采集NTC温度 本文主要是介绍关于NTC激励电压的选择        热敏电阻 NTC(Negative Temperature Coefficient) , 直

    2024年02月02日
    浏览(54)
  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库,STM32F103

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月07日
    浏览(58)
  • FreeRTOS_Stm32F103系列单片机标准库移植

    链接:FreeRTOS 下面的教程是基于从github下载压缩包进行的,最好下载这个或者直接看3.1,从我百度网盘下载。如果是别的下载源也问题不大,大同小异。 此时我们需要下载以下两个仓库, 点进去按下面的步骤下载就行了,另一个也是这样下。 链接: FreeRTOS官网 打开链接我们

    2024年01月22日
    浏览(53)
  • 【单片机】STM32单片机的各个定时器的定时中断程序,标准库

    高级定时器和普通定时器的区别(https://zhuanlan.zhihu.com/p/557896041): TIM1是高级定时器,使用的时钟总线是RCC_APB2Periph_TIM1,和普通定时器不一样。 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用 timer.c timer.h 调用

    2024年02月11日
    浏览(53)
  • STM32玩转物联网实战篇:2.ESP8266 WIFI模块TCP通信示例详解

    开发板功能区分布图 开发板俯视图     ESP8266 WIFI模块内置TCP/IP网络协议,模块支持三种网络模式,AP、STA和AP+STA模式,AP模式:模块作为WIFI热点,等待其他设备的连接,进行局域网的通信,STA模式:模块作为客户端通过路由器连接外网,和服务器进行通信,AP+STA模式:两

    2024年02月03日
    浏览(62)
  • 智能小车红外测速模块的使用方法(基于STM32的标准库)

    基于STM32标准库编程实现智能小车的红外测速所需掌握的知识: (1)外部中断的配置 (2)定时器的配置 (3)串口的配置 红外测速的核心思路 : (1)红外测速模通电后,会发出红外线,利用测速盘对红外线进行遮光,使测速模块连接STM32的中断引脚触发中断。每次发生中

    2024年02月04日
    浏览(49)
  • 单片机毕业设计 stm32发送短信消息(GMS模块)

    Hi,大家好,学长今天向大家介绍如何使用GMS模块,达到单片机发送短信的效果,应用场景非常广泛 ** 单片机发送短信消息(GMS模块)** 大家可用于 课程设计 或 毕业设计 GSM模块使用上海SIMcom公司的SIM900高精度无线GSM/GPRS完全四频芯片,使用SMT封装且融 合了高性能的ARM926EJ

    2024年02月07日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包