IIC详解

来源:互联网 发布:战略管理 知乎 编辑:程序博客网 时间:2024/06/14 14:59
本文的程序是主控室STM32F107,读取的芯片是PCF8563。各种宏定义和文件会在末尾说明。

1、IIC的定义:

IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的一种简单、双向、二线制、同步串行总线,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。这种方式简化了信号传输总线接口。

I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

SDA(数据线)和SCL(时钟线)都是集电极开路或漏极开路结构的,只能输出“0”,不能输出“1”,都必须接上拉电阻。

当需要输入数据时,将一个读数据用的输入端接在输出端。

SCL线的时钟同步:SCL由于具有线“与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号。

♣. SDA线的仲裁:SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线。

IIC的时序图


2、启动信号


因为 只有两条线,从时序图上 看 也是 很简洁 的。

下面由GIF动画展示启动信号的过程


动画中红色的阴影区域,表示 IIC 启动信号

[cpp] view plain copy
print?
  1. /******************************************************************************* 
  2. ** Function name: I2C_Start 
  3. ** Descriptions: 开始发送一个I2C起始信号 
  4. ** Input parameters: None 
  5. ** output parameters: None 
  6. ** Created Date:  
  7. *******************************************************************************/  
  8. void I2C_Start(void)  
  9. {  
  10. //IO输出  
  11. SDA_OUT();   
  12. SCL_OUT();   
  13. I2C_DELAY();  
  14. //IO置高  
  15. SDA_SET();   
  16. SCL_SET();   
  17. //延时  
  18. I2C_DELAY();   
  19. //为低  
  20. SDA_CLR();  
  21. I2C_DELAY();  
  22. I2C_DELAY();  
  23. SCL_CLR();  
  24.   
  25. }  
