赞
踩
ADC读取引脚上的模拟电压,转换为一个数据,存在寄存器里,就可以进行显示、判断、记录等操作。(PWM就是一个等效模拟量相当于DAC,数模转换,通过脉宽调节来控制LED的亮度、电机的速度。DAC的应用主要在波形生成这些领域,比如信号发生器,音频解码芯片)
电压读取范围和转换结果范围0~3.3V、0-4095都是一一对应的线性关系。
如果电压、光线、温度等高于某个阈值或低于某个阈值时,需要执行一些操作,这个高于某个阈值、低于某个阈值的判断,就可以用模拟看门狗来自动执行,模拟看门狗可以监测指定的某些通道。当AD值高于它设定上的阈值或低于阈值时,它就会申请中断,就可以在中断函数里执行相应的操作,这样就不需要不断的手动读值再用if判断了。
一个外部通道输入端输入的未知编码电压与 一个DAC输出的已知电压,它俩同时输入到电压比较器,进行大小判断。如果DAC输出电压比较大,那么就调小DAC输出,反之增大,直到DAC输出的电压和外部通道输入的电压近视相等,这样DAC输入的数据就是外部电压的编码数据了。
这个电压调节的过程就是逐次逼近寄存器SAR来完成的。为了最快的找到未知的电压编码,通常我们会使用二分法进行寻找,对于8位的ADC,从高位到地位依次判断8次就能找到未知电压的编码,对于12位的ADC,就需要判断12次。
AD转换结束后,DAC的输入数据,就是未知电压的编码,然后输出到8位三态锁存缓冲器。
EOC:转换结束信号。
START:开始信号,给一个输入脉冲,开始转换。
CLOCK:ADC时钟。
Vref(+)、Vref(-):DAC的参考电压(也是整个ADC的参考电压)。
ADC0809:ADC芯片。
GPIO:外部输入。
温度、Vref:内部通道。
触发控制:提供了开始转换这个START信号,触发控制可以选择软件触发和硬件触发。硬件触发主要来自定时器,当然也可以选择外部中断的引脚。
RCC:ADC时钟CLOCK,ADC逐次比较的过程就是由这个时钟推动的。
模拟看门狗:用于监测转换结果的范围,如果超出设定的阈值,就通过中断控制向NVIC申请中断。
EOC:AD转换完成后会有个EOC信号,它会置一个标志位,当然也可以通向NVIC。
开关控制:再库函数中,就是ADC_Cmd函数,用于给ADC上电的。
单次转换、非扫描模式
图中的表就是规则组里的菜单,在非扫描的模式下只有第一个序列1的位置有效,在这里我们可以在序列1的位置指定我们想转换的通道。比如图中的通道2写到序列1,然后我们就可以触发转换,ADC就会对这个通道2进行模数转换,过一小段时间后转换完成,转换结果放在数据寄存器里,同时给EOC标志位直1,整个转换过程就结束了,我们判断这个EOC标志位,如果转换完了,那我们就可以在数据寄存器里读取结果了。如果我们想在启动一次转换,那就需要在触发一次。果如想要换一个通道转换,那就再转换之前,把第一个位置的通道2改成其他通道,然后再启动转换。
连续转换、非扫描模式
它与上一种单次转换不同的是,它在一次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直持续下去。这样就只需要开始触发一次,之后就可以一直转换了,也不用判断是否结束,想要读AD值的时候,直接从数据寄存器取。
单次转换、扫描模式
这个模式也是单次触发,所以每触发一次都需要手动开启。扫描模式就是可以在不同的序列号里选择不同的通道进行转换。选择通道数目,然后每次触发之后,它依次在选择的通道前进行AD转换,转换结果都放在数据寄存器里,这里为了防止数据被覆盖,就需要用DMA即时将数据挪走,所有通道转换完成之后,产生EOC信号,转换结束。
连续转换、扫描模式
结合了连续转换与多通道转换。
这里是电位器产生一个可调的电位器,滑动端就可以输出一个0~3.3V的可调电压输出,PA0接ADC的输入通道。
N1:传感器(可等效为一个可变电阻)。
通过和一个固定电阻串联分压,来得到一个反应传感器电阻值电压的电路。传感器阻值变小时,下拉作用变强,输出端电压就下降;传感器阻值变大时,下拉作用变弱,输出端电压就上升。这个固定电阻一般选择和传感器电阻相近的电阻,这样可以得到一个位于中间电压区域比较好的输出。当然传感器电阻也可以和固定电阻位置换过来,这样输出电压的极性就反过来了,这就是分压方法来输出传感器电阻的电路。
电压转换电路。比如想要测量一个0~5V的VIN电压,但ADC只能接收0-3.3V的电压,在这里使用电阻进行分压,根据分压公式,中间的电压就是VIN/50K×33K ,最后得到的电压范围就是0-3.3V,就可以进入ADC转换。
数据多出来的补0。一般采用右对齐,读取这个16位寄存器就是转换的结果。
第一步:开启RCC时钟,包括ADC和GPIO的时钟,另外这里ADCCLK的分频器也需要配置一下。
第二部:配置GPIO,把需要用的GPIO配置成模拟输入的模式。
第三步:配置多路开关,把左边的通道接收到右边的规则组列表里。
第四步:配置ADC转换器(在库函数里,用结构体来配置,可以配置一大块电路的参数,包括ADC是单次转换还是连续转换、扫描还是非扫描、有几个通道、触发源、数据对齐)
*如果需要配置模拟开门狗,那会有几个函数来配置阈值和监测通道。如果想要开启中断,那就再中断输出控制里用ITConfing函数开启对应的中断输出,然后在NVIC里配置一下优先级,这样就能触发中断了。
最后就是开关控制,调用ADC_Cmd函数开启ADC。
以下是函数说明:
RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟 void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);//ADCCLK分频器,可以对APB2的72MHz时钟选择2 4、6、8分频,输入到ADCCLK。在RCC库函数。 void ADC_DeInit(ADC_TypeDef* ADCx);//恢复缺省配置 void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//Init初始化 void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);//结构体初始化 void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//用于给ADC上电 void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//开启DMA,使用DMA转运数据 void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//中断输出控制 //校准函数,在ADC初始化完成后依次调用 void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准 FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);//获取复位校准状态 void ADC_StartCalibration(ADC_TypeDef* ADCx);//开始校准 FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);//获取开始校准状态 //开始ADC转换,获取标志位判断转换结束 void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//ADC软件开始转换控制 FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);//ADC获取软件开始转换状态 FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//获取标志位 //间断模式 void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);//每隔几个通道间断一次 void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//是否开启间断 void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);//ADC规则组通道配置 void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//ADC外部触发转换控制 //ADC获取转换值 uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//ADC获取转换值,用来读取结果 uint32_t ADC_GetDualModeConversionValue(void);//ADC获取双模式转换值 //模拟看门狗 void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);//是否启动看门狗 void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);//配置高低阈值 void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);//配置看门的通道 void ADC_TempSensorVrefintCmd(FunctionalState NewState);//ADC温度传感器、内部电压控制 //重要~ FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//获取标志位状态 void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//清除标志位 ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);//获取中断状态 void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);//清除中断挂起位 //对ADC注入组进行配置 jected void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
开始初始化
void AD_Init(void) { //开启ADC1、GPIOA的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //ADCCLK分频,72MHz6分频 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //初始化PGPIO,把A0设置为模拟输入 GPIO_InitTypeDef GPIO_InitStructre;//定义一个结构体变量 GPIO_InitStructre.GPIO_Mode=GPIO_Mode_AIN; GPIO_InitStructre.GPIO_Pin=GPIO_Pin_0; GPIO_InitStructre.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructre); //选择规则组的输入通道 ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5); //初始化ADC ADC_InitTypeDef ADC_InitStructre; ADC_InitStructre.ADC_DataAlign=ADC_DataAlign_Right;//对齐 ADC_InitStructre.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发方式 ADC_InitStructre.ADC_Mode=ADC_Mode_Independent;//工作模式 ADC_InitStructre.ADC_ContinuousConvMode=DISABLE;//连续转换模式 ADC_InitStructre.ADC_ScanConvMode=DISABLE;//扫描转换模式 ADC_InitStructre.ADC_NbrOfChannel=1;//通道数目 ADC_Init(ADC1,&ADC_InitStructre); //中断或看门口需要就在后面继续配置 //开启ADC电源 ADC_Cmd(ADC1,ENABLE); //校准 ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) ==SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) ==SET); } //读取ADC返还值 uint16_t AD_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1,ENABLE);//启动 while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) ==RESET);//等待 return ADC_GetConversionValue(ADC1);//读取 }
初始化完成就可以在主函数定义一个常量赋予返还值AD_GetValue()。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。