单通道配置
单通道就比较简单了,并且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
比较重要的我都在代码里注释了,自己看下就可以了。