51單片機(jī)輕松入門—基于STC15W4K系列(C語言版)
李友全 編著:http://www.torrancerestoration.com/bbs/dpj-37954-1.html
第6章 單片機(jī)IIC通信 1 接口定義 2 程序?qū)嵗?/font> 閱讀提示:本章主要講解過去電路使用較多的24C02- 24C512存儲(chǔ)器,對(duì)于現(xiàn)在 主流的STC15W系列單片機(jī),通常都具有內(nèi)部比較器與DataFlash存儲(chǔ)器,可 直接代換代換本章各個(gè)例程功能(詳見第7章) 1 接口定義 I2C總線是兩線式串行總線(連同GND為3線),僅需要時(shí)鐘和數(shù)據(jù)兩根線就可 以進(jìn)行數(shù)據(jù)傳輸,僅需要占用單片機(jī)的2個(gè)IO引腳,使用時(shí)十分方便,I2C總線可 以在同一總線上并接多個(gè)器件,每個(gè)器件都有自己的器件地址(作為對(duì)比:SPI 總線沒有器件地址,通過CPU提供片選線確定是否選中芯片),讀寫操作時(shí)需要 先發(fā)送器件地址,與該地址相符的器件得到確認(rèn)后便執(zhí)行相應(yīng)的操作,而在同一 總線上的其它器件不做響應(yīng),稱之為器件尋址。 單片機(jī)外圍使用I2C接口的器件比較多,最常見的是EEPROM存儲(chǔ)器(如: 24C02)與ADC轉(zhuǎn)換芯片(如:MCP3421) 。 24C02與單片機(jī)的連接電路如下圖所示。
0.png (126.16 KB, 下載次數(shù): 182)
下載附件
2016-3-28 02:24 上傳
24C系列芯片既然作為存儲(chǔ)器使用,我們最關(guān)心的就是如何將數(shù)據(jù)寫入芯片及 寫入成功的數(shù)據(jù)如何讀取出來。 例6.2 使用IAP15W4K58S4單片機(jī)的硬件仿真功能仿真觀察24C02芯片讀寫結(jié)果 (也可用24C01/04/08/16) 。本例無頁面限制,快速,適合連續(xù)讀寫多個(gè)字 節(jié),本程序先向芯片寫入一組數(shù)據(jù),然后讀出,若讀出的數(shù)據(jù)與寫入的數(shù)據(jù)相同 則表明實(shí)驗(yàn)結(jié)果是正確的。 為了簡(jiǎn)化,我們直接移植成熟的程序代碼(配套例程中提供)。 ① 除主程序MAIN.C外,其余*.C與*.H文件全部復(fù)制到你自己的文件夾并將*.C文 件加入工程,如圖所示。
%E7%AC%AC6%E7%AB%A0-iic%E9%80%9A%E4%BF%A1-5.jpg (29.53 KB, 下載次數(shù): 140)
下載附件
2016-3-28 02:30 上傳
② 根據(jù)實(shí)際硬件連接修改引腳定義。在IIC.H中有如下語句,可設(shè)置為任意IO口,注 意上拉。 sbit SCL=P3^7; // 串行時(shí)鐘(代碼包必須) sbit SDA=P4^1; // 串行數(shù)據(jù)(代碼包必須) ③ 根據(jù)硬件修改從機(jī)地址。在24C01_02.H中有:#define SlaveADDR 0xA0 // 從機(jī) 地址格式為:1010 ***0。其中的***對(duì)應(yīng)器件引腳 A2A1A0,,用于設(shè)置器件地 址,當(dāng)硬件上A2A1A0接GND時(shí), ***=000。 ④ 在要求嚴(yán)格的情況下,根據(jù)R/C時(shí)鐘頻率修改延時(shí)函數(shù)參數(shù)。myfun.c中的延時(shí)函 數(shù)delay1ms()和delay10ms()延時(shí)參數(shù)由第1章介紹的軟件計(jì)算得出。 ⑤ 根據(jù)R/C時(shí)鐘頻率修改宏定義。IIC.H中的語句 “#define tt 26”的常數(shù)26對(duì)應(yīng) myfun.c中的延時(shí)函數(shù)void delay (unsigned char t)中的參數(shù)t,此常數(shù)值確定 5uS延時(shí)時(shí)間,延時(shí)可以更長(zhǎng),不能短,時(shí)鐘頻率為22.1184MHz時(shí)t=26。 ⑥ 這里的例子使用的是24C02芯片,若換用24C04/08/16,為了提高多字節(jié)數(shù)據(jù)跨頁 寫入速度,則需要對(duì)24C01_02.C中函數(shù)WrToRomPageB內(nèi)部常數(shù)0x07改為0x0f。
主程序代碼如下(注意是硬件仿真觀察實(shí)驗(yàn)結(jié)果): #include "STC15W4K.H" // 注意宏定義后面沒分號(hào) #include "24C01_02.H" #include "myfun.h" void main() { u8 i; u8 test_data[20]={0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0, 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81,0x91,0xa1}; port_mode(); // 所有IO口設(shè)為準(zhǔn)雙向弱上拉方式。 WrToRomB(SlaveADDR, 5,test_data,20); // 器件地址、存儲(chǔ)單元地址、數(shù)據(jù)指針、寫入字節(jié)數(shù) for(i=0;i<20;i++) { test_data[ i ]=0; } RdFromROM(SlaveADDR, 5,test_data,20); // 連續(xù)讀取20個(gè)字節(jié)數(shù)據(jù) while(1); } 例6.5利用24C02記錄單片機(jī)上電次數(shù)(使用工作組方式) 頭文件代碼如下: #define E2P_RECORD_ADDR 0x00 // 存儲(chǔ)單元地址 #define POWER_UP_MARK 0xAB // 第一次使用標(biāo)記 struct POWER_UP { u32 times; u8 flag; }; // 主程序代碼如下: #include "PowerUP.H" #include "24C01_02.H" #include "myfun.h" struct POWER_UP Power_up; void main() { RdFromROM(SlaveADDR,E2P_RECORD_ADDR,(u8*)&Power_up,sizeof(struct POWER_UP)); // 芯片硬件地址、存儲(chǔ)單元地址、數(shù)據(jù)組、寫入字節(jié)數(shù) if (Power_up.flag != POWER_UP_MARK) // 存儲(chǔ)器第一次使用 { } else { }
Power_up.flag = POWER_UP_MARK; Power_up.times = 1;
Power_up.times++; WrToRomB(SlaveADDR, E2P_RECORD_ADDR,(u8 *)&Power_up,sizeof(struct POWER_UP));
// 芯片硬件地址、存儲(chǔ)單元地址、數(shù)據(jù)組、寫入字節(jié)數(shù) UART_init(); UART_Send_StrNum("上電次數(shù):",Power_up.times); // 串口輸出上電次數(shù),波特率:9600 /22.1184MHZ while(1); } 結(jié)果如圖所示。
%E7%AC%AC6%E7%AB%A0-iic%E9%80%9A%E4%BF%A1-10.jpg (65.18 KB, 下載次數(shù): 175)
下載附件
2016-3-28 02:30 上傳
例6.6 利用24C02斷電瞬間存儲(chǔ)數(shù)據(jù)。斷電存儲(chǔ)就是在系統(tǒng)斷電瞬間保存RAM中的重要數(shù)據(jù) 到EEPROM,在下次系統(tǒng)上電時(shí)再讀出EEPROM中的數(shù)據(jù)并運(yùn)行,斷電檢測(cè)電路原理如圖所 示。
0.png (218.38 KB, 下載次數(shù): 139)
下載附件
2016-3-28 02:28 上傳
利用單片機(jī)外中斷檢測(cè)交流電源的有無,交流供電正常時(shí)INT2每10mS進(jìn)入一次中斷,在中斷 程序中重裝定時(shí)器T1初值讓定時(shí)器一直不產(chǎn)生溢出中斷,交流斷電時(shí),定時(shí)器計(jì)數(shù)值不斷增 加直到溢出,溢出中斷程序中單片機(jī)立即保存數(shù)據(jù)到EEPROM 。定時(shí)器定時(shí)時(shí)間要求大于 10mS即可,比如取12或15mS,另外特別注意單片機(jī)外中斷引腳必須外接上拉電阻。 對(duì)于現(xiàn)在主流的STC15W系列單片機(jī),通常都具有內(nèi)部比較器與DataFlash存儲(chǔ)器,可直接 代換24C系列存儲(chǔ)器使用,斷電檢測(cè)電路更加簡(jiǎn)單,如上圖單片機(jī)VCC與GND間接2只電阻即可。
|