7 ADC(二)

7.2 AD单通道&AD多通道

1)AD单通道

函数说明:

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);	//用来配置ADCCLK分频器的2,4,6,8(在rcc库函数里)

————————————————————————————————————————————————————————————————————————————————————————————————————————————————
//ADC基本功能和规则组的配置
//Init三剑客
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);						//给ADC上电
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);					//开启DWA输出信号
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);				//获取软件触发开始转换状态(获取CR2的SWSTART)这个函数很少用

//配置间断模式
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);		//每隔几个通道间断一次
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);			//是否启用间断模式

//ADC规则组通道配置(配置点菜)
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获取转换值(获取AD转换的数据寄存器)
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
//ADC获取双模式转换值
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);	//获取标志位状态EOC
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);		//清除中断挂起位

在这里插入图片描述

流程:

第一步:RCC开启时钟,开启GPIO和ADC的时钟,ADCCLK分频器配置
第二部:配置GPIO,把需要用的GPIO口配置成输入模式
第三步:配置多路开关,把左边的通道接入到右边的规则组列表里
第四步:配置ADC转换器,用结构体来配置(AD转换器、AD数据寄存器、触发控制等)
第五步,调用ADC_Cmd(),开启ADC,然后进行校准

主函数:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

uint16_t ADValue;
float voltage;

int main(void)
{
	OLED_Init();
	AD_Init();

	OLED_ShowString(1, 1, "ADValue:");
	OLED_ShowString(2, 1, "Voltage:0.00V");
	
	while (1)
	{
		ADValue = AD_GetValue();
		voltage = (float)ADValue / 4095 * 3.3;						//将ADValue强制转换为浮点数类型
		OLED_ShowNum(1, 9, ADValue, 4);
		OLED_ShowNum(2, 9, voltage, 1);								//整数
		OLED_ShowNum(2, 11, (uint16_t)(voltage * 100) % 100, 2);	//小数:将浮点数乘以100,再强制转换为16位无符号整数,最后对100取模,得到小数点后两位的值。
		Delay_ms(100);
	}
}

AD.C

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	//第一步:RCC开启时钟,开启GPIO和ADC的时钟,ADCCLK分频器配置
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	//第二部:配置GPIO,把需要用的GPIO口配置成输入模式
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	//ADC专属模式
	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); //ADC1上配置一个常规通道,使其可以采集ADC通道0的模拟电压值,并且使用55.5个时钟周期作为采样时间

	
	//第四步:配置ADC转换器,用结构体来配置(AD转换器、AD数据寄存器、触发控制等)
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;					//独立模式,ADC可以单独工作,并不依赖其他STM32内部或外部的时钟或扫描机制。
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;				//采集到的ADC数据会在右对齐后被存入ADC转换缓存区中
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//ADC外部触发转换配置代码,这里表示不使用外部触发方式来启动ADC转换(这里选择软件触发)
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;					//ADC连续转换模式配置代码,这里表示非连续转换,即采用单次转换
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;						//ADC扫描模式配置代码,这里表示非扫描模式
	ADC_InitStructure.ADC_NbrOfChannel = 1;								//ADC转换通道数量配置代码,只使用一个ADC通道进行转换
	ADC_Init(ADC1,&ADC_InitStructure);
	
	//第五步,调用ADC_Cmd(),开启ADC,然后进行校准
	ADC_Cmd(ADC1, ENABLE);
	ADC_ResetCalibration(ADC1);							 //在进行ADC模块校准之前,需要先进行复位操作
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);	 //ADC校准复位后,需要等待校准重置完成。使用while语句判断校准复位是否完成
	ADC_StartCalibration(ADC1);							 //校准复位完成后,开始进行ADC模块的校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);		 //ADC校准开始后,需要等待校准完成。使用while语句来判断校准是否完成,完成后继续执行下面的代码。
}

