日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32 ADC转换实验

發(fā)布時間:2023/12/10 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32 ADC转换实验 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

摘自:STM32 ADC轉換實驗
作者:追兮兮
發(fā)布時間: 2020-10-29 09:42:24
網(wǎng)址:https://blog.csdn.net/weixin_44234294/article/details/109333307

STM32 ADC 簡介

STM32 擁有 1~3 個 ADC(STM32F101/102 系列只有 1 個 ADC),這些 ADC 可以獨立使用,也可以使用雙重模式(提高采樣率)。STM32 的 ADC 是 12 位逐次逼近型的模擬數(shù)字轉換器。它有 18 個通道,可測量 16 個外部和 2 個內部信號源。各通道的 A/D 轉換可以單次、連續(xù)、掃描或間斷模式執(zhí)行。ADC 的結果可以左對齊或右對齊方式存儲在 16 位數(shù)據(jù)寄存器中。 模擬看門狗特性允許應用程序檢測輸入電壓是否超出用戶定義的高/低閥值。
STM32F103 系列最少都擁有 2 個 ADC,我們選擇的 STM32F103ZET 包含有 3 個 ADC。STM32 的 ADC 最大的轉換速率為 1Mhz,也就是轉換時間為 1us(在 ADCCLK=14M,采樣周期為 1.5 個 ADC 時鐘下得到),不要讓 ADC 的時鐘超過 14M,否則將導致結果準確度下降。
STM32 將 ADC 的轉換分為 2 個通道組:規(guī)則通道組和注入通道組。規(guī)則通道相當于你正 常運行的程序,而注入通道呢,就相當于中斷。在你程序正常執(zhí)行的時候,中斷是可以打斷你的執(zhí)行的。同這個類似,注入通道的轉換可以打斷規(guī)則通道的轉換, 在注入通道被轉換完成之后,規(guī)則通道才得以繼續(xù)轉換。

ADC 控制寄存器

ADC_CR1 的各位描述

ADC_CR1 的 SCAN 位,該位用于設置掃描模式,由軟件設置和清除,如果設置為 1,則使用掃描模式,如果為 0,則關閉掃描模式。在掃描模式下,由 ADC_SQRx 或 ADC_JSQRx 寄存器選中的通道被轉換。如果設置了 EOCIE 或 JEOCIE,只在最后一個通道轉換完畢后才會產生 EOC 或 JEOC 中斷。
ADC_CR1[19:16]用于設置 ADC 的操作模式,詳細的對應關系如圖

ADC 狀態(tài)寄存器(ADC_SR)

該寄存器保存了 ADC 轉換時的各種狀態(tài):

這里我們要用到的是 EOC 位,我們通過判斷該位來決定是否此次規(guī)則通道的 AD 轉換已經(jīng)完成,如果完成我們就從 ADC_DR 中讀取轉換結果,否則等待轉換完成。

ADC轉換實驗一般步驟

1. 開啟 PA 口時鐘和 ADC1 時鐘,設置 PA1 為模擬輸入
STM32F103ZET6 的 ADC 通道 1 在 PA1 上,所以,我們先要使能 PORTA 的時鐘和 ADC1時鐘,然后設置 PA1 為模擬輸入。使能 GPIOA 和 ADC 時鐘用RCC_APB2PeriphClockCmd 函數(shù),設置 PA1 的輸入方式,使用 GPIO_Init 函數(shù)即可。這里我們列出 STM32 的 ADC 通道與GPIO 對應表:

/*開啟PA口的時鐘和ADC1的時鐘,設置PA1位模擬輸入*/GPIO_InitTypeDef GPIO_InitStruce;RCC_APB2PeriphClockCmd(ADC_GPIO_RCC,ENABLE);//使能時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);GPIO_InitStruce.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入GPIO_InitStruce.GPIO_Pin = ADC_GPIO_PIN;//引腳1GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ADC_GPIO_PORT,&GPIO_InitStruce);

2. 復位 ADC1,同時設置 ADC1 分頻因子。
開啟 ADC1 時鐘之后,我們要復位 ADC1,將 ADC1 的全部寄存器重設為缺省值之后我們就可以通過 RCC_CFGR 設置 ADC1 的分頻因子。分頻因子要確保 ADC1 的時鐘(ADCCLK)不要超過 14Mhz。 這個我們設置分頻因子位 6,時鐘為 72/6=12MHz,庫函數(shù)的實現(xiàn)方法是:

RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  • 1

ADC 時鐘復位的方法是:

ADC_DeInit(ADC1);
  • 1
