1.ADC简介
1.简述(根据第二点):
原本只有高、低电平之分,现在通过ADC可以得到具体的电压值(数字电路只有高低电平)
2.转换频率:1MHz(根据第三点的1us转换时间)
3.模拟看门狗:
可以监测指定的某个通道(达到某个条件就会申请中断,在中断中执行某些操作)
4.另外:
DAC是数字-模拟转换器,PWM也是数字到模拟的桥梁,通过调整占空比来模拟信号
2.ADC内部结构
1.普通ADC内部结构
总结:通过比较器,DAC采用二分法输出已知编码的电压与输入电路中未知编码的电压比较,逐次逼近未知编码,最后输出正确的电压值(VREF是参考电压,结果取决于其电压值)
2.STM32的ADC内部结构
注意:注入通道由4个数据寄存器,可以同时存4个数据;而规则通道只有一个数据寄存器,同时传入16个数据时只能通过1个,其他的会被挤掉,所以最好配合DMA(数据转运帮手)使用。
触发ADC开始转换的信号:软件触发,程序中手写代码;硬件触发,利用定时器的更新事件触发,也可以选择外部中断引脚(即EXTI)来触发转换
VDDA和VSSA是内部模拟部分的电源
ADCCLK是用于驱动内部逐次比较的时钟,在RCC中通过ADC分频器后得到(最大14MHz),所以ADC分频器只能选择6分频(12MHz)和8分频(9MHz)
EOC:规则组的完成信号(标志位)
JEOC:注入组的完成信号(标志位)
3.ADC基本结构
部分解释:触发控制就是选择软件触发还是硬件触发,开关控制就是ADC_Cmd函数给ADC上电
4.细节
1.输入通道(对应的GPIO口)
注意:STM32只有ADC1和ADC2
2.规则组的4种转换模式
1.单次转换,非扫描模式
解释:在非扫描模式下,16个序列就只有序列1有效,在此选择通道后,ADC对这个通道进行模数转换,完成后在EOC置1即可。(每次都会结束)
2.连续转换,非扫描模式
解释:一直进行非扫描模式的转换。(像读AD值的时候直接读数据寄存器)
3.单次转换,扫描模式
解释:通道数目需要直接手动写入参数,在扫描模式下,16个序列可以自由使用,但是每次转换都会有多个结果放在数据寄存器里,这就意味着需要用DMA及时将数据挪走。
4.连续转换,扫描模式
上面已经解释过两个模式的具体区别,在此不再解释。
3.触发控制(规则组的触发源)
倒数第二个触发源的类型究竟是引脚还是定时器需要用AFIO重映射来确定
4.数据对齐
原因:ADC是12位的,转换结果是一个12位的数据,但是数据寄存器是16位的(一般用右对齐)
5.转换时间
这就是稳定情况下最快1us的来源
6.校准(了解)
5.实战代码
1.部分函数的功能
//ADCCLK的配置函数(配置ADCCLK分频器) void RCC_ADCCLKConfig(uint32_t RCC_PCLK2); //配置ADC转换器 void ADC_DeInit(ADC_TypeDef* ADCx); void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//开启DMA输出信号 void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);//中断输出控制 void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准 FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);//获取复位校准状态 void ADC_StartCalibration(ADC_TypeDef* ADCx);//开始校准 FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);//获取开始校准状态 void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//用于软件触发 FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); //ADC获取软件开始转换状态(不能判断是否结束) FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//获取标志位状态(看EOC) //配置间断模式 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外部触发转换控制(是否允许外部触发转换) uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); //ADC获取转值(读取AD转换的数据寄存器,即读取转换结果) uint32_t ADC_GetDualModeConversionValue(void); //ADC获取双模式转换值 //注入组 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 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); //配置看门通道 //ADC温度传感器内部参考电压控制 void ADC_TempSensorVrefintCmd(FunctionalState NewState); 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);//清除中断挂起位2.配置思路
1.RCC开启时钟(把GPIO和ADC的时钟打开,包括ADCCLK的分频器也要配置)
2.配置GPIO(配置成模拟输入模式)
3.配置开关,将左边的通道接入右边的规则组里(就是选择通道)
4.配置ADC转换器(转换模式、通道数、触发源、数据对齐等)
5.开启ADC
3.基本配置格式(AD单通道、非扫描模式)
//ADC都是APB2上的设备 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟 //需要用到PA0口将可调的电压输出 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //配置ADCCLK RCC_ADCCLKConfig(RCC_PCLK2_Div6); //配置GPIO时钟 GPIO_InitTypeDef GPIO_InitStructure;//结构体定义 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模拟输入(GPIO无效,即为ADC专属模式) GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//IO口 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //选择规则组的输入通道(在序列1写入通道0) ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5); //初始化ADC ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//ADC模式(独立还是双模式) 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 //校准 ADC_ResetCalibration(ADC1);//复位校准 while(ADC_GetResetCalibrationStatus(ADC1)==SET);//获取复位校准状态 ADC_StartCalibration(ADC1);//开始校准 while(ADC_GetCalibrationStatus(ADC1)==SET);//获取开始校准状态