stm32miniADC可以采集0v和3.3v但采集不了0.7v https://ask.csdn.net/questions/4645843
采用ADC1,16個通道有4個不正常(通道3 5 6 7)。
通道2正常

通道3一直3.29v,接0.07v是為2.89v,感覺被上拉

采集0v和3.3v正常


代碼
代碼
adc.h
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
#define N 50 //每通道采 50 次
#define M 16 //最多為 16 個通道
void GPIO_Configuration(void);
void RCC_Configuration(void);
void ADC1_Configuration(void);
void DMA_Configuration(void);
void Init_All_Periph(void);
u16 GetVolt(u16 advalue);
void filter(void);
#endif
adc.c
#include "adc.h"
#include "delay.h"
extern vu16 AD_Value[N][M]; //用來存放 ADC 轉換結果,也是 DMA 的目標地址
extern vu16 After_filter[M]; //用來存放求平均值之后的結果
/*GPIO 管腳的配置
選用 ADC 的通道分別對應的管腳為
PA0 0
PA1 1
PA2 2
...
...
...
PA7 7
PB0 8
PB1 9
PC0 10
PC1 11
PC2 12
PC3 13
PC4 14
PC5 15
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//PA0/1/2?作為模擬通道輸入引腳?????????????????????????
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);
//PB0/1?作為模擬通道輸入引腳?????????????????????????
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入引腳
GPIO_Init(GPIOB, &GPIO_InitStructure);
//PC0/1/2/3/4/5?作為模擬通道輸入引腳?????????????????????????
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入引腳
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/*配置系統時鐘,使能各外設時鐘*/
void RCC_Configuration(void)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable?Prefetch?Buffer
FLASH_SetLatency(FLASH_Latency_2); //Set?2?Latency?cycles
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB?clock??=?SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //APB2?clock?=?HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //APB1?clock?=?HCLK/2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6); //PLLCLK?=?12MHz?*?6?=?72MHz
RCC_PLLCmd(ENABLE); //Enable?PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait?till?PLL?is?ready??
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select?PLL?as?system?clock?source
while(RCC_GetSYSCLKSource() != 0x08); //Wait?till?PLL?is?used?as?system?clock?source
/*使能各個外設時鐘*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB
| RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO
|RCC_APB2Periph_USART1, ENABLE ); //使能 ADC1 通道時鐘,各個管腳時鐘
/*?Configure?ADCCLK?such?as?ADCCLK?=?PCLK2/6?*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12,ADC 最大時間不能超過 14M
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 傳輸
}
/*配置 ADC1*/
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_DeInit(ADC1); //將外設?ADC1?的全部暫存器重設為預設值
/*?ADC1?configuration?‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 作業模式:ADC1 和 ADC2作業在獨立模式
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 = M; //順序進行規則轉換的 ADC 通道的數目
ADC_Init(ADC1, &ADC_InitStructure); //根據 ADC_InitStruct 中指定的引數初始化外設ADCx 的暫存器
/*?ADC1?regular?channel11?configuration?*/
//設定指定 ADC 的規則組通道,設定它們的轉化順序和采樣時間
//ADC1,ADC 通道 x,規則采樣順序值為 y,采樣時間為 239.5 周期
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_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 10, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 11, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 12, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 13, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 14, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 15, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 16, ADC_SampleTime_239Cycles5 );
//?開啟 ADC 的 DMA 支持(要實作 DMA 功能,還需獨立配置 DMA 通道等引數)
ADC_DMACmd(ADC1, ENABLE);
/*?Enable?ADC1?*/
ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1
/*?Enable?ADC1?reset?calibaration?register?*/
ADC_ResetCalibration(ADC1); //復位指定的 ADC1 的校準暫存器
/*?Check?the?end?of?ADC1?reset?calibration?register?*/
while(ADC_GetResetCalibrationStatus(ADC1)); //獲取ADC1復位校準暫存器的狀態,設定狀態則等待
/*?Start?ADC1?calibaration?*/
ADC_StartCalibration(ADC1); //開始指定 ADC1 的校準狀態
/*?Check?the?end?of?ADC1?calibration?*/
while(ADC_GetCalibrationStatus(ADC1)); //獲取指定ADC1的校準程式,設定狀態則等待
}
/*配置 DMA*/
void DMA_Configuration(void)
{
/*?ADC1??DMA1?Channel?Config?*/
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //將 DMA 的通道 1 暫存器重設為預設值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外設ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //DMA 記憶體基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //記憶體作為資料傳輸的目的地
DMA_InitStructure.DMA_BufferSize = N*M; //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(DMA1_Channel1, &DMA_InitStructure); //根據 DMA_InitStruct 中指定的引數初始化 DMA 的通道
}
//配置所有外設
void Init_All_Periph(void)
{
RCC_Configuration();
GPIO_Configuration();
ADC1_Configuration();
DMA_Configuration();
/*?Start?ADC1?Software?Conversion?*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE); //啟動 DMA 通道
}
/*獲取 ADC 的值,將二進制換算為十進制*/
u16 GetVolt(u16 advalue)
{
return (u16)(advalue * 330 / 4096); //求的結果擴大了 100 倍,方便下面求出小數
}
/*求平均值函式*/
void filter(void)
{
int sum = 0;
int i;
u8 count;
for(i=0;i<M;i++)
{
for ( count=0;count<N;count++)
{
sum += AD_Value[count][i];
}
After_filter[i]=sum/N;
sum=0;
}
}
main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"
#include "myiic.h"
#include "usart.h"
#include "adc.h"
#include "dma.h"
vu16 AD_Value[N][M]; //用來存放 ADC 轉換結果,也是 DMA 的目標地址
vu16 After_filter[M]; //用來存放求平均值之后的結果
//ALIENTEK Mini STM32開發板范例代碼19
//IIC實驗
extern int read;
extern int write;
int main()
{
int i;
int add;
u16 value[M];
float val[M];
delay_init();
uart_init(9600);
IIC_Init();
Init_All_Periph();
delay_ms(1);
while(1)
{
filter(); /*求平均值函式*/
for(i=0;i< M;i++) /*列印相關資料*/
{
value[i]= GetVolt(After_filter[i]);
val[i]=((float)value[i])/100;
printf("value[%d]:\t%.2fv\r\n",i,val[i]) ;
delay_ms(10);
}
printf("\r\n");
printf("\r\n");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/235795.html
標籤:單片機/工控
