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