零基础STM32单片机编程入门(四)ADC详解及实战含源码视频

文章目录

一.概要

ADC(Analog to Digital Converter),即模数转换器,是将连续的模拟信号转换为离散的数字信号的单片机外设。典型的模拟数字转是将模拟信号转换为表示一定比例电压值的数字信号,比如温度传感器等一些传感器,输出的信号是0~3.3V的电压信号。

例如温度传感器输出电压0V代表采集到的温度是0­°C,输出电压3.3V代表温度是100­°C,温度跟电压成线性比例关系,如果单片机ADC外设采集的到电压是1.65V,那就代表温度是50­°C(100°C*1.65/3.3),如果单片机ADC外设采集到的电压是3.3V,那就代表温度是100­°C。

二.STM32F103C8T6单片机ADC外设特点

STM32F103C8T6含有2个12位的模拟/数字转换器(ADC1,ADC2),每个ADC共用多达10个外部通道,可以实现单次或连续转换,1MHz转换速率,转换范围:0~3.6V,ADC供电要求:2.4V~3.6 V。ADC1同时含有2个内部通道:连接到芯片内部温度传感器和内部参考电压(VREFINT = 1.2V)

10个外部通道对应的单片机上的引脚如下图

三.STM32单片机ADC内部结构图

ADC内部结构图如下

1.ADC相关引脚说明

(1)VDDA(Analog Supply Voltage)

ADC模块的模拟电源引脚,通常连接到MCU的模拟电源线路。VDDA提供ADC模块所需的模拟电源电压,确保ADC的正常工作和准确的模拟信号转换。

(2)VSSA(Analog Ground Voltage)

ADC模块的模拟地引脚,通常连接到MCU的模拟地线路。

(3)VREF+(Positive Voltage Reference)

ADC模块的正参考电压引脚,通常连接到外部提供的正参考电压源。VREF+确定了ADC转换过程中的上限电压参考点,通常对应于模拟输入信号的最大量程值。在ADC转换过程中,被测量的模拟信号会与VREF+进行比较,以确定其对应的数字量,STM32F103C8T6是没有这个引脚,64脚和小于64脚的STM32F103型号,其VREF+在芯片内部与VCC信号线相连,没有引到片外,这样AD的参考电压就是VCC上的电压。

(4)VREF-(Negative Voltage Reference)

ADC模块的负参考电压引脚,通常连接到外部提供的负参考电压源或地。VREF-确定了ADC转换过程中的下限电压参考点,通常对应于模拟输入信号的最小量程值。

STM32F103C8T6也没有这个引脚。

2.ADC通道分类

在STM32的ADC模块中,分成了两种不同类型的通道类型:规则通道和注入通道,它们适应于不同的采集场景,在功能框图所示:

ADC规则通道

规则通道顾名思义就是,最平常的通道、也是最常用的通道,平时的ADC转换都是用规则通道模式的。它允许用户配置ADC以便按照预定的顺序对这些通道进行连续或单次采样。

ADC注入通道

注入通道是相对于规则通道的,注入通道可以在规则通道转换时,强行插入转换,相当于一个"中断通道"吧。当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执行完毕后,再回到之前规则通道进行转换。这种功能使得注入通道特别适合于采集突发事件或需要高优先级响应的应用,比如实时监控或故障检测。

3.触发源

ADC转换的输入、通道、转换顺序都已经说明了,但ADC转换是怎么触发的呢?就像通信协议一样,都要规定一个起始信号才能传输信息,ADC也需要一个触发信号来实行模/数转换。

其一就是通过直接配置寄存器触发,通过配置控制寄存器CR2的ADON位,写1时开始转换,写0时停止转换。在程序运行过程中只要调用库函数,将CR2寄存器的ADON位置1就可以进行转换,比较好理解。

另外,还可以通过内部定时器或者外部IO触发转换,也就是说可以利用内部时钟让ADC进行周期性的转换,也可以利用外部IO使ADC在需要时转换,具体的触发由控制寄存器CR2决定。

4.转换周期

可独立设置各通道采样时间ADC会在数个ADCCLK周期内对输入电压进行采样,可使用ADC_SMPR1和ADC_SMPR2寄存器中的SMP[2:0]位修改周期数。每个通道均可以使用不同的采样时间进行采样。

总转换时间的计算公式如下:

Tconv=采样时间+12个周期

示例:

ADCCLK = 30 MHz且采样时间=3个周期时:

Tconv= 3+12=15个周期=0.5us (APB2为60MHz时)

最小采样时间0.42us(ADC时钟=36MHz,采样周期为3周期下得到)。

5.电压转换计算

