藍橋杯嵌入式基礎板模塊之ADC模塊-溫度傳感器的單通道採集與多通道採集

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 = DISABLE;
	//ADC轉換可以在一次轉換後停止,然後再次觸發後進行下一次轉換;也可以是持續不斷地轉換下去。
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	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 的傳輸方向,就如前面所說的,DMA 可以雙向傳輸,也可以單向傳輸
	//這裏設置的是單向傳輸,如果需要雙向傳輸:把 DMA_DIR_PeripheralSRC 改成DMA_DIR_PeripheralDST 即可。
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	//因爲我們設置數組的長度爲3
	DMA_InitStructure.DMA_BufferSize = 3;
	//下面這句是設置 DMA 的外設遞增模式,如果 DMA 選用的通道(CHx)有多個外設連接,需要使用外設遞增模式:DMA_PeripheralInc_Enable;
	//我的例子裏 DMA 只與 ADC1 建立了聯繫,所以選用DMA_PeripheralInc_Disable。
	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

比較重要的我都在代碼裏註釋了,自己看下就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章