CKS32F4xx系列
ADC單通道電壓采集
ADC可以將現(xiàn)實(shí)世界中連續(xù)變化的模擬量,如溫度、壓力、流量、速度、光強(qiáng)等,轉(zhuǎn)換成離散的數(shù)字量,輸入到計(jì)算機(jī)中進(jìn)行處理。按照原理不同,ADC可以分為積分型、逐次逼近型(SAR)、并行比較型、Σ-?調(diào)制型、電容陣列逐次比較型及壓頻變換型。逐次逼近型(SAR)ADC由比較器和DA轉(zhuǎn)換器構(gòu)成,它從最高有效MSB位開始通過逐次比較,按順序以位位單位對(duì)輸入電壓與內(nèi)置DA轉(zhuǎn)換器輸出電壓進(jìn)行比較,經(jīng)過多次比較輸出相應(yīng)的數(shù)字值。逐次逼近型(SAR)ADC的電路規(guī)模屬于中等,它的優(yōu)點(diǎn)是速度較快、功耗低、成本適中。
ADC簡(jiǎn)介
CKS32F4xx系列產(chǎn)品內(nèi)嵌3個(gè)12位SAR型ADC,每個(gè)ADC多達(dá)19個(gè)復(fù)用通道,可測(cè)量來自16個(gè)外部、2個(gè)內(nèi)部和VBAT通道的信號(hào),具有獨(dú)立模式、雙重模式和三種模式,并支持單次、連續(xù)、掃描或間斷采樣模式下進(jìn)行A/D轉(zhuǎn)換,對(duì)于不同AD轉(zhuǎn)換要求幾乎都有合適的模式可選,轉(zhuǎn)換的結(jié)果可以按照左對(duì)齊或右對(duì)齊的方式存儲(chǔ)在16位數(shù)據(jù)寄存器中。下圖是CKS32F4xx系列產(chǎn)品ADC的結(jié)構(gòu)框圖,每個(gè)模塊的具體描述和技術(shù)參數(shù)可以參閱《CKS32F4xx參考手冊(cè)》。
ADC主要特性
分辨率支持12位,10位,8位,6位,可軟件配置
支持轉(zhuǎn)換結(jié)束產(chǎn)生中斷、包括規(guī)則通道和注入通道
支持單次、連續(xù)、間隔轉(zhuǎn)換模式
可獨(dú)立設(shè)置各通道采樣時(shí)間
規(guī)則通道轉(zhuǎn)換和注入通道轉(zhuǎn)換均有外部觸發(fā)選項(xiàng),支持軟件或者硬件觸發(fā)轉(zhuǎn)換
支持模擬看門狗
支持雙重或者三重模式(具有2個(gè)或以上ADC的器件)
支持雙重或者三重模式下可配置的DMA數(shù)據(jù)存儲(chǔ)
可配置雙重或者三重交替采樣模式下的轉(zhuǎn)換延遲時(shí)間間隔
ADC供電要求:全速模式下為2.4V到3.6V,低速模式下為1.8V
ADC輸入電壓范圍:Vref-≤Vin≤Vref+
規(guī)則通道轉(zhuǎn)換期間可產(chǎn)生DMA請(qǐng)求
固件庫中與ADC相關(guān)的主要API
CKS32F4xx系列固件庫中與ADC相關(guān)的API定義在cks32f4xx_adc.h和cks32f4xx_adc.c兩個(gè)文件中,前者為頭文件,包含寄存器地址、常量定義、API函數(shù)聲明,后者為API的具體實(shí)現(xiàn)。CKS32F4xx系列產(chǎn)品最多有3個(gè)ADC,編號(hào)分別為ADC1、ADC2、ADC3,大多數(shù)API的第一個(gè)參數(shù)為ADC_TypeDef*ADCx,表示操作的ADC實(shí)體編號(hào)。下表列出了常用的API函數(shù):
API函數(shù)原型 | 函數(shù)功能 |
void ADC_DeInit(void) | 復(fù)位ADC外設(shè)寄存器 |
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) | 根據(jù)ADC_InitStruct中參數(shù)初始化ADC |
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct) | 復(fù)位結(jié)構(gòu)體成員 |
void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct) | 根據(jù)結(jié)構(gòu)體參數(shù)初始化ADC外設(shè) |
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能或者禁止ADC外設(shè) |
void ADC_TempSensorVrefintCmd(FunctionalState NewState) | 使能或者禁止溫度傳感器通道 |
void ADC_VBATCmd(FunctionalState NewState) | 使能或者禁止VBAT通道 |
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) | 設(shè)置ADC規(guī)則通道的參數(shù)和采樣時(shí)間 |
void ADC_SoftwareStartConv(ADC_TypeDef* ADCx) | 軟件啟動(dòng)ADC轉(zhuǎn)換 |
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx) | 得到ADC轉(zhuǎn)換狀態(tài) |
voidADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能或者禁止每個(gè)規(guī)則轉(zhuǎn)換通道的EOC |
void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能或者禁止ADC的連續(xù)轉(zhuǎn)換模式 |
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number) | 配置ADC規(guī)則組通道的間斷模式 |
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能或者禁止ADC的規(guī)則組通道 |
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) | 得到規(guī)則通道最后一次轉(zhuǎn)換的數(shù)值 |
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能或者禁止ADC的DMA請(qǐng)求 |
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) | 設(shè)置ADC注入通道的參數(shù)和采樣時(shí)間 |
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length) | 配置注入通道序列長度 |
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) | 設(shè)置注入通道轉(zhuǎn)換值偏移 |
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv) | 配置注入通道的外部觸發(fā) |
void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx) | 配置注入通道轉(zhuǎn)換 |
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) | 使能注入通道組的間斷模式 |
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState) | 使能或者禁止ADC中斷 |
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) | 檢測(cè)ADC特定標(biāo)志是否設(shè)置 |
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) | 清除ADC標(biāo)志 |
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT) | 通過相應(yīng)標(biāo)志檢測(cè)是否發(fā)生相應(yīng)中斷 |
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT) | 清除中斷掛起位 |
實(shí)現(xiàn)ADC單通道電壓采集
CKS32F4xx系列的ADC功能繁多,我們?cè)O(shè)計(jì)幾個(gè)實(shí)驗(yàn)盡量完整的展示ADC的功能。本次課堂主要介紹比較基礎(chǔ)實(shí)用的單通道電壓采集,實(shí)現(xiàn)開發(fā)板上引腳電壓的采集并通過串口打印至PC端串口調(diào)試助手。單通道電壓采集適用AD轉(zhuǎn)換完成中斷,在中斷服務(wù)函數(shù)中讀取數(shù)據(jù),不使用DMA傳輸,在后期多通道采集實(shí)驗(yàn)中再使用DMA傳輸。相關(guān)核心代碼實(shí)現(xiàn)如下:
(1)ADC宏定義
// ADC GPIO 宏定義 #define TEMP_ADC_GPIO_PORT GPIOB #define TEMP_ADC_GPIO_PIN GPIO_Pin_0 #define TEMP_ADC_GPIO_CLK RCC_AHB1Periph_GPIOB // ADC 序號(hào)宏定義 #define TEMP_ADC ADC1 #define TEMP_ADC_CLK RCC_APB2Periph_ADC1 #define TEMP_ADC_CHANNEL ADC_Channel_8 // ADC 中斷宏定義 #define Temp_ADC_IRQ ADC_IRQn #define Temp_ADC_INT_FUNCTION ADC_IRQHandler
(2)ADC GPIO初始化
static void Temp_ADC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(TEMP_ADC_GPIO_CLK, ENABLE);// 使能 GPIO 時(shí)鐘 GPIO_InitStructure.GPIO_Pin = TEMP_ADC_GPIO_PIN; // 配置 IO GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 配置為模擬輸入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉 GPIO_Init(TEMP_ADC_GPIO_PORT, &GPIO_InitStructure); }
使用到GPIO時(shí)候都必須開啟對(duì)應(yīng)的GPIO時(shí)鐘,GPIO用于AD轉(zhuǎn)換功能必須配置為模擬輸入模式。
(3)配置ADC工作模式
static void Temp_ADC_Mode_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; RCC_APB2PeriphClockCmd(TEMP_ADC_CLK , ENABLE); // 開啟ADC時(shí)鐘 // -------------------ADC Common 結(jié)構(gòu)體 參數(shù) 初始化------------------------ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; // 獨(dú)立ADC模式 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 時(shí)鐘為fpclk x分頻 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 禁止DMA直接訪問模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; // 采樣時(shí)間間隔 ADC_CommonInit(&ADC_CommonInitStructure); // -------------------ADC Init 結(jié)構(gòu)體 參數(shù) 初始化-------------------------- ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; // ADC 分辨率 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 禁止掃描模式,多通道采集才需要 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 連續(xù)轉(zhuǎn)換 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止外部邊沿觸發(fā) ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //外部觸發(fā)通道,本例子使用軟件觸發(fā),此值隨便賦值即可 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //數(shù)據(jù)右對(duì)齊 ADC_InitStructure.ADC_NbrOfConversion = 1; //轉(zhuǎn)換通道 1個(gè) ADC_Init(TEMP_ADC, &ADC_InitStructure); // 配置 ADC 通道轉(zhuǎn)換順序?yàn)?,第一個(gè)轉(zhuǎn)換,采樣時(shí)間為3個(gè)時(shí)鐘周期 ADC_RegularChannelConfig(TEMP_ADC, TEMP_ADC_CHANNEL, 1, ADC_SampleTime_56Cycles); // ADC 轉(zhuǎn)換結(jié)束產(chǎn)生中斷,在中斷服務(wù)程序中讀取轉(zhuǎn)換值 ADC_ITConfig(TEMP_ADC, ADC_IT_EOC, ENABLE); ADC_Cmd(TEMP_ADC, ENABLE); // 使能ADC ADC_SoftwareStartConv(TEMP_ADC);//開始ADC轉(zhuǎn)換,軟件觸發(fā) }
首先,使用ADC_InitTypeDef和ADC_CommonInitTypeDef結(jié)構(gòu)體分別定義一個(gè)ADC初始化和ADC通用類型變量。調(diào)用RCC_APB2PeriphClockCmd()開啟ADC時(shí)鐘。接下來使用ADC_CommonInitTypeDef結(jié)構(gòu)體變量ADC_CommonInitStructure來配置ADC為獨(dú)立模式、分頻系數(shù)為2、不需要設(shè)置DMA模式、20個(gè)周期的采樣延遲,并調(diào)用ADC_CommonInit函數(shù)完成ADC通用工作環(huán)境配置。我們使用ADC_InitTypeDef結(jié)構(gòu)體變量ADC_InitStructure來配置ADC1為12位分辨率、單通道采集不需要掃描、啟動(dòng)連續(xù)轉(zhuǎn)換、使用內(nèi)部軟件觸發(fā)無需外部觸發(fā)事件、使用右對(duì)齊數(shù)據(jù)格式轉(zhuǎn)換通道為1,并調(diào)用ADC_Init函數(shù)完成ADC1工作環(huán)境配置。
ADC_RegularChannelConfifig函數(shù)用來綁定ADC通道轉(zhuǎn)換順序和時(shí)間。它接收4個(gè)形參,第一個(gè)形參選擇ADC外設(shè),可為ADC1、ADC2或ADC3;第二個(gè)形參通道選擇,總共可選18個(gè)通道;第三個(gè)形參為轉(zhuǎn)換順序,可選為1到16;第四個(gè)形參為采樣周期選擇,采樣周期越短,ADC轉(zhuǎn)換數(shù)據(jù)輸出周期就越短但數(shù)據(jù)精度也越低,采樣周期越長,ADC轉(zhuǎn)換數(shù)據(jù)輸出周期就越長同時(shí)數(shù)據(jù)精度越高。PC3對(duì)應(yīng)ADC通道ADC_Channel_13,這里我們選擇ADC_SampleTime_56Cycles即56周期的采樣時(shí)間。
利用ADC轉(zhuǎn)換完成中斷可以非常方便的保證我們讀取到的數(shù)據(jù)是轉(zhuǎn)換完成后的數(shù)據(jù)而不用擔(dān)心該數(shù)據(jù)可能是ADC正在轉(zhuǎn)換時(shí)“不穩(wěn)定”數(shù)據(jù)。我們使用ADC_ITConfifig函數(shù)使能ADC轉(zhuǎn)換完成中斷,并在中斷服務(wù)函數(shù)中讀取轉(zhuǎn)換結(jié)果數(shù)據(jù)。ADC_Cmd函數(shù)控制ADC轉(zhuǎn)換啟動(dòng)和停止。
最后使用軟件觸發(fā)調(diào)用ADC_SoftwareStartConvCmd函數(shù)進(jìn)行使能配置。
(4)在Temp_ADC_NVIC_Config函數(shù)中配置ADC轉(zhuǎn)換完成中斷的優(yōu)先級(jí)分組和優(yōu)先級(jí)。
static void Temp_ADC_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 配置優(yōu)先級(jí)分組 NVIC_InitStructure.NVIC_IRQChannel = Temp_ADC_IRQ; // 配置中斷優(yōu)先級(jí) NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
(5)ADC中斷服務(wù)程序
void ADC_IRQHandler(void) { if(ADC_GetITStatus(TEMP_ADC,ADC_IT_EOC)==SET) { ADC_ConvertedValue = ADC_GetConversionValue(TEMP_ADC); // 讀取ADC的轉(zhuǎn)換值 } ADC_ClearITPendingBit(TEMP_ADC,ADC_IT_EOC); }
中斷服務(wù)函數(shù)一般定義在cks32f4xx_it.c文件內(nèi),我們使能了ADC轉(zhuǎn)換完成中斷,因此在ADC轉(zhuǎn)換完成后就會(huì)進(jìn)入中斷服務(wù)函數(shù),在中斷服務(wù)函數(shù)內(nèi)直接讀取ADC轉(zhuǎn)換結(jié)果保存在變量ADC_ConvertedValue(在main.c中定義)中。ADC_GetConversionValue函數(shù)是獲取ADC轉(zhuǎn)換結(jié)果值的庫函數(shù),只有一個(gè)形參為ADC外設(shè),可選為ADC1、ADC2或ADC3,該函數(shù)返回一個(gè)16位的ADC轉(zhuǎn)換結(jié)果值。
(6)Main程序
int main(void) { Debug_USART_Config(); //初始化USART1 Temp_Init(); while(1) { ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 讀取轉(zhuǎn)換的AD值 printf(" The current AD value = %f V ",ADC_Vol); Delay(0xffffee); } }
主函數(shù)先配置調(diào)試串口相關(guān)參數(shù),接下來調(diào)用Temp_Init函數(shù)進(jìn)行ADC初始化配置并啟動(dòng)ADC。在ADC中斷服務(wù)函數(shù)中把AD轉(zhuǎn)換結(jié)果保存在變量ADC_ConvertedValue中,可以計(jì)算出對(duì)應(yīng)的IO口電壓值,最后把相關(guān)數(shù)據(jù)打印至串口調(diào)試助手。
審核編輯:湯梓紅
-
轉(zhuǎn)換器
+關(guān)注
關(guān)注
27文章
8602瀏覽量
146723 -
寄存器
+關(guān)注
關(guān)注
31文章
5295瀏覽量
119838 -
adc
+關(guān)注
關(guān)注
98文章
6396瀏覽量
543814 -
比較器
+關(guān)注
關(guān)注
14文章
1630瀏覽量
107046 -
電壓采集
+關(guān)注
關(guān)注
2文章
21瀏覽量
14152
原文標(biāo)題:MCU微課堂|CKS32F4xx系列ADC單通道電壓采集
文章出處:【微信號(hào):中科芯MCU,微信公眾號(hào):中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論