本帖最后由 51hei小林 于 2016-10-9 23:59 編輯
之前介紹ADC時,是用ADC測量內部1.225V的參考電壓,通過這個參考電壓的轉化值反推參考電壓的實際值.這里要注意,我說的內部參考電壓和參考電壓是兩個不同的概念,內部參考電壓就是內部的一個1.225V基準電壓,這個電壓比較準確,不會受外接干擾,其值也不會改變,一直是1.225V.在STM8L里,這個電壓作為一個獨立的通道,可以連接到ADC中,供ADC采樣,校準自己的參考電壓,也可以連接到STM8L的內部比較器的輸入端作為一個基準電壓,還可以通過引腳輸出這個電壓. 參考電壓,是Vref+和Vref-引腳之間的電壓,這個電壓是外部的,會隨著外部電壓的變化而變化,在ADC采樣時,這個電壓是采樣時的參考電壓. 上次的例程根據比例關系:
(參考電壓/4096)=(內部參考電壓/內部參考電壓轉換值)
已經求出了參考電壓的值為2.99V,好吧上次測的其實是2.98V,今天用萬用表量了下,是2.99V.為了這次程序的采集數據的準確,還是用2.99V.
本例程和上次的ADC測量內部參考電壓例程,并沒有太大卻別,只是增加了DMA部分.原以為,采樣內部通道和外部通道會有很大區別,實際上,只要選擇一下采樣的外部通道,同時關閉對應的施密特觸發器,其余程序和上次一樣就可以了.也不需要去設置引腳的輸入輸出狀態,保持默認就行.
使用DMA將ADC轉換后的數據傳輸到一個數組中,本例程采樣9次數據,傳輸完9次數據后會產生一個傳輸完成中斷,在中斷中求9次的和,計算平均值,同時計算采樣的電壓.
DMA的四個通道都可以作為ADC傳輸數據通道,我們需要使用SYSCFG_RMPCR1這個寄存器來設置具體使用的通道.本例程使用DMA的通道一來傳輸數據.

在本例程中,仍然使用IAR強大的查看變量功能,進行數據的顯示,沒有使用板子上的LCD液晶屏,主要原因是為了程序簡單,其實是因為我比較懶.本來對數據的處理應該進行濾波處理的,我也僅僅簡單的算了下9次采樣的平均值,起不到平滑數據的作用,ADC采樣的數據確實每次都不一樣,軟件濾波很重要.
在IAR查看變量,如果變量不是全局變量,在Live Watch窗口或Watch窗口中是看不到數據的,所以只好把這個變量聲明為局部靜態變量,同樣可以顯示出數值.
下圖是實際的硬件連接圖,用來一個電位器,三個腳分別連接到板子的VDD,GND,PD5腳,具體連接是:電位器兩邊的腳接VDD,GND,中間接PD5.

