01、ADC簡介
ADC是Analog-to-DigitalConverter的縮寫,指模/數轉換器或者模擬/數字轉換器,是指將連續變數的模擬信號轉換為離散的數字信號的器件,典型的模擬數字轉換器將模擬信號轉換為表示一定比例電壓值的數字信號,
從STM32F207的資料手冊中下圖看到,STM32F207VC有3個精度為12bit的ADC控制器,有16個外部通道,而144腳的STM32F207Zx和176腳的STM32F207Ix因為帶PF腳,所以多8個通道,為24個外部通道,各通道的A/D轉換可以單次、連續、掃描或間斷執行,ADC轉換的結果可以左對齊或右對齊儲存在16位資料暫存器中,

02、STM32的ADC外設
上面說到,STM32F207有3個12bit的ADC控制器,下文將以ADC3的通道10講解,
首先我們確認下ADC外設所在的地址總線,從STM32F207資料手冊中下圖看到,ADC屬于APB2總線下,APB2時鐘頻率是60MHz,具體STM32如果通過外部25M晶振得到的60MHz的APB2,請看《STM32F207時鐘系統決議》,

對應GPIO,我們從STM32F207資料手冊中看到,我們可以使用PC0作為ADC3的通道10,

這里需要說明的是,之前的文章使用其他外設時,比如《STM32PWM輸出》中,尋找對應的管腳時,我們都是從STM32F207資料手冊的Alternatefunctionmapping表中尋找,這是因為ADC對應的管腳使用的是Additionalfunctions,PWM對應的管腳使用的是Alternatefunctions,
區別是:
Additionalfunctions:附加,輔助功能,引腳被連接到其他模塊使用,使用時直接普通配置即可,例如ADC的采用輸入通道,配置為模擬輸入,
Alternate functions:復用功能,即將IO口用作普通輸入輸出以外的功能,例如串口輸入輸出,使用時需要配置復用模式,
在之前的文章《STM32GPIO詳解》中有如下介紹,

STM32標準外設庫中有如下代碼
typedef enum { GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */ GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */ GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */ }GPIOMode_TypeDef;
其中GPIO_Mode_AF對應的就是Alternate functions:復用功能,GPIO_Mode_AN對應的就是Additional functions:附加,輔助功能,
03、STM32ADC框圖講解
下圖是STM32ADC的結構框圖,我們將其劃分為7個部分進行講解,

1、輸入電壓范圍
ADC所能測量的電壓范圍就是VREF-≤ VIN ≤ VREF+,把VSSA 和VREF-接地,把VREF+和VDDA 接3V3,得到ADC的輸入電壓范圍為:0~3.3V,

2、輸入通道
ADC的信號時通過輸入通道進入單片機內部的,單片機通過ADC模塊將模擬信號轉換為數字信號,上圖示記②的部分顯示了外部的16個通道,連接的GPIO,對應的關系如上面講解的,需要在STM32F207資料手冊的STM32F20xpin and ball definitions表格中尋找,實際上STM32還有內部通道,ADC1的通道 16連接到了芯片內部的溫度傳感器,Vrefint 連接到了通道17,ADC2的模擬通道 16和 17連接到了內部的VSS,
3、轉換通道
外部的16個通道在轉換時又分為規則通道和注入通道,其中規則通道最多有16路,注入通道最多有4路(注入通道貌似使用不多),下面簡單介紹一下倆種通道:
規則通道
規則通道顧名思義就是,最平常的通道、也是最常用的通道,平時的ADC轉換都是用規則通道實的,規則通道和它的轉換順序在ADC_SQRx暫存器中選擇,規則組轉換的總數應寫入ADC_SQR1暫存器的L[3:0]中,
注入通道
注入通道是相對于規則通道的,注入通道可以在規則通道轉換時,強行插入轉換,相當于一個“中斷通道”吧,當有注入通道需要轉換時,規則通道的轉換會停止,優先執行注入通道的轉換,當注入通道的轉換執行完畢后,再回到之前規則通道進行轉換,最多4個通道,注入組和它的轉換順序在ADC_JSQR暫存器中選擇,注入組里轉化的總數應寫入ADC_JSQR暫存器的L[1:0]中,
一個ADC控制器有多個通道,這就涉及使用多個通道進行轉換就涉及到一個先后順序的問題了,畢竟規則轉換通道只有一個資料暫存器,多個通道的使用順序分為倆種情況:規則通道的轉換順序和注入通道的轉換順序,
規則通道轉換順序
規則通道中的轉換順序由三個暫存器控制:SQR1、SQR2、SQR3,它們都是32位暫存器,SQR暫存器控制著轉換通道的數目和轉換順序,只要在對應的暫存器位SQx中寫入相應的通道,這個通道就是第x個轉換,通過SQR1暫存器就能了解其轉換順序在暫存器上的實作了,
注入通道轉換順序
和規則通道轉換順序的控制一樣,注入通道的轉換也是通過注入暫存器來控制,只不過只有一個JSQR暫存器來控制,控制關系如下:

