深圳 公司網(wǎng)站建設(shè)優(yōu)化關(guān)鍵詞排名哪家好
028 - STM32學(xué)習(xí)筆記 - 結(jié)構(gòu)體學(xué)習(xí)(二)
上節(jié)對ADC基礎(chǔ)知識進(jìn)行了學(xué)習(xí),這節(jié)在了解一下ADC相關(guān)的結(jié)構(gòu)體。
一、ADC初始化結(jié)構(gòu)體
在標(biāo)準(zhǔn)庫函數(shù)中基本上對于外設(shè)都有一個初始化結(jié)構(gòu)體xx_InitTypeDef
(其中xx為外設(shè)名,例如之前使用過的GPIO_InitTypeDef
),結(jié)構(gòu)體成員用來設(shè)置外設(shè)的工作模式,通過標(biāo)準(zhǔn)庫函數(shù)xx_Init()
調(diào)用將這些設(shè)定的參數(shù)送入外攝對應(yīng)的寄存器。
對于ADC來說也是這樣的操作,先看一下ADC_InitTypeDef
結(jié)構(gòu)體的定義:
ADC_InitTypeDef結(jié)構(gòu)體
typedef struct {uint32_t ADC_Resolution; //設(shè)置ADC分辨率選擇FunctionalState ADC_ScanConvMode; //設(shè)置ADC掃描選擇FunctionalState ADC_ContinuousConvMode; //設(shè)置ADC連續(xù)轉(zhuǎn)換模式選擇uint32_t ADC_ExternalTrigConvEdge; //設(shè)置ADC外部觸發(fā)極性uint32_t ADC_ExternalTrigConv; //設(shè)置ADC外部觸發(fā)選擇uint32_t ADC_DataAlign; //設(shè)置輸出數(shù)據(jù)對齊方式uint8_t ADC_NbrOfChannel; //設(shè)置轉(zhuǎn)換通道數(shù)目
} ADC_InitTypeDef;
ADC_Resolution
:用于配置ADC的分辨率,可選的分辨率有12 位、10 位、8 位和 6 位。分辨率越高, AD轉(zhuǎn)換數(shù)據(jù)精度越高,轉(zhuǎn)換時間也越長;分辨率越低,AD轉(zhuǎn)換數(shù)據(jù)精度越低,轉(zhuǎn)換時間也越短。
ADC_Resolution_12b //12位精度
ADC_Resolution_10b //10位精度
ADC_Resolution_8b //8位精度c
ADC_Resolution_6b //6位精度
ADC_ScanConvMode
:該成員主要用于配置ADC是否使用掃描,可選參數(shù)為ENABLE和DISABLE,如果只用到一個通道,配置為DISABLE,如果時多個通道,則選擇ENABLE。
ADC_ContinuousConvMode
:用于配置啟動自動連續(xù)轉(zhuǎn)換還是單次轉(zhuǎn)換,可選參數(shù)為ENABLE(連續(xù)轉(zhuǎn)換)和DISABLE(單次轉(zhuǎn)換)。如果選擇為單次轉(zhuǎn)換,那么每次轉(zhuǎn)換完成后,都需要手動控制才能重新啟動轉(zhuǎn)換。
ADC_ExternalTrigConvEdge
:設(shè)置外部觸發(fā)極性,如果使用外部觸發(fā),可選有:
ADC_ExternalTrigConvEdge_None //禁止觸發(fā)檢測
ADC_ExternalTrigConvEdge_Rising //上升沿觸發(fā)檢測
ADC_ExternalTrigConvEdge_Falling //下降沿觸發(fā)檢測
ADC_ExternalTrigConvEdge_RisingFalling //上升下降沿均檢測
ADC_ExternalTrigConv
:外部觸發(fā)模式選擇,可選的觸發(fā)條件如下圖-4,常用的一般使用軟件自動觸發(fā):
ADC_DataAlign
:設(shè)置轉(zhuǎn)換結(jié)果數(shù)據(jù)對其模式,可選有右對齊ADC_DataAlign_Right
或者左對齊ADC_DataAlign_Left
,這里我們選擇右對齊。
ADC_NbrOfChannel
:設(shè)置AD轉(zhuǎn)換通道數(shù)目。
ADC_CommonInitTypeDef結(jié)構(gòu)體
除了ADC_InitTypeDef
初始化結(jié)構(gòu)體外,還有ADC_CommonInitTypeDef通用初始化結(jié)構(gòu),ADC_CommonInitTypeDef結(jié)構(gòu)體內(nèi)容決定了三個ADC共用的工作環(huán)境。
typedef struct{uint32_t ADC_Mode; //ADC模式選擇uint32_t ADC_Prescaler; //ADC分頻系數(shù)uint32_t ADC_DMAAccessMode; //DMA模式配置uint32_t ADC_TwoSamplingDelay; //采樣延遲
}ADC_CommonInitTypeDef;
ADC_Mode
:ADC工作模式選擇在前面有學(xué)習(xí)過,有獨立模式、雙重模式以及三重模式;
ADC_Prescaler
:ADC時鐘分頻系數(shù)選擇,ADC時鐘是由PCLK2分頻而來,分頻系數(shù)決定ADC時鐘頻率,可選的分頻系數(shù)位2、4、6和8,在之前也學(xué)習(xí)過ADC的最大時鐘配置為36MHz。
ADC_DMAAccessMode
:DMA模式設(shè)置,在雙重或者三重模式下才需要設(shè)置,可以設(shè)置三種模式,分別為:
ADC_DMAAccessMode_Disabled //獨立模式下選擇
ADC_DMAAccessMode_1 //模式1
ADC_DMAAccessMode_2 //模式2
ADC_DMAAccessMode_3 //模式3
ADC_TwoSamplingDelay
:2個采樣階段之前的延遲,僅適用于雙重或三重交錯模式。
二、獨立模式單通道采集實驗
在F429實驗板上,提供了一個板載貼片滑動變阻器,供我們調(diào)試ADC時使用,原理圖如下:
滑動變阻器動觸點連接到STM32的ADC通道引腳(GPIOC_3),固定觸點一邊接0V,一邊接3.3V,因此旋轉(zhuǎn)滑動變阻器調(diào)節(jié)旋鈕時,動觸點的電壓會在0~3.3V之間變化。
根據(jù)以上電路設(shè)計,設(shè)計個模擬量采集程序,具體需要實現(xiàn)如下步驟:
- 初始化配置ADC目標(biāo)引腳為模擬輸入模式;
- 使能ADC時鐘(再次強調(diào),使用外設(shè)一定要先開啟時鐘!!!);
- 配置通用ADC為獨立模式,采樣4分頻;
- 設(shè)置目標(biāo)ADC為12位分辨率,1通道的連續(xù)轉(zhuǎn)換,不需要外部觸發(fā);
- 設(shè)置ADC轉(zhuǎn)換通道順序及采樣時間;
- 配置使能ADC轉(zhuǎn)換完成中斷,在中斷內(nèi)讀取轉(zhuǎn)換完數(shù)據(jù);
- 啟動ADC轉(zhuǎn)換;
- 使能軟件觸發(fā)ADC轉(zhuǎn)換。
這里需要注意,沒用使用到DMA進(jìn)行數(shù)據(jù)傳輸,而是使用中斷方式進(jìn)行讀取。
bsp_adc.h
#ifndef __BSP_ADC_H_
#define __BSP_ADC_H_#include "stm32f4xx.h"#define R_ADC_IRQ ADC_IRQn
#define R_ADC_INT_FUNCTION ADC_IRQHandler
#define R_ADC_GPIO_PORT GPIOC
#define R_ADC_GPIO_PIN GPIO_Pin_3
#define R_ADC_GPIO_CLK RCC_AHB1Periph_GPIOC#define R_ADC ADC1
#define R_ADC_CLK RCC_APB2Periph_ADC1
#define R_ADC_CHANNEL ADC_Channel_13void R_ADC_Init(void);
#endif
bsp_adc.c
#include "bsp_adc.h"/** @brief 初始化ADC GPIO引腳* @parm 無* @retval 無*/
static void R_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(R_ADC_GPIO_CLK,ENABLE); //開啟ADC外設(shè)引腳時鐘GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN; //配置引腳位3引腳GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //配置引腳為模擬輸入GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //配置為無上下拉GPIO_Init(R_ADC_GPIO_PORT,&GPIO_InitStructure); //初始化引腳
}/** @brief 配置ADC引腳工作模式* @parm 無* @retval 無*/
static void R_ADC_Mode_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;RCC_APB2PeriphClockCmd(R_ADC_CLK,ENABLE);//-----------------ADC Common結(jié)構(gòu)體參數(shù)初始化--------------//ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //設(shè)置模式為獨立模式ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; //設(shè)置為4分頻ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //禁止DMA直接訪問模式ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles; //設(shè)置采樣間隔周期為10個周期ADC_CommonInit(&ADC_CommonInitStructure);//-----------------ADC Init結(jié)構(gòu)體參數(shù)初始化--------------//ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //設(shè)置ADC采樣分辨率為12位ADC_InitStructure.ADC_ScanConvMode = DISABLE; //多通道下才會用到掃描模式,這里直接禁止ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //設(shè)置為連續(xù)轉(zhuǎn)換ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //禁用外部邊沿觸發(fā)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //設(shè)置為右對齊ADC_InitStructure.ADC_NbrOfConversion = 1; //轉(zhuǎn)換通道只有1個ADC_Init(R_ADC,&ADC_InitStructure);ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL,1,ADC_SampleTime_56Cycles); //配置ADC通道轉(zhuǎn)換順序為1,第一個轉(zhuǎn)換,才壓根時間為56個時鐘周期ADC_ITConfig(R_ADC,ADC_IT_EOC,ENABLE); //ADC轉(zhuǎn)換結(jié)束產(chǎn)生中斷,在中斷服務(wù)程序中讀取轉(zhuǎn)換數(shù)值ADC_Cmd(R_ADC,ENABLE); //使能ADCADC_SoftwareStartConv(R_ADC); //開始ADC轉(zhuǎn)換,由軟件觸發(fā)
}static void R_ADC_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //設(shè)置中斷向量組為1NVIC_InitStructure.NVIC_IRQChannel = R_ADC_IRQ; //配置中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //設(shè)置主優(yōu)先級為1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //設(shè)置此優(yōu)先級為1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能NVIC_Init(&NVIC_InitStructure); //初始化中斷
}
void R_ADC_Init(void)
{R_ADC_GPIO_Config();R_ADC_Mode_Config();R_ADC_NVIC_Config();
}
main.c
#include "stm32f4xx.h"
#include "bsp_usart_dma.h"
#include "bsp_systick.h"
#include "bsp_adc.h"
#include <stdio.h>
__IO uint16_t ADC_Value;
float ADC_Vol = 0;
int main(void)
{DEBUG_USART1_Config();R_ADC_Init();SysTick_Init();printf("\r\n---------------ADC實驗(中斷模式)----------------\r\n");while(1){Delay_ms(1000);printf("\r\n ADC數(shù)據(jù)(未轉(zhuǎn)換) = 0x%04X \r\n",ADC_Value);ADC_Vol =(float)(ADC_Value*3.3/4096); // 讀取轉(zhuǎn)換的 AD 值 printf("\r\n ADC數(shù)據(jù)(已轉(zhuǎn)換) = %.2f V \r\n",ADC_Vol);}
}
stm32f4xx_it.c
//此處記得在頭文件中聲明函數(shù)
extern __IO uint16_t ADC_ConvertedValue;
void ADC_IRQHandler(void)
{if (ADC_GetITStatus(R_ADC,ADC_IT_EOC)==SET) //獲取ADC中斷狀態(tài){ADC_ConvertedValue = ADC_GetConversionValue(R_ADC); // 等待轉(zhuǎn)換完成后,讀取ADC的轉(zhuǎn)換值}ADC_ClearITPendingBit(R_ADC,ADC_IT_EOC); //清除狀態(tài)寄存器
}
輸出結(jié)果如下,調(diào)整電位器會發(fā)現(xiàn)數(shù)值在0V~3.3V之間變化。
單通道相對比較簡單,這里先了解一下,后面在學(xué)習(xí)一下多通道并且啟用DMA傳輸模式。