ADC簡(jiǎn)介
測(cè)量方式
采用二分法比較數(shù)據(jù)
IO通道
ADC基本結(jié)構(gòu)及配置路線
獲取數(shù)字變量需要用到用到光敏電阻的AO口,AO端口接在PA0引腳即可
測(cè)得的模擬數(shù)據(jù)與實(shí)際光照強(qiáng)度之間的關(guān)系為
光照強(qiáng)度 = 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);//開(kāi)啟ADC1的時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開(kāi)啟GPIOA的時(shí)鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時(shí)鐘 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ī)則組列表第一個(gè)位置,寫(xiě)入通道0這個(gè)通道*/
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ù)右對(duì)齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨(dú)立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開(kāi)啟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);//開(kāi)始校準(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){//獲取光照強(qiáng)度
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);
}
}
效果:
此代碼的不足之處在于每次寫(xiě)入數(shù)字都會(huì)提前占據(jù)固定位置,這個(gè)固定位置在整個(gè)過(guò)程是不能更改的,十分影響觀感
所以添加求數(shù)字長(zhǎng)度的函數(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);//開(kāi)啟ADC1的時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開(kāi)啟GPIOA的時(shí)鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時(shí)鐘 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ī)則組列表第一個(gè)位置,寫(xiě)入通道0這個(gè)通道*/
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ù)右對(duì)齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨(dú)立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開(kāi)啟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);//開(kāi)始校準(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){//獲取光照強(qiáng)度
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();
}
}
效果:
寫(xiě)入數(shù)據(jù)是采用覆蓋制,例如上次寫(xiě)入的數(shù)據(jù)是1234
,本次寫(xiě)入的數(shù)據(jù)是999
,那么此時(shí)展現(xiàn)的效果為9994
,由于ADO取值范圍為[0 ~4095],LUX(光照強(qiáng)度)取值范圍為[1, 100],所以為了不影響數(shù)據(jù)的合理性,所以必須要在每次寫(xiě)入新數(shù)據(jù)時(shí)必須要清理一下OLED
但是由于提供的清屏函數(shù)每次都是將全部數(shù)據(jù)清理掉,所以畫(huà)面刷新也要從新再全部刷新一次所以整體畫(huà)面會(huì)不連貫
所以我寫(xiě)入了一個(gè)只清屏某個(gè)部分的函數(shù)
添加代碼:
/*
直接用清屏函數(shù)整體刷新會(huì)導(dǎo)致OLED畫(huà)面不連貫
清除行函數(shù):保留本行字符串,清除本行剩余部分
row:清除的具體行
len:不希望被清除的字符串長(zhǎng)度
*/
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ù)有兩個(gè)參數(shù):其中row指你想要進(jìn)行清屏操作的具體行,OLED上一共能顯示4行
其中l(wèi)en代表row行從左到右len長(zhǎng)度區(qū)間的字符串將會(huì)被保留,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);//開(kāi)啟ADC1的時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//開(kāi)啟GPIOA的時(shí)鐘
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC模塊工作時(shí)鐘 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ī)則組列表第一個(gè)位置,寫(xiě)入通道0這個(gè)通道*/
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ù)右對(duì)齊
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//觸發(fā)方式,不使用外部觸發(fā),即軟件觸發(fā)
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC工作模式為獨(dú)立模式
ADC_InitStruct.ADC_NbrOfChannel = 1;//通道數(shù)目
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//非掃描
ADC_Init(ADC1, &ADC_InitStruct);
//開(kāi)啟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);//開(kāi)始校準(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){//獲取光照強(qiáng)度
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:"長(zhǎng)度為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);
}
}
效果:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-765121.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-765121.html
到了這里,關(guān)于Stm32_標(biāo)準(zhǔn)庫(kù)_8_ADC_光敏傳感器_測(cè)量具體光照強(qiáng)度的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!