- /*硬件連接*/
- // PD5(ADC1_IN9) <----
- /****************************************************************************************
- *開發環境:IAR for stm8 v1.40.1
- *硬件平臺:STM8L-DISCOVERY
- *功能說明:測量ADC通道9的外部電壓,通道9對應的引腳為PD5,在此引腳接了一個電位器,用于輸出一個
- * 可變的電壓,提供給ADC測量
- *作 者:茗風
- ****************************************************************************************/
- #include"iostm8l152c6.h"
- #include"stdbool.h"
- #include"stdint.h"
- #define ADC_DRH_ADRESS 0x5344
- uint16_t ui16RX_buffer[9]={0};
- /******************************************************************************************************
- * 名 稱:void delay_10ms(uint8_t x_ms)
- * 功 能:延時10ms
- * 入口參數:無
- * 出口參數:無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- void delay_100ms(void)
- {
- uint8_t i,j;
- for(i=0;i<255;i++)//2*255個指令周期
- for(j=0;j<255;j++);//2*255個指令周期
- //delay_10ms共消耗 x_ms*2*255+2*x_ms個指令周期
- //255*2*255+2*255=130610us=130ms
- //此延時函數,延時時間為130ms
- //16M/8/2=1M 一個指令周期為1us
- }
- /******************************************************************************************************
- * 名 稱:void GPIO_Init(void)
- * 功 能:初始化PC7為高速推挽輸出
- * 入口參數:無
- * 出口參數:無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- void GPIO_Config(void)
- {
- PC_CR1_C17 =1;//推挽輸出
- PC_CR2_C27 =1;//高速輸出
- PC_DDR_DDR7 =1;//PC7輸出
- PC_ODR_ODR7 =0;//輸出低電平
- }
- /******************************************************************************************************
- * 名 稱:void ADC_Init(void)
- * 功 能:初始化ADC
- * 入口參數:無
- * 出口參數:無
- * 說 明:ADC1的測量通道為ADC1_IN9,單次轉換模式
- * 范 例:無
- ******************************************************************************************************/
- void ADC_Init(void)
- {
- CLK_PCKENR2_PCKEN20=1; //國際慣例,開啟ADC1外設時鐘
- ADC1_CR1_ADON=1; //wakes up the ADC from Power down mode.
- ADC1_CR2_PRESC=1;//Select a sample time of 10 μs
- // 0: f(ADC_CLK) = CK
- // 1: f(ADC_CLK) = CK/2 //系統時鐘此時為默認的16M/8=2M,這里分頻后,fadc=2M/2=1M
-
- ADC1_SQR1_DMAOFF=0; //使能DMA
-
- ADC1_CR3_SMTP2=0x06;//采樣時間為24 ADC clock cycles,也就是24*1us=24us
- //000: 4 ADC clock cycles
- //001: 9 ADC clock cycles
- //010: 16 ADC clock cycles
- //011: 24 ADC clock cycles
- //100: 48 ADC clock cycles
- //101: 96 ADC clock cycles
- //110: 192 ADC clock cycles
- //111: 384 ADC clock cycles
- ADC1_SQR3_CHSEL_S9=1; //選擇通道9
- ADC1_TRIGR3_TRIG9=1; //關閉通道9的施密特觸發器
- // ADC1_CR1_EOCIE=1;
- }
- /******************************************************************************************************
- * 名 稱:void DMA_Config(void)
- * 功 能:啟用DMA
- * 入口參數:無
- * 出口參數:無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- void DMA_Config(void)
- {
- //------打開DAM時鐘------
- CLK_PCKENR2_PCKEN24=1;
-
- //----設置ADC的DMA通道----
- SYSCFG_RMPCR1_ADC1DMA_REMAP=1;
- /* 00: ADC1 DMA request/acknowledge mapped on DMA1 channel 0
- 01: ADC1 DMA request/acknowledge mapped on DMA1 channel 1
- 10: ADC1 DMA request/acknowledge mapped on DMA1 channel 2
- 11: ADC1 DMA request/acknowledge mapped on DMA1 channel 3 */
-
- //------設置傳送的字節數,------
- DMA1_C1NDTR=9;
-
- //------設置通道優先級------
- DMA1_C1SPR_PL0=0;DMA1_C1SPR_PL1=1;
- //------設置傳送方向------
- DMA1_C1CR_DIR=0;
- /* 0: Transfer from the peripheral to the memory.
- 1: Transfer from the memory to the peripheral.*/
- //------設置模式------
- DMA1_C1CR_CIRC=1;
- /* Auto-reload mode
- 0: Circular mode disabled.
- 1: Circular mode enabled. */
- //------設置增還是減地址------
- DMA1_C1CR_MINCDEC=1;
- /* 0: Decrement mode.
- 1: Increment mode.*/
- //------設置傳送數據位數------
- DMA1_C1SPR_TSIZE=1;
- /* 0: 8-bit mode
- 1: 16-bit mode */
-
- // DMA1_C3CR_HTIE=1;
- DMA1_C1CR_TCIE=1;//使能DMA傳輸完一組數據中斷
-
- //------設置DMA通道1外設地址------
- DMA1_C1PARH=(uint8_t)((uint16_t)ADC_DRH_ADRESS >> (uint8_t)8);
- DMA1_C1PARL=(uint8_t)ADC_DRH_ADRESS;
-
- //------設置DMA通道1內存地址------
- DMA1_C1M0ARH=(uint8_t)((uint16_t)&ui16RX_buffer >> (uint8_t)8);
- DMA1_C1M0ARL=(uint8_t)&ui16RX_buffer;
-
-
- DMA1_C1CR_EN=1;
-
- DMA1_GCSR_GEN=1;
- }
- void main(void)
- {
- GPIO_Config();
- ADC_Init();
- DMA_Config();
- asm("rim"); //enable interrupts
- while(1)
- {
- delay_100ms();
- ADC1_CR1_START=1;
- }
- }
- /******************************************************************************************************
- * 名 稱: DMA中斷
- * 功 能: DMA事件處理函數
- * 入口參數:無
- * 出口參數:無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- #pragma vector=DMA1_CH1_TC_vector
- __interrupt void DMA1_CH1_TC_ISR(void)
- {
- static uint16_t tmp=0,voltage=0;//static是為了便于使用調試窗口查看變量值
- uint8_t i=0;
- tmp=0;
- voltage=0;
- if(DMA1_C1SPR_TCIF==1)
- {
- PC_ODR_ODR7 ^=0x01;//反轉藍燈電平,僅僅是為了指示ADC和DMA在工作,可去掉
- DMA1_C1SPR_TCIF=0;//不軟件清除此中斷標志位,會導致無法退出此中斷
- for(i=0;i<9;i++)tmp+=ui16RX_buffer[i];
- tmp /=9;//求九次采樣平均值
- voltage=(uint32_t)299*tmp/4096;//計算最終輸出的電壓,結果擴大了100倍
- //299是2.99V參考電壓,擴大了100倍
- asm("nop");
- }
- }
- /******************************************************************************************************
- * 名 稱: ADC中斷
- * 功 能: EOC事件處理函數
- * 入口 參數:無
- * 出口 參數:無
- * 說 明:
- * 范 例:無
- ******************************************************************************************************/
- //#pragma vector=COMP_EF2_vector
- //__interrupt void ADC1_ISR(void)
- //{
- // static uint16_t tmp=0;
- // if(ADC1_SR_EOC==1)
- // {
- // PC_ODR_ODR7 ^=0x01;
- // ADC1_SR_EOC=0;
- // tmp = ADC1_DRH;
- // tmp = (tmp<<8)+ADC1_DRL;
- // tmp=(uint32_t)299*tmp/4096;
- //// VDD_Value=(uint32_t)1225*4096/temp;//得到的數值單位為mv
- // asm("nop");
- // }
- //}
復制代碼 |