参考资料:
STM32F10x系列芯片ADC通道和引脚对应关系。
stm32之adc多路采集+dma传输
8路ADC
adc.h
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define N 100 //每通道采100次,再求平均
#define M 8 //为8个通道
extern u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
extern u16 Average[M]; //用来存放求平均值之后的结果
void Adc_Init(void);
#endif
adc.c
#include "adc.h"
#include "delay.h"
u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址,每完成一次转换,DMA将数据依次存放到数组
u16 Average[M]; //用来存放求平均值之后的结果
//初始化ADC
//这里我们仅以规则通道为例
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA0/PA1/PA2/PA3/PA4/PA5 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为默认值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1独立模式
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数据右对齐
ADC_InitStructure.ADC_NbrOfChannel =8; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_239Cycles5 );
ADC_DMACmd(ADC1, ENABLE); //使能 ADC_DMA
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
dma.h
#ifndef __DMA_H
#define __DMA_H
#include "sys.h"
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr);//配置DMA1_CHx
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);//使能DMA1_CHx
#endif
dma.c
#include "dma.h"
DMA_InitTypeDef DMA_InitStructure;
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/16位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设发送到内存
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE); //启动DMA通道
}
main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dma.h"
int main(void)
{
int i=0,j=0;
float temp,SUM;
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init(); //初始化LCD
Adc_Init(); //ADC初始化
MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&AD_Value,N*M);//DMA1通道1,外设为ADC1,存储器地址&AD_Value,长N*M
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(20,15,200,24,24,"8 Channel ADC+DMA");
POINT_COLOR=MAGENTA;//设置字体为红色
LCD_ShowString(60,40,200,16,16,"ADC_CH0_VOL:0.000V");
LCD_ShowString(60,60,200,16,16,"ADC_CH1_VOL:0.000V");
LCD_ShowString(60,80,200,16,16,"ADC_CH2_VOL:0.000V");
LCD_ShowString(60,100,200,16,16,"ADC_CH3_VOL:0.000V");
LCD_ShowString(60,120,200,16,16,"ADC_CH4_VOL:0.000V");
LCD_ShowString(60,140,200,16,16,"ADC_CH5_VOL:0.000V");
LCD_ShowString(60,160,200,16,16,"ADC_CH6_VOL:0.000V");
LCD_ShowString(60,180,200,16,16,"ADC_CH7_VOL:0.000V");
LCD_ShowString(80,200,200,24,24,"ADC+DMA");
while(1)
{
//while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
for(j=0;j
{
for(i=0;i
{
SUM+=AD_Value
[j]; //每个通道的数据求和,注意是二维数组的每列的数据求和
}
Average[j]=SUM/N; //再取平均
temp=(float)Average[j]*(3.3/4096.0);
Average[j]=temp;
LCD_ShowxNum(156,40+20*j,Average[j],1,16,0);//显示电压值的整数部分
temp-=Average[j];
temp*=1000;
LCD_ShowxNum(172,40+20*j,temp,3,16,0X80);//显示电压值的小数部分
Average[j]=0;//开众提醒置零
SUM=0;//开众提醒置零
}
POINT_COLOR=BLACK;//设置字体为黑色
show_sentence24_24(20,260,200,24,24,"棒棒您好");
show_sentence24_24(100,290,200,24,24,"恭喜成功了");
LED0=!LED0;
delay_ms(250);
}
}
把前面main.c的封装改造一下,其他文件不变:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dma.h"
void Show_other(void);
void ShowCH_Voltage(void);
int main(void)
{
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init(); //初始化LCD
Adc_Init(); //ADC初始化
MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&AD_Value,N*M);//DMA1通道1,外设为ADC1,存储器地址&AD_Value,长N*M
Show_other();
while(1)
{
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET);//每次搬运完,再处理数组得出电压
POINT_COLOR=RED;//设置字体为红色
ShowCH_Voltage();
}
}
void ShowCH_Voltage(void)
{
int i=0,j=0;
float temp,SUM;
for(j=0;j
{
for(i=0;i
{
SUM+=AD_Value[j]; //每个通道的数据求和,注意是二维数组的每列的数据求和
}
Average[j]=SUM/N; //再取平均
temp=(float)Average[j]*(3.3/4096.0);
Average[j]=temp;
LCD_ShowxNum(144,40+30*j,Average[j],1,24,0);//显示电压值的整数部分
temp-=Average[j];
temp*=10000;
LCD_ShowxNum(144+24,40+30*j,temp,4,24,0X80);//显示电压值的小数部分
Average[j]=0;//开众提醒置零
SUM=0;//开众提醒置零
}
}
void Show_other(void)
{
int j=0;
u8 ADC_Ch[20];
POINT_COLOR=MAGENTA;//设置字体为紫色
LCD_ShowString(20,15,200,24,24,"8 Channel ADC+DMA");
show_sentence24_24(20,275,200,24,24,"棒棒恭喜成功");
LCD_ShowString(120,295,200,24,24,"2020/12/4");
for(j=0;j
{
sprintf((char*)ADC_Ch,"ADC_CH%d_VOL:0.0000V",j);//将int变量j打印到ADC_Ch数组。
LCD_ShowString(0,40+30*j,240,24,24,ADC_Ch);
}
}
参考资料:
STM32F10x系列芯片ADC通道和引脚对应关系。
stm32之adc多路采集+dma传输
8路ADC
adc.h
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define N 100 //每通道采100次,再求平均
#define M 8 //为8个通道
extern u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址
extern u16 Average[M]; //用来存放求平均值之后的结果
void Adc_Init(void);
#endif
adc.c
#include "adc.h"
#include "delay.h"
u16 AD_Value[N][M]; //用来存放ADC转换结果,也是DMA的目标地址,每完成一次转换,DMA将数据依次存放到数组
u16 Average[M]; //用来存放求平均值之后的结果
//初始化ADC
//这里我们仅以规则通道为例
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA0/PA1/PA2/PA3/PA4/PA5 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为默认值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1独立模式
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数据右对齐
ADC_InitStructure.ADC_NbrOfChannel =8; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_239Cycles5 );
ADC_DMACmd(ADC1, ENABLE); //使能 ADC_DMA
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
dma.h
#ifndef __DMA_H
#define __DMA_H
#include "sys.h"
void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr);//配置DMA1_CHx
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);//使能DMA1_CHx
#endif
dma.c
#include "dma.h"
DMA_InitTypeDef DMA_InitStructure;
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/16位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设发送到内存
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE); //启动DMA通道
}
main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dma.h"
int main(void)
{
int i=0,j=0;
float temp,SUM;
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init(); //初始化LCD
Adc_Init(); //ADC初始化
MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&AD_Value,N*M);//DMA1通道1,外设为ADC1,存储器地址&AD_Value,长N*M
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(20,15,200,24,24,"8 Channel ADC+DMA");
POINT_COLOR=MAGENTA;//设置字体为红色
LCD_ShowString(60,40,200,16,16,"ADC_CH0_VOL:0.000V");
LCD_ShowString(60,60,200,16,16,"ADC_CH1_VOL:0.000V");
LCD_ShowString(60,80,200,16,16,"ADC_CH2_VOL:0.000V");
LCD_ShowString(60,100,200,16,16,"ADC_CH3_VOL:0.000V");
LCD_ShowString(60,120,200,16,16,"ADC_CH4_VOL:0.000V");
LCD_ShowString(60,140,200,16,16,"ADC_CH5_VOL:0.000V");
LCD_ShowString(60,160,200,16,16,"ADC_CH6_VOL:0.000V");
LCD_ShowString(60,180,200,16,16,"ADC_CH7_VOL:0.000V");
LCD_ShowString(80,200,200,24,24,"ADC+DMA");
while(1)
{
//while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET );
for(j=0;j
{
for(i=0;i
{
SUM+=AD_Value
[j]; //每个通道的数据求和,注意是二维数组的每列的数据求和
}
Average[j]=SUM/N; //再取平均
temp=(float)Average[j]*(3.3/4096.0);
Average[j]=temp;
LCD_ShowxNum(156,40+20*j,Average[j],1,16,0);//显示电压值的整数部分
temp-=Average[j];
temp*=1000;
LCD_ShowxNum(172,40+20*j,temp,3,16,0X80);//显示电压值的小数部分
Average[j]=0;//开众提醒置零
SUM=0;//开众提醒置零
}
POINT_COLOR=BLACK;//设置字体为黑色
show_sentence24_24(20,260,200,24,24,"棒棒您好");
show_sentence24_24(100,290,200,24,24,"恭喜成功了");
LED0=!LED0;
delay_ms(250);
}
}
把前面main.c的封装改造一下,其他文件不变:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "adc.h"
#include "dma.h"
void Show_other(void);
void ShowCH_Voltage(void);
int main(void)
{
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
LCD_Init(); //初始化LCD
Adc_Init(); //ADC初始化
MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR,(u32)&AD_Value,N*M);//DMA1通道1,外设为ADC1,存储器地址&AD_Value,长N*M
Show_other();
while(1)
{
while((DMA_GetFlagStatus(DMA1_FLAG_TC1)) == RESET);//每次搬运完,再处理数组得出电压
POINT_COLOR=RED;//设置字体为红色
ShowCH_Voltage();
}
}
void ShowCH_Voltage(void)
{
int i=0,j=0;
float temp,SUM;
for(j=0;j
{
for(i=0;i
{
SUM+=AD_Value[j]; //每个通道的数据求和,注意是二维数组的每列的数据求和
}
Average[j]=SUM/N; //再取平均
temp=(float)Average[j]*(3.3/4096.0);
Average[j]=temp;
LCD_ShowxNum(144,40+30*j,Average[j],1,24,0);//显示电压值的整数部分
temp-=Average[j];
temp*=10000;
LCD_ShowxNum(144+24,40+30*j,temp,4,24,0X80);//显示电压值的小数部分
Average[j]=0;//开众提醒置零
SUM=0;//开众提醒置零
}
}
void Show_other(void)
{
int j=0;
u8 ADC_Ch[20];
POINT_COLOR=MAGENTA;//设置字体为紫色
LCD_ShowString(20,15,200,24,24,"8 Channel ADC+DMA");
show_sentence24_24(20,275,200,24,24,"棒棒恭喜成功");
LCD_ShowString(120,295,200,24,24,"2020/12/4");
for(j=0;j
{
sprintf((char*)ADC_Ch,"ADC_CH%d_VOL:0.0000V",j);//将int变量j打印到ADC_Ch数组。
LCD_ShowString(0,40+30*j,240,24,24,ADC_Ch);
}
}
举报