【STM32】ADC程序示例

00. 目录

01. ADC简介

STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 19 个通道,可测量 16 个外部源、2 个内部源和 Vbat 通道的信号。这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。

STM32F407ZGT6 包含有 3 个 ADC。STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 0.41us(在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。

STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。

02. 硬件资源

用到的硬件资源有:
1) 指示灯 DS0
2) TFTLCD 模块
3) ADC
4) 杜邦线

03. 编程思路

①开启PA口时钟和ADC1时钟,设置PA1为模拟输入。

RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

GPIO_Init();

② 复位ADC1,同时设置ADC1分频因子。

ADC_DeInit(ADC1);

③ 初始化ADC_CCR寄存器。

ADC_CommonInit();

④初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。

void ADC_Init(ADC_TypeDefADCx,ADC_InitTypeDef* ADC_InitStruct);*

⑤ 使能ADC。

ADC_Cmd(ADC1, ENABLE);

⑥配置规则通道参数:

ADC_RegularChannelConfig();

⑦开启软件转换:ADC_SoftwareStartConvCmd(ADC1);

⑧ 等待转换完成,读取ADC值。

ADC_GetConversionValue(ADC1);

04. 程序示例

adc.h

#ifndef __ADC_H__
#define __ADC_H__

#include "sys.h"

//ADC通道初始化
void ADC1_Init(void);

//获取某个通道的值
u16 Get_Adc(u8 ch);

//获取某个通道给定次数采样平均值
u16 Get_Adc_Average(u8 ch, u8 times);

#endif/*__ADC_H__*/


adc.c


#include "adc.h"
#include "delay.h"


//ADC通道初始化
void ADC1_Init(void)
{
    
    
	GPIO_InitTypeDef gpio_InitTypeDef;
	
	ADC_InitTypeDef ADC_InitStruct;
	
	ADC_CommonInitTypeDef ADC_CommonInitStruct;
	
	//开启ADC1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	
	//开启GPIO时钟 PA5
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 
	
	
	//GPIO初始化 初始化为模拟功能
	gpio_InitTypeDef.GPIO_Pin = GPIO_Pin_5;
	gpio_InitTypeDef.GPIO_Mode = GPIO_Mode_AN;
	gpio_InitTypeDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &gpio_InitTypeDef);
	
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);	  //ADC1复位
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);	//复位结束	
	
	
	//初始化ADC_CCR寄存器
	ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
	ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
	ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div4;
	ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
	ADC_CommonInit(&ADC_CommonInitStruct);
	
	//初始化ADC1
	ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
	ADC_InitStruct.ADC_NbrOfConversion = 1;
	ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;
	ADC_Init(ADC1, &ADC_InitStruct);
	
	//使能ADC
	ADC_Cmd(ADC1, ENABLE);
	
}

//获取某个通道的值
u16 Get_Adc(u8 ch)
{
    
    

	//设置ADC规则组通道 一个序列 采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles);
	
	//开启软件转换
	ADC_SoftwareStartConv(ADC1);
	
	//等待转换结束
	while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)
		;

	//读取ADC的值
	return  ADC_GetConversionValue(ADC1);
}

//获取某个通道给定次数采样平均值
u16 Get_Adc_Average(u8 ch, u8 times)
{
    
    
	u32 tmp_val = 0;
	
	u8 i = 0;
	
	for (i = 0; i < times; i++)
	{
    
    
		tmp_val += Get_Adc(ch);
		delay_ms(5);
	}

	return tmp_val / times;
}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "usmart.h"
#include "lcd.h"
#include "rtc.h"
#include "rng.h"
#include "key.h"
#include "wkup.h"
#include "adc.h"

int main(void)
{
    
     
	u16 value = 0;
	
	float temp = 0;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	
	delay_init(168);
	
	uart_init(115200);
	
	usmart_dev.init(84);

	
	LED_Init();
	
	
	LCD_Init();

	ADC1_Init();
	
		
	POINT_COLOR = RED;
	
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");	
	LCD_ShowString(30,70,200,16,16,"ADC TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@tom");
	LCD_ShowString(30,110,200,16,16,"2020/09/10");	 
	
	//设置字体为蓝色
	POINT_COLOR = BLUE;
	LCD_ShowString(30,130,200,16,16,"ADC1_CH5_VAL:");	 
	LCD_ShowString(30,150,200,16,16,"ADC1_CH5_VOL:0.000V");	 
		
	while(1)
	{
    
    
		value = Get_Adc_Average(ADC_Channel_5, 20);
		
		//显示采样之后的原始值
		LCD_ShowxNum(134, 130, value, 4, 16, 0);
		
		temp = (float)value * (3.3 / 4096);
		value = temp;
		LCD_ShowxNum(134, 150, value, 1, 16, 0);
		
		//小数部分
		temp = temp - value;
		temp *= 1000;
		LCD_ShowxNum(150, 150, temp, 3, 16, 0x80);		
		
		LED1 = !LED1;
		
		delay_ms(250);
	}
}


05. 预留

06. 附录

6.1 【STM32】STM32系列教程汇总

网址:【STM32】STM32系列教程汇总

07. 声明

该教程参考了正点原子的《STM32 F4 开发指南》

猜你喜欢

转载自blog.csdn.net/dengjin20104042056/article/details/108559310