單片機(jī)是一個典型的數(shù)字系統(tǒng)。數(shù)字系統(tǒng)只能對輸入的數(shù)字信號進(jìn)行處理,但是在工業(yè)檢測系統(tǒng)和日常生活中的許多物理量都是模擬量,這些模擬量可以通過傳感器變成與之對應(yīng)的數(shù)字量便于處理和顯示。
A/D和D/A的基本概念
A/D是模擬量到數(shù)字量的轉(zhuǎn)換,依靠的是模數(shù)轉(zhuǎn)換器(Analog to Digital Converter),簡稱ADC。D/A是數(shù)字量到模擬量的轉(zhuǎn)換,依靠的是數(shù)模轉(zhuǎn)換器(Digital to Analog Converter),簡稱DAC。本項(xiàng)目中主要以A/D為例。
模擬量是指變量在一定范圍內(nèi)連續(xù)變化的量,在任意時刻都有相應(yīng)的值與之對應(yīng)。比如天氣溫度值,在每時每刻都有溫度值,也稱之為連續(xù)變化的量。相對應(yīng)的是數(shù)字量,數(shù)字量只有在特定的時間才有相對應(yīng)的值,由于有一定的間隔,不是連續(xù)的,也稱之為離散。ADC就是把連續(xù)的信號用離散的數(shù)字表達(dá)出來。
A/D的主要指標(biāo)
在選取和使用A/D的時候,依靠什么指標(biāo)來判斷很重要。由于AD的種類很多,分為積分型、逐次逼近型、并行/串行比較型等多種類型,同時指標(biāo)也比較多,介紹常用的三種。
1、ADC的位數(shù)
一個n位的ADC表示這個ADC共有2的n次方個刻度。8位的ADC,輸出的是從0~255一共256個數(shù)字量,也就是2的8次方個數(shù)據(jù)刻度。
2、基準(zhǔn)源
基準(zhǔn)源,也叫基準(zhǔn)電壓,是ADC的一個重要指標(biāo),要想把輸入ADC的信號測量準(zhǔn)確,那么基準(zhǔn)源首先要準(zhǔn),基準(zhǔn)源的偏差會直接導(dǎo)致轉(zhuǎn)換結(jié)果的偏差。
3、分辨率
分辨率是數(shù)字量變化一個最小刻度時,模擬信號的變化量,定義為滿刻度量程與2n-1的比值。假定5.10V的電壓系統(tǒng),使用8位的ADC進(jìn)行測量,那么相當(dāng)于0~255一共256個刻度把5.10V平均分成了255份,那么分辨率就是5.10/255 = 0.02V。
PCF8591模塊硬件應(yīng)用說明
PCF8591是Philips公司的產(chǎn)品,是一個單電源低功耗的8位CMOS數(shù)據(jù)采集器件,具有4路模擬輸入,1路模擬輸出和一個串行I2C總線接口用來與單片機(jī)通信,該模塊從某寶采購,如圖1所示,該模塊共有8個引腳,在本項(xiàng)目中接左側(cè)的SCL、SDA、GND、VCC即可。
具有16引腳的芯片即為PCF8591,原理圖如圖2所示。該芯片允許最多8個器件連接到I2C總線而不需要額外的片選電路。器件的地址、控制以及數(shù)據(jù)都是通過I2C總線來傳輸,PCF8591的ADC是逐次逼近型,轉(zhuǎn)換速度取決于I2C的通信速率。由于I2C速度的限制,所以PCF8591是低速的AD和DA集成,主要應(yīng)用在一些轉(zhuǎn)換速度要求不高,希望成本較低的場合,比如電池供電設(shè)備,測量電池的供電電壓。
圖2 PCF8591芯片連接原理圖
圖2中引腳1、2、3、4是4路模擬輸入,對應(yīng)的實(shí)物是圖1中的右側(cè)引腳,通過絲印層即可觀察得到。5、6、7引腳對應(yīng)A0、A1、A2,是I2C總線的硬件地址,用于編程硬件地址,8腳是數(shù)字地GND,9腳和10腳是I2C總線的SDA和SCL。12腳是時鐘選擇引腳,如果接高電平表示用外部時鐘輸入,接低電平則用內(nèi)部時鐘,電路用的是內(nèi)部時鐘,因此12腳直接接GND,同時11腳懸空。13腳是模擬地AGND,在實(shí)際開發(fā)中,如果有比較復(fù)雜的模擬電路,那么AGND部分在布局布線上要特別處理,而且和GND的連接也有多種方式。在板子上沒有復(fù)雜的模擬部分電路,所以把AGND和GND接到一起。14腳是基準(zhǔn)源,15腳是DAC的模擬輸出,16腳是供電電源VCC。
14腳Vref基準(zhǔn)電壓的提供有兩種方法。一是采用簡易的原則,直接接到VCC上去,但是由于VCC會受到整個線路的用電功耗情況影響,相對來說并不是很準(zhǔn)確,通常用于精度要求不高的場合。方法二是使用專門的基準(zhǔn)電壓器件,比如TL431,它可以提供一個精度很高的2.5V的電壓基準(zhǔn),本項(xiàng)目中采用方法一。
** PCF8591模塊使用說明(淘寶購買)**
模塊共有3個黑色短路帽,如圖1 PCF8591模塊所示,通過絲印層觀察可見J4、J5、J6,相應(yīng)的原理圖如圖3所示,分別作用如下:
P5接上P5短路帽,選擇光敏電阻接入電路,AN0通路;
P6接上P6短路帽,選擇0-5V可調(diào)電壓接入電路,AN3通路;
由于在本實(shí)驗(yàn)中讀取該3路的具體值,所以實(shí)驗(yàn)中并未取下短路帽。
圖3 模塊引腳連接方式
這里需要注意的是AN3雖然測的是+5V的值,但是對于AD來說,只要輸入信號超過Vref基準(zhǔn)源,它得到的始終都是最大值,即255,也就是說它實(shí)際上無法測量超過其Vref的電壓信號。需要注意的是,所有輸入信號的電壓值都不能超過VCC,即+5V,否則可能會損壞ADC芯片。
注:如果需要使用四路外部電壓輸入,請將3個紅色短路帽都取下。
模塊功能描述(資料中帶有)
1、模塊支持外部4路電壓輸入采集(電壓輸入范圍 0-5v);
2、模塊集成光敏電阻,可以通過AD采集環(huán)境光強(qiáng)精確數(shù)值;
3、模塊集成熱敏電阻,可以通過AD采集環(huán)境溫度精確數(shù)值;
4、模塊集成1路0-5V電壓輸入采集(通過藍(lán)色電位器調(diào)節(jié)輸入電壓);
5、模塊帶電源指示燈(對模塊供電后指示燈會亮);
6、模塊帶DA輸出指示燈,當(dāng)模塊DA輸出接口電壓達(dá)到一定值,會點(diǎn)亮板上DA輸出指示燈,電壓越大,指示燈亮度越明顯;
7、模塊PCB尺寸:3.6cm*2.3cm;
8、標(biāo)準(zhǔn)雙面板,板厚1.6mm,布局美觀大方,四周設(shè)有通孔,孔徑為:3mm,方便固定。
** PCF8591的軟件編程**
PCF8591的通信接口是I2C。單片機(jī)對PCF8591進(jìn)行初始化,一共發(fā)送三個字節(jié)即可。第一個字節(jié)是器件地址字節(jié),其中7位代表地址,1位代表讀寫方向(最低位),“0”表示主機(jī)向從機(jī)寫數(shù)據(jù),“1”表示主機(jī)向從機(jī)讀數(shù)據(jù)。地址高4位固定是0b1001,低三位是A2,A1,A0,這三位電路上都接了GND,因此也就是0b000,如圖4所示。
圖4 PCF8591地址字節(jié)
在程序中有這么一段代碼,0x48是由高四位和低3位組成的,即0b1001000,由于讀寫位在第0位,所以需要整體左移一位,程序中if用于判斷是否存在該器件,如果不存在則I2CWrite函數(shù)返回1,則執(zhí)行I2CStop();return 0;這兩條語句,return函數(shù)會結(jié)束當(dāng)前函數(shù);反之,返回0,略過if語句,繼續(xù)執(zhí)行下面的語句。
if(I2CWrite(0x48< 1))
{
I2CStop();
return 0;
}
發(fā)送到PCF8591的第二個字節(jié)將被存儲在控制寄存器,用于控制PCF8591的功能。其中第3位和第7位是固定的0,另外6位各自有各自的作用,如圖5所示。
圖5 PCF8591 控制字節(jié)
控制字節(jié)的第6位是DA使能位,這一位置1表示DA輸出引腳使能,會產(chǎn)生模擬電壓輸出功能。第4位和第5位可以實(shí)現(xiàn)把PCF8591的4路模擬輸入配置成單端模式和差分模式,這里只需要知道這兩位是配置AD輸入方式的控制位即可,如圖6所示,本項(xiàng)目中采用“00”模式。
圖6 PCF8591模擬輸入配置方式
控制字節(jié)的第2位是自動增量控制位,自動增量的意思就是,比如一共有4個通道,當(dāng)全部使用的時候,讀完了通道0,下一次再讀,會自動進(jìn)入通道1進(jìn)行讀取,不需要我們指定下一個通道,由于A/D每次讀到的數(shù)據(jù),都是上一次的轉(zhuǎn)換結(jié)果,所以在使用自動增量功能的時候,要特別注意,當(dāng)前讀到的是上一個通道的值!
控制字節(jié)的第0位和第1位就是通道選擇位,00、01、10、11代表了從0到3的一共4個通道選擇。
發(fā)送給PCF8591的第三個字節(jié)D/A數(shù)據(jù)寄存器,表示D/A模擬輸出的電壓值。如果僅僅使用A/D功能的話,就可以不發(fā)送第三個字節(jié)。
I2C總線與通訊時序的介紹
在項(xiàng)目六中接觸到了第一種通信協(xié)議----UART異步串行通信,本項(xiàng)目中學(xué)習(xí)第二種通信協(xié)議----I2C。I2C總線是由PHILIPS公司開發(fā)的兩線式串行總線,多用于連接微處理器及其外圍芯片。I2C總線的主要特點(diǎn)是接口方式簡單,兩條線可以掛多個參與通信的器件,即多機(jī)模式,而且任何一個器件都可以作為主機(jī),當(dāng)然同一時刻只能有一個主機(jī)。I2C屬于同步通信,SCL時鐘線負(fù)責(zé)收發(fā)雙方的時鐘節(jié)拍,SDA數(shù)據(jù)線負(fù)責(zé)傳輸數(shù)據(jù)。I2C的發(fā)送方和接收方都以SCL這個時鐘節(jié)拍為基準(zhǔn)進(jìn)行數(shù)據(jù)的發(fā)送和接收。在本項(xiàng)目中,I2C用于單片機(jī)和PCF8591之間的通信。
** I2C尋址模式**
I2C通信在字節(jié)級的傳輸中,也有固定的時序要求。I2C通信的起始信號(Start)后,首先要發(fā)送一個從機(jī)的地址,這個地址一共有7位,緊跟著的第8位是數(shù)據(jù)方向位(R/W),“0”表示接下來要發(fā)送數(shù)據(jù)(寫),“1”表示接下來是請求數(shù)據(jù)(讀)。
當(dāng)發(fā)送完了這7位地址和1位方向后,如果發(fā)送的這個地址確實(shí)存在,那么這個地址的器件應(yīng)該回應(yīng)一個ACK(拉低SDA即輸出“0”),如果不存在,就沒“人”回應(yīng)ACK(SDA將保持高電平即“1”)。ACK類似在打電話的時候,當(dāng)撥通電話,接聽方撿起電話肯定要回一個“喂”,這就是告訴撥電話的人,這邊有人了。同理,這個第九位ACK實(shí)際上起到的就是這樣一個作用。
在前面提到PCF8591的7位地址中高4位固定是0b1001,緊接低三位是A2,A1,A0,這三位電路上都接了GND,因此也就是0b000,因此PCF8591的7位地址實(shí)際上是二進(jìn)制的0b1001000,也就是0x48。
I2C時序認(rèn)識
I2C總線是由時鐘總線SCL和數(shù)據(jù)總線SDA兩條線構(gòu)成,所有器件的SCL都連到一起,所有SDA都連到一起。I2C總線是開漏引腳并聯(lián)的結(jié)構(gòu),因此外部要添加上拉電阻。對于開漏電路外部加上拉電阻,就組成了線“與”的關(guān)系??偩€上線“與”的關(guān)系就是說,所有接入的器件保持高電平,這條線才是高電平,而任何一個器件輸出一個低電平,那這條線就會保持低電平,因此可以做到任何一個器件都可以拉低電平,也就是任何一個器件都可以作為主機(jī),如圖2所示,添加了R8和R9兩個上拉電阻。
I2C在通信過程中有起始信號、數(shù)據(jù)傳輸和停止信號,如圖7所示。
圖7 I2C通信流程解析
I2C分為起始信號、數(shù)據(jù)傳輸部分、停止信號。其中數(shù)據(jù)傳輸部分,可以一次通信過程傳輸很多個字節(jié),字節(jié)數(shù)是不受限制的,而每個字節(jié)的數(shù)據(jù)最后也跟了一位,這一位叫做應(yīng)答位,通常用ACK表示應(yīng)答,NACK表示非應(yīng)答。
起始信號:UART通信是從一直持續(xù)的高電平出現(xiàn)一個低電平標(biāo)志起始位;而I2C通信的起始信號的定義是SCL為高電平期間,SDA由高電平向低電平變化產(chǎn)生一個下降沿,表示起始信號,如圖7中的Start部分所示,相應(yīng)的代碼如下所示。
void I2CStart()
{
I2C_SDA = 1; //首先確保 SDA、SCL都是高電平
I2C_SCL = 1;
Delay();
I2C_SDA = 0; //先拉低 SDA
Delay();
I2C_SCL = 0; //再拉低 SCL
}
根據(jù)程序的時序圖較易理解,程序中使用了Delay()函數(shù),那么Delay()延時多少時間?在程序定義中可以看到。
#define Delay() { nop (); nop (); nop (); nop (); nop ();}
一個_nop_()表示大概是一個機(jī)器周期,約為5us,為什么是這個值?根據(jù)PCF8591操作手冊要求,如圖8所示,需要持續(xù)tHD;STA 的時間,結(jié)合圖9,tHD;STA 的最小值為4us,沒有最大值,從圖9中還可以看到有的需要持續(xù)5us,所以統(tǒng)一方便定義Delay()的時間為5個_nop_()。
圖8 I2C總線時間限制圖
圖9 具體時間分布圖
數(shù)據(jù)傳輸:I2C通信是高位在前,低位在后。I2C不像UART有固定波特率,但是有時序要求:當(dāng)SCL在低電平的時候,SDA允許變化,也就是說,發(fā)送方必須先保持SCL是低電平,才可以改變數(shù)據(jù)線SDA,輸出要發(fā)送的當(dāng)前數(shù)據(jù)的一位;而當(dāng)SCL在高電平的時候,SDA絕對不可以變化,因?yàn)檫@個時候,接收方要來讀取當(dāng)前SDA的電平信號是0還是1,因此要保證SDA的穩(wěn)定,如圖7中的每一位數(shù)據(jù)的變化,都是在SCL的低電平位置。8位數(shù)據(jù)位后邊跟著的是一位應(yīng)答位。
數(shù)據(jù)傳輸又分為兩種:主機(jī)向從機(jī)寫數(shù)據(jù)和主機(jī)向從機(jī)讀取數(shù)據(jù),再次強(qiáng)調(diào)下一般來說單片機(jī)為主機(jī),從機(jī)為24C02、PCF8591等具備I2C協(xié)議的專用芯片。
1、當(dāng)讀數(shù)據(jù)的時候,從設(shè)備每發(fā)送完8個數(shù)據(jù)位,如果主機(jī)繼續(xù)讀下一個字節(jié),主機(jī)應(yīng)該回答“ACK”以提示從機(jī)準(zhǔn)備下一個數(shù)據(jù),如果主機(jī)不希望讀取更多字節(jié),主機(jī)應(yīng)該回答“NACK”以提示從機(jī)設(shè)備準(zhǔn)備接收Stop信號。
2、當(dāng)寫數(shù)據(jù)的時候,主機(jī)每發(fā)送完8個數(shù)據(jù)位,從機(jī)設(shè)備如果還要一個字節(jié)應(yīng)該回答“ACK”,從機(jī)設(shè)備如果不接受更多的字節(jié)應(yīng)該回答“NACK”,主機(jī)當(dāng)收到“NACK”或者一定時間之后沒收到任何數(shù)據(jù)將視為超時,此時主機(jī)放棄數(shù)據(jù)傳送。
3、無論是讀數(shù)據(jù)還是寫數(shù)據(jù),都是主機(jī)動作!
根據(jù)讀操作特點(diǎn)編寫以下程序,I2CReadACKORNOT函數(shù)中的參數(shù)為1表示繼續(xù)讀下一字節(jié),根據(jù)函數(shù)可知此時回答的是“ACK”;反之,為非1時,主機(jī)回應(yīng)了“NACK”。不同于UART協(xié)議,I2C傳輸數(shù)據(jù)從高位開始,程序中巧妙地設(shè)置了BitCnt的值為0x80,對應(yīng)的二進(jìn)制為0b1000 0000,如果此時從機(jī)傳給主機(jī)的值為0,那么“dat &= ~BitCnt”后,dat的最高位為0,如果從機(jī)傳給主機(jī)的值為1,那么“dat |= BitCnt t”后,dat的最高位為1。一次循環(huán)后BitCnt>>=1,此時BitCnt的值為0x40,對應(yīng)的二進(jìn)制為0b0100 0000。通過此方式,依次讀取出從機(jī)傳給主機(jī)的數(shù)據(jù),最后函數(shù)返回dat值!
unsigned char I2CReadACKORNOT(bit cnt)
{
unsigned char BitCnt;
unsigned char dat;
I2C_SDA = 1; //首先確保主機(jī)釋放SDA
for (BitCnt=0x80; BitCnt!=0; BitCnt >?>=1) //從高位到低位依次進(jìn)行
{
Delay();
I2C_SCL = 1; //拉高SCL
if(I2C_SDA == 0) //讀取SDA的值
dat &= ~BitCnt; //為0時,dat中對應(yīng)位清零
else
dat |= BitCnt; //為1時,dat中對應(yīng)位置1
Delay();
I2C_SCL = 0; //再拉低SCL,以使從機(jī)發(fā)送出下一位
}
if(cnt)
I2C_SDA = 0; //8位數(shù)據(jù)發(fā)送完后,拉低SDA,發(fā)送應(yīng)答信號
else
I2C_SDA = 1;
Delay();
I2C_SCL = 1; //拉高SCL
Delay();
I2C_SCL = 0; //再拉低SCL完成應(yīng)答位,并保持住總線
return dat;
}
對于寫操作類似,不在此重復(fù)敘述。
停止信號:I2C通信停止信號的定義是SCL為高電平期間,SDA由低電平向高電平變化產(chǎn)生一個上升沿,表示結(jié)束信號,如圖7中的Stop部分所示,相應(yīng)的代碼如下所示。
void I2CStop()
{
I2C_SCL = 0; //首先確保SDA、SCL都是低電平
I2C_SDA = 0;
Delay();
I2C_SCL = 1; //先拉高 SCL
Delay();
I2C_SDA = 1; //再拉高 SDA
Delay();
}
實(shí)現(xiàn)現(xiàn)象:
采集PCF8591模塊的3路信號。
評論
查看更多