柚子快報激活碼778899分享:單片機 嵌入式硬件 Stm32
柚子快報激活碼778899分享:單片機 嵌入式硬件 Stm32
ADC簡介
測量方式
采用二分法比較數(shù)據(jù)
IO通道
ADC基本結(jié)構(gòu)及配置路線
獲取數(shù)字變量需要用到用到光敏電阻的AO口,AO端口接在PA0引腳即可 測得的模擬數(shù)據(jù)與實際光照強度之間的關(guān)系為
光照強度 = 100 - 模擬量 / 40;
代碼:
完整樸素代碼:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
void AD_Init(void){//初始化AD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//開啟ADC1的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開啟GPIOA的時鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時鐘 72 / 6 = 12MHZ
/*配置GPIO口*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/*在規(guī)則組列表第一個位置,寫入通道0這個通道*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
/*結(jié)構(gòu)體初始化ADC*/
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//單次轉(zhuǎn)換
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//數(shù)據(jù)右對齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開啟ADC電源
ADC_Cmd(ADC1, ENABLE);
/*給ADC校準(zhǔn)*/
ADC_ResetCalibration(ADC1);//復(fù)位校準(zhǔn)
while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1復(fù)位校準(zhǔn)狀態(tài)
ADC_StartCalibration(ADC1);//開始校準(zhǔn)
while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校準(zhǔn)完成
}
uint16_t AD_Getvailue(void){//獲取信息
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟件觸發(fā)轉(zhuǎn)換
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待轉(zhuǎn)換完成
return ADC_GetConversionValue(ADC1);//讀取數(shù)據(jù)
}
uint16_t Reality_ADLight(uint16_t ADCnum){//獲取光照強度
return 100 - ADCnum / 40;
}
int main(void){
OLED_Init();//初始化OLED
AD_Init();
while(1){
uint16_t num = AD_Getvailue();
uint16_t num1 = Reality_ADLight(num);
OLED_ShowString(1, 1, "ADO:");
OLED_ShowNum(1, 5, num, 5);
OLED_ShowString(2, 1, "LUX:");
OLED_ShowNum(2, 5, num1, 3);
Delay_ms(300);
}
}
效果:
此代碼的不足之處在于每次寫入數(shù)字都會提前占據(jù)固定位置,這個固定位置在整個過程是不能更改的,十分影響觀感
所以添加求數(shù)字長度的函數(shù),方便隨時捕捉并調(diào)正所占空間 添加代碼:
uint8_t length(uint16_t num){
uint8_t length = 0;
while(num > 0){
num = num / 10;
length = length + 1;
}
return length;
}
完整優(yōu)化代碼1:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
void AD_Init(void){//初始化AD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//開啟ADC1的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開啟GPIOA的時鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時鐘 72 / 6 = 12MHZ
/*配置GPIO口*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/*在規(guī)則組列表第一個位置,寫入通道0這個通道*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
/*結(jié)構(gòu)體初始化ADC*/
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//單次轉(zhuǎn)換
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//數(shù)據(jù)右對齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開啟ADC電源
ADC_Cmd(ADC1, ENABLE);
/*給ADC校準(zhǔn)*/
ADC_ResetCalibration(ADC1);//復(fù)位校準(zhǔn)
while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1復(fù)位校準(zhǔn)狀態(tài)
ADC_StartCalibration(ADC1);//開始校準(zhǔn)
while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校準(zhǔn)完成
}
uint16_t AD_Getvailue(void){//獲取信息
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟件觸發(fā)轉(zhuǎn)換
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待轉(zhuǎn)換完成
return ADC_GetConversionValue(ADC1);//讀取數(shù)據(jù)
}
uint8_t length(uint16_t num){
uint8_t length = 0;
while(num > 0){
num = num / 10;
length = length + 1;
}
return length;
}
uint16_t Reality_ADLight(uint16_t ADCnum){//獲取光照強度
return 100 - ADCnum / 40;
}
int main(void){
OLED_Init();//初始化OLED
AD_Init();
while(1){
uint16_t num = AD_Getvailue();
uint16_t num1 = Reality_ADLight(num);
OLED_ShowString(1, 1, "ADO:");
OLED_ShowNum(1, 5, num, length(num));
OLED_ShowString(2, 1, "LUX:");
OLED_ShowNum(2, 5, num1, length(num1));
Delay_ms(300);
OLED_Clear();
}
}
效果:
寫入數(shù)據(jù)是采用覆蓋制,例如上次寫入的數(shù)據(jù)是1234,本次寫入的數(shù)據(jù)是999,那么此時展現(xiàn)的效果為9994,由于ADO取值范圍為[0 ~4095],LUX(光照強度)取值范圍為[1, 100],所以為了不影響數(shù)據(jù)的合理性,所以必須要在每次寫入新數(shù)據(jù)時必須要清理一下OLED
但是由于提供的清屏函數(shù)每次都是將全部數(shù)據(jù)清理掉,所以畫面刷新也要從新再全部刷新一次所以整體畫面會不連貫
所以我寫入了一個只清屏某個部分的函數(shù) 添加代碼:
/*
直接用清屏函數(shù)整體刷新會導(dǎo)致OLED畫面不連貫
清除行函數(shù):保留本行字符串,清除本行剩余部分
row:清除的具體行
len:不希望被清除的字符串長度
*/
void OLED_LoactionClear(uint8_t row, uint8_t len)
{
uint8_t i, j;
for (j = row * 2 - 2; j < row * 2; j++)
{
OLED_SetCursor(j, len * 8);
for(i = len * 8; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
放入位置
需要將其copy到OLED.c文件下,并在OLED.h文件內(nèi)聲明一下 具體函數(shù)使用方法:
OLED_LoactionClear(uint8_t row, uint8_t len); 此函數(shù)有兩個參數(shù):
其中row指你想要進(jìn)行清屏操作的具體行,OLED上一共能顯示4行 其中l(wèi)en代表row行從左到右len長度區(qū)間的字符串將會被保留,row行剩余其他數(shù)據(jù)將全被清除
完整優(yōu)化代碼2:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
void AD_Init(void){//初始化AD
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//開啟ADC1的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開啟GPIOA的時鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時鐘 72 / 6 = 12MHZ
/*配置GPIO口*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/*在規(guī)則組列表第一個位置,寫入通道0這個通道*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
/*結(jié)構(gòu)體初始化ADC*/
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//單次轉(zhuǎn)換
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//數(shù)據(jù)右對齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開啟ADC電源
ADC_Cmd(ADC1, ENABLE);
/*給ADC校準(zhǔn)*/
ADC_ResetCalibration(ADC1);//復(fù)位校準(zhǔn)
while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回ADC1復(fù)位校準(zhǔn)狀態(tài)
ADC_StartCalibration(ADC1);//開始校準(zhǔn)
while(ADC_GetCalibrationStatus(ADC1) == SET);//等待校準(zhǔn)完成
}
uint16_t AD_Getvailue(void){//獲取信息
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟件觸發(fā)轉(zhuǎn)換
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//等待轉(zhuǎn)換完成
return ADC_GetConversionValue(ADC1);//讀取數(shù)據(jù)
}
uint8_t length(uint16_t num){
uint8_t length = 0;
while(num > 0){
num = num / 10;
length = length + 1;
}
return length;
}
uint16_t Reality_ADLight(uint16_t ADCnum){//獲取光照強度
return 100 - ADCnum / 40;
}
int main(void){
OLED_Init();//初始化OLED
AD_Init();
while(1){
uint16_t num = AD_Getvailue();
uint16_t num1 = Reality_ADLight(num);
OLED_ShowString(1, 1, "ADO:");
OLED_LoactionClear(1, length(num) + 3);//"ADO:"長度為3所以要加3
OLED_ShowNum(1, 5, num, length(num));
OLED_ShowString(2, 1, "LUX:");
OLED_LoactionClear(2, length(num1) + 3);
OLED_ShowNum(2, 5, num1, length(num1));
Delay_ms(300);
}
}
效果:
柚子快報激活碼778899分享:單片機 嵌入式硬件 Stm32
精彩鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。