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