ADC(Analog-Digital Converter)模数转换器。
12位逐次逼近型ADC,1us转换时间。
输入电压范围:0 ~ 3.3V,转换结果范围:0 ~ 4095。
18个输入通道,可测量16个外部和2个内部通道。
规则组和注入组两个转换单元。
模拟看门狗自动监测输入电压范围。
STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
ADC1_INx:16个外部通道(GPIO口,见引脚定义表)。
注入组和规则组触发:由硬件触发ADC转换。(软件SWSTART触发未体现)
ADCCLK:ADC的RCC时钟信号(最大14MHz预分频只可选6或8)。
EOC信号:转换完成后。(注入组和规则组均会产生)
JEOC信号:注入组转换完成后。(仅注入组会产生)
模拟看门狗:超出阈值将产生AWD信号。
规则组数据寄存器:只可存放1个数据。
注入组数据寄存器:可存放4个数据。
规则组:一次可选16个通道。(可自动扫描)
注入组:一次可选4个通道。(无DMA请求,产生中断)
转换时间:采样时间(可配置) + 12.5 个周期
单/多通道:每次选择一/多个通道。
单次/连续转换:产生EOC信号后停止/继续转换。
非扫描/扫描模式:菜单列表使用一/多个通道。
DMA/中断:实现数据的自动读取。
ADC1和ADC2的中断映射在同一个中断向量上,而ADC3的中断有自己的中断向量
扫描模式:ADC扫描所有被规则通道或注入通道选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。
连续转换模式:转换不会在组的最后一个通道上停止,而是再次从组的第一个通道继续转换。
DMA:在每次EOC信号后,DMA控制器把规则组通道的转换数据传输到内存中。而注入组的通道转换的数据总是存储在组入组的寄存器中。
间断模式:不是中断,是每转换完几个(0~8)通道就停一下。
触发注入:外部注入触发,启动注入组转换(会打断正在转换的其他通道)。
自动注入:在规则组通道转换之后,注入组通道被自动转换。
void AD_Init(void) //单通道,非扫描模式
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//开启ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//分频6 -> 12MHz,8 -> 9MHz
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
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);
//ADC_SoftwareStartConvCmd(ADC1, ENABLE);//若为连续转换则在此软件触发一次,之后就能自动转换
}
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发(连续转换模式无需)
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换结束(连续转换模式无需)
return ADC_GetConversionValue(ADC1);//得到数据(连续转换模式时仅需此函数即可)
}
/* ADC_DMACmd 使能DMA数据转运
* @ param1 选择ADCx
* @ param2 使能/失能
* @ retval None
*/
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/* ADC_ITConfig 使能ADC中断
* @ param1 选择ADCx
* @ param2 ADC中断的信号源选择
* @ param3 使能/失能
* @ retval None
*/
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
/* ADC_GetITStatus 获得中断标志位
* @ param1 选择ADCx
* @ param2 ADC中断的信号源选择
* @ retval SET/RESET
*/
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
/* ADC_ClearITPendingBit 清除中断标志位
* @ param1 选择ADCx
* @ param2 ADC中断的信号源选择
* @ retval None
*/
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
/* ADC_SoftwareStartConvCmd 使能软件触发
* @ param1 选择ADCx
* @ param2 使能/失能
* @ retval None
*/
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/* ADC_GetSoftwareStartConvStatus 获取软件触发的ADC开始转换状态
* @ param1 选择ADCx
* @ retval SET/RESET
*/
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
/* ADC_ExternalTrigConvCmd 使能外部硬件触发
* @ param1 选择ADCx
* @ param2 使能/失能
* @ retval None
*/
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/* ADC_RegularChannelConfig
* @ param1 选择 ADCx
* @ param2 选择通道(0 ~ 16)
* @ param2 选择通道的排名
* @ param2 选择该通道 ADC 转换的时间
* @ retval None
*/
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
//自动注入
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);
/* ADC_InjectedChannelConfig 注入组通道选择
* @ param1 选择ADCx
* @ param2 选择通道(0 ~ 16)
* @ param2 选择通道的排名
* @ param2 选择该通道 ADC 转换的时间
* @ retval None
*/
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
/* ADC_InjectedSequencerLengthConfig 配置注入组菜单序列长度
* @ param1 选择ADCx
* @ param2 注入组菜单序列长度
* @ retval None
*/
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
/* ADC_SetInjectedOffset 设置注入组通道的转换偏移值
* @ param1 选择ADCx
* @ param2 注入组通道选择
* @ param3 偏移值(即平衡误差)
* @ retval None
*/
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
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_DiscModeChannelCountConfig 配置间断模式
* @ param1 选择ADCx
* @ param2 选择通道个数
* @ retval None
*/
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发(连续转换模式无需)
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待转换结束(连续转换模式无需)
return ADC_GetConversionValue(ADC1);//得到数据(连续转换模式时仅需此函数即可)
}
/* ADC_GetConversionValue 规则组ADC数据(从寄存器中获取最后一次的值)
* @ param1 选择ADCx
* @ retval None
*/
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
/* ADC_GetInjectedConversionValue 注入组ADC数据
* @ param1 选择ADCx
* @ param2 注入组通道选择
* @ retval None
*/
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
/* ADC_GetDualModeConversionValue 双ADC模式
* @ retval None
*/
uint32_t ADC_GetDualModeConversionValue(void);
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
uint16_t AD_Value[4];//.h中声明 exturn uint16_t AD_Value[4] 设为外部可调用
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
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 = ENABLE;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_NbrOfChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);//
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
/* ADC_TempSensorVrefintCmd
* @ param1 使能/失能
* @ retval None
*/
void ADC_TempSensorVrefintCmd(FunctionalState NewState);```
2 EOC/JEOC
+---------------------------->+----+
ADC基本结构 | +----------+ |中断| +----+
|EOC/JEOC |模拟看门狗 | |输出+-->|NVIC|
| +-----+----+ |控制| +----+
+----+16 +--+ +------+----+ |---------->+----+
|GPIO+-->| | | AD转换器 | +--------+--------+
+----+ | | | | | AD数据寄存器 |
| | 16 | | 1 | |
+----+ | +-----+-->规则组--+---+->规则组结果 X 1 |
|温度 +-->| | | | | |
+----+ | | 4 | | 4 | |
| +-----+-->注入组--+---+->注入组结果 X 4 |
+----+ | | | | | |
|VREF+-->| | +-----------+ +-----------------+
+----+ +--+ ^ ^
| |
START | |CLOCK
+-------++ ++--+
|触发选择 | |RCC|
+--------+ +---+
------ BY Flier
2023.9.4
Reference:江协科技、《stm32f10x用户手册》、《stm32库开发实战指南教程》