/*復位ADC1,同時設置ADC1分頻因子*//*ADC時鐘不能超過14M,APB2的時鐘是72M,所以可以選擇6,。72/6 = 12*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);ADC_DeInit(ADC1);//復位ADC
  • 1
  • 2
  • 3
  • 4

3. 初始化 ADC1 參數(shù),設置 ADC1 的工作模式以及規(guī)則序列的相關信息。
在設置完分頻因子之后,我們就可以開始 ADC1 的模式配置了,設置單次轉換模式、觸發(fā)方式選擇、數(shù)據(jù)對齊方式等都在這一步實現(xiàn)。同時,我們還要設置 ADC1 規(guī)則序列的相關信息,我們這里只有一個通道,并且是單次轉換的,所以設置規(guī)則序列中通道數(shù)為 1。這些在庫函數(shù)中是通過函數(shù) ADC_Init 實現(xiàn)的,下面我們看看其定義:

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
  • 1

從函數(shù)定義可以看出,第一個參數(shù)是指定 ADC 號。這里我們來看看第二個參數(shù),跟其他外設初始化一樣,同樣是通過設置結構體成員變量的值來設定參數(shù)。

typedef struct {uint32_t ADC_Mode; FunctionalState ADC_ScanConvMode; FunctionalState ADC_ContinuousConvMode; uint32_t ADC_ExternalTrigConv; uint32_t ADC_DataAlign; uint8_t ADC_NbrOfChannel; }ADC_InitTypeDef;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

參數(shù) ADC_Mode 故名是以是用來設置 ADC 的模式。前面講解過,ADC 的模式非常多,包括獨立模式,注入同步模式等等,這里我們選擇獨立模式,所以參數(shù)為 ADC_Mode_Independent
參數(shù) ADC_ScanConvMode 用來設置是否開啟掃描模式,因為是單次轉換,這里我們選擇不開啟值 DISABLE 即可。
參數(shù) ADC_ContinuousConvMode 用來設置是否開啟連續(xù)轉換模式,因為是單次轉換模式,所以我們選擇不開啟連續(xù)轉換模式,DISABLE 即可。
參數(shù) ADC_ExternalTrigConv 是用來設置啟動規(guī)則轉換組轉換的外部事件,這里我們選擇軟件觸 發(fā),選擇值為 ADC_ExternalTrigConv_None 即可。
參數(shù) DataAlign 用來設置 ADC 數(shù)據(jù)對齊方式是左對齊還是右對齊,這里我們選擇右對齊方式ADC_DataAlign_Right
參數(shù) ADC_NbrOfChannel 用來設置規(guī)則序列的長度,這里我們是單次轉換,所以值為 1 即可。

ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 工作模式:獨立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //AD 單通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //AD 單次轉換模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //轉換由軟件而不是外部觸發(fā)啟動 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC 數(shù)據(jù)右對齊 ADC_InitStructure.ADC_NbrOfChannel = 1; //順序進行規(guī)則轉換的 ADC 通道的數(shù)目 1 ADC_Init(ADC1, &ADC_InitStructure); //根據(jù)指定的參數(shù)初始化外設 ADCx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4. 使能 ADC 并校準
在設置完了以上信息后,我們就使能 AD 轉換器,執(zhí)行復位校準和 AD 校準,注意這兩步
是必須的!不校準將導致結果很不準確。
使能指定的 ADC 的方法是:

ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1
  • 1

執(zhí)行復位校準的方法是:

ADC_ResetCalibration(ADC1);
  • 1

執(zhí)行 ADC 校準的方法是:

ADC_StartCalibration(ADC1); //開始指定 ADC1 的校準狀態(tài)
  • 1

記住,每次進行校準之后要等待校準結束。這里是通過獲取校準狀態(tài)來判斷是否校準是否結束。
下面我們一一列出復位校準和 AD 校準的等待結束方法:

while(ADC_GetResetCalibrationStatus(ADC1)); //等待復位校準結束 while(ADC_GetCalibrationStatus(ADC1)); //等待校 AD 準結束
  • 1
  • 2

5. 配置規(guī)則通道參數(shù)
接下來我們要做的就是設置規(guī)則序列 1 里面的通道,采樣順序,以及通道的采樣周期,然后啟動 ADC 轉換。在轉換結束后,讀取 ADC 轉 換結果值就是了。這里設置規(guī)則序列通道以及采樣周期的函數(shù)是:

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
  • 1
  • 2

我們這里是規(guī)則序列中的第 1 個轉換,同時采樣周期為 239.5,所以設置為:

ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
  • 1

6. 開啟軟件轉換
軟件開啟 ADC 轉換的方法是:

ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的 ADC1 的軟件轉換啟動功能
  • 1

開啟轉換之后,就可以獲取轉換 ADC 轉換結果數(shù)據(jù),方法是:

ADC_GetConversionValue(ADC1);
  • 1

7. 等待轉換完成讀取ADC的值
同時在 AD 轉換中,我們還要根據(jù)狀態(tài)寄存器的標志位來獲取 AD 轉換的各個狀態(tài)信息。庫函數(shù)獲取 AD 轉換的狀態(tài)信息的函數(shù)是:

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
  • 1

比如我們要判斷 ADC1d 的轉換是否結束,方法是:

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束
  • 1

代碼

adc.h

#ifndef _ADC_H_ #define _ADC_H_ #include "sys.h"#define ADC_GPIO_RCC RCC_APB2Periph_GPIOA #define ADC_GPIO_PORT GPIOA #define ADC_GPIO_PIN GPIO_Pin_1void adc_Init(void); u16 Get_Adc(u8 ch); u16 Get_Adc_Average(u8 ch,u8 times);#endif

adc.c

#include "adc.h" #include "delay.h"void adc_Init(void) {GPIO_InitTypeDef GPIO_InitStruce;ADC_InitTypeDef ADC_InitStruce;/*開啟PA口的時鐘和ADC1的時鐘,設置PA1位模擬輸入*/RCC_APB2PeriphClockCmd(ADC_GPIO_RCC,ENABLE);//使能時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);GPIO_InitStruce.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入GPIO_InitStruce.GPIO_Pin = ADC_GPIO_PIN;//引腳1GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ADC_GPIO_PORT,&GPIO_InitStruce);/*復位ADC1,同時設置ADC1分頻因子*//*ADC時鐘不能超過14M,APB2的時鐘是72M,所以可以選擇6,。72/6 = 12*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);ADC_DeInit(ADC1);//復位ADC/*初始化ADC1參數(shù),設置ADC1的工作模式以及規(guī)則序列的相關信息*/ADC_InitStruce.ADC_ContinuousConvMode = DISABLE;//不開啟ADC_InitStruce.ADC_DataAlign = ADC_DataAlign_Right;//選擇右對齊 ADC_InitStruce.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部觸發(fā)ADC_InitStruce.ADC_Mode = ADC_Mode_Independent;//使用獨立模式ADC_InitStruce.ADC_NbrOfChannel = 1;//設置單通道ADC_InitStruce.ADC_ScanConvMode = DISABLE;//不使用掃描模式ADC_Init(ADC1,&ADC_InitStruce);/*使能ADC并校準*/ADC_Cmd(ADC1,ENABLE);//使能ADC_ResetCalibration(ADC1);//使能復位校準while(ADC_GetResetCalibrationStatus(ADC1));//等待復位校準結束ADC_StartCalibration(ADC1);//開啟AD校準while(ADC_GetCalibrationStatus(ADC1));//等待校準結束} u16 Get_Adc(u8 ch) {/*配置規(guī)則通道參數(shù)*/ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);//1:只有一個通道被轉換 ADC_SampleTime_239Cycles5:采樣時間隨便選/*開啟軟件轉換*/ADC_SoftwareStartConvCmd(ADC1,ENABLE);while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//等待軟件交換結束,ADC_FLAG_EOC:轉換結束標志,=reset就是0退出循環(huán)/*等待轉換完成讀取ADC的值*/return ADC_GetConversionValue(ADC1);//返回轉換結果 }u16 Get_Adc_Average(u8 ch,u8 times) {u32 tem_val = 0;u8 t;for(t = 0; t < times; t++){tem_val += Get_Adc(ch);delay_ms(5);}return tem_val/times;}

