瞭解I2C匯流排協議; 掌握S3C2410/S3C2440中I2C介面的使用方法 ...
本章目標: 瞭解I2C匯流排協議; 掌握S3C2410/S3C2440中I2C介面的使用方法; 12.1 I2C匯流排協議及硬體介紹 12.1.1 I2C匯流排協議 1 I2C匯流排的概念 2 I2C匯流排的信號類型 3 I2C匯流排的數據傳輸格式 12.1.2 S3C2410/S3C2440 I2C匯流排控制器 1. S3C2410/S3C2440 I2C匯流排控制器寄存器介紹 S3C2410/S3C2440的I2C介面有4種工作模式:主機發送、主機接收、從機發送、 從機接收。其內部結構如圖12.6所示。 從圖12.6可知,S3C2410/S3C2440提供4個寄存器來完成所有的I2C操作。SDA線上的數據 從IICDS寄存器發出,或傳入IICDS寄存器中;IICADD寄存器中保存S3C2410/S3C2440當做從 機時的地址;IICCON、IICSTAT 兩個寄存器用來控制或標識各種狀態,比如選擇工作模式,發出 S信號、P信號,決定是否發出ACK信號,檢測是否收到ACK信號。各寄存器的用法如下: (1)IICCON寄存器(Multi-master IIC-bus control) IICCON寄存器用於控制是否發出ACK信號、設置發送器的時鐘、開啟IIC中斷,並標識中斷是 否發生。它的各位含義如下表12.2所示。 使用IICCON寄存器時,有如下註意事項: ① 發送模式的時鐘頻率由位[6]、位[3:0]聯合決定。另外,當IICCON[6] = 0時,IICCON[3:0] 不能去0或1。 ② IIC中斷在以下3種情況下發生: 當發出地址信息或接收到一個從機地址並且吻合時; 當總線仲裁失敗時; 當發送/接收完一個位元組的數據(包括響應位)時。 ③ 基於SDA 、SCL線上時間特性的考慮,要發送數據時,先將數據寫入IICDS寄存器, 然後清除中斷。 ④ 如果IICCON[5] = 0,IICCON[4]將不能正常工作。所以即使不使用IIC中斷,也要將 IICCON[5]設為1。 (2)IICSTAT寄存器(Multi-master IIC-bus control/status)。 IICSTAT寄存器用於選擇IIC介面的工作模式,發出S信號、P信號,使能接收/發送功能, 並標識各種狀態,比如匯流排仲裁是否成功、作為從機時是否被定址、是否接收到0地址、是 否接收到ACK信號等。 IICSTAT寄存器的各位如表12.3所示: (3)IICADD寄存器(Multi-master IIC-bus address) 用到位[7:1],表示從機地址。在IICSTAT[4]為1時,才可以寫入;隨時都可以讀出。 (4)IICDS寄存器(Multi-master IIC-bus Tx/Rx data shift) 用到位[7:0],其中保存的是要發送或已經接收到的數據。在IICSTAT[4]為1時才可寫入, 隨時可以讀出。 2.S3C2410/S3C2440 I2C匯流排操作方法 啟動或複位S3C2410/S3C2440 的IIC傳輸有以下兩種方法。 (1)當IICCON[4]即中斷狀態位為0時,通過寫IICSTAT寄存器啟動IIC操作。有以下兩種 情況。 ① 在主機模式: 令IICSTAT[5:4]等於0b11,將發出S信號和IICDS寄存器的數據(定址), 令IICSTAT[5:4]等於0b01,將發出P信號。 ② 在從機模式,令IICSTAT[4]等於1,將等待其他主機發出S信號及地址信息。 (2)當IICCON[4]即中斷狀態位為1時,表示I2C操作被暫停。在這期間設置好其他寄存器 之後,向IICCON[4]寫入0即可恢復I2C操作。 所謂“設置其他寄存器”,有以下3種情況。 ① 對於主機模式,可以按照上面(1)的方法寫IICSTAT寄存器,恢復I2C操作後即可發出 S信號和IICDS寄存器的值(定址),或發出P信號。 ② 對於發送器,可以將下一個要發送的數據寫入IICDS寄存器中,恢復I2C操作後即可發 出這個數據。 ③ 對於接收器,可以從IICDS寄存器中讀出接收到的數據。最後向IICCON[4]寫入0的同時, 設置IICCON[7]以決定在接收到下一個數據後是否發出ACK信號。 通過中斷服務程式驅動I2C傳輸。 (1)當仲裁失敗時,發生中斷——本次傳輸沒有搶到匯流排,可以稍後繼續。 (2)對於主機模式,當發出S信號、地址信息並經過一個SCL周期(對應ACK信號)後,發生 中斷——主機可在此時判斷是否成功定址到從機。 (3)對於從機模式,當接收到的地址與IICADD寄存器吻合時,先發出ACK信號,然後發生 中斷——從機可在此時準備後續的傳輸。 (4)對於發送器,當發送完一個數據並經過一個SCL周期(對應ACK信號)後,發生中斷。這 時可以準備下一個要發送的數據,或發出P信號以停止傳輸。 (5)對於接收器,當接收到一個數據時,先根據IICCON[7]決定是否發出ACK信號後,然後 發生中斷。這是可以讀取IICDS寄存器得到數據,並設置IICCON[7]已決定接收到下一個數據 後是否發出ACK。 對於4種工作模式,S3C2410/S3C2440數據手冊中都有它們的操作流程圖。現在以主機發 送器為例說明,它的工作流程如圖12.7所示,其他的工作模式請參考數據手冊。
下麵結合I2C寄存器的用法,詳細講解圖12.7中各步驟的含義。 (1)配置主機發送器的各類參數 設置GPE15、GPE14引腳用於SDA、SCL,設置IICCON寄存器選擇I2C發送時鐘,最後, 設置IICSTAT[4]為1,這樣,後面才能寫IICDS寄存器。 註意:初始時IICCON[4]為0,不能將IICSTAT設為主機模式,否則就會立刻發出S信號、 發送IICDS寄存器里的值。 (2)將要定址的從機地址寫入IICDS寄存器。 (3)將0xF0寫入IICSTAT寄存器,即設為主機發送器、使能串列輸出功能、發出S信號。 (4)發出S信號後,步驟(2)中設置的IICDS寄存器值也將被髮出,它用來定址從機。 (5)在響應周期之後,發生中斷,此時IICCON[4]為1,I2C傳輸暫停。 (6)如果沒有數據要發送,則跳到步驟(10);否則跳到步驟(7)。 (7)將下一個要發送的數據寫入IICDS寄存器中。 (8)向IICCON[4]中寫入0,恢復I2C傳輸。 (9)這時,IICDS寄存器中的值將被一位一位地發送出去。當8位數據發送完畢,再經過 另一個SCL周期(對應ACK信號)後,中斷再次發生,跳到步驟(5)。 步驟(5)~(9)不斷迴圈知道發出所有數據。當要停止傳輸時,跳到步驟(10)。 (10)將0xF0寫入IICSTAT寄存器,即設為主機發送器、使能串列輸出功能、發出P信號。 註意:這時的P信號並沒有實際發出,只有清除了IICCON[4]後才會發出P信號。 (11)清除IICCON[4],P信號得以發出。 (12)等待一段時間,使得P信號完全發出。 12.2 I2C匯流排操作實例 12.2.1 I2C介面RTC晶元M41t11的操作方法 本書所用開發板中,通過I2C匯流排連接RTC(實時時鐘)晶元M4lt11,它使用電池供電,系 統斷電時也可以維持日期和時間。S3C2410/S3C2440作為I2C主機向M4lt11發送數據以設 置日期和時間、讀取M4lt11以獲取日期和時間。連接圖如圖12.8所示。 M4lt11中有8個寄存器,分別對應秒、分、時、天(星期幾)、日、月、年、控制寄存器, 其中的數據都是以BCD格式保存(BCD格式例子:0x15表示數值15),如表12.4所示。 除上表的8個寄存器(地址為0~7)之外,M4lt11內部還有56位元組的RAM(地址為8~63)。 訪問M4lt11前,先設置寄存器地址,以後每次讀寫操作完成後,M4lt11內部會自動將寄 存器地址加1. 所以讀寫M4lt11分以下兩個步驟: (1)主機向M4lt11發出要操作的寄存器起始地址(0~7)。 (2)要設置M4lt11時,主機連續發出數據;讀取M4lt11時,主機連續讀取數據。 M4lt11的I2C從機地址為0xD0。 12.2.2 程式設計 本實例將在串口上輸出一個菜單,可以選擇設置時間和日期,或者將它們讀出來。將 通過本實例驗證I2C主機的發送、接收操作。 12.2.3 設置/讀取M4lt11的源碼詳解 本實例的源碼在/work/hardware/i2c目錄下。 文件i2c.c封裝了S3C2410/S3C2440作為主機發送器、主機接收器的4個操作函數: i2c_init用於初始化,i2c_write用於發起發送數據,i2c_read用於發起讀取數據, I2CIntHandle是I2C中斷服務程式,用於完成後續的數據傳輸。 1.S3C2410/S3C2440 I2C控制器初始化 i2c_init函數對應於圖12.7中的步驟(1),初始化I2C,代碼如下:
1 行號 2 24行/* 3 25行 *I2C初始化 4 26行 */ 5 27行 void i2c_init(void) 6 28行 { 7 29行 GPEUP |= 0xc000; //禁止內部上拉 8 30行 GPECON |= 0xa0000000; //選擇引腳功能,GPE15:IICSDA,GPE14:IICSCL 9 31行 10 32行 INTMSK &= ~(BIT_IIC); 11 33行 12 34行 /*bit[7] = 1,使能ACK 13 35行 *bit[6] = 0,IICCLK = PCLK/16 14 36行 *bit[5] = 1,使能中斷 15 37行 *bit[3:0] = 0xf,Tx clock = IICCLK/16 16 38行 *PCLK = 50MHz、IICCLK = 3.125MHz,Tx Clock = 0.195MHz 17 39行 */ 18 40行 IICCON = (1 << 7) | (0 << 6) | (1 << 5) | (0xf); //0xaf 19 41行 20 42行 IICADD = 0x10; //S3C24xx slave address = [7:1] 21 43行 IICSTAT = 0x10; //I2C串列輸出使能(Rx/Tx) 22 44行 } 23 45行i2c.c->i2c_init() 第32行在INTMSK寄存器中開啟I2C中斷,這樣,以後調用i2c_read、i2c_write啟動傳 輸時,即可觸發中斷,進而可以在中斷服務程式中進一步完成後續的傳輸。 第40行用於選擇發送時鐘,併進行一些設置:使能ACK、使能中斷。 第42行用於設置S3C2410/S3C2440作為I2C從機時的地址,本實例未用到。 第43行使能I2C串列輸出(設置IICSTAT[4]為1),這樣,在i2c_write、i2c_read 函數中就可以寫IICDS寄存器了。 2.S3C2410/S3C2440 I2C主機發送函數 初始化完成後,就可以調用i2c_read、i2c_write讀寫I2C從機了。它們的使用方法從參數 名稱就可以看出。這兩個函數只是啟動I2C傳輸,然後等待,知道數據在中斷服務程式中傳 輸完畢後再返回。 i2c_write函數的實現如下:
1 行號 2 46行 /* 3 47行 *主機發送 4 48行 *slvAddr:從機地址,buf:數據存放的緩衝區,len:數據長度 5 49行 */ 6 50行 void i2c_write(unsigned int slvAddr, unsigned char *buf, int len) 7 51行 { 8 52行 g_tS3C24xx_I2C.Mode = WRDATA; //寫操作 9 53行 g_tS3C24xx_I2C.Pt = 0; //索引值初始化為0 10 54行 g_tS3C24xx_I2C.pDATA = buf; //保存緩衝區地址 11 55行 g_tS3C24xx_I2C.DataCount = len; //傳輸長度 12 56行 13 57行 IICDS = slvAddr; 14 58行 IICSTAT = 0xf0; //主機發送、啟動 15 59行 16 60行 /*等待直至數據傳輸完畢*/ 17 61行 while(g_tS3C24xx_I2C.DataCount != -1); 18 62行 } 19 63行i2c.c->i2c_write() 第57行將從機地址寫入IICDS寄存器,這樣,在第58行啟動傳輸併發出S信號後,緊接 著就自動發出從機地址。 第58行設置IICSTAT寄存器,將S3C2410/S3C2440設為主機發送器,併發出S信號。 後續的傳輸工作將在中斷服務程式中完成。 第61行等待g_tS3C24xx_I2C.DataCount在中斷服務程式中被設為-1,這表明傳輸完成, 於是返回。 3.S3C2410/S3C2440 I2C主機接收函數 i2c_read函數的實現與i2c_write類似,代碼如下:
1 行號 2 64行 /* 3 65行 *主機接收 4 66行 *slvAddr:從機地址,buf:數據存放的緩衝區,len:數據長度 5 67行 */ 6 68行 void i2c_read(unsigned int alvAddr, unsigned char *buf, int len) 7 69行 { 8 70行 g_tS3C24xx_I2C.Mode = RDDATA; //讀操作 9 71行 g_tS3C24xx_I2C.Pt = -1; //索引值初始化為-1,表示第一個中斷時不接收數據(地址中斷) 10 72行 g_tS3C24xx_I2C.pData = buf; //保存緩衝區地址 11 73行 g_tS3C24xx_I2C.DataCount = len; //傳輸長度 12 74行 13 75行 IICDS = slvAddr; 14 76行 IICSTAT = 0xb0; //主機接收,啟動 15 77行 16 78行 /*等待直至數據傳輸完畢*/ 17 79行 while(g_tS3C24xx_I2C.DataCount != -1); 18 80行 } 19 81行i2c.c->i2c_read() 需要註意的是第71行將索引值設為-1,在中斷處理函數中會根據這個值決定是否從 IICDS寄存器中讀取數據。讀操作時,第1次中斷發生時表示發出了地址,這時候不能 讀取數據。
4.S3C2410/S3C2440 I2C中斷服務程式 I2C操作的主體在中斷服務程式,它分為3部分:首先在SRCPND、INTPND中清除中 斷,後面兩部分對應於寫操作和讀操作。先看清除中斷的代碼:
1 行號 2 82行 /* 3 83行 *I2C中斷服務程式 4 84行 *根據剩餘的數據長度選擇繼續傳輸或者結束 5 85行 */ 6 86行 void I2CInitHandle(void) 7 87行 { 8 88行 unsigned int iicSt, i; 9 89行 10 90行 //清中斷 11 91行 SRCPND = BIT_IIC; 12 92行 INTPND = BIT_IIC; 13 93行 14 94行 iicSt = IICSTAT; 15 95行 16 96行 if(iicSt & 0x8){printf("Bus arbitration failed\n\r");} //仲裁失敗i2c.c->I2CInitHandle() 第91、92行用來清除I2C中斷的代碼。需要註意的是,即使清除中斷後,IICCON寄存器 中的位[4](中斷標識位)仍為1,這導致I2C傳輸暫停。 第94行讀取狀態寄存器IICSTAT,發生中斷時有可能時因為仲裁失敗,在第96行對它進行 處理。本程式忽略仲裁失敗,因為只有一個I2C主機。 接下來是一個switch語句,分別處理寫操作、讀操作。先看寫操作:
1 行號 2 98行 switch(g_tS3C24xx_I2C.Mode) 3 99行 { 4 100行 case WRDATA: 5 101行 { 6 102行 if((g_tS3C24xx_I2C.DataCount--) == 0) 7 103行 { 8 104行 //下麵兩行用於恢復I2C操作,發出P信號 9 105行 IICSTAT = 0xd0; 10 106行 IICCON = 0xaf; 11 107行 Delay(10000); //等待一段時間以便P信號已經發出 12 108行 break; 13 109行 } 14 110行 15 111行 IICDS = g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++]; 16 112行 17 113行 //將數據寫入IICDS後,需要一段時間才能出現在SDA線上 18 114行 for(i = 0; i < 10; i++); 19 115行 20 116行 IICCON = 0xaf; //恢復I2C傳輸 21 117行 break; 22 118行 } 23 119行i2c.c->I2CInitHandle()->switch()->case WRDATA g_tS3C24xx_I2C.DataCount表示剩餘等待傳輸的數據個數,第102行判斷數據是否已經 全部發送完畢:若是,則通過第105、106行發出P信號,停止傳輸; 第105行設置IICSTAT寄存器以便發出P信號,但是由於這時IICCON[4]仍為1,P信號還沒 有實際發出; 當第106行清除IICCON[4]後,P信號才真正發出去; 第107行等待一段時間,確保P信號已經發送完畢。 如果數據還沒有發送完畢,第111行從緩衝區中得到下一個要發送的數據,將它寫入IICDS 寄存器中。稍等之後,即可在第116行清除IICCON[4]以恢復I2C傳輸,這時,IICDS寄存器中
的數據就會發送出去,這將觸發下一個中斷。 I2C讀操作的處理與寫操作相似,代碼如下:
1 行號 2 120行 case RDDATA: 3 121行 { 4 122行 if(g_tS3C24xx_I2C.Pt == -1) 5 123行 { 6 124行 //這次中斷時在發送I2C設備地址後發生的,沒有數據 7 125行 //只接收一個數據時,不要發出ACK信號 8 126行 g_tS3C24xx_I2C.Pt = 0; 9 127行 if(g_tS3C24xx_I2C.DataCount == 1) 10 128行 IICCON = 0x2f; //恢復I2C傳輸,開始接收數據,接收到數據時不發出ACK 11 129行 else 12 130行 IICCON = 0xaf; //恢復I2C傳輸,開始接收數據 13 131行 break; 14 132行 } 15 133行 16 134行 if((g_tS3C24xx_I2C.DataCount--) == 0) 17 135行 { 18 136行 g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS; 19 137行 20 138行 //下麵兩行恢復I2C操作,發出P信號 21 139行 IICSTAT = 0x90; 22 140行 IICCON = 0xaf; 23 141行 Delay(10000); //等待一段時間以便P信號已經發出 24 142行 break; 25 143行 } 26 144行 27 145行 g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS; 28 146行 29 147行 //接收最後一個數據時,不要發出ACK信號 30 148行 if(g_tS3C24xx_I2C.DataCount == 0) 31 149行 IICCON = 0x2f; //恢復I2C傳輸,接收到下一個數據時無ACK 32 150行 else 33 151行 IICCON = 0xaf; //恢復I2C傳輸,接收到下一個數據時發出ACK 34 152行 break; 35 153行 }case RDDATA 讀操作比寫操作多一個步驟:第一次中斷發生時,表示發出了地址,這時候還不能讀取 數據。在代碼中要分辨這點。對應第122~132行:如果g_tS3C24xx_I2C.Pt等於-1,表示 這是第一次中斷,然後修改g_tS3C24xx_I2C.Pt為0,並設置IICCON寄存器恢復I2C傳輸 (第127~130行)。 當數據傳輸已經開始後,每接收到一個數據就會觸發一次中斷。後面的代碼讀取數據, 判斷所有數據是否已經完成:如果完成則發出P信號,否則繼續下一次傳輸。 第134行判斷數據是否已經發送完畢。 第19行設置IICSTAT寄存器以便發出P信號,但是由於這時IICCON[4]仍為1,P信號還沒 有實際發出。 第140行清除IICCON[4]後,P信號才真正發出。 第145~151行用來啟動下一次數據的接收。 第148~151行判斷是否只剩下最後一個數據了:若是,則通過第149行的清除IICCON[4]、 IICCON[7],這樣即可恢復IIC傳輸,並使得接收到數據後,S3C2410/S3C2440不發出ACK 信號(這樣從機即可知道數據傳輸完畢);否則在第151行中只要清除IICCON[4]以恢復IIC傳輸。 中斷服務程式中,當數據數據傳輸完畢時,g_tS3C24xx_I2C.DataCount將自減為-1,這樣, i2c_read或i2C_write函數即可跳出等待,直接返回。 5.RTC晶元M4lt11特性相關的操作 m4lt11.c文件中提供兩個函數m4lt11_set_datetime、m4lt11_get_datetime。它們都通過調 用i2c_read或i2c_write函數來完成與M4lt11的交互。 前面說過,操作M4lt11只需要兩步:發出寄存器地址,發出數據或讀取數據。 m4lt11_set_datetime函數把這兩個步驟合併為一個I2C寫操作,m4lt11_get_datetime函數先發 起一個I2C寫傳輸,再發起一個I2C讀傳輸。 m4lt11_set_datetime函數代碼如下:
1 行號 2 29行 /* 3 30行 *寫m4lt11,設置日期和時間 4 31行 */ 5 32行 int m4lt11_set_datetime(struct rtc_time *dt) 6 33行 { 7 34行 unsigned char leap_yr; 8 35行 struct{ 9 36行 unsigned char addr; 10 37行 struct rtc_registers rtc; 11 38行 }__attribute__ ((packed)) addr_and_regs; 12 ... .../*設置rtc結構,即根據傳入的參數構造各寄存器的值*/ 13 76行 i2c_write(0xD0, (unsigned char *)&addr_and_regs, sizeof(addr_and_regs)); 14 77行 15 78行 return 0; 16 79行 }m4lt11.c->m4lt11_set_datetime() 省略號表示的代碼用來設置addr_and_regs結構體。這個結構體分為兩部分: addr_and_regs表示M4lt11寄存器地址(它被設為0); addr_and_regs.rtc表示M4lt11的8個寄存器——秒、分、時、天(星期幾)、日、月、年、控制寄存器。 根據傳入參數填充好addr_and_regs結構體後,就可以啟動I2C寫操作了。 第38行使用“__attribute__((packed))”設置這個結構體為緊湊格式。使得它的大小 為9位元組(否則大小為12位元組):1位元組用來保存寄存器的地址,8位元組用來保存8個寄存器的值。 m4lt11_get_datetime函數的代碼與m4lt11_set_datetime函數類似,如下所示:
1 行號 2 81行 /* 3 82行 *讀取m4lt11,獲取日期與時間 4 83行 */ 5 84行 int m4lt11_get_datetime(struct rtc_time *dt) 6 85行 { 7 86行 unsigned char addr[1] = {0}; 8 87行 struct rtc_registers rtc; 9 88行 10 89行 memset(&rtc, 0, sizeof(rtc)); 11 90行 12 91行 i2c_write(0xD0, addr, 1); 13 92行 i2c_read(0xD0, (unsigned char *)&rtc, sizeof(rtc)); 14 93行 15 ... .../*根據讀出的各寄存器的值,設置dr結構體*/ 16 110行 return 0; 17 111行 }m4lt11.c->m4lt11_get_datetime() 第91行發起一次I2C寫傳輸,設置要操作的M4lt11寄存器地址為0; 第92行發起一次I2C讀傳輸,讀出M4lt11各寄存器的值; 省略號對應的代碼根據讀出的各寄存器的值,設置dr結構。M4lt11中以BCD碼表示 日期與時間,需要轉換為程式使用的一般二進位格式。 12.2.4 I2C實例的連接腳本 本實例要用到第8章NAND Flash控制器的代碼將代碼從NAND Flash複製到SDRAM 中。由於nand代碼中用到全局變數,而全局變數要運行與可讀寫的記憶體中,為了方便, 使用連接腳本將這些初始代碼放到Steppingstone中。 連接腳本為i2c.lds,內容如下:
1 SECTIONS{ 2 . = 0x00000000; 3 .init : AT(0){head.o init.o nand.o} 4 . = 0x30000000; 5 .text : AT(4096){ *(.text)} 6 .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)){*(.rodata*)} 7 .data ALIGN(4) :AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)){*(.data)} 8 __bss_start = .; 9 .bss ALIGN(4) :{ *(.bss) *(COMMON)} 10 __bss_end = .; 11 }i2c.lds 第2~3行將head.S和nand.c對應的代碼的運行地址設為0,載入地址(存在NAND Flash 上的地址)設為0。從NAND Flash啟動時,這些代碼被覆制到Steppingstone後就可以直接運行。
第4行設置其餘代碼的運行地址為0x3000 0000;第5行將代碼段的載入地址設為4096, 表示代碼段將存在NAND Flash地址4096處。 第6~7行的“AT(...)”設置rodata段、data段的載入地址依次位於代碼段之後。 “LOADADDR(...)”表示某段的載入地址,SIZEOF(...)表示它的大小。這兩行的前面使用 “ALIGN(4)”使得它們的運行地址為4位元組對齊。為了使各段之間載入地址的相應偏移值等於 地址的相對偏移,需要將“AT(...)”中的值也設為4位元組對齊:先加上3,然後與~(0x03)進 行與操作(將低2位清0)。 12.2.5 實例測試 本程式在main函數中通過串口輸出一個菜單,用於設置或讀取時間,步驟如下: (1)使用串口將開發板的COM0和PC的串口相連,打開PC的穿褲工具設為115200、8N1; (2)在i2c目錄下執行make,將可執行文件燒入NAND Flash中運行; (3)在PC的串口工具上,可以看到如下菜單:
#### RTC Menu #### Data format: 'year.month.day w hour:min:sec', 'w' is week day eg:2007.08.30 4 01:16:57 [S] Set the RTC [R] Read the RTC Enter your selection:(4)要設置RTC,輸入"s"或“S”。可以看到如下字元。
Enter data&time:在串口工具中按照"year.month.day w hour:min:sec"格式輸入日期與時間,比如:"2007.08.30 4 01:16:57",然後按回車鍵。 註意:只能輸入2000.01.1至2099.12.31之間的日期與時間;年月日與星期必須真實存 在,否則RTC晶元無法正常工作。 (5)要可讀取RTC,輸入"r"或"R",即可看到當前日期與時間,串口上回輸出類似 下麵的結果。
*** Now is: 2007.08.30 4 01:16:57 ***(6)斷電後重啟,輸入“R”,仍可看到正確的時間。 附:代碼: 鏈接: https://pan.baidu.com/s/1kV24a9L 密碼: tfab