折腾了两天ADC多通道采样,采样的结果都很乱,完全不是预期值。在amobbs求助也没有找到结果。于是决定从简单开始,一步步折腾着破ADC。
【ADC试验1实验说明】
1、这个实验仅仅是初始化一个ADC,对其输入进行采样。
2、使用STM32F4的ADC1进行采样,采样值不输出之在编译器里边观察。
3、使用ST外设库进行实验
4、本实验只为采集到数据,采样周期、采样间隔设置为最大。
【ADC试验1实验结果】
成功采集到了ADC1,通道1引脚PA1上的输入。数据稳定不跳变。
【ADC试验1实验步骤】
1、首先怀疑是工程中使用的USART、EXTI什么的影响了ADC的。重建工程,加入ST外设库,添加引用位置。这一步就不说了。
2、开启GPIOA、ADC时钟。因为使用ADC1的通道1,对应的PA1引脚作为输入。
ADC挂接在APB2时钟上,GPIOA挂接在AHB1时钟上。所以要开启这两个时钟。
代码如下:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
3、输入引脚配置
输入端口PA,引脚1.模拟输入,引脚时钟100M
//PA1 PA2 PA3,模拟输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_PinSource1 | GPIO_PinSource2 | GPIO_PinSource3;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
4、ADC通用的初始化
这是F4系列新出来的东西,与F1不同。这里通过库函数配置一个新增的寄存器ADC_CCR,这个配置将影响片上所有的ADC。
//ADC通用配置
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //不用DMA
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //独立采样
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; //速度尽可能低
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
5、ADC1初始化
之后对单独的ADC1进行配置,设定一些参数。最后的ADC_RegularChannelConfig完成通道选择和扫描顺序设置
主要参数:连续采样/数据右对齐/不用外部触发/采样通道数1/12位精度
//ADC1配置
ADC_InitStructyre.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructyre.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructyre.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructyre.ADC_NbrOfConversion = 1; //通道数
ADC_InitStructyre.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructyre.ADC_ScanConvMode = ENABLE;
ADC_Init(ADC1,&ADC_InitStructyre);
ADC_Cmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_144Cycles);
6、手动开始ADC采样,由于配置为连续扫描所有只需要开启一次即可:
使用函数ADC_SoftwareStartConv(ADC1);完成
7、获取ADC采样数据:
可以通过读ADC的DR或者使用库函数ADC_GetConversionValue来完成。我使用的是库函数。
adcvalue1 = ADC_GetConversionValue(ADC1);
adcvota = adcvalue1 *3300 / 0xfff;
8、最后加上串口功能,让数据回显
while(1)
{
adcvalue1 = ADC_GetConversionValue(ADC1);
adcvota = adcvalue1 *3300 / 0xfff;
for(i = 0;i<10000;i++)
{
sum += adcvota;
if(i ==9999)
{
avgvota = sum/10000;
sum = 0;
printf("avg vota is: %d\r\n",avgvota);
}
}
}
9、完整的代码:
#include <stm32f4xx.h>
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_conf.h"#include "usart.h"
#include <stdio.h>
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructyre;int adcvalue1,adcvalue2,adcvalue3;
int adcvota ;int i,sum,avgvota;
int main()
{
USART_Config();
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
//PA1 PA2 PA3,模拟输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_PinSource1 | GPIO_PinSource2 | GPIO_PinSource3;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//ADC通用配置
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //不用DMA
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //独立采样
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; //速度尽可能低
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
//ADC1配置
ADC_InitStructyre.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructyre.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructyre.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructyre.ADC_NbrOfConversion = 1;
ADC_InitStructyre.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructyre.ADC_ScanConvMode = ENABLE;
ADC_Init(ADC1,&ADC_InitStructyre);
ADC_Cmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_144Cycles);
ADC_SoftwareStartConv(ADC1);
sum = 0;
while(1)
{
adcvalue1 = ADC_GetConversionValue(ADC1);
adcvota = adcvalue1 *3300 / 0xfff;
for(i = 0;i<10000;i++)
{
sum += adcvota;
if(i ==9999)
{
avgvota = sum/10000;
sum = 0;
printf("avg vota is: %d\r\n",avgvota);
}
}
}
}
//重定义printf
int fputc(int ch,FILE *f)
{
//检查发送寄存器为空之后再往里边放数据
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
//USART发送一个字符
USART_SendData(USART1, (uint8_t) ch);
return ch;
}