一、ADC的基本介绍
ADC模拟->数字转换
ADC可以将模拟信号转换为数字信号。
而DAM则是相反,将数字信号转换为模拟信号。
下图为ADC基本结构
左边是输入通道,16个GPIO口,外加两个内部的通道。
然后进入AD转换器,AD转换器里有两个组,一个是规则组,一个是注入组,规则组最多可以选择16个通道,注入组最多可以选择4个通道,转换的结果可以存放在AD数据寄存器里。
AD数据寄存器中可以存放一个规则组结果,四个注入组结果。转换完成后会有EOC信号,会置一个标志位,通向NVIC。
模拟看门狗用于监测转换结果的范围,如果超出设定的阈值,就通过中断输出控制,向NVIC申请中断。
START触发控制可以选择软件触发和硬件触发。软件触发可以直接使用软件进行触发,即在软件中进行使用库函数;硬件触发主要是来自定时器,也可以用外部中断的引脚。
RCC内部时钟推动ADC逐次比较。
右下角的开关控制在库函数中就是ADC_Cmd(),用于给ADC上电的。
二、ADC的转化时间
ADC转换的步骤:采样->保持->量化->编码
ADC转换的时间即在量化编码之前设置一个采样开关,收集外部电压。当外部电压被存储好后,断开采样开关,再进行AD转换。(在量化编码的过程中,电压始终保持不变。)
所以打开采样开关收集外部电压到断开采样开关进行AD转换的时间就为ADC的转换时间。
本文中使用的ADCCLK = 72MHz / 6 = 12MHz
转换时间:采样时间 + 固定周期(12.5)= 55.5+12.5=68
68/12MHz=5.6us
三、代码部分
AD:
首先是初始化部分
void AD_Init(void)
{
/*GPIO初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//ADC专属通道
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*ADC初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//ADC分频时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);//ADC1通道0 序列1,采样时钟55
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//非扫描模式(单通道)
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//同上
ADC_InitStructure.ADC_NbrOfChannel = 1;//同上
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//复位校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);//等待校准完成
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
然后是获取AD转化值部分
/*读取ADC转换后的数据*/
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //触发转换
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待转换5.6us
return ADC_GetConversionValue(ADC1);
}
main:
int main(void)
{
AD_Init();
OLED_Init();
OLED_ShowString(1,1,"ADValue:");
while (1)
{
OLED_ShowNum(1,9,AD_GetValue(),4);
}
}
四、现象
接线图如下
STM32F103C8T6外接一个电位器和一个OLED显示AD值。
当用螺丝刀向左旋转电位器时,AD值变小;向右则变大。