#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#include "delay.h"
//-------------单通道 ADC读取----------------
void Adc_Init(void);
u16 get_ADC_Values(u8 ch,u8 rank);
u16 get_ADC_Average(u8 ch,u8 rank,u8 count);
//-------------单通道 ADC DMA读取----------------
void ADC_DMA_Init(void);
u16 get_ADC_DMA_Average(u8 count);
//-------------多通道 ADC DMA读取----------------
void ADC_DMA_Multichannel_Init(u32 ADC_Buff);
#endif
ADC.c实现上面定义的函数:
#include "adc.h"
//单通道 DMA adc数据
volatile u16 adc_values;
//-------------单通道 ADC读取----------------
void Adc_Init() {
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//ADC1通道11的转换时间为T=(239.5+12.5) x 1/12=21us。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1);//复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC 独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单次扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//单次转换模式
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;//ADC1 和ADC2 工作在同步规则模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1 ;//进行规则转换的ADC通道数量
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC1
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//开启复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准成功
ADC_StartCalibration(ADC1);//开始校验ADC1
while(ADC_GetCalibrationStatus(ADC1));//等待校验成功
}
u16 get_ADC_Values(u8 ch, u8 rank) {
//设置指定ADC规则通道,设置转换时间
ADC_RegularChannelConfig(ADC1, ch, rank, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开启软件转换
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待转换结束
return ADC_GetConversionValue(ADC1);
}
//返回ADC平均值
u16 get_ADC_Average(u8 ch, u8 rank, u8 count) {
u32 temp_val = 0;
u8 i;
for(i = 0; i < count; i++) {
temp_val += get_ADC_Values(ch, rank);
delay_ms(5);
}
return temp_val / count;
}
//-------------单通道 ADC DMA读取----------------
void ADC_DMA_Init() {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//初始化IO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//复位DMA1 通道1 ADC
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&adc_values;//变量基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
DMA_InitStructure.DMA_BufferSize = 1;//数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//变量内存地址不变
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1
ADC_DeInit(ADC1);//复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描
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
//ADC时钟 不能大于14MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//设置指定ADC规则通道,设置转换时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
//使能ADC DMA
ADC_DMACmd(ADC1, ENABLE);
//使能ADC
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//复位校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成
ADC_StartCalibration(ADC1);//ADC校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换
}
//返回ADC平均值
u16 get_ADC_DMA_Average(u8 count) {
u32 temp_val = 0;
u8 i;
for(i = 0; i < count; i++) {
temp_val += adc_values;
delay_ms(5);
}
return temp_val / count;
}
//-------------多通道 ADC DMA读取----------------
void ADC_DMA_Multichannel_Init(u32 ADC_Buff) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
//使能DMA1时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//初始化IO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//复位DMA1 通道1 ADC
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;//ADC内存基地址
DMA_InitStructure.DMA_MemoryBaseAddr = ADC_Buff;//变量基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到内存
DMA_InitStructure.DMA_BufferSize = 3;//数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设内存地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//变量内存地址增长
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16字节 12位ADC
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16字节
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA1 通道1
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA 通道1
ADC_DeInit(ADC1);//复位ADC1
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 = 3;//转换3个通道
ADC_Init(ADC1, &ADC_InitStructure);//初始化ADC
//ADC时钟 不能大于14MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12MHz
//设置指定ADC规则通道,设置转换时间
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_3, 3, ADC_SampleTime_239Cycles5);
//使能ADC DMA
ADC_DMACmd(ADC1, ENABLE);
//使能ADC
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);//复位校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成
ADC_StartCalibration(ADC1);//ADC校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换
}
主函数调用:
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "string.h"
#include "usart.h"
#include "adc.h"
//3个通道ADC值
u16 ADC_BUFF[3];
int main(void)
{
u16 tep_val;
float adc_v;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init();
//初始化串口IO
uart_init(115200);
//单通道ADC DMA初始化
// ADC_DMA_Init();
//-------------多通道 ADC DMA读取----------------
ADC_DMA_Multichannel_Init((u32)ADC_BUFF);
while(1)
{
//-------------单通道 ADC DMA读取----------------
//ADC通道1 获取10次取平均值
// tep_val = get_ADC_DMA_Average(10);
// adc_v = (float)tep_val * (3.3 / 4096);
// printf("\r\nADC1 PA1 = %d\r\n", tep_val);
// printf("ADC1 PA1 = %fV\r\n", adc_v);
//-------------多通道 ADC DMA读取----------------
tep_val = ADC_BUFF[0];//ADC 通道1
adc_v = (float)tep_val * (3.3 / 4096);
printf("\r\nADC1 PA1 = %d\r\n", tep_val);
printf("ADC1 PA1 = %fV\r\n", adc_v);
tep_val = ADC_BUFF[1];//ADC 通道2
adc_v = (float)tep_val * (3.3 / 4096);
printf("\r\nADC1 PA2 = %d\r\n", tep_val);
printf("ADC1 PA2 = %fV\r\n", adc_v);
tep_val = ADC_BUFF[2];//ADC 通道3
adc_v = (float)tep_val * (3.3 / 4096);
printf("\r\nADC1 PA3 = %d\r\n", tep_val);
printf("ADC1 PA3 = %fV\r\n", adc_v);
delay_ms(500);
}
}