目的/效果
1 LCD1602 顯示 可調電阻、光敏電阻、熱敏電阻值(AD)
2 模擬信號控制LED明暗(DA)
一,STC單片機模塊
二,AD/DA?
2.1 AD/DA 介紹
AD(Analog to Digital):模擬-數字轉換,將模擬信號轉換為計算機可操作的數字信號
DA(Digital to Analog):數字-模擬轉換,將計算機輸出的數字信號轉換為模擬信號
AD/DA轉換打開了計算機與模擬信號的大門,極大的提高了計算機系統的應用范圍,也為模擬信號數字化處理提供了可能。
2.1.1 揚聲器(麥克風)
揚聲器(麥克風),像我們電腦里存的數字音樂就是數字信號,怎么才能將它輸出到揚聲器進行播放呢?就需要DA將這個數字信號代表的電壓轉換成實際的電壓,形成一個連續的電壓波形,再送給麥克風,這樣就可以聽到數字信號儲存的音樂了。
2.1.2 麥克風
?麥克風,也可以通過這種電阻分壓的形式,將人說話的聲音信號轉換為一個電壓信號,然后通過電壓采集,那數字系統就可以采集到這個聲音信號了。
2.1.3 熱敏電阻
熱敏電阻,阻值會隨著溫度的變化而變化。如果我們把上圖的光敏電阻換成熱敏電阻,也就可以獲取熱敏電阻這一點的電壓,從而可以知道溫度的高低。
2.1.4 光敏電阻
光敏電阻,阻值會隨著光線的變化而變化。
2.2 電路模型
模擬量和數字量是成正比的,比如說模擬量是0V,則數字量就是0;如果模擬量是5V,則數字量就是255;如果模擬量是2.5V,則數字量就是255/2;
AD/DA與單片機數據傳送可使用并口(速度快、原理簡單),也可使用串口(接線少、使用方便)
可將AD/DA模塊直接集成在單片機內,這樣直接寫入/讀出寄存器就可進行AD/DA轉換,單片機的IO口可直接復用為AD/DA的通道。
2.2.1 AD 裝換
AD轉換通常有多個輸入通道,用多路選擇開關連接至AD轉換器,以實現AD多路復用的目的,提高硬件利用率?
2.2.2 DA 裝換?
DA的應用一般可以用PWM來代替,所以DA的使用沒有AD廣泛。
2.3?運算放大器
運算放大器(簡稱“運放”)是具有很高放大倍數的放大電路單元。內部集成了差分放大器、電壓放大器、功率放大器三級放大電路,是一個性能完備、功能強大的通用放大電路單元,由于其應用十分廣泛,現已作為基本的電路元件出現在電路圖中
運算放大器可構成的電路有:電壓比較器、反相放大器、同相放大器、電壓跟隨器、加法器、積分器、微分器等
運算放大器電路的分析方法:虛短、虛斷(負反饋條件下)?
2.3.1 運放原理
我們這里簡單理解下面的電路,
V+,V-?這兩個是電源,上正下負,分別可以接5V和-5V,也可以分別接5V和地,一般來說這種接法是比較多。
Un、Up 是輸入
Uout 是輸出
他的特性如下圖
運放的內部工作我們可以認為里面是一個開關,這個開關可以打到VCC即5V的一邊,也可以打到GND即0V的一邊。
那這個開關什么時候打到VCC這邊或GND的一邊呢?
這取決于Up和Un的差值。
當Up>Un時,(開關打到VCC)則輸出電壓就接近于正電源電壓Uout=5V
當Up<Un時,(開關打到GND)則輸出電壓就接近于負電源電壓Uout=0V
當Up和Un差不多大時,則輸出電壓=A(Up-Un)+2.5
A是運放的放大倍率,運放的固有參數,我們一開始并不需要太關注這個參數,只需要知道一般來說A都非常大,可以達到幾十萬,也就是說這根線會非常陡峭,或者說這部分的寬度非常窄。Up和Un相差幾十微伏或者更小時,才會進入這個區間。?
?
以上理論知識,下面開始看運放的第一個實際應用。
運放LM358
運放作為一個電壓比較器來使用,我們常見的運放LM358。
只需要用到其中一個就可以了,給它接好電源和地,然后Up這邊用信號發生器給它輸入一個正弦波,Un這邊通過這個可調電阻,讓它從0V到5V開始變化。??????
給光敏電阻光照時,Un>Up,運放就輸出低電平.
沒有光照時,Un<Up,運放就輸出高電平.
那么運放作為一個電壓比較器來使用時,我們發現這個實際應用中我們主要用到的是運放的這兩個區間:
也就是運放的非線性區或者叫飽和區
而運放真正的核心其實是在這一個狹窄的區間里,也就是線性區?
但是這個區間實在是太狹窄了,為了能夠用到這個區間,需要引入一個概念:負反饋。
負反饋
這么說,有了負反饋,運算放大器才能被稱為是運算放大器,否則只能被稱為放大器。
下面我們來看一下這張圖
將Un和輸出接在一起,問Un電壓是多少?
此時Un大概等于Un=2.9999x
因為只要Un和Up不相等,或者說差的很多,那么輸出電壓就一定會變成5V或者0V,進而通過這個路徑反饋回來,不斷修正Un的電壓,直到它和Up電壓差不多為止。?
也就是會對應到這條線上的某一個點,這就是所謂的負反饋。?
負反饋的過程
因為當Up>Un時,Uout要從Un上升到5V,上升到3.1V左右時,此時 Uout=Un>Up,Uout又要下降到0,但在下降到2.9V時,Uout=Un<Up,于是Uout又要上升。所以Uout會在 Up 附近震蕩,且越來越接近Up。 如果初學者想不明白負反饋的過程也沒關系,
我們只需要記住一個非常重要的結論: 當給運放引入負反饋,也就是把輸出和Un接在一起時,Un就約等于Up。同時又因為Up和Un差的實在太少了,只相差幾十微伏不到,所以我們就認為Up等于Un了。
這里的負反饋不一定是完全短接,通過一個電阻電容連接都是可以的。然后在這些電路中輸入輸出的關系分別是這樣子的(如圖中的關系式),你會發現第一個電路實現了比例的運算,第二個電路實現了加法的運算,而這個電路實現了積分的運算。
同向發放大器
假如說流過負載的電流有1A,那么此時Rs這一端大概會產生一個10mV的電壓。 這個電壓實在太小了,以至于我們沒有辦法很好的測量到,所以此時運放的這部分電路就派上用處了。假設此時R1是49千歐姆,R2是1千歐姆,那么這個運放就可以把Rs上的電壓放大50倍輸出。這樣我們就可以很方便的通過測量輸出電壓。反推負載上的電流了。?
Uout=(1+R1/R2)Uin=(1+49k/1k)10mV=500mV
運放的兩個主要應用場景。 一個作為比較器使用,一個是作為比例放大器來使用?
電壓比較器?
反向放大器
電壓跟隨器
虛短狀態:負反饋狀態下負極輸入的電壓和正極輸入的電壓是基本相等的。
虛斷狀態:由于輸入阻抗比較大,電流既不從負極輸入端流入也不流出。??
2.4?DA?
2.4.1?DA原理
?
我們知道了當Rfb=R時的輸出電壓,那么如果Rfb不等于R呢?電壓的表達式怎么來的呢?我們知道這其實是一個我們前面講過的反向放大器模型。如果我們能算出這一點的電流,那么電流通過反饋電阻分壓,就可以得出輸出電壓了。
由上圖分析:兩個2R并聯,流過兩個2R的電流為I0,?I1=2I0;阻值則為R。在與經過I的R串聯。
同理:
I2=2I1, 阻值2R;
I3=2*I2,總阻值2R
?……
I=2*I7,總阻值2R;線路中的總阻值為R;I=Vref/R;
所以,I=2*I7=4*I6=8*I5=16*I4=32*I3=64*I2=128*I1=256*I0;I0=Verf/(256*R);
所以我們可以將電路的I分為256份。I0=I/256;
我們在分析簡單的,單D0閉合1時,數字信號為 0000 0001(0x01=1)?,電路電流如下圖
電流I02=I-I0=255*I0;
同理可得:當D7-D0? 輸入 1000 0000(0x80=128) 時I02=I6+I5+I4+I3+I2+I1+I0=I7=128*I0;
D7-D0? ? 0001 0001=0x11=17 ,I02=17*I0;
2.4.2 DAC(PWM)模塊??(脈沖寬度調制)?
?輸出電壓 ? ? Vout=(PWM占空比)×Vh;
?
2.4.2.1 什么是PWM
?脈沖寬度調制(PWM),是英文“Pulse Width Modulation”的縮寫,簡稱脈寬調制,是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,廣泛應用在從測量、通信到功率控制與變換的許多領域中。 ?
2.4.2.2 PWM的頻率
是指1秒鐘內信號從高電平到低電平再回到高電平的次數(一個周期);
也就是說一秒鐘PWM有多少個周期
單位: Hz
表示方式: 50Hz 100Hz
2.4.2.3 PWM的周期
T=1/f
周期=1/頻率
50Hz = 20ms 一個周期
如果頻率為50Hz ,也就是說一個周期是20ms 那么一秒鐘就有 50次PWM周期
2.4.2.4 占空比
是一個脈沖周期內,高電平的時間與整個周期時間的比例
單位:?%?(0%-100%)
表示方式:20%?
周期為T
T1為高電平時間
T2 為低電平時間
假設周期T為 1s 那么頻率就是 1Hz 那么高電平時間0.5s ,低電平時間0.5s 總的占空比就是 0.5 /1 =50%
?控制LED的通斷時間比例,占空比。如下圖
2.5 AD?
輸出數字量 ? ?(D7~D0)=V_IN/V_REF×256 …… 結果取整
?
其實以上的工作原理是利用的二分法查找這種方法
比如,輸入一個在0V~5V范圍的模擬電壓,我們首先讓DAC產生一個2.5V的中間值和這個未知電壓進行比較,如果這個未知電壓比2.5V小的話,我們就把DAC調成(0+2.5)/2=1.25V再進行對比,如果比未知電壓大的話,我們就把ADC調成(1.25+2.5)/2的電壓和它對比,如此循環,最終8次對比就可以和未知電壓的值接近了。
根據這個例子,我們其實是將DAC的8位數據從左往右,就是將第一位置1,第二位置1......這樣開始和未知電壓進行對比。那么比如首先把DAC的2.5V,即1000 0000(也即128)和未知電壓進行對比,如果未知量比這個數小,那么我們把第一位置0,第二位置1,即0100 0000(表示64,也即1.25V),如果未知量比這個數大,那么這個1就保留,再把第三個置1,即0110 0000(表示96,也即(1.25+2.5)/2)再比較......依次判斷8位,最終這8位數據取出來就是表示我們的未知電壓。
2.6?AD/DA芯片
我們主要介紹ADC0809和DA0832,這兩個芯片是比較老舊的,但是它比較經典。所以我們主要了解它們的原理,實際應用的話還是可以用現在新的一些開發板上的AD、DA芯片。?
2.6.1 DA0832
2.6.2?ADC0809
?2.6.3 XPT2046
2.6.3.1 簡介
XPT2046是一款4線制電阻式觸摸屏控制器,內含12位分辨率125KHz轉換速率逐步逼近型A/D轉換器。XPT2046支持從1.5V到5.25V的低電壓I/0接口。XPT2046能通過執行兩次A/D轉換查出被按的屏幕位置,除此之外,還可以測量加在觸摸屏上的壓力。內部自帶⒉.5V參考電壓,可以作為輔助輸入、溫度測量和電池監測之用,電池監測的電壓范圍可以從OV到6V。XPT2046片內集成有一個溫度傳感器。在2.7V的典型工作狀態下,關閉參考電壓,功耗可小于0.75mW。XPT2046采用微小的封裝形式:TSSOP-16,QFN-16和VFBGA一48。工作溫度范圍為-40℃~~+85℃。與 ADS7846、TSC2046、AK4182A完全兼容。
2.6.3.2 電路圖
?單端模式輸入配置 如下表
?差分模式輸入配置?
?
2.6.3.3? 時序圖
24時鐘周期轉換時序
16時鐘轉換時序?
?詳細時序如下?
?準備讀數據
XPT2046_CS=0;//低電平Delay_ms(1);XPT2046_DCLK=0;//低電平Delay_ms(1);
?寫入地址
//發地址for(i=0;i<8;i++){XPT2046_DIN=Addr&(0x80>>i); XPT2046_DCLK=1;//高電平 Delay_ms(1);XPT2046_DCLK=0;//低電平Delay_ms(1);}
接收數據?
?
//收數據for(i=0;i<12;i++){AD_Value=AD_Value<<1;Delay_ms(1);XPT2046_DCLK=1;//高電平Delay_ms(1);XPT2046_DCLK=0;//置低電平,下降沿輸出數據Delay_ms(1);AD_Value=AD_Value|XPT2046_DOUT;//取數,轉換 }
?重置
只需要將CS置高電平
//重置XPT2046_CS=1;
?2.6.3.4 讀取數據完整代碼
/*** 函 數:讀取信號值* 參 數:Addr 信號值地址* 返 回 值:無*/
int XPT2046_ReadAD(unsigned char Addr)
{int AD_Value,i;XPT2046_CS=0;//低電平Delay_ms(1);XPT2046_DCLK=0;//低電平Delay_ms(1);//發地址for(i=0;i<8;i++){XPT2046_DIN=Addr&(0x80>>i); XPT2046_DCLK=1;//高電平 Delay_ms(1);XPT2046_DCLK=0;//低電平Delay_ms(1);}//收數據for(i=0;i<12;i++){AD_Value=AD_Value<<1;Delay_ms(1);XPT2046_DCLK=1;//高電平Delay_ms(1);XPT2046_DCLK=0;//置低電平,下降沿輸出數據Delay_ms(1);AD_Value=AD_Value|XPT2046_DOUT;//取數,轉換 }//重置XPT2046_CS=1;//return AD_Value;
}
三,創建Keil項目
?詳細參考:51單片機STC89C52RC——創建Keil項目-CSDN博客
四,代碼?
項目完整代碼請參考《STC89C52RC: 51單片機學習資料、代碼 - Gitee.com》
main.c
#include <REGX52.H>#include "XPT2046.h"
#include "Delay.h"
#include "lcd1602.h"
#include "timer0.h"
unsigned int Counter,Compare=90,Model=0;// 模式切換 0-AD(模數),1-DA(數模)
/*** 函 數:顯示可調電位器的值* 參 數:無* 返 回 值:無*/
void ShowDianWei()
{int AIN0;float ADC_VOL;AIN0=XPT2046_ReadAD(0x94);//LCD_ShowBinNum(1,1,AIN0,12);ADC_VOL=(5.0*AIN0/4096)*10;LCD_ShowNum(2,1,((int)ADC_VOL)/10,1);LCD_ShowString(2,2,".");LCD_ShowNum(2,3,((int)ADC_VOL)%10,1);LCD_ShowNum(2,4,((int)(ADC_VOL*10))%10,1);LCD_ShowNum(2,5,((int)(ADC_VOL*100))%10,1);
}
/*** 函 數:顯示光敏電阻的值* 參 數:無* 返 回 值:無*/
void ShowGuangMin()
{int AIN1;AIN1=XPT2046_ReadAD(0xA4);//LCD_ShowBinNum(1,1,AIN1,12);LCD_ShowNum(2,7,AIN1/1000,1);LCD_ShowNum(2,8,AIN1%1000/100,1);LCD_ShowNum(2,9,AIN1%100/10,1);LCD_ShowNum(2,10,AIN1%10,1);}
/*** 函 數:顯示熱敏電阻的值* 參 數:無* 返 回 值:無*/
void ShowReMin()
{int AIN2;AIN2=XPT2046_ReadAD(0xD4);//LCD_ShowBinNum(1,1,AIN2,12);LCD_ShowNum(2,12,AIN2/1000,1);LCD_ShowNum(2,13,AIN2%1000/100,1);LCD_ShowNum(2,14,AIN2%1000%100/10,1);LCD_ShowNum(2,15,AIN2%1000%100%10,1);
}
/*** 函 數: 數字型號 轉 模擬信號* 參 數:無* 返 回 值:無*/
void SetDA()
{int i=0;for(i=0;i<100;i++){Compare=i;Delay_ms(5);}for(i=100;i>0;i--){Compare=i;Delay_ms(5);}
}
/*** 函 數:主函數* 參 數:無* 返 回 值:無*/
void main()
{if(Model==1) {Timer0_Init();//初始化定時器 }LCD_Init();while(1){switch(Model){case 0:{//依次顯示 電位器 光敏 熱敏LCD_ShowString(1,1," DW GM RM");ShowDianWei();//電位器Delay_ms(10);ShowGuangMin();//光敏電阻Delay_ms(10);ShowReMin();//熱敏電阻Delay_ms(10); break;}case 1:{ LCD_ShowString(1,1,"DA ");LCD_ShowString(2,1," ");SetDA();break;}}} while(1){}
}/*** 函 數:定時器中斷函數* 參 數:無* 返 回 值:無*/
void Timer0_Routine() interrupt 1
{TL0 = 0x9C; //設置定時初值TH0 = 0xFF; //設置定時初值Counter++;Counter%=100;if(Counter>=Compare){P2_1=1;//熄滅}else {P2_1=0;//點亮}
}
五,代碼編譯、下載到51單片機
代碼編譯請參考
《51單片機STC89C52RC——代碼編譯-CSDN博客》
代碼下載請參考
《51單片機STC89C52RC——STCAI-ISP代碼下載-CSDN博客》