找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 20226|回復(fù): 37
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)入門經(jīng)驗分享8-關(guān)于IIC通信詳解及PCF8563芯片顯示時間

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:74187 發(fā)表于 2018-10-13 11:20 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
                                    關(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)


  1. /*******************************************************************************
  2. * 文件名:PCF8563.c
  3. * 描  述:工程c模塊文件
  4. * 功 能:底層模塊文件
  5. * 作者:MADE BY DA HE TAO
  6. * 版本號:1.0.4(2015.03.02)
  7. *******************************************************************************/
  8. #define _PCF8563_C
  9. #include "main.h"



  10. /*******************************************************************************
  11. * 文件名:變量定義
  12. * 描  述:   
  13. * 功  能:
  14. * 作  者:大核桃
  15. * 版本號:1.0.1(2017.05.23)
  16. *******************************************************************************/
  17. uint8 buffer[7];//數(shù)據(jù)存儲緩存
  18. sTime CurTime;

  19. /*******************************************************************************
  20. * 文件名:void IIC_Delay()
  21. * 描  述:
  22. * 功  能:
  23. * 作  者:大核桃
  24. * 版本號:1.0.1(2017.03.03)
  25. *******************************************************************************/
  26. void IIC_Delay()
  27. {
  28.         _nop_();
  29.         _nop_();
  30.         _nop_();
  31.         _nop_();
  32.         _nop_();
  33.         _nop_();
  34. }

  35. /*******************************************************************************
  36. * 文件名:void IIC_Start(void)
  37. * 描  述: IIC啟動
  38. * 功  能:
  39. * 作  者:大核桃
  40. * 版本號:1.0.1(2017.03.03)
  41. *******************************************************************************/
  42. void IIC_Start(void)
  43. {
  44.         IIC_SDA = 1;        //為SDA下降啟動做準(zhǔn)備
  45.         IIC_SCL = 1;        //在SCL高電平時,SDA為下降沿時候總線啟動

  46.         IIC_Delay();
  47.         IIC_SDA = 0;        //突變,總線啟動
  48.         IIC_Delay();
  49.         IIC_SCL = 0;
  50.         IIC_Delay();
  51. }

  52. /*******************************************************************************
  53. * 文件名:void IIC_Stop(void)
  54. * 描  述: IIC停止
  55. * 功  能:
  56. * 作  者:大核桃
  57. * 版本號:1.0.1(2017.03.03)
  58. *******************************************************************************/
  59. void IIC_Stop(void)
  60. {
  61.         IIC_SDA = 0;        //為SDA上升做準(zhǔn)備

  62.         IIC_Delay();
  63.         IIC_SCL = 1;        //在SCL高電平時,SDA為上升沿時候總線停止
  64.         IIC_Delay();
  65.         IIC_SDA = 1;        //突變,總線停止
  66.         IIC_Delay();
  67. }
  68. /*******************************************************************************
  69. * 文件名:void IIC_Ack(u8 a)
  70. * 描  述: 主機(jī)向從機(jī)發(fā)送應(yīng)答信號
  71. * 功  能:0:應(yīng)答信號 1:非應(yīng)答信號
  72. * 作  者:大核桃
  73. * 版本號:1.0.1(2017.03.03)
  74. *******************************************************************************/
  75. void IIC_Ack(bit a)
  76. {                        
  77.         if(a)        IIC_SDA = 1;        //放上應(yīng)答信號電平
  78.         else        IIC_SDA = 0;

  79.         IIC_Delay();
  80.         IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  81.         IIC_Delay();
  82.         IIC_SCL = 0;        //突變,將應(yīng)答信號發(fā)送過去
  83.         IIC_Delay();
  84. }

  85. /*******************************************************************************
  86. * 文件名:u8 IIC_Write_Byte(u8 dat)
  87. * 描  述: 向IIC總線發(fā)送一個字節(jié)數(shù)據(jù)
  88. * 功  能:dat:要發(fā)送的數(shù)據(jù)          ack:返回應(yīng)答信號
  89. * 作  者:大核桃
  90. * 版本號:1.0.1(2017.03.03)
  91. *******************************************************************************/
  92. uint8 IIC_Write_Byte(uint8 dat)
  93. {
  94.         uint8 iic_ack=0;        //iic應(yīng)答標(biāo)志
  95.         uint8 mask = 0;

  96. //        for(i = 0;i < 8;i++)
  97. //        {
  98. //                if(dat & 0x80)        IIC_SDA = 1;        //判斷發(fā)送位,先發(fā)送高位
  99. //                else        IIC_SDA = 0;
  100. //                IIC_Delay();
  101. //                IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  102. //                IIC_Delay();
  103. //                IIC_SCL = 0;        //突變,將數(shù)據(jù)位發(fā)送過去
  104. //                dat<<=1;        //數(shù)據(jù)左移一位
  105. //        }        //字節(jié)發(fā)送完成,開始接收應(yīng)答信號

  106.         for(mask = 0x80; mask!= 0x00; mask >>= 1)
  107.         {
  108.                 if(mask & dat)
  109.                 {
  110.                   IIC_SDA = 1;        
  111.                 }
  112.                 else
  113.                 {
  114.                         IIC_SDA = 0;
  115.                 }

  116.                 IIC_Delay();
  117.                 IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  118.                 IIC_Delay();
  119.                 IIC_SCL = 0;        //突變,將數(shù)據(jù)位發(fā)送過去


  120.         }

  121.         IIC_SDA = 1;        //釋放數(shù)據(jù)線
  122.         IIC_Delay();
  123.         IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  124.         IIC_Delay();
  125.         //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
  126.         
  127.         iic_ack |= IIC_SDA;        //讀入應(yīng)答位
  128.         IIC_SCL = 0;
  129.         return iic_ack;        //返回應(yīng)答信號
  130. }
  131. /*******************************************************************************
  132. * 文件名:u8 IIC_Read_Byte(void)
  133. * 描  述: 從IIC總線上讀取一個字節(jié)數(shù)據(jù)
  134. * 功  能:x:讀取到的數(shù)據(jù)
  135. * 作  者:大核桃
  136. * 版本號:1.0.1(2017.03.03)
  137. *******************************************************************************/
  138. uint8 IIC_Read_Byte(void)
  139. {
  140.         uint8 x=0;
  141.         uint8 mask;

  142.         IIC_SDA = 1;        //首先置數(shù)據(jù)線為高電平

  143. //        for(i = 0;i < 8;i++)
  144. //        {
  145. //                x <<= 1;        //讀入數(shù)據(jù),高位在前
  146. //                IIC_Delay();
  147. //                IIC_SCL = 1;        //突變
  148. //                IIC_Delay();
  149. //               
  150. //                if(IIC_SDA)        
  151. //                x |= 0x01;        //收到高電平
  152. //
  153. //                IIC_SCL = 0;
  154. //                IIC_Delay();
  155. //        }        //數(shù)據(jù)接收完成

  156.         for(mask = 0x80; mask != 0x00; mask >>= 1)
  157.         {
  158.                 IIC_Delay();
  159.                 IIC_SCL = 1;        //突變
  160.                 IIC_Delay();

  161.                 if(IIC_SDA)
  162.                 {
  163.                         x |= mask;        
  164.                 }
  165.                 else
  166.                 {
  167.                         x &= ~mask;//
  168.                 }

  169.                 IIC_SCL = 0;
  170.                 IIC_Delay();
  171.         }

  172.         IIC_SCL = 0;

  173.         return x;        //返回讀取到的數(shù)據(jù)
  174. }

  175. /*******************************************************************************
  176. * 文件名:static unsigned char RTC_BinToBcd2(unsigned char BINValue)
  177. * 描  述: 將BIN轉(zhuǎn)換為BCD
  178. * 功  能:
  179. * 作  者:大核桃
  180. * 版本號:1.0.1(2017.03.03)
  181. *******************************************************************************/
  182. static unsigned char RTC_BinToBcd2(unsigned char BINValue)
  183. {
  184.         unsigned char bcdhigh = 0;
  185.         
  186.         while (BINValue >= 10)
  187.         {
  188.                 bcdhigh++;
  189.                 BINValue -= 10;
  190.         }
  191.         
  192.         return ((unsigned char)(bcdhigh << 4) | BINValue);
  193. }

  194. /*******************************************************************************
  195. * 文件名:static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
  196. * 描  述: 將BCD轉(zhuǎn)換為BIN
  197. * 功  能:
  198. * 作  者:大核桃
  199. * 版本號:1.0.1(2017.03.03)
  200. *******************************************************************************/
  201. static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
  202. {
  203.         unsigned char tmp = 0;
  204.         
  205.         tmp = ((unsigned char)(BCDValue & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
  206.         return (tmp + (BCDValue & (unsigned char)0x0F));
  207. }

  208. /*******************************************************************************
  209. * 文件名:void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
  210. * 描  述: PCF8563某寄存器寫入一個字節(jié)數(shù)據(jù)
  211. * 功  能:REG_ADD:要操作寄存器地址          dat:    要寫入的數(shù)據(jù)
  212. * 作  者:大核桃
  213. * 版本號:1.0.1(2017.03.03)
  214. *******************************************************************************/
  215. void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
  216. {
  217.         IIC_Start();
  218.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  219.         {
  220.                 IIC_Write_Byte(REG_ADD);
  221.                 IIC_Write_Byte(dat);  //發(fā)送數(shù)據(jù)
  222.         }
  223.         IIC_Stop();
  224. }

  225. /*******************************************************************************
  226. * 文件名:unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
  227. * 描  述: PCF8563某寄存器讀取一個字節(jié)數(shù)據(jù)
  228. * 功  能:REG_ADD:要操作寄存器地址          讀取得到的寄存器的值
  229. * 作  者:大核桃
  230. * 版本號:1.0.1(2017.03.03)
  231. *******************************************************************************/
  232. unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
  233. {
  234.         unsigned char ReData;
  235.         
  236.         IIC_Start();
  237.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  238.         {
  239.                 IIC_Write_Byte(REG_ADD);  //確定要操作的寄存器
  240.                 IIC_Start();  //重啟總線
  241.                 IIC_Write_Byte(0xa3);  //發(fā)送讀取命令
  242.                 ReData = IIC_Read_Byte();  //讀取數(shù)據(jù)
  243.                 IIC_Ack(1);  //發(fā)送非應(yīng)答信號結(jié)束數(shù)據(jù)傳送
  244.         }
  245.         IIC_Stop();
  246.         return ReData;
  247. }

  248. /*******************************************************************************
  249. * 文件名:void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  250. * 描  述: PCF8563寫入多組數(shù)據(jù)
  251. * 功  能:REG_ADD:要操作寄存器起始地址          num:    寫入數(shù)據(jù)數(shù)量           *WBuff: 寫入數(shù)據(jù)緩存
  252. * 作  者:大核桃
  253. * 版本號:1.0.1(2017.03.03)
  254. *******************************************************************************/
  255. void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  256. {
  257.         unsigned char i = 0;
  258.                         
  259.         IIC_Start();
  260.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  261.         {
  262.                 IIC_Write_Byte(REG_ADD);  //定位起始寄存器地址
  263.                 for(i = 0;i < num;i++)
  264.                 {
  265.                         IIC_Write_Byte(*pBuff);  //寫入數(shù)據(jù)
  266.                         pBuff++;
  267.                 }
  268.         }
  269.         IIC_Stop();
  270. }
  271. /*******************************************************************************
  272. * 文件名:void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  273. * 描  述: PCF8563讀取多組數(shù)據(jù)
  274. * 功  能:REG_ADD:要操作寄存器起始地址          num:    寫入數(shù)據(jù)數(shù)量           *WBuff: 讀取數(shù)據(jù)緩存
  275. * 作  者:大核桃
  276. * 版本號:1.0.1(2017.03.03)
  277. *******************************************************************************/
  278. void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  279. {
  280.         unsigned char i = 0;
  281.         
  282.         IIC_Start();
  283.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  284.         {
  285.                 IIC_Write_Byte(REG_ADD);  //定位起始寄存器地址
  286.                 IIC_Start();  //重啟總線
  287.                 IIC_Write_Byte(0xa3);  //發(fā)送讀取命令
  288.                 for(i = 0;i < num;i++)
  289.                 {
  290.                         *pBuff = IIC_Read_Byte();  //讀取數(shù)據(jù)
  291.                         if(i == (num - 1))        IIC_Ack(1);  //發(fā)送非應(yīng)答信號
  292.                         else IIC_Ack(0);  //發(fā)送應(yīng)答信號
  293.                         pBuff++;
  294.                 }
  295.         }
  296.         IIC_Stop();        
  297. }

  298. /*******************************************************************************
  299. * 文件名:void SetRealTime(sTime* time)
  300. * 描  述: PCF8563設(shè)置時間信息
  301. * 功  能:
  302. * 作  者:大核桃
  303. * 版本號:1.0.1(2017.03.03)
  304. *******************************************************************************/
  305. void SetRealTime(sTime* time)
  306. {
  307.         //
  308.         //拷貝數(shù)據(jù)
  309.         time->mon &= ~PCF_Century_SetBitC;

  310.         buffer[0] = time->sec;
  311.         buffer[1] = time->min;
  312.         buffer[2] = time->hour;
  313.         buffer[3] = time->day;
  314.         buffer[4] = time->week;
  315.         buffer[5] = time->mon;
  316.         buffer[6] = time->year;
  317.         //寫入數(shù)據(jù)到寄存器
  318.         //
  319.         PCF8563_Write_nByte(PCF8563_Address_Seconds, 7, buffer);
  320. }

  321. /*******************************************************************************
  322. * 文件名:void GetRealTime(sTime* time)
  323. * 描  述: PCF8563讀取時間信息
  324. * 功  能:
  325. * 作  者:大核桃
  326. * 版本號:1.0.1(2017.03.03)
  327. *******************************************************************************/
  328. void GetRealTime(sTime* time)
  329. {
  330.         PCF8563_Read_nByte(PCF8563_Address_Seconds, 7, buffer);        //讀取寄存器數(shù)值
  331.         buffer[0] &= PCF8563_Shield_Seconds;         //屏蔽無效位
  332.         buffer[1] &= PCF8563_Shield_Minutes;
  333.         buffer[2] &= PCF8563_Shield_Hours;
  334.         buffer[3] &= PCF8563_Shield_Days;
  335.         buffer[4] &= PCF8563_Shield_WeekDays;
  336.         buffer[5] &= PCF8563_Shield_Months_Century;
  337.         buffer[6] &= PCF8563_Shield_Years;
  338.         
  339.         time->year  = buffer[6];
  340.         time->mon   = buffer[5];
  341.         time->week = buffer[4];
  342.         time->day   = buffer[3];
  343.         time->hour  = buffer[2];
  344.         time->min = buffer[1];
  345.         time->sec = buffer[0];

  346. }

  347. /*******************************************************************************
  348. * 文件名: void PCF8563Init(void)
  349. * 描  述:  PCF8563初始化時間   
  350. * 功  能:
  351. * 作  者:大核桃
  352. * 版本號:1.0.1(2017.05.23)
  353. *******************************************************************************/
  354. void PCF8563Init(void)
  355. {        
  356.         sTime code InitTime[] = {0x17,0x06,0x21, 0x22,0x11,0x00,0x03}; //年月日時分秒星期
  357.         SetRealTime(&InitTime);
  358. }
復(fù)制代碼
打開器件的數(shù)據(jù)手冊


關(guān)于IIC的起始信號和停止信號的定義



從上圖可以看出,在SCL高電平的時候,SDA由高電平到低電平的跳變作為START信號
/*******************************************************************************
  1. * 文件名:void IIC_Start(void)
  2. * 描  述: IIC啟動
  3. * 功  能:
  4. * 作  者:大核桃
  5. * 版本號:1.0.1(2017.03.03)
  6. *******************************************************************************/
  7. void IIC_Start(void)
  8. {
  9.         IIC_SDA = 1;        //為SDA下降啟動做準(zhǔn)備
  10.         IIC_SCL = 1;        //在SCL高電平時,SDA為下降沿時候總線啟動

  11.         IIC_Delay();
  12.         IIC_SDA = 0;        //突變,總線啟動
  13.         IIC_Delay();
  14.         IIC_SCL = 0;
  15.         IIC_Delay();
  16. }
復(fù)制代碼
再來看停止信號的定義



在SCL為高電平的時候,SDA由低電平到高電平的跳變作為停止信號
  1. /*******************************************************************************
  2. * 文件名:void IIC_Stop(void)
  3. * 描  述:     IIC停止
  4. * 功  能:
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. void IIC_Stop(void)
  9. {
  10.         IIC_SDA = 0;        //為SDA上升做準(zhǔn)備

  11.         IIC_Delay();
  12.         IIC_SCL = 1;        //在SCL高電平時,SDA為上升沿時候總線停止
  13.         IIC_Delay();
  14.         IIC_SDA = 1;        //突變,總線停止
  15.         IIC_Delay();
  16. }
復(fù)制代碼
看著時序圖很容易就能夠理解的。

接下來我們看下位傳輸?shù)氖疽鈭D


從上圖可以看出,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)程序如下:
  1. /*******************************************************************************
  2. * 文件名:void IIC_Ack(u8 a)
  3. * 描 述: 主機(jī)向從機(jī)發(fā)送應(yīng)答信號
  4. * 功 能:0:應(yīng)答信號 1:非應(yīng)答信號
  5. * 作 者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. void IIC_Ack(bit a)
  9. {        
  10. if(a)        IIC_SDA = 1;        //放上應(yīng)答信號電平
  11. else        IIC_SDA = 0;

  12. IIC_Delay();
  13. IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  14. IIC_Delay();
  15. IIC_SCL = 0;        //突變,將應(yīng)答信號發(fā)送過去
  16. IIC_Delay();
  17. }
復(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的過程。我們再來看一下輸入信號,


如果你輸出一個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)答的由來。





接下來我們再來看下IIC總線讀寫字節(jié)函數(shù),這個很有參考意義,因為不管是啥協(xié)議,不是從高位開始讀寫就是從低位開始讀寫,具體的時序可能不一樣,但是這個實現(xiàn)的過程是比較有參考意義的,先來看IIC總線寫字節(jié)函數(shù),代碼如下
  1. /*******************************************************************************
  2. * 文件名:u8 IIC_Write_Byte(u8 dat)
  3. * 描  述: 向IIC總線發(fā)送一個字節(jié)數(shù)據(jù)
  4. * 功  能:dat:要發(fā)送的數(shù)據(jù)          ack:返回應(yīng)答信號
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. uint8 IIC_Write_Byte(uint8 dat)
  9. {
  10.         uint8 iic_ack=0;        //iic應(yīng)答標(biāo)志
  11.         uint8 mask = 0;

  12. //        for(i = 0;i < 8;i++)
  13. //        {
  14. //                if(dat & 0x80)        IIC_SDA = 1;        //判斷發(fā)送位,先發(fā)送高位
  15. //                else        IIC_SDA = 0;
  16. //                IIC_Delay();
  17. //                IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  18. //                IIC_Delay();
  19. //                IIC_SCL = 0;        //突變,將數(shù)據(jù)位發(fā)送過去
  20. //                dat<<=1;        //數(shù)據(jù)左移一位
  21. //        }        //字節(jié)發(fā)送完成,開始接收應(yīng)答信號

  22.         for(mask = 0x80; mask!= 0x00; mask >>= 1)
  23.         {
  24.                 if(mask & dat)
  25.                 {
  26.                   IIC_SDA = 1;        
  27.                 }
  28.                 else
  29.                 {
  30.                         IIC_SDA = 0;
  31.                 }

  32.                 IIC_Delay();
  33.                 IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  34.                 IIC_Delay();
  35.                 IIC_SCL = 0;        //突變,將數(shù)據(jù)位發(fā)送過去


  36.         }

  37.         IIC_SDA = 1;        //釋放數(shù)據(jù)線
  38.         IIC_Delay();
  39.         IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  40.         IIC_Delay();
  41.         //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
  42.         
  43.         iic_ack |= IIC_SDA;        //讀入應(yīng)答位
  44.         IIC_SCL = 0;
  45.         return iic_ack;        //返回應(yīng)答信號
  46. }
復(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ā)送完畢,就是這樣。

再來看下面這種寫法
  1.         for(mask = 0x80; mask!= 0x00; mask >>= 1)
  2.         {
  3.                 if(mask & dat)
  4.                 {
  5.                   IIC_SDA = 1;        
  6.                 }
  7.                 else
  8.                 {
  9.                         IIC_SDA = 0;
  10.                 }

  11.                 IIC_Delay();
  12.                 IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  13.                 IIC_Delay();
  14.                 IIC_SCL = 0;        //突變,將數(shù)據(jù)位發(fā)送過去


  15.         }
復(fù)制代碼
這種寫法是移位,先讀高位,讓位移動,而不是讓數(shù)據(jù)移動,正好移動8次,這個寫法很好,推薦給大家,很容易讓人理解,寫完8個循環(huán)之后,拉高SDA,準(zhǔn)備讀取SDA輸入的信號,就是這樣。同樣的讀字節(jié)函數(shù),請自我分析完成,一樣的道理。

  1.         IIC_SDA = 1;        //釋放數(shù)據(jù)線
  2.         IIC_Delay();
  3.         IIC_SCL = 1;        //為SCL下降做準(zhǔn)備
  4.         IIC_Delay();
  5.         //字節(jié)發(fā)送完成,開始接收應(yīng)答信號
  6.         
  7.         iic_ack |= IIC_SDA;        //讀入應(yīng)答位
  8.         IIC_SCL = 0;
  9.         return iic_ack;        //返回應(yīng)答信號
復(fù)制代碼
再來看下要操作PCF8563這個芯片,要遵循下面這個時序,先來看代碼

  1. /*******************************************************************************
  2. * 文件名:void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
  3. * 描  述: PCF8563某寄存器寫入一個字節(jié)數(shù)據(jù)
  4. * 功  能:REG_ADD:要操作寄存器地址          dat:    要寫入的數(shù)據(jù)
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
  9. {
  10.         IIC_Start();
  11.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  12.         {
  13.                 IIC_Write_Byte(REG_ADD);
  14.                 IIC_Write_Byte(dat);  //發(fā)送數(shù)據(jù)
  15.         }
  16.         IIC_Stop();
  17. }
復(fù)制代碼






從上圖可以看出一個完整的寫模式包括 起始信號+設(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ù)
  1. /*******************************************************************************
  2. * 文件名:unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
  3. * 描  述: PCF8563某寄存器讀取一個字節(jié)數(shù)據(jù)
  4. * 功  能:REG_ADD:要操作寄存器地址          讀取得到的寄存器的值
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
  9. {
  10.         unsigned char ReData;
  11.         
  12.         IIC_Start();
  13.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  14.         {
  15.                 IIC_Write_Byte(REG_ADD);  //確定要操作的寄存器
  16.                 IIC_Start();  //重啟總線
  17.                 IIC_Write_Byte(0xa3);  //發(fā)送讀取命令
  18.                 ReData = IIC_Read_Byte();  //讀取數(shù)據(jù)
  19.                 IIC_Ack(1);  //發(fā)送非應(yīng)答信號結(jié)束數(shù)據(jù)傳送
  20.         }
  21.         IIC_Stop();
  22.         return ReData;
  23. }
復(fù)制代碼
我們看下他的時序圖:


注意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)。
  1. /*******************************************************************************
  2. * 文件名:void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  3. * 描  述: PCF8563寫入多組數(shù)據(jù)
  4. * 功  能:REG_ADD:要操作寄存器起始地址          num:    寫入數(shù)據(jù)數(shù)量           *WBuff: 寫入數(shù)據(jù)緩存
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.03.03)
  7. *******************************************************************************/
  8. void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  9. {
  10.         unsigned char i = 0;
  11.                         
  12.         IIC_Start();
  13.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  14.         {
  15.                 IIC_Write_Byte(REG_ADD);  //定位起始寄存器地址
  16.                 for(i = 0;i < num;i++)
  17.                 {
  18.                         IIC_Write_Byte(*pBuff);  //寫入數(shù)據(jù)
  19.                         pBuff++;
  20.                 }
  21.         }
  22.         IIC_Stop();
  23. }
  24. /*******************************************************************************
  25. * 文件名:void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  26. * 描  述: PCF8563讀取多組數(shù)據(jù)
  27. * 功  能:REG_ADD:要操作寄存器起始地址          num:    寫入數(shù)據(jù)數(shù)量           *WBuff: 讀取數(shù)據(jù)緩存
  28. * 作  者:大核桃
  29. * 版本號:1.0.1(2017.03.03)
  30. *******************************************************************************/
  31. void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
  32. {
  33.         unsigned char i = 0;
  34.         
  35.         IIC_Start();
  36.         if(!(IIC_Write_Byte(0xa2)))  //發(fā)送寫命令并檢查應(yīng)答位
  37.         {
  38.                 IIC_Write_Byte(REG_ADD);  //定位起始寄存器地址
  39.                 IIC_Start();  //重啟總線
  40.                 IIC_Write_Byte(0xa3);  //發(fā)送讀取命令
  41.                 for(i = 0;i < num;i++)
  42.                 {
  43.                         *pBuff = IIC_Read_Byte();  //讀取數(shù)據(jù)
  44.                         if(i == (num - 1))        IIC_Ack(1);  //發(fā)送非應(yīng)答信號
  45.                         else IIC_Ack(0);  //發(fā)送應(yīng)答信號
  46.                         pBuff++;
  47.                 }
  48.         }
  49.         IIC_Stop();        
  50. }
復(fù)制代碼
好了,就到這里吧,這個程序的結(jié)果是寫入PCF8563時間信息,PCF8563讀取到的時間信息顯示在數(shù)碼管上。



代碼上傳
011 PCF8563顯示時鐘.rar (201.48 KB, 下載次數(shù): 300)




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏24 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:404894 發(fā)表于 2018-10-23 07:51 來自手機(jī) | 只看該作者
正好這不懂,謝謝啦
回復(fù)

使用道具 舉報

板凳
ID:414735 發(fā)表于 2018-10-24 16:52 | 只看該作者
好詳細(xì),很久沒有看到那么用心的人了
回復(fù)

使用道具 舉報

地板
ID:415803 發(fā)表于 2018-10-26 14:44 | 只看該作者
學(xué)到了,Thanks♪(・ω・)ノ
回復(fù)

使用道具 舉報

5#
ID:417572 發(fā)表于 2018-10-29 22:10 | 只看該作者
謝謝!
回復(fù)

使用道具 舉報

6#
ID:414974 發(fā)表于 2018-10-30 12:21 | 只看該作者
帖子很好,詳細(xì)正好用到
回復(fù)

使用道具 舉報

7#
ID:417976 發(fā)表于 2018-10-31 14:17 | 只看該作者
正好這不懂
回復(fù)

使用道具 舉報

8#
ID:419388 發(fā)表于 2018-11-1 21:19 | 只看該作者
很給力
回復(fù)

使用道具 舉報

9#
ID:420405 發(fā)表于 2018-11-4 11:24 | 只看該作者
新手看不懂啊=-=
回復(fù)

使用道具 舉報

10#
ID:420710 發(fā)表于 2018-11-7 12:23 | 只看該作者
感謝分享,學(xué)習(xí)了
回復(fù)

使用道具 舉報

11#
ID:422629 發(fā)表于 2018-11-7 22:38 | 只看該作者
帖子很好,詳細(xì)正好用到
回復(fù)

使用道具 舉報

12#
ID:424351 發(fā)表于 2018-11-11 01:39 | 只看該作者
學(xué)習(xí)了非常感謝!
回復(fù)

使用道具 舉報

13#
ID:207886 發(fā)表于 2018-11-11 16:04 | 只看該作者
感謝樓主分享,謝謝
回復(fù)

使用道具 舉報

14#
ID:425919 發(fā)表于 2018-11-18 19:28 | 只看該作者
完全看不懂呀
回復(fù)

使用道具 舉報

15#
ID:435317 發(fā)表于 2018-11-29 09:48 | 只看該作者
新手  這個資料正好
回復(fù)

使用道具 舉報

16#
ID:443613 發(fā)表于 2018-12-11 22:27 來自手機(jī) | 只看該作者
學(xué)習(xí)到了,謝謝大佬
回復(fù)

使用道具 舉報

17#
ID:461889 發(fā)表于 2019-1-23 09:59 | 只看該作者

學(xué)習(xí)到了,謝謝大佬
回復(fù)

使用道具 舉報

18#
ID:293301 發(fā)表于 2019-4-23 10:16 | 只看該作者
看不懂,哈哈,感覺資料不錯
回復(fù)

使用道具 舉報

19#
ID:471507 發(fā)表于 2019-4-24 08:34 | 只看該作者
謝謝樓主~
回復(fù)

使用道具 舉報

20#
ID:516953 發(fā)表于 2019-4-24 09:35 | 只看該作者
帖子很好,詳細(xì)正好用到
回復(fù)

使用道具 舉報

21#
ID:522706 發(fā)表于 2019-4-28 10:44 來自手機(jī) | 只看該作者
看不懂
回復(fù)

使用道具 舉報

22#
ID:333657 發(fā)表于 2019-5-6 14:50 | 只看該作者
感謝大佬,學(xué)習(xí)了
回復(fù)

使用道具 舉報

23#
ID:125704 發(fā)表于 2019-10-15 15:35 | 只看該作者
感謝大佬,學(xué)習(xí)了
回復(fù)

使用道具 舉報

24#
ID:438690 發(fā)表于 2019-11-23 22:13 | 只看該作者
不錯,要看了
回復(fù)

使用道具 舉報

25#
ID:410680 發(fā)表于 2020-2-21 20:08 | 只看該作者
謝謝分享,學(xué)習(xí)學(xué)習(xí)
回復(fù)

使用道具 舉報

26#
ID:397897 發(fā)表于 2020-3-7 23:31 | 只看該作者
感謝干貨分享!
回復(fù)

使用道具 舉報

27#
ID:275111 發(fā)表于 2020-3-11 10:33 | 只看該作者
看來搜索還是有用處的。贊。
回復(fù)

使用道具 舉報

28#
ID:372579 發(fā)表于 2020-3-19 19:50 | 只看該作者
這是篇好的教程
回復(fù)

使用道具 舉報

29#
ID:119642 發(fā)表于 2020-7-2 10:07 | 只看該作者
心細(xì)的男孩子。漂亮給力。
回復(fù)

使用道具 舉報

30#
ID:748312 發(fā)表于 2020-11-19 11:58 | 只看該作者
介紹的很詳細(xì),謝謝了
回復(fù)

使用道具 舉報

31#
ID:853787 發(fā)表于 2020-12-4 09:54 | 只看該作者
9呢 沒第9呢
回復(fù)

使用道具 舉報

32#
ID:421260 發(fā)表于 2021-10-25 08:10 | 只看該作者
講的非常詳細(xì),感謝。正好要用到這個芯片。
回復(fù)

使用道具 舉報

33#
ID:217099 發(fā)表于 2021-11-4 09:58 | 只看該作者
好老師,細(xì)致又毫無保留。技術(shù)領(lǐng)域需要這樣的人!
回復(fù)

使用道具 舉報

34#
ID:988362 發(fā)表于 2021-12-5 21:48 | 只看該作者
好老師講的非常詳細(xì),感謝分享
回復(fù)

使用道具 舉報

35#
ID:267707 發(fā)表于 2022-2-21 10:02 | 只看該作者

好老師講的非常詳細(xì),感謝分享
回復(fù)

使用道具 舉報

36#
ID:437013 發(fā)表于 2022-7-30 15:49 | 只看該作者
正好需要這樣的資料
回復(fù)

使用道具 舉報

37#
ID:1049825 發(fā)表于 2022-10-31 19:11 | 只看該作者
用心的人,樂意分享的人值得大家尊重!
回復(fù)

使用道具 舉報

38#
ID:457181 發(fā)表于 2023-7-12 12:13 | 只看該作者
謝謝分享!剛好要用到。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表