[讀取電壓值設定步驟]
(1) 開啟 ADC1 時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
(2) 設定 ADC1 分頻因子
使用 RCC_ADCCLKConfig() 設置 ADC1 的分頻因子。分頻因子要確保 ADC1 的時鐘(ADCCLK)不要超過 14 Mhz。因此設置分頻因子位為 6,時鐘為 72 / 6 = 12MHz。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
(3) 將 ADC 恢復初始值
ADC_DeInit(ADC1);
(4) 使用 GPIOA 的總線時鐘並使用 GPIO_Init()函式設定 GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模擬輸入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
(5) 設定 ADC1 的工作模式、資料對齊等,並初始化 ADC1
ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 用來設置 ADC 為獨立模式 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 設定資料靠右對齊 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 設定啟動規則轉換的外部事件為 None ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 設定停用連續轉換模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 設定停用掃描模式 ADC_InitStructure.ADC_NbrOfChannel = 1; // 設定規則序列開啟的通道:1 個 ADC_Init(ADC1, &ADC_InitStructure); // 初始化
(6) 設定其在序列器中的相應等級為 1 及其採樣時間為 55.5,並啟動 ADC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_Cmd(ADC1, ENABLE); //啟用 ADC1
(7) 執行複位校準,不準將導致結果不正確
ADC_ResetCalibration(ADC1); //重置指定的 ADC 的校準暫存器 while (ADC_GetResetCalibrationStatus(ADC1) == SET); //等待上一步操作完成 ADC_StartCalibration(ADC1); //開始指定ADC的校準狀態 while (ADC_GetCalibrationStatus(ADC1) == SET); //等待上一步操作完成
(8) 進入主程式迴圈,執行以下轉換副程式
uint16_t ADCX_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); //指定 ADC1 軟體轉換功能 while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); //回傳最新的 ADC1 轉換結果。 }
[材料]
- STM32F103C8T6 主板 x 1
- OLED SSD1306 顯示器 x 1
- 麵包板 x 1
- STLINK V2 模擬下載器 x 1
- 可變電阻 x 1
- 連接線 x n 條
[接線與電路圖]
可變電阻的左右兩個接腳接在 GND 及 3.3V,另一腳接在 STM32F103x PA0,與 SSD1306 連接的方式如下:STM32F103x | SSD1306 OLED |
---|---|
3.3v | VDD |
GND | GND |
B8 | SCK/SCL |
B9 | SDA |
[程式]
主程式一開始先對 ADC 進行初始化,進入迴圈循環後,透過 ADC 讀取數值,將 0~4096 的值轉換成 0~3.3V,主程式 main.c 如下:#include "stm32f10x.h" #include "delay.h" #include "oled.h" #include "bmp.h" #include "adcx.h" float ADValue; int main (void) { uint16_t vtg; delay_init(); //延時函數初始化 OLED_Init(); //初始化OLED ADCX_Init(); OLED_Clear(0); //清除螢幕 OLED_ShowString(1, 2, "ADValue:",16); OLED_ShowString(1, 4, "Voltage:",16); while (1) { ADValue = ADCX_GetValue(0); OLED_ShowNum(70, 2, ADValue, 4, 16); OLED_ShowNum(70, 4, ADValue / 4096 * 3.3, 1, 16); //整數位 OLED_ShowString(80, 4, ".",16); vtg = (uint16_t)(ADValue / 4096 * 3.3 * 100) % 100; //小數點後兩位 if (vtg < 10) { OLED_ShowNum(88, 4, vtg, 2, 16); OLED_ShowString(87, 4,"0",16); //個位數時前面補0 } else { OLED_ShowNum(88, 4, vtg, 2, 16); } delay_ms(500); } }adcx.c 程式如下:
#include "stm32f10x.h" void ADCX_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); //重設 ADC1 ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1) == SET); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1) == SET); } uint16_t ADCX_GetValue(u8 ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_55Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); }adcx.h 程式如下:
#ifndef __ADCX_H #define __ADCX_H void ADCX_Init(void); uint16_t ADCX_GetValue(u8 ch); #endif
完整的程式請參考 Github:7. ADC Dispaly Voltage on OLED
張貼留言