需要注意的是,只有當JL=4的時候,注入通道的轉換順序才會按照JSQ1、JSQ2、JSQ3、JSQ4的順序執行,當JL<4時,注入通道的轉換順序恰恰相反,也就是執行順序為:JSQ4、JSQ3、JSQ2、JSQ1,
配置轉換順序的函式
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime)
04、觸發源
ADC轉換的輸入、通道、轉換順序都已經說明了,但ADC轉換是怎么觸發的呢?就像通信協議一樣,都要規定一個起始信號才能傳輸資訊,ADC也需要一個觸發信號來實行模/數轉換,
其一就是通過直接配置暫存器觸發,通過配置控制暫存器CR2的ADON位,寫1時開始轉換,寫0時停止轉換,在程式運行程序中只要呼叫庫函式,將CR2暫存器的ADON位置1就可以進行轉換,比較好理解,
另外,還可以通過內部定時器或者外部IO觸發轉換,也就是說可以利用內部時鐘讓ADC進行周期性的轉換,也可以利用外部IO使ADC在需要時轉換,具體的觸發由控制暫存器CR2決定,
05、轉換周期
可獨立設定各通道采樣時間
ADC會在數個ADCCLK周期內對輸入電壓進行采樣,可使用ADC_SMPR1和ADC_SMPR2
暫存器中的SMP[2:0]位修改周期數,每個通道均可以使用不同的采樣時間進行采樣,
總轉換時間的計算公式如下:
Tconv=采樣時間+12個周期
示例:
ADCCLK = 30 MHz且采樣時間=3個周期時:
Tconv= 3+12=15個周期=0.5us (APB2為60MHz時)
最小采樣時間0.42us(ADC時鐘=36MHz,采樣周期為3周期下得到),
06、資料暫存器
轉換完成后的資料就存放在資料暫存器中,但資料的存放也分為規則通道轉換資料和注入通道轉換資料的,
規則資料暫存器
規則資料暫存器負責存放規則通道轉換的資料,通過32位暫存器ADC_DR來存放,
注入資料暫存器
注入通道轉換的資料暫存器有4個,由于注入通道最多有4個,所以注入通道轉換的資料都有固定的存放位置,不會跟規則暫存器那樣產生資料覆寫的問題, ADC_JDRx是 32位的,低 16位有效,高 16位保留,資料同樣分為左對齊和右對齊,具體是以哪一種方式存放,由ADC_CR2的 11 位ALIGN 設定,
07、中斷
可以產生4種中斷

