基於STM8的ADC讀取
想學會如何在STM8上使用ADC這個功能,我們先得了解單片機中ADC究竟是什麽。
ADC是模擬信號轉成數值信號,單片機只能識別TTL電平,其實就是 1 或者 0 ,但是如果我們給它一個3.3V電壓,單片機就無法識別,,若想使用單片機讀取出來得時候,它必須將模擬量變成數字量。
了解完後,我們就開始講解了。
編譯環境:
我的編譯環境是IAR,這款軟件是現在STM8的主流平臺,比較推薦。不過我打算等到STCubeMX更新出比較方便的版本後再去使用Keil5,因為我在用STM32的時候就是利用Keil5,的確很方便,你們也可以學著用一下。
主芯片:
我的主芯片是STM8S系列中的003,其中STM8S的003、005、和103、105,配置一樣(外設和CPU頻率,FLASH),在代碼相同的情況下均可進行燒寫。
庫文件的添加:
我們的工程可以在IAR的例程中復制,操作過程:打開STM8S_StdPeriph_Lib(這是一個官方的庫文件,下載IAR STM8包的時候就攜帶,裏面有庫文件和相對應的例程),將Libraries文件復制到你工程所在的文件下,並將裏面的庫函數添加到你的IAR工程列表當中,如圖。
添加完成後,有可能你會看到一些C文件會有紅色的小點報錯,這是因為你選的芯片上沒有該功能,你需要將其刪掉才能不報錯。
添加成功後,我們需要將頭文件添加進來,如圖。
你們也可以跟我一樣,將不同功能的函數分開寫成C文件和H文件,如圖。
代碼編寫:
首先,我們需要配置一下內部晶振,並且初始化你所要使用的GPIO、串口。其次,配置ADC,最後對ADC讀取函數的進行一個調用,獲取ADC值,再用Uart輸出。
晶振配置:
將所有的晶振幅值都寫成枚舉,這樣的話可以直接通過在主函數調用再傳參改變它的晶振大小。
1 void Clk_Config(uint8_t SYS_CLOCK) 2 { 3 switch(SYS_CLOCK) 4 { 5 case SYS_CLOCK_2MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8); break; 6 case SYS_CLOCK_4MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV4); break; 7 case SYS_CLOCK_8MHZ : CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2); break; 8 case SYS_CLOCK_16MHZ: CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); break; 9 default: break; 10 } 11 }
GPIO配置:
這裏將一些所要用到基礎的的引角初始化,特殊的GPIO口我們就另外再說。
1 void MX_GPIO_Init(void) 2 { 3 //LED 4 GPIO_Init(Led_Opt_GPIO_Port,Led_Opt_Pin, GPIO_MODE_OUT_PP_HIGH_FAST); 5 6 }
Uart配置:
在STM8S003中,Uart只有 Uart1 可用,所以在這裏就只使用這個。將Uart的發送、接收引角在Uart初始化函數裏面初始,主要的配置參數為:115200波特率、1個停止位、無奇偶校驗位、同步模式禁用、SLK PIN禁用、發送和接收都開啟。
調用UART1_ITConfig( )函數令Uart開啟中斷。
1 void MX_UART1_Init(void) 2 { 3 UART1_DeInit(); 4 GPIO_Init(Uart_TX_GPIO_Port, Uart_TX,GPIO_MODE_OUT_PP_HIGH_FAST); 5 GPIO_Init(Uart_RX_GPIO_Port, Uart_RX,GPIO_MODE_IN_PU_IT); 6 UART1_Init(115200,UART1_WORDLENGTH_8D,UART1_STOPBITS_1,UART1_PARITY_NO,UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENABLE); 7 UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE); 8 UART1_Cmd(ENABLE);//啟用串口 9 10 enableInterrupts(); 11 }
ADC:
STM8SF003這款芯片能用的是5個AD采樣通道,分別為為AIN2~AIN6。其一個通道AIN7,但在官方手冊中我沒找到有對其描述的,感興趣的朋友可以去察看芯片的英文手冊進行研究,也許會找到和我不一樣的結果。
在ADC頭文件中,將ADC1所有的ADC1_CHANNEL(ADC通道)都進行枚舉,以方便調用。
1 /* Enum ----------------------------------------------------------------------*/ 2 3 enum ADC1_CHANNEL 4 { //bit 8 7 6 5 4 3 2 1 5 6 ADC1_CHANNEL2 = 0x01, // 0 0 0 0 0 0 0 1 7 ADC1_CHANNEL3 = 0x02, // 0 0 0 0 0 0 1 0 8 ADC1_CHANNEL4 = 0x04, // 0 0 0 0 0 1 0 0 9 ADC1_CHANNEL5 = 0x08, // 0 0 0 0 1 0 0 0 10 ADC1_CHANNEL6 = 0x10 // 0 0 0 1 0 0 0 0 11 12 };
在ADC.C文件中,分為了多個函數,降低他們的耦合性,也方便理解。
首先是ADC中引角的初始化,將你所選通道的引角進行初始化,沒有選到的就不進行初始化。
1 /******************************************************************************* 2 * Function Name : MX_ADC_GPIO_Init 3 * Description : ADC GPIO Init 4 * Input : ADC1_CHANNEL
5 * Output : None 6 * Return : None 7 ********************************************************************************/ 8 9 void MX_ADC_GPIO_Init(uint8_t ADC1_CHANNEL) 10 { 11 switch(ADC1_CHANNEL) 12 { 13 case ADC1_CHANNEL2: GPIO_Init(ADC_Opt_GPIOC_Port,ADC_channe2_Pin,GPIO_MODE_IN_PU_NO_IT);break; 14 case ADC1_CHANNEL3: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe3_Pin,GPIO_MODE_IN_PU_NO_IT);break; 15 case ADC1_CHANNEL4: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe4_Pin,GPIO_MODE_IN_PU_NO_IT);break; 16 case ADC1_CHANNEL5: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe5_Pin,GPIO_MODE_IN_PU_NO_IT);break; 17 case ADC1_CHANNEL6: GPIO_Init(ADC_Opt_GPIOD_Port,ADC_channe6_Pin,GPIO_MODE_IN_PU_NO_IT);break; 18 } 19 20 }
然後是ADC1的選擇通道初始化:ADC連續讀取,所選的通道,二分頻,外部轉換觸發,外部觸發器不開啟,數據右對齊,施密特觸發,不開啟。(註意:STMS8003中的串口使用了PD5和PD6,與ADC1中通道5、通道6發生沖突,故不可使用。如需使用,請將串口的TX\RX引角更改換為其它的引角。)
1 /******************************************************************************* 2 * Function Name : MX_ADC1_CHANNEL_Init 3 * Description : ADC CHANNEL Init 4 * Input : ADC1_CHANNEL 5 * Output : None 6 * Return : None 7 ********************************************************************************/ 8 9 void MX_ADC1_CHANNEL_Init(uint8_t ADC1_CHANNEL) 10 { 11 switch(ADC1_CHANNEL) 12 { 13 case ADC1_CHANNEL2: 14 { 15 ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_2, 16 ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 17 ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL2, DISABLE);break; 18 } 19 case ADC1_CHANNEL3: 20 { 21 ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_3, 22 ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 23 ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL3, DISABLE);break; 24 } 25 case ADC1_CHANNEL4: 26 { 27 ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_4, 28 ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 29 ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL4, DISABLE);break; 30 } 31 case ADC1_CHANNEL5: 32 { 33 ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_5, 34 ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 35 ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL5, DISABLE);break; 36 } 37 case ADC1_CHANNEL6: 38 { 39 ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6, 40 ADC1_PRESSEL_FCPU_D2, ADC1_EXTTRIG_TIM, DISABLE, 41 ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL6, DISABLE);break; 42 } 43 } 44 }
這裏就是將所有的ADC初始化進行一個統一的一個歸類。
1 /******************************************************************************* 2 * Function Name : MX_ADC1_Init 3 * Description : ADC Init 4 * Input : ADC1_CHANNEL 5 * Output : None 6 * Return : None 7 ********************************************************************************/ 8 void MX_ADC1_Init(uint8_t ADC1_CHANNEL) 9 { 10 //初始化GPIO 11 MX_ADC_GPIO_Init(ADC1_CHANNEL); 12 13 //初始化ADC1所有寄存器 14 ADC1_DeInit(); 15 16 //配置ADC1寄存器中的參數 17 MX_ADC1_CHANNEL_Init(ADC1_CHANNEL); 18 19 //使能ADC1 20 ADC1_Cmd(ENABLE); 21 22 //ADC1轉換開始 23 ADC1_StartConversion(); 24 }
最後就是數據獲取,可以選擇直接獲取數據,也可以獲取十次數據後取平均數。
註意:
ADC獲取的值是AD值,需要將其進行代入公式中才能得到電壓值。
Vin = (ADC * Vref) / 1024
VCC很明顯可以使用萬用表先測出來,1024是因為STM8S這款的AD是10位精度。
這裏測試的VCC是3.35V,VCC另外一個意思就是單片機的供給電源。
1 /******************************************************************************* 2 * Function Name : MX_ADC1_Get_Data 3 * Description : get VCC data 4 * Input : None 5 * Output : None 6 * Return : fVCC 7 ********************************************************************************/ 8 float MX_ADC1_Get_Data(void) 9 { 10 int iADC1_Value; 11 float fVCC; 12 13 //讀取轉換結果 14 iADC1_Value = ADC1_GetConversionValue(); 15 fVCC = (iADC1_Value * 3.350)/1024; 16 return fVCC; 17 18 } 19 20 21 /******************************************************************************* 22 * Function Name : MX_ADC1_Get_Average_Data 23 * Description : Get VCC ten times average data. 24 * Input : None 25 * Output : None 26 * Return : fAverage_VCC 27 ********************************************************************************/ 28 float MX_ADC1_Get_Average_Data(void) 29 { 30 int i; 31 float fAverage_VCC = 0.0; 32 33 for(i=0;i<10;i++) 34 { 35 fAverage_VCC += MX_ADC1_Get_Data(); 36 } 37 fAverage_VCC /= 10; 38 39 return fAverage_VCC; 40 41 }
將上面需要用到的函數在主函數中調用打印即可。
測試結果:
我用的調試儀器是可調式電源,可通過旋鈕控制電壓的輸出大小。
當沒有輸出電壓時,打印的值為0V.
當可調式電源輸出的電壓值為3.3V,串口助手上打印的也是3.3V。
當可調式電源輸出的電壓值為24V,串口助手上打印的也是24V。
註意:請不要將24V電源直接通入單片機中,我是自己設置了一條電路進行測試的。ADC的最大輸入電壓是3.3V,為了安全起見,請不要超過該值。
註意:請不要將24V電源直接通入單片機中,我是自己設置了一條電路進行測試的。ADC的最大輸入電壓是3.3V,為了安全起見,請不要超過該值。
註意:請不要將24V電源直接通入單片機中,我是自己設置了一條電路進行測試的。ADC的最大輸入電壓是3.3V,為了安全起見,請不要超過該值。
基於STM8的ADC讀取說明到此結束,感謝大家觀看。
作 者:浩宇99?
出 處: https://www.cnblogs.com/zhenghaoyu/p/10672864.html
版權聲明:本文原創發表於 博客園,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。
基於STM8的ADC讀取