ADC是什么?模拟数字转换器(Analog-to-Digital Converter)。
一、ADC概述
stm32f013c8t6有两个ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道、2个内部通道(温度传感器、内部参考电压)。实际stm32f013c8t6只有10个通道(IN0-IN9)+ 2个内部通道。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右 对齐方式存储在16位数据寄存器中。
ADC的输入时钟不得超过14MHz(常用12MHz),它是由PCLK2经分频产生。
1.1、电压输入范围
ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。一般把 VSSA 和 VREF- 接地,把 VREF+ 和 VDDA 接 3V3,得到 ADC 的输入电压范围为:0~3.3V
1.2、通道
外部的 16 个通道在转换时又分为规则通道和注入通道,其中规则通道最多有 16 路,注入通道最多
有 4 路。
规则通道: 规则通道就是很规矩的意思,常用的就是规则通道
注入通道: 可以理解为VIP,有特权的人,可以插队
1.3、转换顺序
每个ADC 只有一个数据寄存器(DR), 16 个通道一起共用这个寄存器,所以需要指定规则转换通道的转换顺序。规则通道中的转换顺序由三个寄存器控制:SQR1 、 SQR2 、 SQR3 ,它们都是 32 位寄存器。 SQR 寄存器控制着转换通道的数目和转换顺序,只要在对应的寄存器位SQx 中写入相应的通道,这个通道就是第x 个转换。

注入通道的转换顺序也是通过注入寄存器来控制

1.4、触发源
ADC 转换可以由 ADC_CR2(控制寄存器) 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候停止转换。
ADC 还支持触发转换,这个触发包括内部定时器触发和外部 IO 触发。具体选择哪一种触发源,由 ADC_CR2(控制寄存器 ) 的 EXTSEL[2:0] 和 JEXTSEL[2:0] 位来控制
1.5、转换时间
ADC是挂载在APB2总线(PCLK2)上的,经过分频器得到ADC时钟(ADCCLK),最高 14 MHz。
转换时间 = 采样时间 + 12.5 个周期
12.5 个周期是固定的,一般我们设置 PCLK2=72M ,经过 ADC 预分频器能分频到最大的时钟只能
是 12M ,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us
1.6、数据寄存器
规则组的数据放在 ADC_DR 寄存器, 注入组的数据放在 JDRx 。
1.7、模式
扫描模式
关闭:只转换 ADC_SQRx 或 ADC_JSQR 选中的第一个通道
打开:扫描所有被 ADC_SQRx 或 ADC_JSQR 选中的所有通道
单次转换:
ADC只执行一次转换。该模式既可通过设置 ADC_CR2 寄存器的 ADON 位 ( 只适用于规则通道) 启动也可通过外部触发启动 ( 适用于规则通道或注入通道 ) ,这时 CONT 位为 0 。 一旦选择通道的转换完成:
● 如果一个规则通道被转换:
─ 转换数据被储存在 16 位 ADC_DR 寄存器中
─ EOC( 转换结束 ) 标志被设置
─ 如果设置了 EOCIE ,则产生中断。
● 如果一个注入通道被转换:
─ 转换数据被储存在 16 位的 ADC_DRJ1 寄存器中
─ JEOC( 注入转换结束 ) 标志被设置
─ 如果设置了 JEOCIE 位,则产生中断。
连续转换:转换一次之后,立马进行下一次转换,此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。每个转换后:
● 如果一个规则通道被转换:
─ 转换数据被储存在 16 位的 ADC_DR 寄存器中
─ EOC( 转换结束 ) 标志被设置
─ 如果设置了 EOCIE ,则产生中断。
● 如果一个注入通道被转换:
─ 转换数据被储存在 16 位的 ADC_DRJ1 寄存器中
─ JEOC( 注入转换结束 ) 标志被设置
─ 如果设置了 JEOCIE 位,则产生中断
二、单规则通道 case
完整代码
描述: PA0(ADC通道0) 接入MQ2(烟雾传感器)的A0口,然后通过串口打印出来
CubeMX主要配置:

main函数主要代码如下:
int main(void)
{uint32_t result;HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_ADC1_Init();MX_USART1_UART_Init();while (1){HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1, 50);result = HAL_ADC_GetValue(&hadc1);printf("result = %f\r\n", 3.3/4096 * result);HAL_Delay(500);}
}
2.1、 MX_ADC1_Init
主要是来装配数据,并初始化,两个主要的步骤是HAL_ADC_Init和HAL_ADC_ConfigChannel
void MX_ADC1_Init(void)
{ADC_ChannelConfTypeDef sConfig = {0};hadc1.Instance = ADC1;hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;hadc1.Init.ContinuousConvMode = DISABLE;hadc1.Init.DiscontinuousConvMode = DISABLE;hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion = 1;// adc 通用配置if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}// 规则通道配置sConfig.Channel = ADC_CHANNEL_0;sConfig.Rank = ADC_REGULAR_RANK_1;sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK){Error_Handler();}}
2.2、HAL_ADC_Init
2.3、HAL_ADC_ConfigChannel
2.4、HAL_ADC_Start
2.5、HAL_ADC_PollForConversion
以上函数暂时不分析了,等有时间再处理,ADC代码太长了。。。
三、双规则通道 case
完整代码
描述:
PA0(ADC通道0) 接入MQ2(烟雾传感器)的A0口,然后通过串口打印出来
PA1(ADC通道1) 接入轨迹检测传感器(烟雾传感器)的A0口,然后通过串口打印出来
CubeMX主要配置:

主要代码如下:
int main(void)
{uint32_t result;uint32_t result1;HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_ADC1_Init();MX_USART1_UART_Init();HAL_ADCEx_Calibration_Start(&hadc1);while (1){HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1, 50);result = HAL_ADC_GetValue(&hadc1);HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1, 50);result1 = HAL_ADC_GetValue(&hadc1);printf("result = %f\r\n", 3.3/4096 * result);printf("result1 = %f\r\n", 3.3/4096 * result1);HAL_ADC_Stop(&hadc1);HAL_Delay(1000);}
}
四、双规则通道 case(关闭扫描模式)
完整代码
核心代码如下
uint16_t ADC_Read(uint32_t Channel)
{ADC_ChannelConfTypeDef sConfig = {0};sConfig.Channel = Channel; /* 通道 */sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; /* 采样时间 */if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {Error_Handler();}HAL_ADC_Start(&hadc1);HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);return (uint16_t)HAL_ADC_GetValue(&hadc1);
}while (1){result = ADC_Read(ADC_CHANNEL_0);result1 = ADC_Read(ADC_CHANNEL_1);printf("result = %f\r\n", 3.3/4096 * result);printf("result1 = %f\r\n", 3.3/4096 * result1);HAL_Delay(1000);}
五、注入通道
待补充