久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
基于STM32F4的多通道ADC采集,采用DMA的形式,親測有效
[打印本頁]
作者:
我的南方有佳人
時間:
2019-10-11 08:46
標題:
基于STM32F4的多通道ADC采集,采用DMA的形式,親測有效
基于STM32F4的多通道ADC采集
單片機源程序如下:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "fliter.h"
#include "adc.h"
#include "oled.h"
extern u8 AD_Flag; //AD轉換完成標志位
extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的轉換值
extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
extern u16 ADC_filter_Value[NOFCHANEL];
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置系統中斷優先級分組2
delay_init(168); //初始化延時函數
uart_init(115200); //初始化串口波特率為115200
ADC_X_Init(); //ADC初始化
LED_Init(); //LED燈初始化
OLED_Init(); //OLED初始化
/************一開始的顯示*************/
OLED_ShowCHinese(12,0,0,1); //輸
OLED_ShowCHinese(24,0,1,1); //入
OLED_ShowCHinese(36,0,4,1); //電
OLED_ShowCHinese(48,0,5,1); //壓
OLED_ShowCHinese(60,0,10,1); //:
OLED_ShowCHinese(12,12,2,1); //輸
OLED_ShowCHinese(24,12,3,1); //出
OLED_ShowCHinese(36,12,6,1); //電
OLED_ShowCHinese(48,12,7,1); //流
OLED_ShowCHinese(60,12,10,1); //:
OLED_ShowString(12,24,"DAC:",12);
OLED_Refresh_Gram();//更新顯示到OLED
while(1)
{
AD_Flag=AD_voltage; ADC_filter_Value[0]=middleValueFilter();
AD_Flag=AD_current; ADC_filter_Value[1]=middleValueFilter();
AD_Flag=AD_DAC; ADC_filter_Value[2]=middleValueFilter();
ADC_Final_DisplayValue[0] =(double) ADC_filter_Value[0]/4096*3.3*6; //電壓檢測
ADC_Final_DisplayValue[1] =(double) ADC_filter_Value[1]/4096*3.3; //電流檢測
ADC_Final_DisplayValue[2] =(double) ADC_filter_Value[2]/4096*3.3; //DAC檢測
OLED_ShowFloatNum_12(72,0,ADC_Final_DisplayValue[0],2,12);
OLED_ShowFloatNum_12(72,12,ADC_Final_DisplayValue[1],2,12);
OLED_ShowFloatNum_12(72,24,ADC_Final_DisplayValue[2],2,12);
OLED_Refresh_Gram();//更新顯示到OLED
delay_ms(500);
}
}
復制代碼
#include "usart.h"
#include "adc.h"
#include "delay.h"
#include "fliter.h"
#include "led.h"
extern u8 AD_Flag; //AD轉換完成標志位
extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的轉換值
extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
u16 ADC_filter_Value[NOFCHANEL];
extern u16 ADC_ConvertedValue[NOFCHANEL];
// 軟件延時
void Delay_ruan(__IO uint32_t nCount)
{
for(; nCount != 0; nCount--);
}
//中位值濾波
//方法:連續采樣N次(N取奇數)把N次采樣值按大小排列取中間值為本次有效值
//優點:能有效克服因偶然因素引起的波動干擾;對溫度、液位等變化緩慢的被測參數有良好的濾波效果
//缺點:對流量,速度等快速變化的參數不宜
#define N 30
u16 middleValueFilter() //會獲取30個ADC轉換值,然后取中間的一個作為本次采樣周期的輸出值
{
u16 value_buf[N];
u16 i,j,k,temp;
for( i = 0; i < N; ++i)
{
value_buf[i] = getValue();
}
for(j = 0 ; j < N-1; ++j)
{
for(k = 0; k < N-j-1; ++k)
{
//從小到大排序,冒泡法排序
if(value_buf[k] > value_buf[k+1])
{
temp = value_buf[k];
value_buf[k] = value_buf[k+1];
value_buf[k+1] = temp;
}
}
}
return value_buf[(N-1)/2];
}
/*******************獲得ADC轉換的值*******************/
u16 getValue()
{
Delay_ruan(5); //軟件延時一下再獲取ADC的值,但是這個時間怎么確定呢?
if(AD_Flag==AD_voltage) //獲取ADC電壓的值
{
return ADC_ConvertedValue[0]; //因為ADC1的數據數據寄存器地址連接到了ADC_ConvertedValue數組上,所以ADC1采集到的值會傳輸到數組中,
}
if(AD_Flag==AD_current) //獲取ADC采集電流的值
{
return ADC_ConvertedValue[1];
}
if(AD_Flag==AD_DAC) //獲取DAC的值
{
return ADC_ConvertedValue[2];
}
}
//**************疑問*************//
//ADC1用了兩個通道,我怎么知道什么時候電流或者電壓的值存放到數組里?是否存到了對應的位置?
//因為存儲地址是連續的,所以ADC采集獲得的值會根據順序存入到數組中
復制代碼
#include "adc.h"
#include "delay.h"
u8 AD_Flag; //AD轉換完成標志位
u16 ADC_ConvertedValue[NOFCHANEL]={0}; //用于存放ADC的轉換值
float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最終顯示值
/*********************IO口復用為ADC******************/
void ADC_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //結構體定義
/*=====================通道1======================*/
/********** 使能 GPIO 時鐘****/
RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK1,ENABLE);
/********配置 IO************/
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復用時,作為ADC或者DAC,不能選復用,必須選模擬輸入,其他的都是復用
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
/*******初始化IO口*********/
GPIO_Init(ADC_GPIO_PORT1, &GPIO_InitStructure);
/*=====================通道2======================*/
/********** 使能 GPIO 時鐘****/
RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK2,ENABLE);
/********配置 IO************/
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復用時,作為ADC或者DAC,不能選復用,必須選模擬輸入,其他的都是復用
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
/*******初始化IO口*********/
GPIO_Init(ADC_GPIO_PORT2, &GPIO_InitStructure);
//// /*=====================通道3=======================*/
/********** 使能 GPIO 時鐘****/
RCC_AHB1PeriphClockCmd( ADC_GPIO_CLK3,ENABLE);
/********配置 IO************/
GPIO_InitStructure.GPIO_Pin =ADC_GPIO_PIN3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引腳復用時,作為ADC或者DAC,不能選復用,必須選模擬輸入,其他的都是復用
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
/*******初始化IO口*********/
GPIO_Init(ADC_GPIO_PORT3, &GPIO_InitStructure);
}
/***********配置ADC和DMA*************/
void ADC_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure; // DMA初始化結構體
ADC_InitTypeDef ADC_InitStructure; // ADC初始化結構體
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/*-------------------DMA Iint 結構體參數 初始化---------------------*/
/************開啟DMA時鐘*************************/
RCC_AHB1PeriphClockCmd(DMAX_CLK, ENABLE);
// 外設基址為:ADC 數據寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC_X->DR; //外設的數據寄存器地址怎么確定,(u32)&name->DR(name為外設名)
// 存儲器地址,實際上就是一個內部SRAM的變量
DMA_InitStructure.DMA_Memory0BaseAddr =(u32)ADC_ConvertedValue; //存放ADC轉換值的數組地址(可以理解為存放ADC轉換值的寄存器與這個數組直接連接在一起)
// 數據傳輸方向為外設到存儲器
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //確定方向很重要
// 緩沖區大小為,指一次傳輸的數據量
DMA_InitStructure.DMA_BufferSize = NOFCHANEL; //存放ADC轉換值的數組的數據量
// 外設寄存器只有一個,地址不用遞增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// 存儲器地址固定(這里明明寫的是增加,為什么還說固定,是錯誤了么)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //(這里應該是增加,因為要把多個數據存到一個數組里,地址應該是變化的)
// // 外設數據大小為半字,即兩個字節
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //這里指的是一個數據的大小,STM32是32位的,所以一個字是32位,半字是16位
// 存儲器數據大小也為半字,跟外設數據大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //外設數據大小是不是要和存儲器數據大小相同?是的
// 循環傳輸模式 (ADC要不斷采集數據,所以要循環模式)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// DMA 傳輸通道優先級為高,當使用一個DMA通道時,優先級設置不影響
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
// 禁止DMA FIFO ,使用直連模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
// FIFO 大小,FIFO模式禁止時,這個不用配置
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
// 選擇 DMA 通道,通道存在于流中
DMA_InitStructure.DMA_Channel =DMA_Channel__x;
//初始化DMA流,流相當于一個大的管道,管道里面有很多通道
DMA_Init(DMA_Stream__x, &DMA_InitStructure);
/****使能DMA流*********/
DMA_Cmd(DMA_Stream__x, ENABLE);
/*-------------ADC_X 初始化------------------*/
/***************使能ADC時鐘*****************************/
RCC_APB2PeriphClockCmd(ADC_CLK_ENABLE, ENABLE);
/*-------------------ADC Common 結構體 參數 初始化---------------*/
// 獨立ADC模式
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
// 時鐘為fpclk x分頻
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
// 禁止DMA直接訪問模式
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
// 采樣時間間隔
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
//初始化ADC Common 結構體
ADC_CommonInit(&ADC_CommonInitStructure);
/* -------------------ADC Init 結構體 參數 初始化-----------------*/
// ADC 分辨率
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// 掃描模式,多通道采集需要
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
// 連續轉換
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
//禁止外部邊沿觸發
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
//外部觸發通道,本例子使用軟件觸發,此值隨便賦值即可
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
//數據右對齊
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//轉換通道NOFCHANEL個
ADC_InitStructure.ADC_NbrOfConversion = NOFCHANEL;
/******ADC 結構體初始化*********/
ADC_Init(ADC_X, &ADC_InitStructure);
/*----------------配置 ADC 通道轉換順序和采樣時間周期-----------------*/
// 配置 ADC 通道轉換順序和采樣時間周期
ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL1, 1, ADC_SampleTime_56Cycles); //ADC通道1引腳是GPIOB_Pin_0
ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL2, 2, ADC_SampleTime_56Cycles); //ADC通道2引腳是GPIOB_Pin_1
ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL3, 3, ADC_SampleTime_56Cycles); //ADC通道3引腳是GPIOA_Pin_6
// 使能DMA請求 after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd(ADC_X, ENABLE);
/*************使能ADC DMA*************/
ADC_DMACmd(ADC_X, ENABLE);
/*************使能ADC******************/
ADC_Cmd(ADC_X, ENABLE);
//開始adc轉換,軟件觸發
ADC_SoftwareStartConv(ADC_X);
}
void ADC_X_Init(void)
{
ADC_GPIO_Config();
ADC_Mode_Config();
}
復制代碼
所有資料51hei提供下載:
STM32F4 多通道DMAADC.7z
(644.37 KB, 下載次數: 278)
2019-10-11 17:03 上傳
點擊文件名下載附件
基于STM32F4的多通道ADC采集,采用DMA形式,里面注釋詳細,有利于初學者學習
下載積分: 黑幣 -5
作者:
121212ad
時間:
2020-3-13 08:31
終于找到407的了
作者:
zp17777
時間:
2020-5-20 11:12
真的是感謝樓主的無私,先研究一下
作者:
303579
時間:
2020-6-5 21:23
樓主請問有電路圖嗎?可以分享一下嗎
作者:
mnz119
時間:
2021-7-27 10:47
感謝,先研究下
作者:
lngd128
時間:
2021-7-28 14:26
可以用來電池電壓采集使用
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
国产寡妇亲子伦一区二区三区四区
|
国产精品偷乱一区二区三区
|
久久精品二区
|
亚洲精品一二三四
|
一级片免费视频
|
亚洲黄色小视频
|
天天躁日日躁bbbbb
|
久久国产小视频
|
国产一区二三区
|
www.爱爱
|
av黄页
|
国产精品一区二区三区四区
|
日本色综合
|
黄色大片av
|
色噜噜狠狠一区二区三区
|
亚洲国产精品一区
|
亚洲国产成人av
|
中文字幕黄色
|
91久久国产综合久久91精品网站
|
国产资源视频
|
最新国产精品
|
日本在线视频观看
|
www.久久爱
|
91小视频在线观看
|
久久av片
|
欧美日韩国产精品
|
九九热这里
|
久久久免费精品视频
|
国产伦理一区
|
久久国产影院
|
日本一本视频
|
国产小视频在线
|
一区二区视频在线播放
|
四虎影视库
|
久久91精品
|
99国产精品99久久久久久粉嫩
|
91免费网
|
波多野结衣乳巨码无在线观看
|
欧美在线视频一区二区
|
国产一级片免费观看
|
男女视频网站
|