//启动转换,获取结果
uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//ADC转换开始前需要启动转换操作。这里使用了ADC_SoftwareStartConvCmd(ADC1, ENABLE)函数来启动ADC1的软件转换操作。
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//启动转换后,需要等待ADC的转换完成。这里使用while语句来判断,直到转换完成后,继续执行下面的代码。
	return ADC_GetConversionValue(ADC1);					//转换完成后,可以通过ADC_GetConversionValue(ADC1)函数来获取转换结果。
}

2)AD多通道

采用扫描模式实现多通道,最好配合AWA防止数据覆盖,本次利用单次转换非扫描模式,只要在每次触发转换之前,手动更改一下列表第一个位置通道即可。

主函数:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

uint16_t AD0, AD1, AD2, AD3;


int main(void)
{
	OLED_Init();
	AD_Init();

	OLED_ShowString(1, 1, "AD0:");
	OLED_ShowString(2, 1, "AD1:");
	OLED_ShowString(3, 1, "AD2:");
	OLED_ShowString(4, 1, "AD3:");
	
	while (1)
	{
		AD0 = AD_GetValue(ADC_Channel_0);
		AD1 = AD_GetValue(ADC_Channel_1);
		AD2 = AD_GetValue(ADC_Channel_2);
		AD3 = AD_GetValue(ADC_Channel_3);
		
		OLED_ShowNum(1, 5, AD0, 4);
		OLED_ShowNum(2, 5, AD1, 4);
		OLED_ShowNum(3, 5, AD2, 4);
		OLED_ShowNum(4, 5, AD3, 4);

		Delay_ms(100);
	}
}

AD.C

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	//第一步:RCC开启时钟,开启GPIO和ADC的时钟,ADCCLK分频器配置
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	//第二部:配置GPIO,把需要用的GPIO口配置成输入模式
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	//ADC专属模式
	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); //ADC1上配置一个常规通道,使其可以采集ADC通道0的模拟电压值,并且使用55.5个时钟周期作为采样时间

	
	//第四步:配置ADC转换器,用结构体来配置(AD转换器、AD数据寄存器、触发控制等)
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;					//独立模式,ADC可以单独工作,并不依赖其他STM32内部或外部的时钟或扫描机制。
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;				//采集到的ADC数据会在右对齐后被存入ADC转换缓存区中
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//ADC外部触发转换配置代码,这里表示不使用外部触发方式来启动ADC转换(这里选择软件触发)
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;					//ADC连续转换模式配置代码,这里表示非连续转换,即采用单次转换
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;						//ADC扫描模式配置代码,这里表示非扫描模式
	ADC_InitStructure.ADC_NbrOfChannel = 1;								//ADC转换通道数量配置代码,只使用一个ADC通道进行转换
	ADC_Init(ADC1,&ADC_InitStructure);
	
	//第五步,调用ADC_Cmd(),开启ADC,然后进行校准
	ADC_Cmd(ADC1, ENABLE);
	ADC_ResetCalibration(ADC1);							 //在进行ADC模块校准之前,需要先进行复位操作
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);	 //ADC校准复位后,需要等待校准重置完成。使用while语句判断校准复位是否完成
	ADC_StartCalibration(ADC1);							 //校准复位完成后,开始进行ADC模块的校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);		 //ADC校准开始后,需要等待校准完成。使用while语句来判断校准是否完成,完成后继续执行下面的代码。
}

//启动转换,获取结果
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	//在触发转换前,指定通道,传参进去
    ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5); 
	
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//ADC转换开始前需要启动转换操作。这里使用了ADC_SoftwareStartConvCmd(ADC1, ENABLE)函数来启动ADC1的软件转换操作。
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//启动转换后,需要等待ADC的转换完成。这里使用while语句来判断,直到转换完成后,继续执行下面的代码。
	return ADC_GetConversionValue(ADC1);					//转换完成后,可以通过ADC_GetConversionValue(ADC1)函数来获取转换结果。
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值