AD单通道/模拟看门狗

本文详细介绍了在STM32F10x平台上如何使用单通道AD转换器进行数据采集,并配合ADC模拟看门狗实现阈值检测。通过ADC_Init()函数配置通道、时钟、模式,以及校准过程,同时展示了如何在中断中处理模拟看门狗触发的事件。
摘要由CSDN通过智能技术生成

1.AD单通道(单次转换,非扫描模式)

1.1 接线图

1.2 AD.c

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC时钟
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC时钟分频,6分频,72/6=12,12MHz小于14MHz
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//将IO口配置为模拟输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//查表得知PA0口为ADC通道0口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC规则组输入通道,因为IO口选择PA0,所以此处通道为ADC通道0,序列号,采样时间
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//采用多通道可以多次配置
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	
	ADC_InitTypeDef ADC_Initstructure;
	ADC_Initstructure.ADC_Mode = ADC_Mode_Independent;//ADC模式,单ADC模式,区别于双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;//通道数为1
	ADC_Init(ADC1,&ADC_Initstructure);
	
	ADC_Cmd(ADC1, ENABLE);//开启ADC
	
	ADC_ResetCalibration(ADC1);//校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//获取所选ADC复位校准寄存器状态,等待校准完成。判断CR2_RSTCAL状态,经查阅参考手册 
	                                                  //ADC控制寄存器 2(ADC_CR2)得知当校准完成后,该位自动置0,置0后跳出循环,等待结束
	
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1)== SET);//获取所选ADC校准状态,等待校准完成。原理同上
	
}

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件启动AD转换
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);//获取EOC标志位,检查转换是否完成,检查ADC状态寄存器(ADC_SR)寄存器的EOC标志位
	                                                    //经查阅参考手册得,转换结束位,该位由硬件在(规则或注入)通道组转换结束时设置,由软件清除或由读取ADC_DR时清除
                                                        //0:转换未完成;1:转换完成,所以在此处while循环中判断条件为EOC是否等于RESET,转换结束即可跳出循环
	//ADC_ClearFlag(ADC1,ADC_FLAG_EOC);//因为读取ADC_DR时自动清除EOC标志位,所以此处无需这条代码
	return ADC_GetConversionValue(ADC1);//返回常规通道的最后一次ADCx转换结果数据。因为此代码是读取ADC_DR寄存器,读取后自动自动清除EOC标志位
}

 需要注意:

  • AD校准中,在等待校准完成时,while的判断条件,具体根据寄存器ADC_CR2描述来配合

  • 在等待转换完成读取EOC标志位时的判断条件, 具体根据寄存器ADC_SR描述来配合

1.3 main.c

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

uint16_t ADValue;
int main(void)
{
	OLED_Init();
	AD_Init();
	
	OLED_ShowString(1,1,"ADValue:");
	while (1)
	{
		ADValue = AD_GetValue();//将获取AD值赋给ADValue;
		OLED_ShowNum(1,9,ADValue,4);
	}
}

1.4 实验结果

  •  通过调整旋钮来改变阻值,进而改变输出电压的大小,并通过AD转换输出

2.  AD单通道配合ADC模拟看门狗

模拟看门狗可以检测通道的高低阈值,当ADC转换结果在阈值高线和阈值低线之间时,模拟看门狗可以触发进入中。

本实验通过看模拟看门狗检测通道,dangADC转换结果大于2000或者小于1000时,进入中断,并点亮一个LED灯

2.1 AD.c

#include "stm32f10x.h"                  // Device header
#include "LED.h"
#include "Delay.h"

uint16_t ADget;
uint16_t biaozhi;

