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