main.c

#include "stm32f10x.h" #include "adc.h" #include "delay.h" #include "led.h" #include "key.h" #include "lcd.h" #include "usart.h"int main(void) {u16 adcx;float temp;delay_init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置中斷優(yōu)先級分組為2,2位搶占優(yōu)先級,2位響應優(yōu)先級uart_init(115200);//串口初始化115200LED_Init();//初始化LEDLCD_Init();//初始化LCDadc_Init();//初始化ADCPOINT_COLOR = RED;//設置字體為紅色LCD_ShowString(60,50,200,16,16,"Hello STM32"); LCD_ShowString(60,110,200,16,16,"2020/10/27"); //顯示提示信息POINT_COLOR=BLUE;//設置字體為藍色LCD_ShowString(60,130,200,16,16,"ADC_CH0_VAL:"); LCD_ShowString(60,150,200,16,16,"ADC_CH0_VOL:0.000V"); while(1){adcx=Get_Adc_Average(ADC_Channel_1,10);//選擇通道1,獲取10次取平均值LCD_ShowxNum(156,130,adcx,4,16,0);//顯示ADC的值temp=(float)adcx*(3.3/4096);//算出電壓值,12位的參考電壓3.3adcx=temp;//取整數(shù)部分LCD_ShowxNum(156,150,adcx,1,16,0);//顯示電壓值。顯示整數(shù)部分temp-=adcx;//減掉整數(shù)部分temp*=1000;LCD_ShowxNum(170,150,temp,3,16,0X80);//顯示小數(shù)點后面LED0=!LED0;delay_ms(250); }}

實驗現(xiàn)象

PA1接3.3V

PA1接GND

需要整個工程文件可私聊

總結

以上是生活随笔為你收集整理的STM32 ADC转换实验的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。