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);
}
五、注入通道
待补充