STM32ADC模块-温度传感器的单通道采集与多通道采集

STM32ADC模块-温度传感器的单通道采集与多通道采集

在这里插入图片描述

单通道配置

单通道就比较简单了,并且Duck不比用DMA,这里正好讲解一下,STM32内部自带的一个温度传感器。
adc.c

#include "adc.h"
void Adc_Init(void){
	ADC_InitTypeDef ADC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1/*|RCC_APB2Periph_GPIOB*/, ENABLE);
	
	//如果用的是温度传感器则不需要初始化引脚,反之则必须
	//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0   ;
	//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	//	GPIO_Init(GPIOB, &GPIO_InitStructure);

	/* ADC1 configuration ------------------------------------------------------*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	
	//使能温度传感器模块,如果说不用的话,可以不用的
	ADC_TempSensorVrefintCmd(ENABLE);
	
	ADC_Cmd(ADC1, ENABLE);
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	
}

double Adc1_GetVal(u8 Channel_x){
	 //设置指定ADC的规则组通道,一个序列,采样时间	
	//ADC1,ADC通道,采样时间为239.5周期,周期越大,测得越准确
	ADC_RegularChannelConfig(ADC1, Channel_x, 1, ADC_SampleTime_239Cycles5 );	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
	//返回最近一次ADC1规则组的转换结果
	return (double)ADC_GetConversionValue(ADC1)*3.3/4095;	
}

//这个形参mode针对温度传感器的,如果说用的是普通ADC采样,则mode参数给0
double Get_Adc_Average(u8 ch,u8 times,u8 mode)
{
	double temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Adc1_GetVal(ch);
		Delay_Ms(5);
	}
	temp_val=temp_val/times;
	
	if(mode==1){
		temp_val = (1430 - 1000*temp_val)/4.3 + 25;
	}
	
	return temp_val;
} 	 

adc.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_H
#define __ADC_H

/* Includes ------------------------------------------------------------------*/
#include "main.h"

void Adc_Init(void);
double Adc1_GetVal(u8 Channel_x);
double Get_Adc_Average(u8 ch,u8 times,u8 mode);
#endif

该注意的内容都在代码注释的很清楚了!

多通道配置

多通道就是读取多个通道,此模式需要适用DMA。适用场景:连续采集多个通道的ADC。这里我选用的是比如PA1,PA2,PB0。

adc.c

#include "adc.h"
//这个数组就是用来存放DMA读到的数据,因此我们外部引用,就可以直接使用了
__IO uint16_t ADCConvertedValue[3];
void Adc_Init(void){
	ADC_InitTypeDef ADC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0   ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	DMA_DeInit(DMA1_Channel1);
	//ADC1_DR_Address这个是ADC的地址(固定值),我在adc.h直接定义了
	DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
	//这里设置的是数据存放的地址,因为数组名本身就是地址,所以把取地址去掉了
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValue;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	//因为我们设置数组的长度为3
	DMA_InitStructure.DMA_BufferSize = 3;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	//下面的这句是设置DMA的内存递增模式,DMA 访问多个内存参数时,需要使用DMA_MemoryInc_Enable
	//当DMA只访问一个内存参数时可设置成 :DMA_MemoryInc_Disable。
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	//下面的这句是设置 DMA 的传输模式:连续不断的循环模式
	//若只想访问一次后就不要访问了,可以设置成通用模式:DMA_Mode_Normal。
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	//下面的这句是设置 DMA 的优先级别:可以分为 4 级:VeryHigh,High,Medium,Low.
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);
	DMA_Cmd(DMA1_Channel1,ENABLE);

	/* ADC1 configuration ------------------------------------------------------*/
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	//因为我们用了三个通道,所以这里用3
	ADC_InitStructure.ADC_NbrOfChannel = 3;
	ADC_Init(ADC1, &ADC_InitStructure);
	//ADC_RegularChannelConfig中有四个参数
	//第一个为ADC1,第二个取决于你前面初始化IO口对应的是ADC的通道几,第三个为Rank的序号
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_239Cycles5);

	ADC_DMACmd(ADC1, ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

adc.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_H
#define __ADC_H

/* Includes ------------------------------------------------------------------*/
#include "main.h"

#define ADC1_DR_Address    ((uint32_t)0x4001244C)
void Adc_Init(void);
extern __IO uint16_t ADCConvertedValue[3];

#endif

比较重要的我都在代码里注释了,自己看下就可以了。

发布了4 篇原创文章 · 获赞 5 · 访问量 2092

猜你喜欢

转载自blog.csdn.net/qq_43605009/article/details/104919738