首先思考一個問題,我們的世界是數(shù)字的還是模擬的? 當(dāng)然是模擬的了,所有的量都是在一定范圍內(nèi)連續(xù)變化的。我們?yōu)榱四軌蚋臃奖愕拿枋鲞@些量,對它們進行了數(shù)字化。而數(shù)字量就不一樣了,它是分立的的幾個值。 舉個例子,我們形容一個人的身高,模擬的說法是一米七到一米七五之間,數(shù)字的說法就是一米七三。 接下來說AD轉(zhuǎn)換器,它的出現(xiàn)也是為了讓我們能更方便、更直接的描述電壓的高低。AD轉(zhuǎn)換器,英文全稱為Analog-to-Digital Converter,是模擬量到數(shù)字量的一個轉(zhuǎn)換過程,主要用于電壓的采集。它的出現(xiàn)就如同有了一把尺子,很容易就能量出電壓的高低。 在電子設(shè)備中,經(jīng)常要檢測各種模擬量:溫度、壓力、速度、流量、重力加速度等等,這些模擬量都被相應(yīng)的傳感器轉(zhuǎn)換為電壓信號,我們只需要測量電壓的高低,就能得到相應(yīng)參數(shù)。 AD的主要參數(shù)有哪些? 1、AD的位數(shù):表明這個AD共有2^n個刻度,8位AD,輸出的刻度是0~255. 2、分辨率:就是AD能夠分辨的最小的模擬量變化,假設(shè)5.10V的系統(tǒng)用8位的AD采樣,那么它能分辨的最小電壓就是5.10/255=0.02V。 3、INL:Interger NONliner 積分非線性度,表示了ADC器件在所有的數(shù)值點上對應(yīng)的模擬值,和真實值之間誤差最大的那一點的誤差值。也就是,輸出數(shù)值偏離線性最大的距離。單位是LSB(即最低位所表示的量)。比如12位ADC:TLC2543,INL值為1LSB。那么,如果基準(zhǔn)4.095V,測某電壓得的轉(zhuǎn)換結(jié)果是1000,那么,真實電壓值可能分布在0.999~1.001V之間。 4、DNL:Differencial NonLiner-差分非線性度,理論上說,模數(shù)器件相鄰量個數(shù)據(jù)之間,模擬量的差值都是一樣的。就相一把疏密均勻的尺子。但實際并不如此。一把分辨率1毫米的尺子,相鄰兩刻度之間也不可能都是1毫米整。那么,ADC相鄰兩刻度之間最大的差異就叫差分非線性值(Differencial NonLiner)。DNL值如果大于1,那么這個ADC甚至不能保證是單調(diào)的,輸入電壓增大,在某個點數(shù)值反而會減小。這種現(xiàn)象在SAR(逐位比較)型ADC中很常見。 5、基準(zhǔn)源:有內(nèi)部基準(zhǔn)源、外部基準(zhǔn)源等等。 6、轉(zhuǎn)換速率:也就是轉(zhuǎn)換周期的倒數(shù),轉(zhuǎn)換周期就是完成一次AD轉(zhuǎn)換所需的時間。 今天要用到的器件是PCF8591,為什么選它?太多的開發(fā)板上用它做演示了,而且還是IIC總線通信的。既學(xué)習(xí)了AD采樣,又學(xué)習(xí)了IIC總線。 先上應(yīng)用電路: 如上圖所示,PCF8591的9腳和10腳,一個是數(shù)據(jù)線SDA,一個是時鐘線SCL。分別接到單片機的P2.0 , P2.1上面。 為什么選這兩個引腳?因為51單片機上沒有IIC總線接口,需要用普通的IO模擬,所以它隨便選了兩個IO接上就行。 VREF是什么?基準(zhǔn)電壓,也是它能測量的最大電壓。 如何控制?今天先不說IIC總線,只說控制流程。 看器件手冊可以知道: 分四步: 1、發(fā)送地址字節(jié),選擇該器件。 2、發(fā)送控制字節(jié),選擇相應(yīng)通道。 // 3、重新發(fā)送地址字節(jié),選擇該器件。 4、接收目標(biāo)通道的數(shù)據(jù)。 這次的程序流程是:AD采樣,串口發(fā)送,循環(huán)執(zhí)行。 下面是AD采樣源代碼: 本程序下載鏈接(附帶 PCF8591中文資料pdf資料):
PCF8591AD采樣.rar
(459.16 KB, 下載次數(shù): 948)
2015-4-8 22:46 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
-------------------------------------------------------------------------------------
下面介紹PCF8591的DA輸出:
忽然發(fā)現(xiàn),已經(jīng)寫到AD/DA這里來了。嚴(yán)格來說,已經(jīng)不是51單片機的內(nèi)容了,而是周邊應(yīng)用電路的一些東西。這些東西涉及的知識面比較廣,什么都有可能提到。 關(guān)于AD/DA,或者其它設(shè)備,我的學(xué)習(xí)思路是先模仿,再深究。 因為無論是課本也好,器件手冊也好,大部分講的都是原理或者寄存器,起到的是一個工具書的作用,類似于語文課上用的字典。但是這就出現(xiàn)了一個問題,很多人想通過看課本或者看器件手冊的方式來掌握這些設(shè)備。 這個思路有問題嗎?沒有問題嗎? 還記得我剛才說的話么,它們就類似于語文課上用的字典,但是,有誰是通過看字典學(xué)會說話的�。。� 我們都是通過模仿別人學(xué)會說話的,遇到不認識的字才去查字典!但是很多人或者很多學(xué)校都把這兩件事的順序搞反了。 記得之前我在英飛凌官網(wǎng)進行芯片選型,網(wǎng)頁都翻爛了,找不到合適的。因為英飛凌不是我家開的,我不能保證每次都能順利的找到我想要的東西。 但是,我同事參加了一次電子展,在展會上遇到了英飛凌的展臺,然后問他們,他們一聽我們的需求,馬上找出一堆能滿足我們要求的芯片。 這就是思路的問題! 扯遠了,說回到DA控制。 DA轉(zhuǎn)換(Digital to Analog),是將數(shù)字量變成模擬量的一個過程。AD與DA剛好是相反的兩個過程,AD是把模擬信號變成單片機可識別的數(shù)字信號;DA是把單片機可識別的數(shù)字信號變成連續(xù)變化的模擬量。這兩種功能的應(yīng)用范圍都非常廣泛! 主要參數(shù)如下,具體什么意思就不講了,大家可以百度一下。(因為我編不出來了...) 1)分辯率(Resolution) 2) 轉(zhuǎn)換速率(Conversion Rate) 3)量化誤差 (Quantizing Error) 4)偏移誤差(Offset Error) 5)滿刻度誤差(Full Scale Error) 6)線性度(Linearity) 其他指標(biāo)還有:絕對精度(Absolute Accuracy) ,相對精度(Relative Accuracy),微分非線性,單調(diào)性和無錯碼,總諧波失真(Total Harmonic Distotortion縮寫THD)和積分非線性。 看到這么多參數(shù),是不是很暈? 搞了這些年電子,感觸最深的有一點是:無論做什么,先求有,再求好! 不要總想一口吃個胖子,沒那么多天才。參數(shù)是很多,但是沒要求你一下子全都記住,甚至你可以只記一兩個。先把大致的應(yīng)用流程跑一遍,跑下來,你才對這個設(shè)備有一個整體的概念,然后針對你的要求,比對相應(yīng)的參數(shù),進行修改、調(diào)試。 哪怕是在工作中,也不一定會考慮全部的參數(shù)。例如轉(zhuǎn)換時間,我到現(xiàn)在也沒認真看PIC內(nèi)部的AD采樣轉(zhuǎn)換時間有多久,因為有些設(shè)備對實時性要求很低,速度慢一些也沒事。 然后是控制流程,認真看器件手冊的,或者看了昨天日志的,都知道是怎樣一個流程: 第一步:寫器件地址; 第二步:寫控制位。 第三步:寫入數(shù)據(jù)。 好了,上程序。通過DA輸出漸變電壓控制LED,形成呼吸燈的效果。里面有個警告: *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS 大家可以研究下,如何消除警告。 程序源碼如下: - /**********************51單片機學(xué)習(xí)例程************************
- * 平臺: Keil U34 + STC89C52RD
- * 名稱:IIC協(xié)議 PCF8591ADDA轉(zhuǎn)換 ,此程序通過IIC協(xié)議對DAAD芯片操作, 并輸出模擬量,用LED亮度漸變指示
- * 編寫:起航
- * 晶振:11.0592MHZ
- ******************************************************************/
- #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
- #include <intrins.h> //包含NOP空指令函數(shù)_nop_();
- #define AddWr 0x90 //寫數(shù)據(jù)地址
- #define AddRd 0x91 //讀數(shù)據(jù)地址
- sbit RST=P2^4; //關(guān)掉時鐘芯片輸出
- sbit Sda=P2^0; //定義總線連接端口
- sbit Scl=P2^1;
- sbit Fm=P2^3; //FM
- sbit dula=P2^6;
- sbit wela=P2^7;
- // bit ADFlag; //定義AD采樣標(biāo)志位
- unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//7段數(shù)共陰碼管段碼表
- data unsigned char Display[8];//定義臨時存放數(shù)碼管數(shù)值
- /*------------------------------------------------
- 延時程序
- ------------------------------------------------*/
- void mDelay(unsigned char j)
- {
- unsigned int i;
- for(;j>0;j--)
- {
- for(i=0;i<125;i++)
- {;}
- }
- }
- /*------------------------------------------------
- 初始化定時器1
- ------------------------------------------------*/
- void Init_Timer1(void)
- {
- TMOD |= 0x10;
- TH1=0xff; /* Init value */
- TL1=0x00;
- //PT1=1; /* 優(yōu)先級 */
- EA=1; /* interupt enable */
- ET1=1; /* enable timer1 interrupt */
- TR1=1;
- }
- /*------------------------------------------------
- 啟動IIC總線
- ------------------------------------------------*/
- void Start(void)
- {
- Sda=1;
- _nop_();
- Scl=1;
- _nop_();
- Sda=0;
- _nop_();
- Scl=0;
- }
- /*------------------------------------------------
- 停止IIC總線
- ------------------------------------------------*/
- void Stop(void)
- {
- Sda=0;
- _nop_();
- Scl=1;
- _nop_();
- Sda=1;
- _nop_();
- Scl=0;
- }
- /*------------------------------------------------
- 應(yīng)答IIC總線
- ------------------------------------------------*/
- void Ack(void)
- {
- Sda=0;
- _nop_();
- Scl=1;
- _nop_();
- Scl=0;
- _nop_();
- }
- /*------------------------------------------------
- 發(fā)送一個字節(jié)
- ------------------------------------------------*/
- void Send(unsigned char Data)
- {
- unsigned char BitCounter=8;
- unsigned char temp;
- do
- {
- temp=Data;
- Scl=0;
- _nop_();
- if((temp&0x80)==0x80)
- Sda=1;
- else
- Sda=0;
- Scl=1;
- temp=Data<<1;
- Data=temp;
- BitCounter--;
- }
- while(BitCounter);
- Scl=0;
- }
- /*------------------------------------------------
- 寫入DA數(shù)模轉(zhuǎn)換值
- ------------------------------------------------*/
- void DAC(unsigned char Data)
- {
- Start();
- Send(AddWr); //寫入芯片地址
- Ack();
- Send(0x40); //寫入控制位,使能DAC輸出
- Ack();
- Send(Data); //寫數(shù)據(jù)
- Ack();
- Stop();
-
- }
- void fmg(void)//fm關(guān)
- {
- Fm=1; // 關(guān) fm
- }
- void cmg(void)//數(shù)碼管鎖存函數(shù) 關(guān)時鐘DS1302
- {
- dula=1;
- P0=0x00;
- dula=0;
- wela=1;
- P0=0x00;
- wela=0;
- RST=0; // 關(guān)時鐘DS1302
- }
- /*------------------------------------------------
- 主程序
- ------------------------------------------------*/
- void main()
- {
- unsigned char num; //DA數(shù)模輸出變量
- Init_Timer1();
- cmg();//數(shù)碼管鎖存
- fmg();
- while(1)
- {
- DAC(num); //DA輸出,可以用LED模擬電壓變化
- num++; //累加,到256后溢出變?yōu)?,往復(fù)循環(huán)。顯示在LED上亮度逐漸變化
- mDelay(20); //延時用于清晰看出變化
- }
- }
復(fù)制代碼下載鏈接:
PCF8591DAC_LED.zip
(29.03 KB, 下載次數(shù): 409)
2015-4-8 22:46 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|