/********************************************************************************* Function name: I2C_Start** Descriptions: 开始发送一个I2C起始信号** Input parameters: None** output parameters: None** Created Date: *******************************************************************************/void I2C_Start(void){//IO输出SDA_OUT(); SCL_OUT(); I2C_DELAY();//IO置高SDA_SET(); SCL_SET(); //延时I2C_DELAY(); //为低SDA_CLR();I2C_DELAY();I2C_DELAY();SCL_CLR();}

3、停止信号

理解了开始信号,再来看 停止信号,分分秒秒 就会的事情,前提:先理解 开始信号后,再来看 停止信号。


[cpp] view plain copy
print?
  1. /******************************************************************************* 
  2. ** Function name: I2C_Stop 
  3. ** Descriptions: 发送一个I2C总线结束信号 
  4. ** Input parameters: None 
  5. ** output parameters: None 
  6. ** Created Date:  
  7. *******************************************************************************/  
  8. void I2C_Stop(void)  
  9. {  
  10. //IO输出  
  11. SDA_OUT();   
  12. SCL_OUT();  
  13. //IO置0  
  14. SDA_CLR();   
  15. SCL_CLR();   
  16. I2C_DELAY();  
  17. SCL_SET();  
  18. //延时  
  19. I2C_DELAY();   
  20. I2C_DELAY();  
  21. I2C_DELAY();  
  22. //SDA置1  
  23. SDA_SET();  
  24. I2C_DELAY();  
  25. I2C_DELAY();  
  26. }  
/********************************************************************************* Function name: I2C_Stop** Descriptions: 发送一个I2C总线结束信号** Input parameters: None** output parameters: None** Created Date: *******************************************************************************/void I2C_Stop(void){//IO输出SDA_OUT(); SCL_OUT();//IO置0SDA_CLR(); SCL_CLR(); I2C_DELAY();SCL_SET();//延时I2C_DELAY(); I2C_DELAY();I2C_DELAY();//SDA置1SDA_SET();I2C_DELAY();I2C_DELAY();}

4、IIC 写 一个 字节

学习了 启动 和停止 信号后,就可以开始学习 写入一个字节 命令了


该命令 过程是,




文字描述还是比较 抽象 的,看一下 动画




利用 C51 编写代码,如下




[cpp] view plain copy
print?
  1. *******************************************************************************  
  2. ** Function name: I2C_Send_byte  
  3. ** Descriptions: 主机从I2C总线发送一个字节  
  4. ** Input parameters: data  
  5. ** output parameters: 0-false 1_ture  
  6. ** Created Date:   
  7. *******************************************************************************/  
  8. uint8 I2C_Send_byte(uint8 data)  
  9. {  
  10. uint8 k;  
  11. //发送8bit数据  
  12. for(k=0;k<8;k++){  
  13. I2C_DELAY();  
  14. if(data&0x80){  
  15. SDA_SET();  
  16. }  
  17. else{  
  18. SDA_CLR();  
  19. }  
  20. data=data<<1;  
  21. I2C_DELAY();  
  22. SCL_SET();  
  23. I2C_DELAY();  
  24. I2C_DELAY();  
  25. SCL_CLR();  
  26. }  
  27. //延时读取ACK响应  
  28.   
  29. I2C_DELAY();  
  30. SDA_SET();  
  31. //置为输入线  
  32. SDA_IN();  
  33. I2C_DELAY();  
  34. SCL_SET();   
  35. I2C_DELAY(); //这里出现了问题,延时变的无限大  
  36. //读数据  
  37. k=SDA_READ();  
  38. I2C_DELAY();  
  39. SCL_CLR();  
  40. I2C_DELAY();  
  41. SDA_OUT();  
  42. if(k){ ////NACK响应  
  43. return 0;  
  44. }  
  45. return 1;  
  46.   
  47. }  
********************************************************************************* Function name: I2C_Send_byte** Descriptions: 主机从I2C总线发送一个字节** Input parameters: data** output parameters: 0-false 1_ture** Created Date: *******************************************************************************/uint8 I2C_Send_byte(uint8 data){uint8 k;//发送8bit数据for(k=0;k<8;k++){I2C_DELAY();if(data&0x80){SDA_SET();}else{SDA_CLR();}data=data<<1;I2C_DELAY();SCL_SET();I2C_DELAY();I2C_DELAY();SCL_CLR();}//延时读取ACK响应I2C_DELAY();SDA_SET();//置为输入线SDA_IN();I2C_DELAY();SCL_SET(); I2C_DELAY(); //这里出现了问题,延时变的无限大//读数据k=SDA_READ();I2C_DELAY();SCL_CLR();I2C_DELAY();SDA_OUT();if(k){ ////NACK响应return 0;}return 1;}



5、IIC 读取一个字节

读取字节 的 资料 不多,和写一个字节有区别,不过 如果理解怎样写一个字节后,再理解 读字节 难度不大。

[cpp] view plain copy
print?
  1. /******************************************************************************* 
  2. ** Function name:       I2C_Receive_byte 
  3. ** Descriptions:        主机从I2C总线接收一个字节 
  4. ** Input parameters:    None 
  5. ** output parameters:   data 
  6. ** Created Date:         
  7. *******************************************************************************/  
  8. uint8 I2C_Receive_byte(void)  
  9. {  
  10.   uint32 k,data;  
  11.   //接收8bit数据  
  12.   //置为输入线  
  13.     
  14.   SDA_IN();  
  15.   data=0;  
  16.   for(k=0;k<8;k++){  
  17.       I2C_DELAY();  
  18.       SCL_SET();  
  19.       I2C_DELAY();  
  20.       //读数据  
  21.       data=data|SDA_READ();  
  22.       data=data<<1;  
  23.       I2C_DELAY();  
  24.       SCL_CLR();  
  25.       I2C_DELAY();   
  26.   }  
  27.   data=data>>1; //往回移动1次  
  28.   //返回ACK响应  
  29.   //置为输出线  
  30.   SDA_OUT();  
  31.   SDA_CLR(); //输出0-ACK  
  32.   I2C_DELAY();  
  33.   SCL_SET();  
  34.   I2C_DELAY();  
  35.   I2C_DELAY();  
  36.   SCL_CLR();  
  37.   I2C_DELAY();  
  38.   SDA_OUT();  
  39.   //返回读取的数据  
  40.   return (uint8)data;  
  41. }  
/********************************************************************************* Function name:       I2C_Receive_byte** Descriptions:        主机从I2C总线接收一个字节** Input parameters:    None** output parameters:   data** Created Date:        *******************************************************************************/uint8 I2C_Receive_byte(void){  uint32 k,data;  //接收8bit数据  //置为输入线  SDA_IN();  data=0;  for(k=0;k<8;k++){      I2C_DELAY();      SCL_SET();      I2C_DELAY();      //读数据      data=data|SDA_READ();      data=data<<1;      I2C_DELAY();      SCL_CLR();      I2C_DELAY();   }  data=data>>1; //往回移动1次  //返回ACK响应  //置为输出线  SDA_OUT();  SDA_CLR(); //输出0-ACK  I2C_DELAY();  SCL_SET();  I2C_DELAY();  I2C_DELAY();  SCL_CLR();  I2C_DELAY();  SDA_OUT();  //返回读取的数据  return (uint8)data;}

6IIC发应答和检测应答

MASTER 指主控制端,在一般系统中就是我们常说的单片机了;SLAVE是指具备I2C协议的专用IC

1SCL一直由Master控制,SDA依照数据传送的方向,读数据时由Slave控制SDA,写数据时由Master控制SDA。当8位数据传送完毕之后,应答位或者否应答位的SDA控制权与数据位传送时相反。
2
,开始位“Start”和停止位“Stop”,只能由Master来发出。
3
,地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”
4
,当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”Slave设备如果没有空间接受更多的字节应该回答“NACK”Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”
5
,当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
6
,当Master速度过快Slave端来不及处理时,Slave设备可以拉低SCL不放(SCL=0将发生线与)以阻止Master发送更多的数据。此时Master将视情况减慢或结束数据传送。

7器件的地址



再来看一些常用器件的地址码




8、写一个字节(下挂多个设备)

写一个字节方式,写完一个字节后就发停止符


9、指定任意地址读(下挂多个设备)


[cpp] view plain copy
print?
  1. /******************************************************************************* 
  2. ** Function name:       I2C_Write_nbyte 
  3. ** Descriptions:        向I2C总线器件上指定的地址写入多个数据 
  4. ** Input parameters:    1=addr,2_sub_addr,3-p,4-num 
  5. ** output parameters:   0-false,1-ture 
  6. ** Created Date:         
  7. *******************************************************************************/  
  8. uint8 I2C_Write_nbyte(uint8 addr,uint8 sub_addr,uint8 *data_cache,uint32 num)  
  9. {  
  10.   uint32 temp_state,k;  
  11.   //启动I2C总线  
  12.   I2C_Start();  
  13.   I2C_Start();  
  14.   //发送器件地址  
  15.   temp_state=I2C_Send_byte(addr&0xFE);//写模式  
  16.   if(!temp_state){  
  17.      goto err_i2c;  
  18.   }  
  19.   //发送器件子地址  
  20.   temp_state=I2C_Send_byte(sub_addr);  
  21.   if(!temp_state){  
  22.      goto err_i2c;  
  23.   }  
  24.   //发送后面的数据  
  25.   for(k=0;k<num;k++){  
  26.           
  27.       temp_state=I2C_Send_byte(data_cache[k]);//写  
  28.       if(!temp_state){  
  29.          goto err_i2c;  
  30.       }     
  31.   }  
  32.     
  33.   I2C_Stop();  
  34.   return 1;  
  35. err_i2c:  
  36.      I2C_Stop();  
  37.      return 0;  
  38.     
  39. }  
  40. /******************************************************************************* 
  41. ** Function name:       I2C_Read_nbyte 
  42. ** Descriptions:        从I2C总线器件上指定的地址读取多个数据 
  43. ** Input parameters:    1=addr,2_sub_addr,3-p,4-num 
  44. ** output parameters:   0-false,1-ture 
  45. ** Created Date:         
  46. *******************************************************************************/  
  47. uint8 I2C_Read_nbyte(uint8 addr,uint8 sub_addr,uint8 *data_cache,uint32 num)  
  48. {  
  49.   uint32 temp_state,k;  
  50.   //启动I2C总线  
  51.   I2C_Start();  
  52.   I2C_Start();  
  53.   //发送器件地址  
  54.   temp_state=I2C_Send_byte(addr&0xFE);//写模式  
  55.   if(!temp_state){  
  56.      goto err_i2c;  
  57.   }  
  58.   //发送器件子地址  
  59.   temp_state=I2C_Send_byte(sub_addr);  
  60.   if(!temp_state){  
  61.      goto err_i2c;  
  62.   }  
  63.   //重启动I2C总线  
  64.   I2C_Start();  
  65.   //发送器件地址  
  66.   temp_state=I2C_Send_byte(addr|0x01);//读模式  
  67.   if(!temp_state){  
  68.      goto err_i2c;  
  69.   }  
  70.   //读取后面的数据  
  71.   for(k=0;k<num;k++){  
  72.       data_cache[k]=I2C_Receive_byte();//读取数据    
  73.   }  
  74.     
  75.   I2C_Stop();  
  76.   return 1;  
  77. err_i2c:  
  78.      I2C_Stop();  
  79.      //I2C_Start();  
  80.      return 0;  
  81.     
  82. }  
/********************************************************************************* Function name:       I2C_Write_nbyte** Descriptions:        向I2C总线器件上指定的地址写入多个数据** Input parameters:    1=addr,2_sub_addr,3-p,4-num** output parameters:   0-false,1-ture** Created Date:        *******************************************************************************/uint8 I2C_Write_nbyte(uint8 addr,uint8 sub_addr,uint8 *data_cache,uint32 num){  uint32 temp_state,k;  //启动I2C总线  I2C_Start();  I2C_Start();  //发送器件地址  temp_state=I2C_Send_byte(addr&0xFE);//写模式  if(!temp_state){     goto err_i2c;  }  //发送器件子地址  temp_state=I2C_Send_byte(sub_addr);  if(!temp_state){     goto err_i2c;  }  //发送后面的数据  for(k=0;k<num;k++){      temp_state=I2C_Send_byte(data_cache[k]);//写      if(!temp_state){         goto err_i2c;      }     }  I2C_Stop();  return 1;err_i2c:     I2C_Stop();     return 0;}/********************************************************************************* Function name:       I2C_Read_nbyte** Descriptions:        从I2C总线器件上指定的地址读取多个数据** Input parameters:    1=addr,2_sub_addr,3-p,4-num** output parameters:   0-false,1-ture** Created Date:        *******************************************************************************/uint8 I2C_Read_nbyte(uint8 addr,uint8 sub_addr,uint8 *data_cache,uint32 num){  uint32 temp_state,k;  //启动I2C总线  I2C_Start();  I2C_Start();  //发送器件地址  temp_state=I2C_Send_byte(addr&0xFE);//写模式  if(!temp_state){     goto err_i2c;  }  //发送器件子地址  temp_state=I2C_Send_byte(sub_addr);  if(!temp_state){     goto err_i2c;  }  //重启动I2C总线  I2C_Start();  //发送器件地址  temp_state=I2C_Send_byte(addr|0x01);//读模式  if(!temp_state){     goto err_i2c;  }  //读取后面的数据  for(k=0;k<num;k++){      data_cache[k]=I2C_Receive_byte();//读取数据    }  I2C_Stop();  return 1;err_i2c:     I2C_Stop();     //I2C_Start();     return 0;}

10、写字符串 和 读字符串(下挂多个设备)

写字符串方式,写完一个字节后 继续 写字节,直到发停止符
读字符串方式,读完一个字节后 继续 读字节,直到发停止符


11、PCF8563芯片的简介






驱动程序如下:


[cpp] view plain copy
print?
  1. /********************************************************************************************************* 
  2. ** Function name: PCF8563_Set 
  3. ** Descriptions: 设置PCF8563 
  4. ** input parameters: NONE 
  5. ** Output parameters: NONE 
  6. ** Returned value: NONE 
  7. *********************************************************************************************************/  
  8. uint8 PCF8563_Set(timeType *tp)  
  9. {  
  10. uint32 k;  
  11. uint8 year;  
  12. uint8 week;  
  13. uint8 tempdata[7];  
  14. ///////转换成BCD码  
  15. tempdata[0] = tp->second;  
  16. tempdata[1] = tp->minute;  
  17. tempdata[2] = tp->hour;  
  18. tempdata[3] = tp->day;  
  19. if(tp->week==7){  
  20. week=0;  
  21. }  
  22. else{  
  23. week=tp->week;   
  24. }   
  25. tempdata[4] = week;  
  26. tempdata[5] = tp->month;  
  27.   
  28. //if (tp->year >= 2000){  
  29. tempdata[5] &= 0x7F; ////世纪位清零  
  30. // year = tp->year - 2000;  
  31. tempdata[6] = tp->year;  
  32. //}  
  33. //else{  
  34. //  tempdata[5] |= 0x80; ////世纪位置位  
  35. // year = tp->year - 1900;  
  36. // tempdata[6] = HEC_to_BCD(year);  
  37. //}   
  38. //判断是否校时成功  
  39. k=0;  
  40. while(k<10){   
  41. if(I2C_Write_nbyte(PCF8563ADR, 0x02,tempdata, 7)==1){   
  42. return(1);  
  43. }  
  44. k++;  
  45. //延时等待3ms  
  46. #if WDOG_EN  
  47. wdogFeed();  
  48. #endif  
  49. SysCtlDelay(40*1000);   
  50. }  
  51.   
  52. return(0);  
  53. }  
  54. /********************************************************************************************************* 
  55. ** Function name: PCF8563_Read 
  56. ** Descriptions: 读取PCF8563 
  57. ** input parameters: tp 指向时间结构体的指针 
  58. ** Output parameters: FALSE or TRUE 
  59. ** Returned value: NONE 
  60. *********************************************************************************************************/  
  61. uint8 PCF8563_Read(timeType *tp)  
  62. {  
  63. uint32 time_flag;  
  64. uint32 div_run_4;  
  65. uint8 G_time_temp[7];  
  66. timeType time_G;   
  67.   
  68. time_flag=0;  
  69.   
  70. if(I2C_Read_nbyte(PCF8563ADR, 0x02,G_time_temp,7) == 0){  
  71. return 0; //////直接返回,使用以前的旧值  
  72. }  
  73.   
  74.   
  75. time_G.second = BCD_to_HEC((G_time_temp[0]&0x7f));  
  76. time_G.minute = BCD_to_HEC((G_time_temp[1]&0x7f));  
  77. time_G.hour = BCD_to_HEC((G_time_temp[2]&0x3f));  
  78. time_G.day = BCD_to_HEC((G_time_temp[3]&0x3f));  
  79. time_G.week = BCD_to_HEC((G_time_temp[4]&0x07));  
  80.   
  81. if(time_G.week==0){  
  82. time_G.week=7;  
  83. }  
  84. time_G.month = BCD_to_HEC((G_time_temp[5]&0x1f));  
  85. time_G.year = BCD_to_HEC(G_time_temp[6]);  
  86.   
  87. if(G_time_temp[5]&0x80){  
  88. time_G.year+=1900;   
  89. }  
  90. else{  
  91. time_G.year+=2000;   
  92. }  
  93.   
  94. //判断是否是闰年,在1949~2049年之内  
  95. div_run_4 = time_G.year / 4;  
  96. div_run_4 = div_run_4 * 4;  
  97. //检查是否整除  
  98. if(div_run_4 == time_G.year){  
  99. //说明闰年  
  100. div_run_4 = 1;  
  101. }  
  102. else{  
  103. //非闰年  
  104. div_run_4 = 0;  
  105. }  
  106.   
  107. //////获得实际的时间值  
  108. //对时间进行检查  
  109. //1949~2049  
  110. if(time_G.second > 59){ //秒错误  
  111. time_flag++;  
  112. }  
  113. if(time_G.minute > 59){ //分错误  
  114. time_flag++;  
  115. }  
  116. if(time_G.hour > 23){ //时错误  
  117. time_flag++;  
  118. }  
  119.   
  120. if(time_G.day > 31){ //日错误  
  121. time_flag++;  
  122. }  
  123. if(time_G.day== 0){ //日错误  
  124. time_flag++;  
  125. }  
  126. if(time_G.month > 12){ //月错误  
  127. time_flag++;  
  128. }  
  129. if(time_G.month == 0){ //月错误  
  130. time_flag++;  
  131. }  
  132. //检查月与日  
  133. //检查二月  
  134. if(div_run_4){  
  135. //检查闰月  
  136. if((time_G.month == 2) && (time_G.day > 29)){ //月错误  
  137. time_flag++;  
  138. }  
  139. }  
  140. else{  
  141. //检查闰月  
  142. if((time_G.month == 2) && (time_G.day > 28)){ //月错误  
  143. time_flag++;  
  144. }  
  145. }  
  146. //检查其他月  
  147. switch(time_G.month){  
  148. case 1:  
  149. case 3:  
  150. case 5:  
  151. case 7:  
  152. case 8:  
  153. case 10:  
  154. case 12:{  
  155. if(time_G.day>31){ //日错误  
  156. time_flag++;  
  157. }  
  158. break;  
  159. }  
  160. case 4:  
  161. case 6:  
  162. case 9:  
  163. case 11:{  
  164. if(time_G.day>30){ //日错误  
  165. time_flag++;  
  166. }  
  167. break;  
  168.   
  169. }   
  170. }  
  171. if(time_G.week>=8){ //周错误  
  172. time_flag++;  
  173. }  
  174. if((time_G.year>=2050)||(time_G.year<1949)){ //周错误  
  175. time_flag++;  
  176. }  
  177.   
  178. if(time_flag!=0){  
  179. rtc_state=1;  
  180. return 4;  
  181. }  
  182.   
  183. *tp=time_G;  
  184.   
  185.   
  186. return 1;  
  187. }  
  188.   
  189. /********************************************************************************************************* 
  190. ** Function name: PCF8563_Read_BCD 
  191. ** Descriptions: 读取PCF8563,BCD码表示 
  192. ** input parameters: tp 指向时间结构体的指针 
  193. ** Output parameters: FALSE or TRUE 
  194. ** Returned value: NONE 
  195. *********************************************************************************************************/  
  196. uint8 PCF8563_Read_BCD(timeType *tp)  
  197. {  
  198. uint8 temp[7];  
  199.   
  200. if(I2C_Read_nbyte(PCF8563ADR, 0x02,temp,7) == 0){  
  201. return 0; //////直接返回,使用以前的旧值  
  202. }  
  203.   
  204. tp->second = ((temp[0]&0x7f));  
  205. tp->minute = ((temp[1]&0x7f));  
  206. tp->hour = ((temp[2]&0x3f));  
  207. tp->day = ((temp[3]&0x3f));  
  208. tp->week = ((temp[4]&0x07));  
  209. if(tp->week==0){  
  210. tp->week=7;  
  211. }  
  212. tp->month = temp[5]&0x1f;  
  213. tp->year = temp[6];  
  214.   
  215. if(temp[5]&0x80){  
  216. tp->year |= 0x1900;  
  217. }  
  218. else{  
  219. tp->year |= 0x2000;  
  220. }  
  221. return 1;  
  222. }  
/*********************************************************************************************************** Function name: PCF8563_Set** Descriptions: 设置PCF8563** input parameters: NONE** Output parameters: NONE** Returned value: NONE*********************************************************************************************************/uint8 PCF8563_Set(timeType *tp){uint32 k;uint8 year;uint8 week;uint8 tempdata[7];///////转换成BCD码tempdata[0] = tp->second;tempdata[1] = tp->minute;tempdata[2] = tp->hour;tempdata[3] = tp->day;if(tp->week==7){week=0;}else{week=tp->week; } tempdata[4] = week;tempdata[5] = tp->month;//if (tp->year >= 2000){tempdata[5] &= 0x7F; ////世纪位清零// year = tp->year - 2000;tempdata[6] = tp->year;//}//else{//  tempdata[5] |= 0x80; ////世纪位置位// year = tp->year - 1900;// tempdata[6] = HEC_to_BCD(year);//} //判断是否校时成功k=0;while(k<10){ if(I2C_Write_nbyte(PCF8563ADR, 0x02,tempdata, 7)==1){ return(1);}k++;//延时等待3ms
#if WDOG_ENwdogFeed();#endifSysCtlDelay(40*1000); }return(0);}/*********************************************************************************************************** Function name: PCF8563_Read** Descriptions: 读取PCF8563** input parameters: tp 指向时间结构体的指针** Output parameters: FALSE or TRUE** Returned value: NONE*********************************************************************************************************/uint8 PCF8563_Read(timeType *tp){uint32 time_flag;uint32 div_run_4;uint8 G_time_temp[7];timeType time_G; time_flag=0;if(I2C_Read_nbyte(PCF8563ADR, 0x02,G_time_temp,7) == 0){return 0; //////直接返回,使用以前的旧值}time_G.second = BCD_to_HEC((G_time_temp[0]&0x7f));time_G.minute = BCD_to_HEC((G_time_temp[1]&0x7f));time_G.hour = BCD_to_HEC((G_time_temp[2]&0x3f));time_G.day = BCD_to_HEC((G_time_temp[3]&0x3f));time_G.week = BCD_to_HEC((G_time_temp[4]&0x07));if(time_G.week==0){time_G.week=7;}time_G.month = BCD_to_HEC((G_time_temp[5]&0x1f));time_G.year = BCD_to_HEC(G_time_temp[6]);if(G_time_temp[5]&0x80){time_G.year+=1900; }else{time_G.year+=2000; }//判断是否是闰年,在1949~2049年之内div_run_4 = time_G.year / 4;div_run_4 = div_run_4 * 4;//检查是否整除if(div_run_4 == time_G.year){//说明闰年div_run_4 = 1;}else{//非闰年div_run_4 = 0;}//////获得实际的时间值//对时间进行检查//1949~2049if(time_G.second > 59){ //秒错误time_flag++;}if(time_G.minute > 59){ //分错误time_flag++;}if(time_G.hour > 23){ //时错误time_flag++;}if(time_G.day > 31){ //日错误time_flag++;}if(time_G.day== 0){ //日错误time_flag++;}if(time_G.month > 12){ //月错误time_flag++;}if(time_G.month == 0){ //月错误time_flag++;}//检查月与日//检查二月if(div_run_4){//检查闰月if((time_G.month == 2) && (time_G.day > 29)){ //月错误time_flag++;}}else{//检查闰月if((time_G.month == 2) && (time_G.day > 28)){ //月错误time_flag++;}}//检查其他月switch(time_G.month){case 1:case 3:case 5:case 7:case 8:case 10:case 12:{if(time_G.day>31){ //日错误time_flag++;}break;}case 4:case 6:case 9:case 11:{if(time_G.day>30){ //日错误time_flag++;}break;} }if(time_G.week>=8){ //周错误time_flag++;}if((time_G.year>=2050)||(time_G.year<1949)){ //周错误time_flag++;}if(time_flag!=0){rtc_state=1;return 4;}*tp=time_G;return 1;}/*********************************************************************************************************** Function name: PCF8563_Read_BCD** Descriptions: 读取PCF8563,BCD码表示** input parameters: tp 指向时间结构体的指针** Output parameters: FALSE or TRUE** Returned value: NONE*********************************************************************************************************/uint8 PCF8563_Read_BCD(timeType *tp){uint8 temp[7];if(I2C_Read_nbyte(PCF8563ADR, 0x02,temp,7) == 0){return 0; //////直接返回,使用以前的旧值}tp->second = ((temp[0]&0x7f));tp->minute = ((temp[1]&0x7f));tp->hour = ((temp[2]&0x3f));tp->day = ((temp[3]&0x3f));tp->week = ((temp[4]&0x07));if(tp->week==0){tp->week=7;}tp->month = temp[5]&0x1f;tp->year = temp[6];if(temp[5]&0x80){tp->year |= 0x1900;}else{tp->year |= 0x2000;}return 1;}



以上程序完整代码和PCF8563的中文数据手册下载地址:点击下载