转换后的数据是一个12位的二进制数,我们需要把这个二进制数代表的模拟量(电压)用数字表示出来。比如测量的电压范围是0~3.3V,ADC转换后的寄存器读到的数是x,因为12位ADC在转换时将电压的范围大小(也就是3.3)分为4096(2^12)份,所以真实电压的计算方法就是: y=3.3* x / 4096(V)

6.更精确电压转换计算

STM32F103C8T6是VDD3.3V做参考电压,但是这种方法在供电电压有可能随外部一些其他用电器工作使用的大电流而导致电压不稳定,内部参考电压能更加精确计算采样到的电压,具体方法是在测量某个通道的电压值之前,先读出参照电压的ADC测量数值(Vrefint Channel),记为ADrefint;再读出要测量通道的ADC转换数值,记为ADchx;则要测量的电压为:

Vchx = VREFINT * (ADchx/ADrefint)

四.规则通道ADC采集信号流向

1.单次转换模式

配置为单次模式使能,扫描模式失能。这样ADC的这个通道,转换一次后,就停止转换,需要下一次启动才可以。

2.连续转换模式

配置为连续模式使能,扫描模式失能。这样ADC的这个通道,转换一次后,接着进行下一次转换,不断连续。

五.CubeMX配置一个ADC采集例程

STM32F103C8T6小系统板PA4 引脚上的进行 ADC 电压采集,杜邦线连接 PA4 引脚与 VDD(3.3V),应该能读到单片机供电的电压值。

打开STM32CubeMX软件,新建工程

Part Number处输入STM32F103C8,再双击就创建新的工程

配置下载口引脚

配置外部晶振引脚

配置PA4引脚为ADC1的通道4,进行电压采集

配置系统主频

配置工程文件名,保存路径,KEIL5工程输出方式

生成工程

用Keil5打开工程

Main.c中添加代码


STLINK连接好板子后,Keil 5进入调试,在Watch界面查看两个变量的值,ADC采样到的值是0xfff,转换成电压值就是3300mV。

main代码如下:

c 复制代码
/* USER CODE BEGIN 0 */
int ADCData;
uint16_t VolDta;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();//外部8M晶振,系统72M主频

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();//PA4引脚配置成ADC1 Channel4输入
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
 
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)//启动校准
  {
    Error_Handler();
  }
	HAL_ADC_Start(&hadc1);//启动ADC

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  ADCData=HAL_ADC_GetValue(&hadc1);//获取ADC采集值
		VolDta=ADCData*3300/4095;//ADC采集值转换成电压值,单位mV
		HAL_Delay(200);//等待200ms
		HAL_ADC_Start(&hadc1);//再次启动ADC	
		HAL_Delay(200);
    /* USER CODE BEGIN 3 */
  }
  
  /* USER CODE END 3 */
}

六.CubeMX工程源代码下载

链接:https://pan.baidu.com/s/1A3tst65eeeLbxwtFvOe0iA

提取码:7wht

如果链接失效,可以联系博主给最新链接

程序下载下来之后解压就行

七.讲解视频链接地址

ADC外设视频讲解

八.小结

ADC外设是STM32单片机开发中的最基本操作,学会了ADC,可以采集外部的一些传感器的模拟信号,适应更多模块的驱动。

相关推荐
小白在路上~37 分钟前
51单片机嵌入式开发:STC89C52操作GPIO口LED灯
c语言·开发语言·单片机·嵌入式硬件·51单片机·dsp开发
KINO321 小时前
51单片机外部中断(按键识别)
单片机·51单片机·嵌入式
番茄灭世神11 小时前
利用STM32的定时器输出PWM方波
stm32·单片机·嵌入式硬件
m0_6442226111 小时前
HarmonyOS开发实战:UDP通讯示例规范
网络·驱动开发·嵌入式硬件·udp·harmonyos·鸿蒙·harmonyos next
人才程序员12 小时前
【51单片机入门】速通定时器
c语言·c++·单片机·嵌入式硬件·mcu·51单片机·proteus
Stark-Gs13 小时前
位置型PID和增量型PID的区别和优缺点
mcu·算法·电机
XD74297163615 小时前
【TB作品】步进电机控制器,ATMEGA16单片机,Proteus仿真
单片机·proteus·仿真·步进电机·atmega16
南耿先生15 小时前
我在高职教STM32——LCD液晶显示(1)
stm32·单片机·嵌入式硬件
xiaoyaoyou.xyz15 小时前
嵌入式UI开发-lvgl+wsl2+vscode系列:5、事件(Events)
单片机·ui·lvgl
莫邪博客16 小时前
【STM32修改串口波特率】
stm32·单片机·嵌入式硬件