①DMA溢位中斷
當配置了DMA,且DMA溢位時產生中斷
②規則通道轉換完成中斷
規則通道資料轉換完成之后,可以產生一個中斷,可以在中斷函式中讀取規則資料暫存器的值,這也是單通道時讀取資料的一種方法,
③注入通道轉換完成中斷
注入通道資料轉換完成之后,可以產生一個中斷,并且也可以在中斷中讀取注入資料暫存器的值,達到讀取資料的作用,
④模擬看門狗事件
當輸入的模擬量(電壓)不再閾值范圍內就會產生看門狗事件,就是用來監視輸入的模擬量是否常,
08、電壓轉換
轉換后的資料是一個12位的二進制數,我們需要把這個二進制數代表的模擬量(電壓)用數字表示出來,比如測量的電壓范圍是0~3.3V,轉換后的二進制數是x,因為12位ADC在轉換時將電壓的范圍大小(也就是3.3)分為4096(2^12)份,所以轉換后的二進制數x代表的真實電壓的計算方法就是:
y=3.3* x / 4096
09、電路圖設計
電路圖很簡單,可以在ADC引腳上輸入不同的電壓,也可以直接方便的使用滑動變阻器實作不同的電壓變化,

10、代碼設計
ADC外設配置的結構體
typedef struct { uint32_t ADC_Resolution; /*!< Configures the ADC resolution dual mode. This parameter can be a value of @ref ADC_resolution */ FunctionalState ADC_ScanConvMode; /*!< Specifies whether the conversion is performed in Scan (multichannels) or Single (one channel) mode. This parameter can be set to ENABLE or DISABLE */ FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion is performed in Continuous or Single mode. This parameter can be set to ENABLE or DISABLE. */ uint32_t ADC_ExternalTrigConvEdge; /*!< Select the external trigger edge and enable the trigger of a regular group. This parameter can be a value of @ref ADC_external_trigger_edge_for_regular_channels_conversion */ uint32_t ADC_ExternalTrigConv; /*!< Select the external event used to trigger the start of conversion of a regular group. This parameter can be a value of @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */ uint32_t ADC_DataAlign; /*!< Specifies whether the ADC data alignment is left or right. This parameter can be a value of @ref ADC_data_align */ uint8_t ADC_NbrOfConversion; /*!< Specifies the number of ADC conversions that will be done using the sequencer for regular channel group. This parameter must range from 1 to 16. */ }ADC_InitTypeDef;
ADC_Resolution:ADC 作業模式選擇,ADC解析度
ADC_ScanConvMode:ADC 掃描(多通道)或者單次(單通道)模式選擇
ADC_ContinuousConvMode:ADC 單次轉換或者連續轉換選擇
ADC_ExternalTrigConvEdge:ADC 外部觸發極性配置
ADC_ExternalTrigConv:ADC 轉換觸發信號選擇
ADC_DataAlign:ADC 資料暫存器對齊格式
ADC_NbrOfConversion:ADC轉換通道數目
typedef struct { uint32_t ADC_Mode;//多重ADC模式選擇 uint32_t ADC_Prescaler; //ADC預分頻 uint32_t ADC_DMAAccessMode; //DMA訪問模式 uint32_t ADC_TwoSamplingDelay; //2個采樣階段之間的延遲 }ADC_CommonInitTypeDef;
ADC_CommonInitTypeDef用來配置ADC_CCR暫存器的相關引數
ADC外設和DMA配置代碼
/** * @brief ADC3 channel10 with DMA configuration * @param None * @retval None */ void ADC3_CH10_DMA_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); /* DMA2 Stream0 channel2 configuration **************************************/ DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); /* Configure ADC3 Channel10 pin as analog input ******************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); /* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC3 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; 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; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC3, &ADC_InitStructure); /* ADC3 regular channel7 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles); /* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); /* Enable ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE); /* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE); }
代碼下載驗證測驗

硬體和軟體開源地址:
https://github.com/strongercjd/STM32F207VCT6
點擊查看本文所在的專輯,STM32F207教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/262756.html
標籤:嵌入式
上一篇:電腦提示GfileGuard
