|
關(guān)于IIC通信詳解及PCF8563芯片顯示時間數(shù)據(jù)
這一節(jié),我們的程序代碼主要是將PCF8563芯片采集到的時間數(shù)據(jù)顯示在數(shù)碼管上,但是在完成這個任務(wù)之前,我們先來看下IIC協(xié)議,了解這個協(xié)議很重要,沒辦法,IIC確實讓人稀里糊涂的,先把PCF8563部分的代碼貼出來,然后我們對照PCF8563的數(shù)據(jù)手冊來看IIC的底層讀寫是怎么實現(xiàn)的。代碼如下:解釋看下面文字,我們的重點不是PCF8563這個芯片,而是IIC協(xié)議,這個代碼也是我整理網(wǎng)上的,先把數(shù)據(jù)手冊上傳
PCF8563數(shù)據(jù)手冊.pdf
(630.02 KB, 下載次數(shù): 233)
2018-10-13 09:41 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
- /*******************************************************************************
- * 文件名:PCF8563.c
- * 描 述:工程c模塊文件
- * 功 能:底層模塊文件
- * 作者:MADE BY DA HE TAO
- * 版本號:1.0.4(2015.03.02)
- *******************************************************************************/
- #define _PCF8563_C
- #include "main.h"
- /*******************************************************************************
- * 文件名:變量定義
- * 描 述:
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- uint8 buffer[7];//數(shù)據(jù)存儲緩存
- sTime CurTime;
- /*******************************************************************************
- * 文件名:void IIC_Delay()
- * 描 述:
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Delay()
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- /*******************************************************************************
- * 文件名:void IIC_Start(void)
- * 描 述: IIC啟動
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Start(void)
- {
- IIC_SDA = 1; //為SDA下降啟動做準(zhǔn)備
- IIC_SCL = 1; //在SCL高電平時,SDA為下降沿時候總線啟動
- IIC_Delay();
- IIC_SDA = 0; //突變,總線啟動
- IIC_Delay();
- IIC_SCL = 0;
- IIC_Delay();
- }
- /*******************************************************************************
- * 文件名:void IIC_Stop(void)
- * 描 述: IIC停止
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Stop(void)
- {
- IIC_SDA = 0; //為SDA上升做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 1; //在SCL高電平時,SDA為上升沿時候總線停止
- IIC_Delay();
- IIC_SDA = 1; //突變,總線停止
- IIC_Delay();
- }
- /*******************************************************************************
- * 文件名:void IIC_Ack(u8 a)
- * 描 述: 主機(jī)向從機(jī)發(fā)送應(yīng)答信號
- * 功 能:0:應(yīng)答信號 1:非應(yīng)答信號
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Ack(bit a)
- {
- if(a) IIC_SDA = 1; //放上應(yīng)答信號電平
- else IIC_SDA = 0;
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 0; //突變,將應(yīng)答信號發(fā)送過去
- IIC_Delay();
- }
- /*******************************************************************************
- * 文件名:u8 IIC_Write_Byte(u8 dat)
- * 描 述: 向IIC總線發(fā)送一個字節(jié)數(shù)據(jù)
- * 功 能:dat:要發(fā)送的數(shù)據(jù) ack:返回應(yīng)答信號
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- uint8 IIC_Write_Byte(uint8 dat)
- {
- uint8 iic_ack=0; //iic應(yīng)答標(biāo)志
- uint8 mask = 0;
- // for(i = 0;i < 8;i++)
- // {
- // if(dat & 0x80) IIC_SDA = 1; //判斷發(fā)送位,先發(fā)送高位
- // else IIC_SDA = 0;
- // IIC_Delay();
- // IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- // IIC_Delay();
- // IIC_SCL = 0; //突變,將數(shù)據(jù)位發(fā)送過去
- // dat<<=1; //數(shù)據(jù)左移一位
- // } //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
- for(mask = 0x80; mask!= 0x00; mask >>= 1)
- {
- if(mask & dat)
- {
- IIC_SDA = 1;
- }
- else
- {
- IIC_SDA = 0;
- }
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 0; //突變,將數(shù)據(jù)位發(fā)送過去
- }
- IIC_SDA = 1; //釋放數(shù)據(jù)線
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
-
- iic_ack |= IIC_SDA; //讀入應(yīng)答位
- IIC_SCL = 0;
- return iic_ack; //返回應(yīng)答信號
- }
- /*******************************************************************************
- * 文件名:u8 IIC_Read_Byte(void)
- * 描 述: 從IIC總線上讀取一個字節(jié)數(shù)據(jù)
- * 功 能:x:讀取到的數(shù)據(jù)
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- uint8 IIC_Read_Byte(void)
- {
- uint8 x=0;
- uint8 mask;
- IIC_SDA = 1; //首先置數(shù)據(jù)線為高電平
- // for(i = 0;i < 8;i++)
- // {
- // x <<= 1; //讀入數(shù)據(jù),高位在前
- // IIC_Delay();
- // IIC_SCL = 1; //突變
- // IIC_Delay();
- //
- // if(IIC_SDA)
- // x |= 0x01; //收到高電平
- //
- // IIC_SCL = 0;
- // IIC_Delay();
- // } //數(shù)據(jù)接收完成
- for(mask = 0x80; mask != 0x00; mask >>= 1)
- {
- IIC_Delay();
- IIC_SCL = 1; //突變
- IIC_Delay();
- if(IIC_SDA)
- {
- x |= mask;
- }
- else
- {
- x &= ~mask;//
- }
- IIC_SCL = 0;
- IIC_Delay();
- }
- IIC_SCL = 0;
- return x; //返回讀取到的數(shù)據(jù)
- }
- /*******************************************************************************
- * 文件名:static unsigned char RTC_BinToBcd2(unsigned char BINValue)
- * 描 述: 將BIN轉(zhuǎn)換為BCD
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- static unsigned char RTC_BinToBcd2(unsigned char BINValue)
- {
- unsigned char bcdhigh = 0;
-
- while (BINValue >= 10)
- {
- bcdhigh++;
- BINValue -= 10;
- }
-
- return ((unsigned char)(bcdhigh << 4) | BINValue);
- }
- /*******************************************************************************
- * 文件名:static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
- * 描 述: 將BCD轉(zhuǎn)換為BIN
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
- {
- unsigned char tmp = 0;
-
- tmp = ((unsigned char)(BCDValue & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
- return (tmp + (BCDValue & (unsigned char)0x0F));
- }
- /*******************************************************************************
- * 文件名:void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
- * 描 述: PCF8563某寄存器寫入一個字節(jié)數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器地址 dat: 要寫入的數(shù)據(jù)
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
- {
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD);
- IIC_Write_Byte(dat); //發(fā)送數(shù)據(jù)
- }
- IIC_Stop();
- }
- /*******************************************************************************
- * 文件名:unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
- * 描 述: PCF8563某寄存器讀取一個字節(jié)數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器地址 讀取得到的寄存器的值
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
- {
- unsigned char ReData;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //確定要操作的寄存器
- IIC_Start(); //重啟總線
- IIC_Write_Byte(0xa3); //發(fā)送讀取命令
- ReData = IIC_Read_Byte(); //讀取數(shù)據(jù)
- IIC_Ack(1); //發(fā)送非應(yīng)答信號結(jié)束數(shù)據(jù)傳送
- }
- IIC_Stop();
- return ReData;
- }
- /*******************************************************************************
- * 文件名:void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- * 描 述: PCF8563寫入多組數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器起始地址 num: 寫入數(shù)據(jù)數(shù)量 *WBuff: 寫入數(shù)據(jù)緩存
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- {
- unsigned char i = 0;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
- for(i = 0;i < num;i++)
- {
- IIC_Write_Byte(*pBuff); //寫入數(shù)據(jù)
- pBuff++;
- }
- }
- IIC_Stop();
- }
- /*******************************************************************************
- * 文件名:void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- * 描 述: PCF8563讀取多組數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器起始地址 num: 寫入數(shù)據(jù)數(shù)量 *WBuff: 讀取數(shù)據(jù)緩存
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- {
- unsigned char i = 0;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
- IIC_Start(); //重啟總線
- IIC_Write_Byte(0xa3); //發(fā)送讀取命令
- for(i = 0;i < num;i++)
- {
- *pBuff = IIC_Read_Byte(); //讀取數(shù)據(jù)
- if(i == (num - 1)) IIC_Ack(1); //發(fā)送非應(yīng)答信號
- else IIC_Ack(0); //發(fā)送應(yīng)答信號
- pBuff++;
- }
- }
- IIC_Stop();
- }
- /*******************************************************************************
- * 文件名:void SetRealTime(sTime* time)
- * 描 述: PCF8563設(shè)置時間信息
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void SetRealTime(sTime* time)
- {
- //
- //拷貝數(shù)據(jù)
- time->mon &= ~PCF_Century_SetBitC;
- buffer[0] = time->sec;
- buffer[1] = time->min;
- buffer[2] = time->hour;
- buffer[3] = time->day;
- buffer[4] = time->week;
- buffer[5] = time->mon;
- buffer[6] = time->year;
- //寫入數(shù)據(jù)到寄存器
- //
- PCF8563_Write_nByte(PCF8563_Address_Seconds, 7, buffer);
- }
- /*******************************************************************************
- * 文件名:void GetRealTime(sTime* time)
- * 描 述: PCF8563讀取時間信息
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void GetRealTime(sTime* time)
- {
- PCF8563_Read_nByte(PCF8563_Address_Seconds, 7, buffer); //讀取寄存器數(shù)值
- buffer[0] &= PCF8563_Shield_Seconds; //屏蔽無效位
- buffer[1] &= PCF8563_Shield_Minutes;
- buffer[2] &= PCF8563_Shield_Hours;
- buffer[3] &= PCF8563_Shield_Days;
- buffer[4] &= PCF8563_Shield_WeekDays;
- buffer[5] &= PCF8563_Shield_Months_Century;
- buffer[6] &= PCF8563_Shield_Years;
-
- time->year = buffer[6];
- time->mon = buffer[5];
- time->week = buffer[4];
- time->day = buffer[3];
- time->hour = buffer[2];
- time->min = buffer[1];
- time->sec = buffer[0];
- }
- /*******************************************************************************
- * 文件名: void PCF8563Init(void)
- * 描 述: PCF8563初始化時間
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.05.23)
- *******************************************************************************/
- void PCF8563Init(void)
- {
- sTime code InitTime[] = {0x17,0x06,0x21, 0x22,0x11,0x00,0x03}; //年月日時分秒星期
- SetRealTime(&InitTime);
- }
復(fù)制代碼 打開器件的數(shù)據(jù)手冊
IIC起始和停止.JPG (213.74 KB, 下載次數(shù): 145)
下載附件
2018-10-13 09:46 上傳
關(guān)于IIC的起始信號和停止信號的定義
起始.JPG (39.35 KB, 下載次數(shù): 132)
下載附件
2018-10-13 09:56 上傳
從上圖可以看出,在SCL高電平的時候,SDA由高電平到低電平的跳變作為START信號
/*******************************************************************************
- * 文件名:void IIC_Start(void)
- * 描 述: IIC啟動
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Start(void)
- {
- IIC_SDA = 1; //為SDA下降啟動做準(zhǔn)備
- IIC_SCL = 1; //在SCL高電平時,SDA為下降沿時候總線啟動
- IIC_Delay();
- IIC_SDA = 0; //突變,總線啟動
- IIC_Delay();
- IIC_SCL = 0;
- IIC_Delay();
- }
復(fù)制代碼 再來看停止信號的定義
停止.JPG (19.61 KB, 下載次數(shù): 133)
下載附件
2018-10-13 09:57 上傳
在SCL為高電平的時候,SDA由低電平到高電平的跳變作為停止信號
- /*******************************************************************************
- * 文件名:void IIC_Stop(void)
- * 描 述: IIC停止
- * 功 能:
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Stop(void)
- {
- IIC_SDA = 0; //為SDA上升做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 1; //在SCL高電平時,SDA為上升沿時候總線停止
- IIC_Delay();
- IIC_SDA = 1; //突變,總線停止
- IIC_Delay();
- }
復(fù)制代碼 看著時序圖很容易就能夠理解的。
接下來我們看下位傳輸?shù)氖疽鈭D
IIC.JPG (201.05 KB, 下載次數(shù): 129)
下載附件
2018-10-13 10:13 上傳
從上圖可以看出,SCL為高電平的時候,SDA上的數(shù)據(jù)被認(rèn)為是有效的,是可以被讀取或者寫入的,SCL為低電平的時候,SDA的數(shù)據(jù)是不穩(wěn)定的,可以任意變化。
關(guān)于應(yīng)答信號和非應(yīng)答信號
IIC規(guī)定應(yīng)答信號是0,非應(yīng)答信號是1,如下圖所示這樣,相關(guān)程序如下:
- /*******************************************************************************
- * 文件名:void IIC_Ack(u8 a)
- * 描 述: 主機(jī)向從機(jī)發(fā)送應(yīng)答信號
- * 功 能:0:應(yīng)答信號 1:非應(yīng)答信號
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void IIC_Ack(bit a)
- {
- if(a) IIC_SDA = 1; //放上應(yīng)答信號電平
- else IIC_SDA = 0;
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 0; //突變,將應(yīng)答信號發(fā)送過去
- IIC_Delay();
- }
復(fù)制代碼
請注意這個子函數(shù)不是用來寫字節(jié)使用的,是單片機(jī)讀數(shù)據(jù)專用的,啥意思呢?單片機(jī)寫字節(jié)的時候,是從機(jī)返回的應(yīng)答位,是PCF8563主動返回的,這里的主動相當(dāng)于是一個按鍵信號,這里的IO是作為按鍵輸入了,不再是輸出信號,這也解釋了為什么很多人寫代碼,總要加一個拉高等于釋放的解釋,什么是釋放?從51單片機(jī)IO的結(jié)構(gòu)上判斷,如下圖所示,內(nèi)部總線寫一個0,在寫鎖存器的幫助下,Q會輸出一個0,Q~輸出一個1,MOS管導(dǎo)通,拉低到低電位,如果內(nèi)部總線寫一個1,MOS不導(dǎo)通,那么IO會被上拉電阻拉到高電平。這就是IO的輸出0或者1的過程。我們再來看一下輸入信號,
IO結(jié)構(gòu).JPG (26.38 KB, 下載次數(shù): 134)
下載附件
2018-10-13 10:29 上傳
如果你輸出一個0,那么單片機(jī)還能夠讀取外部信號嗎?不可能的,因為一直都是0的,就算你按下按鍵也是百搭的,所以必須要拉高,釋放掉,這樣按鍵按下的時候才會在單片機(jī)讀引腳信號的幫助下被寫入內(nèi)部總線上。這下應(yīng)該明白了吧?
剛才我們說了寫字節(jié)要返回的應(yīng)答位,那么上面這個子函數(shù)是讀字節(jié)的,誰來讀?當(dāng)然是單片機(jī)來讀啊,也就是說單片機(jī)每讀取一個字節(jié),都要向PCF8563發(fā)送一個應(yīng)答位,表示我還要讀你的數(shù)據(jù),PCF8563這邊的地址都是自動累加的,不需要管,等到單片機(jī)不想讀了,發(fā)送一個非應(yīng)答信號1,結(jié)束通信,這就是應(yīng)答和非應(yīng)答的由來。
硬打信號.JPG (193.99 KB, 下載次數(shù): 137)
下載附件
2018-10-13 10:18 上傳
接下來我們再來看下IIC總線讀寫字節(jié)函數(shù),這個很有參考意義,因為不管是啥協(xié)議,不是從高位開始讀寫就是從低位開始讀寫,具體的時序可能不一樣,但是這個實現(xiàn)的過程是比較有參考意義的,先來看IIC總線寫字節(jié)函數(shù),代碼如下
- /*******************************************************************************
- * 文件名:u8 IIC_Write_Byte(u8 dat)
- * 描 述: 向IIC總線發(fā)送一個字節(jié)數(shù)據(jù)
- * 功 能:dat:要發(fā)送的數(shù)據(jù) ack:返回應(yīng)答信號
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- uint8 IIC_Write_Byte(uint8 dat)
- {
- uint8 iic_ack=0; //iic應(yīng)答標(biāo)志
- uint8 mask = 0;
- // for(i = 0;i < 8;i++)
- // {
- // if(dat & 0x80) IIC_SDA = 1; //判斷發(fā)送位,先發(fā)送高位
- // else IIC_SDA = 0;
- // IIC_Delay();
- // IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- // IIC_Delay();
- // IIC_SCL = 0; //突變,將數(shù)據(jù)位發(fā)送過去
- // dat<<=1; //數(shù)據(jù)左移一位
- // } //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
- for(mask = 0x80; mask!= 0x00; mask >>= 1)
- {
- if(mask & dat)
- {
- IIC_SDA = 1;
- }
- else
- {
- IIC_SDA = 0;
- }
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 0; //突變,將數(shù)據(jù)位發(fā)送過去
- }
- IIC_SDA = 1; //釋放數(shù)據(jù)線
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
-
- iic_ack |= IIC_SDA; //讀入應(yīng)答位
- IIC_SCL = 0;
- return iic_ack; //返回應(yīng)答信號
- }
復(fù)制代碼 看到被注釋掉的那部分了嗎?和沒有被注釋掉的那部分的作用是一樣一樣的,這個我們先不管他,對于寫單個字節(jié),IIC是這么規(guī)定的,先從高位開始讀寫,每寫入一個字節(jié),從機(jī)要返回一個應(yīng)答位,這里的主機(jī)指的是單片機(jī),這里的從機(jī)指的是采用IIC接口的器件,比如AT24C02,PCF8563等等,也就是說單片機(jī)寫入PCF8563某寄存器一個字節(jié)后,PCF8563要主動返回一個應(yīng)答位,這個應(yīng)答位是0來表示,非應(yīng)答位用1來表示,實現(xiàn)過程看前邊關(guān)于IO的解釋。上面這2種寫字節(jié)是一樣的,先來看第一種,我們要讀一個字節(jié),總共8位數(shù)據(jù),那么,新建一個循環(huán),先從高位開始發(fā),那么,就這樣寫,如果data數(shù)據(jù)的最高位是1,那么IIC_SDA就是1,否則IIC_SDA就是0,然后就是拉高IIC_SCL讓數(shù)據(jù)保持穩(wěn)定,讓總線來接收這個信號,結(jié)束完之后,數(shù)據(jù)左移就可以了,直到把8位數(shù)據(jù)發(fā)送完畢,就是這樣。
再來看下面這種寫法
- for(mask = 0x80; mask!= 0x00; mask >>= 1)
- {
- if(mask & dat)
- {
- IIC_SDA = 1;
- }
- else
- {
- IIC_SDA = 0;
- }
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- IIC_SCL = 0; //突變,將數(shù)據(jù)位發(fā)送過去
- }
復(fù)制代碼 這種寫法是移位,先讀高位,讓位移動,而不是讓數(shù)據(jù)移動,正好移動8次,這個寫法很好,推薦給大家,很容易讓人理解,寫完8個循環(huán)之后,拉高SDA,準(zhǔn)備讀取SDA輸入的信號,就是這樣。同樣的讀字節(jié)函數(shù),請自我分析完成,一樣的道理。
- IIC_SDA = 1; //釋放數(shù)據(jù)線
- IIC_Delay();
- IIC_SCL = 1; //為SCL下降做準(zhǔn)備
- IIC_Delay();
- //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
-
- iic_ack |= IIC_SDA; //讀入應(yīng)答位
- IIC_SCL = 0;
- return iic_ack; //返回應(yīng)答信號
復(fù)制代碼 再來看下要操作PCF8563這個芯片,要遵循下面這個時序,先來看代碼
- /*******************************************************************************
- * 文件名:void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
- * 描 述: PCF8563某寄存器寫入一個字節(jié)數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器地址 dat: 要寫入的數(shù)據(jù)
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
- {
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD);
- IIC_Write_Byte(dat); //發(fā)送數(shù)據(jù)
- }
- IIC_Stop();
- }
復(fù)制代碼
IIC寫字節(jié).JPG (177.77 KB, 下載次數(shù): 129)
下載附件
2018-10-13 10:40 上傳
從上圖可以看出一個完整的寫模式包括 起始信號+設(shè)備地址+應(yīng)答信號+數(shù)據(jù)地址+應(yīng)答信號+數(shù)據(jù)+應(yīng)答信號+停止信號 組成,每寫入一個字節(jié),PCF8563都要返回一個應(yīng)答信號0,表示我正確的接收了,相當(dāng)于一個回執(zhí)。PCF8563的寫設(shè)備地址固定是0XA2,通過程序,可以很容易的理解上面的代碼了。
再來看下PCF8563讀單個字節(jié)函數(shù)
- /*******************************************************************************
- * 文件名:unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
- * 描 述: PCF8563某寄存器讀取一個字節(jié)數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器地址 讀取得到的寄存器的值
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
- {
- unsigned char ReData;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //確定要操作的寄存器
- IIC_Start(); //重啟總線
- IIC_Write_Byte(0xa3); //發(fā)送讀取命令
- ReData = IIC_Read_Byte(); //讀取數(shù)據(jù)
- IIC_Ack(1); //發(fā)送非應(yīng)答信號結(jié)束數(shù)據(jù)傳送
- }
- IIC_Stop();
- return ReData;
- }
復(fù)制代碼 我們看下他的時序圖:
讀字節(jié)時序圖.JPG (171.36 KB, 下載次數(shù): 142)
下載附件
2018-10-13 11:09 上傳
注意PCF8563讀寄存器字節(jié)的設(shè)備地址固定0XA3,按照時序圖,很容易就能夠理解這段代碼的。
寫多個字節(jié)和讀多個字節(jié)的函數(shù)也是比較容易的,唯一要注意的是時序圖中的解釋,ack from master 和ack from slave 這個一定要理解明白,寫字節(jié)對應(yīng)的是slave,是主機(jī)寫,從機(jī)返回應(yīng)答,from master 是讀字節(jié),是主機(jī)發(fā)出應(yīng)答或者非應(yīng)答,從機(jī)響應(yīng)。
- /*******************************************************************************
- * 文件名:void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- * 描 述: PCF8563寫入多組數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器起始地址 num: 寫入數(shù)據(jù)數(shù)量 *WBuff: 寫入數(shù)據(jù)緩存
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- {
- unsigned char i = 0;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
- for(i = 0;i < num;i++)
- {
- IIC_Write_Byte(*pBuff); //寫入數(shù)據(jù)
- pBuff++;
- }
- }
- IIC_Stop();
- }
- /*******************************************************************************
- * 文件名:void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- * 描 述: PCF8563讀取多組數(shù)據(jù)
- * 功 能:REG_ADD:要操作寄存器起始地址 num: 寫入數(shù)據(jù)數(shù)量 *WBuff: 讀取數(shù)據(jù)緩存
- * 作 者:大核桃
- * 版本號:1.0.1(2017.03.03)
- *******************************************************************************/
- void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
- {
- unsigned char i = 0;
-
- IIC_Start();
- if(!(IIC_Write_Byte(0xa2))) //發(fā)送寫命令并檢查應(yīng)答位
- {
- IIC_Write_Byte(REG_ADD); //定位起始寄存器地址
- IIC_Start(); //重啟總線
- IIC_Write_Byte(0xa3); //發(fā)送讀取命令
- for(i = 0;i < num;i++)
- {
- *pBuff = IIC_Read_Byte(); //讀取數(shù)據(jù)
- if(i == (num - 1)) IIC_Ack(1); //發(fā)送非應(yīng)答信號
- else IIC_Ack(0); //發(fā)送應(yīng)答信號
- pBuff++;
- }
- }
- IIC_Stop();
- }
復(fù)制代碼 好了,就到這里吧,這個程序的結(jié)果是寫入PCF8563時間信息,PCF8563讀取到的時間信息顯示在數(shù)碼管上。
代碼上傳
011 PCF8563顯示時鐘.rar
(201.48 KB, 下載次數(shù): 300)
2018-10-13 11:19 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
|