stm32F103之ADC模数转换

一、ADC简介

  通常是指一个将模拟信号转变为数字信号的电子元件。通常的模数转换器是把经过与标准量比较处理后的模拟量转换成以二进制数值表示的离散信号的转换器。   

  12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。

二、ADC功能框图

掌握了ADC 的功能框图,就可以对ADC 有一个整体的把握,在编程的时候可以做到了然如胸,不会一知半解。框图讲解采用从左到右的方式,跟ADC 采集数据,转换数据,传输数据的方向大概一致。

三、ADC功能描述

1、电压输入范围

  ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。

  设计原理图的时候一般把VSSA和VREF-接地,把VREF+和VDDA 接3V3,得到ADC的输入电压范围为:0~3.3V。

2、输入通道

  我们确定好ADC 输入电压之后,那么电压怎么输入到ADC?这里我们引入通道的概念,STM32 的ADC 多达18 个通道,其中外部的16 个通道就是框图中的ADCx_IN0、ADCx_IN1...ADCx_IN5。这16 个通道对应着不同的IO 口,具体是哪一个IO 口可以从手册查询到。其中ADC1/2/3 还有内部通道:ADC1的通道16连接到了芯片内部的温度传感器,Vrefint 连接到了通道17。ADC2 的模拟通道16 和17 连接到了内部的VSS。ADC3 的模拟通道9、14、15、16 和17 连接到了内部的VSS。

我们在编程的时候需要根据使用的IO引脚来确定具体的通道。外部的16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4 路。那这两个通道有什么区别?在什么时候使用?

规则通道

规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道。

注入通道

注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。

3、转换顺序

规则序列

规则序列寄存器有3 个,分别为SQR3、SQR2、SQR1。SQR3 控制着规则序列中的第一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],第一次转换的是位4:0 SQ1[4:0],如果通道16 想第一次转换,那么在SQ1[4:0]写16 即可。SQR2 控制着规则序列中的第7 到第12 个转换,对应的位为:SQ7[4:0]~SQ12[4:0],如果通道1 想第8 个转换,则SQ8[4:0]写1即可。SQR1 控制着规则序列中的第13 到第16 个转换,对应位为:SQ13[4:0]~SQ16[4:0],如果通道6 想第10 个转换,则SQ10[4:0]写6 即可。具体使用多少个通道,由SQR1 的位L[3:0]决定,最多16 个通道。

注入序列

注入序列寄存器JSQR 只有一个,最多支持4 个通道,具体多少个由JSQR 的JL[2:0]决定。如果JL 的 值小于4 的话,则JSQR 跟SQR决定转换顺序的设置不一样,第一次转换的不是JSQR1[4:0],而是JCQRx[4:0] ,x = (4-JL),跟SQR 刚好相反。如果JL=00(1 个转换),那么转换的顺序是从JSQR4[4:0]开始,而不是从JSQR1[4:0]开始,这个要注意,编程的时候不要搞错。当JL 等于4 时,跟SQR 一样。

4、触发源

通道选好了,转换的顺序也设置好了,那接下来就该开始转换了。ADC 转换可以由ADC 控制寄存器2: ADC_CR2 的ADON 这个位来控制,写1 的时候开始转换,写0 的时候停止转换,这个是最简单也是最好理解的开启ADC 转换的控制方式,理解起来没啥技术含量。
除了这种庶民式的控制方法,ADC 还支持触发转换,这个触发包括内部定时器触发和外部IO 触发。触发源有很多,具体选择哪一种触发源,由ADC 控制寄存器2:ADC_CR2 的EXTSEL[2:0] 和JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由ADC 控制寄存器2:ADC_CR2 的EXTTRIG 和JEXTTRIG 这两位来激活。其中ADC3 的规则转换和注入转换的触发源与ADC1/2 的有所不同,在框图上已经表示出来。

5、数据寄存器

 

一切准备就绪后,ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR寄存器,注入组的数据放在JDRx。

规则数据寄存器

ADC 规则组数据寄存器ADC_DR 只有一个,是一个32 位的寄存器,低16 位在单ADC时使用,高16 位是在ADC1 中双模式下保存ADC2 转换的规则数据,双模式就是ADC1 和ADC2 同时使用。在单模式下,ADC1/2/3 都不使用高16 位。因为ADC 的精度是12 位,无论ADC_DR 的高16 或者低16 位都放不满,只能左对齐或者右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。
规则通道可以有16 个这么多,可规则数据寄存器只有一个,如果使用多通道转换,那转换的数据就全部都挤在了DR 里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该把数据取走,或者开启DMA 模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开启DMA 传输。

注入数据寄存器

ADC 注入组最多有4 个通道,刚好注入数据寄存器也有4 个,每个通道对应着自己的寄存器,不会跟规则寄存器那样产生数据覆盖的问题。ADC_JDRx 是32 位的,低16 位有效,高16 位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。

6、中断

转换结束中断

数据转换结束后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断。其中转换结束中断很好理解,跟我们平时接触的中断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断服务程序。

模拟看门狗中断

当被ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我们开启了模拟看门狗中断,其中低阈值和高阈值由ADC_LTR 和ADC_HTR 设置。例如我们设置高阈值是2.5V,那么模拟电压超过2.5V 的时候,就会产生模拟看门狗中断,反之低阈值也一样。

DMA 请求

规则和注入通道转换结束后,除了产生中断外,还可以产生DMA 请求,把转换好的数据直接存储在内存里面。要注意的是只有ADC1 和ADC3 可以产生DMA 请求。有关DMA请求需要配合《STM32F10X-中文参考手册》DMA控制器这一章节来学习。一般我们在使用ADC 的时候都会开启DMA 传输。

 

   

转载于:https://www.cnblogs.com/cailan/p/9655322.html

  • 9
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用STM32F103C8T6进行转换时,使用STM32Cube库来编写代码。以下是一个简单的示例代码,用于配置和启动ADC转换器)并获取转换结果: ```c #include "stm32f1xx_hal.h" ADC_HandleTypeDef hadc; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); while (1) { // 启动ADC转换 HAL_ADC_Start(&hadc); // 等待转换完成 HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY); // 获取转换结果 uint32_t adcValue = HAL_ADC_GetValue(&hadc); // 处理转换结果 // ... // 延时一段时间 HAL_Delay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig; __HAL_RCC_ADC1_CLK_ENABLE(); hadc.Instance = ADC1; hadc.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc) != HAL_OK) { Error_Handler(); } sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 这段代码使用了HAL库来进行初始化和配置。首先,需要调用`SystemClock_Config`函数来配置系统时钟。然后,使用`MX_GPIO_Init`函数来初始化GPIO引脚,将其配置为拟输入式。最后,使用`MX_ADC1_Init`函数来初始化ADC,并配置通道和采样时间。 在主循环中,首先调用`HAL_ADC_Start`函数启动ADC转换。然后,使用`HAL_ADC_PollForConversion`函数等待转换完成。一旦转换完成,可以使用`HAL_ADC_GetValue`函数获取转换结果。在获取结果后,可以进行进一步的处理。最后,使用`HAL_Delay`函数延时一段时间,然后再次进行转换

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值