void AD_Init(void)
{
	LED_Init();
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC时钟
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC时钟分频,6分频,72/6=12,12MHz小于14MHz
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//将IO口配置为模拟输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//查表得知PA0口为ADC通道0口
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//ADC规则组输入通道,因为IO口选择PA0,所以此处通道为ADC通道0,序列号,采样时间
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//采用多通道可以多次配置
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
	
	ADC_InitTypeDef ADC_Initstructure;
	ADC_Initstructure.ADC_Mode = ADC_Mode_Independent;//ADC模式,单ADC模式,区别于双ADC模式
	ADC_Initstructure.ADC_DataAlign = ADC_DataAlign_Right;//参数值右对齐
	ADC_Initstructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发选择:不使用外部触发
	ADC_Initstructure.ADC_ContinuousConvMode = ENABLE;//单次转换还是连续转换
	ADC_Initstructure.ADC_ScanConvMode = DISABLE;//多通道还是单通道
	ADC_Initstructure.ADC_NbrOfChannel = 1;//通道数为1
	ADC_Init(ADC1,&ADC_Initstructure);
	
	ADC_Cmd(ADC1, ENABLE);//开启ADC
	
	ADC_AnalogWatchdogSingleChannelConfig(ADC1,ADC_Channel_0);//看门狗检测ADC1,通道0
	ADC_AnalogWatchdogThresholdsConfig(ADC1,0x07D0,0x03E8);//上下限确定
	ADC_AnalogWatchdogCmd(ADC1,ADC_AnalogWatchdog_SingleRegEnable);//ADC看门狗启动模式
	
	ADC_ITConfig(ADC1,ADC_IT_AWD,ENABLE);//开启ADC中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC配置
	
	NVIC_InitTypeDef NVIC_Initstructure;
	NVIC_Initstructure.NVIC_IRQChannel = ADC1_2_IRQn;
	NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority =2;
	NVIC_Initstructure.NVIC_IRQChannelSubPriority =2;
	NVIC_Init(&NVIC_Initstructure);
	
	ADC_ResetCalibration(ADC1);//校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);//获取所选ADC复位校准寄存器状态,等待校准完成。判断CR2_RSTCAL状态,经查阅参考手册 
	                                                  //ADC控制寄存器 2(ADC_CR2)得知当校准完成后,该位自动置0,置0后跳出循环,等待结束
	
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1)== SET);//获取所选ADC校准状态,等待校准完成。原理同上
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件启动AD转换
}

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件启动AD转换
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);//获取EOC标志位,检查转换是否完成,检查ADC状态寄存器(ADC_SR)寄存器的EOC标志位
//	                                                    //经查阅参考手册得,转换结束位,该位由硬件在(规则或注入)通道组转换结束时设置,由软件清除或由读取ADC_DR时清除
//                                                        //0:转换未完成;1:转换完成,所以在此处while循环中判断条件为EOC是否等于RESET,转换结束即可跳出循环
//	//ADC_ClearFlag(ADC1,ADC_FLAG_EOC);//因为读取ADC_DR时自动清除EOC标志位,所以此处无需这条代码
	return ADC_GetConversionValue(ADC1);//返回常规通道的最后一次ADCx转换结果数据。因为此代码是读取ADC_DR寄存器,读取后自动自动清除EOC标志位
     

}

uint16_t ADC12_GET(void)//自定义函数,返回看门狗中断的状态
{
	    uint16_t zhongjianzhi;
        zhongjianzhi = biaozhi;
		biaozhi = 0;
	    return zhongjianzhi;
}

void ADC1_2_IRQHandler(void)
{
	if(ADC_GetITStatus(ADC1,ADC_IT_AWD)== SET)//判断是否产生中断标志位
	{
		biaozhi = 1;
	}
	
	ADC_ClearITPendingBit(ADC1,ADC_IT_AWD);//清除标志位
	
}

 中断里面的函数尽可能不要太复杂,可以再外面执行相应的功能

2.2 main.c

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

uint16_t ADValue;
float Voltage;
uint16_t zhuangtai;
int main(void)
{
	OLED_Init();
	AD_Init();
	LED_Init();
	
	OLED_ShowString(1,1,"ADValue:");
	OLED_ShowString(2,1,"Voltage:0.00V");
	OLED_ShowString(3,1,"biaozhi:");

	while (1)
	{
		zhuangtai = ADC12_GET();//将函数返回值赋值给zhuangtai
		ADValue = AD_GetValue();//将获取AD值赋给ADValue;
		Voltage = (float)AD_GetValue() / 4095 * 3.3;
		OLED_ShowNum(1,9,ADValue,4);
		OLED_ShowNum(2,9,Voltage,1);
		OLED_ShowNum(2,11,(uint16_t)(Voltage*100)%100,2);
		OLED_ShowNum(3,9,zhuangtai,1);

		if(zhuangtai==1)//进入看门狗中断,亮灯
		{
			LED1_ON();
		}
		else LED1_OFF();//未进入看门狗中断
		
	}
}

2.3 led.c

#include "stm32f10x.h"                  // Device header

void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);
}

void LED2_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_2);
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}

2.4 实验现象

ADC模拟看门狗

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值