查看: 1348|回复: 4
打印 上一主题 下一主题

基于AVR16的PCF8563时钟程序-I2C读写

[复制链接]
跳转到指定楼层
沙发
发表于 2014-8-16 12:01:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include <iom16v.h>
  2. #include <macros.h>


  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. /***********I2C(TWI)基本指令*************/
  6. #define I2C_START()                            TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTA)   //TWI中断标志位,TWI允许位,TWI起始信号状态位
  7. #define I2C_STOP()                          TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTO)   //TWI中断标志位,TWI允许位,TWI停止信号状态位
  8. #define I2C_ACK()                          TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWEA)    //TWI中断标志位,TWI允许位,TWI应答(ACK)允许位
  9. #define I2C_NAK()                          TWCR = BIT(TWINT)|BIT(TWEN)              //TWI中断标志位,TWI允许位
  10. #define I2C_CHECK_STATUS(X)          {while(!(TWCR&BIT(TWINT))); if((TWSR&0xF8)!=(X)) return 0;}
  11.                                                                        //等待TWI完成当前工作,判断状态寄存器当前状态(即屏蔽低3位)
  12. #define I2C_WRITE(X)                  TWDR = (X)                               //I2C写入数据
  13. #define I2C_READ(X)                          (X) = TWDR                               //I2C读取数据

  14. /***********TWSR&0xF8 状态码************/
  15. #define START                                  0x08
  16. #define RE_START                          0x10
  17. #define MT_SLA_ACK                          0x18
  18. #define MT_SLA_NAK                          0x20
  19. #define MT_DATA_ACK                          0x28
  20. #define MT_DATA_NAK                          0x30                                      //用于检测I2C当前通信状态
  21. #define SLA_DATA_FAIL                  0x38
  22. #define MR_SLA_ACK                          0x40
  23. #define MR_SLA_NAK                          0x48
  24. #define MR_DATA_ACK                          0x50
  25. #define MR_DATA_NAK                          0x58

  26. /**********PCF8563器件地址及参数**********/
  27. #define SLA_R_PCF8563                  0xA3                                      //PCF8563时钟芯片读地址
  28. #define SLA_W_PCF8563                  0xA2                                      //PCF8563时钟芯片写地址
  29. #define PAGE_SIZE_PCF8563          16                                        //PCF8563时钟芯片页容量大小
  30. #define NUM_PAGE_PCF8563          1                                         //PCF8563时钟芯片页数


  31. uchar seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};   //断码表
  32. uchar table[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};                //位码表
  33. uchar buf[]={0,0,0,0,0,0,0,0};                                          //数据缓存区
  34. uchar buffer[]={0,0,0,0,0,0,0,0};                                          //数据缓存区


  35. /************************************************************************
  36. 函数名称:void delay_ms(uint x)
  37. 函数功能:1ms延时子程序
  38. 输入参数:uint t
  39. 返回参数:无
  40. ************************************************************************/
  41. void delay_ms(uint t)
  42. {
  43.     uint i,j;
  44.     for(j=0;j<t;j++)
  45.         for(i=0;i<1141;i++);
  46. }

  47. /************************************************************************
  48. 函数名称:void delay(uint x)
  49. 函数功能:1us延时子程序
  50. 输入参数:uint t
  51. 返回参数:无
  52. ************************************************************************/
  53. void delay(uint t)
  54. {
  55.     uint j;
  56.     for(j=0;j<t;j++)
  57.         ;
  58. }

  59. /************************************************************************
  60. 函数名称: uchar I2C_Write_n_Bytes(uchar SLA_W, uint ADDR,uint N, uchar *DAT)
  61. 函数功能: I2C主机写N字节数据到从器件
  62. 输入参数:uchar SLA_W, uint ADDR,uint N, uchar *DAT
  63. 返回参数:1
  64. 参数说明:
  65.             SLA_W:          从器件写地址
  66.             ADDR:          从器件内部起始地址写数据
  67.             N:                  写数据字节数
  68.             DAT:          源数据起始地址
  69. ************************************************************************/
  70. uchar I2C_Write_n_Bytes(uchar SLA_W, uint ADDR,uint N, uchar *DAT)
  71. {
  72.     uint i;
  73.     I2C_START();                        //启动I2C通信
  74.     I2C_CHECK_STATUS(START);            //检测I2C状态

  75.     I2C_WRITE(SLA_W);                   //I2C写入地址数据
  76.     I2C_NAK();
  77.     I2C_CHECK_STATUS(MT_SLA_ACK);

  78.     if(SLA_W!=SLA_W_PCF8563)
  79.     {
  80.         I2C_WRITE((uchar)ADDR>>8);
  81.         I2C_NAK();
  82.         I2C_CHECK_STATUS(MT_DATA_ACK);
  83.     }
  84.     I2C_WRITE((uchar)ADDR);
  85.     I2C_NAK();
  86.     I2C_CHECK_STATUS(MT_DATA_ACK);
  87.     /**********写入N个数据***********/
  88.     for(i=0;i<N;i++)
  89.     {
  90.         I2C_WRITE(DAT[i]);
  91.         I2C_NAK();
  92.         I2C_CHECK_STATUS(MT_DATA_ACK);
  93.     }

  94.     I2C_STOP();                             //I2C通信结束
  95.     return 1;
  96. }

  97. /************************************************************************
  98. 函数名称: uchar I2C_Read_n_Bytes(uchar SLA_R, uint ADDR,uint N, uchar *DAT)
  99. 函数功能: I2C主机读N字节数据到从器件
  100. 输入参数:uchar SLA_R, uint ADDR,uint N, uchar *DAT
  101. 返回参数:1
  102. 参数说明:
  103.             SLA_R:          从器件读地址
  104.             ADDR:          从器件内部起始地址读数据
  105.             N:                  读数据字节数
  106.             DAT:          源数据起始地址
  107. ************************************************************************/
  108. uchar I2C_Read_n_Bytes(uchar SLA_R, uint ADDR,uint N, uchar *DAT)
  109. {
  110.     uint i;

  111.     I2C_START();
  112.     I2C_CHECK_STATUS(START);

  113.     I2C_WRITE((SLA_R)-1);
  114.     I2C_NAK();
  115.     I2C_CHECK_STATUS(MT_SLA_ACK);

  116.     if(SLA_R!=SLA_R_PCF8563)
  117.     {
  118.         I2C_WRITE((uchar)ADDR>>8);
  119.         I2C_NAK();
  120.         I2C_CHECK_STATUS(MT_DATA_ACK);
  121.     }
  122.     I2C_WRITE((uchar)ADDR);
  123.     I2C_NAK();
  124.     I2C_CHECK_STATUS(MT_DATA_ACK);

  125.     I2C_START();
  126.     I2C_CHECK_STATUS(RE_START);

  127.     I2C_WRITE(SLA_R);
  128.     I2C_NAK();
  129.     I2C_CHECK_STATUS(MR_SLA_ACK);

  130.     if(N>1)
  131.     {
  132.         for(i=0;i<N-1;i++)
  133.         {
  134.             I2C_ACK();
  135.             I2C_CHECK_STATUS(MR_DATA_ACK);
  136.             I2C_READ(DAT[i]);
  137.         }
  138.     }
  139.     I2C_NAK();
  140.     I2C_CHECK_STATUS(MR_DATA_NAK);
  141.     DAT[N-1]=TWDR;

  142.     I2C_STOP();
  143.     return 1;
  144. }

  145. /************************************************************************
  146. 函数名称: void PCF8563_stop(void)
  147. 函数功能: 关闭PCF8563
  148. 输入参数:无
  149. 返回参数:无

  150. ************************************************************************/
  151. void PCF8563_stop(void)
  152. {
  153.     uchar stopcode=0x20;
  154.     I2C_Write_n_Bytes(SLA_W_PCF8563,0,1,&stopcode);
  155. }


  156. /************************************************************************
  157. 函数名称: void PCF8563_start(void)
  158. 函数功能: 启动PCF8563
  159. 输入参数:无
  160. 返回参数:无

  161. ************************************************************************/
  162. void PCF8563_start(void)
  163. {
  164.     uchar startcode=0x00;
  165.     I2C_Write_n_Bytes(SLA_W_PCF8563,0,1,&startcode);
  166. }

复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?加入因仑

x
回复

使用道具 举报

板凳
 楼主| 发表于 2014-8-16 12:02:15 | 只看该作者
本帖最后由 lxe 于 2014-8-16 12:04 编辑
  1. /************************************************************************
  2. 函数名称: void PCF8563_set(uchar year,uchar month,uchar day,uchar week,uchar hour,uchar minute,uchar second)
  3. 函数功能: PCF8563时钟设置
  4. 输入参数:
  5. 返回参数:无
  6. 参数说明:(BCD码)
  7.             year:    年(0x00到0x99)
  8.             month:         月(0x01到0x12)
  9.             day:         日(0x01到0x31)
  10.             hour:         时(0x00到0x23)
  11.             minute:         分(0x00到0x59)
  12.             second:         秒(0x00到0x59)
  13.             week:         星期(0x01到0x07)(非BCD码)
  14. ************************************************************************/
  15. void PCF8563_set(uchar year,uchar month,uchar day,uchar week,uchar hour,uchar minute,uchar second)
  16. {
  17.     uchar time[7];
  18.     time[6] = year;                                 //年
  19.     time[5] = month;                                //月
  20.     time[4] = week;                                 //星期
  21.     time[3] = day;                                  //日
  22.     time[2] = hour;                                 //时
  23.     time[1] = minute;                               //分
  24.     time[0] = second;                               //秒
  25.     PCF8563_stop();                                 //关闭PCF8563
  26.     I2C_Write_n_Bytes(SLA_W_PCF8563,2,7,time);      //通过I2C向PCF8563写入设定的时间
  27.     PCF8563_start();                                //启动PCF8563
  28. }


  29. /************************************************************************
  30. 函数名称: void PCF8563_read(uchar *time)
  31. 函数功能: PCF8563时钟读取
  32. 输入参数:uchar *time
  33. 返回参数:无
  34. 参数说明:
  35.             time:          存放读出时间的数组名
  36.             time[6]:  年(0x00到0x99)
  37.             time[5]:  月(0x01到0x12)
  38.             time[3]:  日(0x01到0x31)
  39.             time[2]:  时(0x00到0x23)
  40.             time[1]:  分(0x00到0x59)
  41.             time[0]:  秒(0x00到0x59)
  42.             time[4]:  星期(0x01到0x07)
  43. ************************************************************************/
  44. void PCF8563_read(uchar *time)
  45. {
  46.     uchar second = 0,minute = 0,hour = 0,day = 0,month = 0,year = 0;
  47.     I2C_Read_n_Bytes(SLA_R_PCF8563,2,7,time);
  48.     time[6] &= 0x7F;                            //年
  49.     time[5] &= 0x1F;                            //月
  50.     time[4] &= 0x07;                            //星期
  51.     time[3] &= 0x3F;                            //日
  52.     time[2] &= 0x3F;                            //时
  53.     time[1] &= 0x7F;                            //分
  54.     time[0] &= 0x7F;                            //秒

  55.     second = (time[0]/16)*10+(time[0]%16);      //将BCD码的秒转换成10进制
  56.     minute = (time[1]/16)*10+(time[1]%16);      //将BCD码的分转换成10进制
  57.     hour   = (time[2]/16)*10+(time[2]%16);      //将BCD码的时转换成10进制
  58.     day    = (time[3]/16)*10+(time[3]%16);      //将BCD码的日转换成10进制
  59.     month  = (time[5]/16)*10+(time[5]%16);      //将BCD码的月转换成10进制
  60.     year   = (time[6]/16)*10+(time[6]%16);      //将BCD码的年转换成10进制

  61.     buf[7] = second % 10;                       //取秒个位
  62.     buf[6] = second / 10;                       //取秒十位
  63.     buf[5] = 10;                                //显示间隔符-
  64.     buf[4] = minute%10;                         //取分个位
  65.     buf[3] = minute/10;                         //取分十位
  66.     buf[2] = 10;                                //显示间隔符-
  67.     buf[1] = hour%10;                           //取时个位
  68.     buf[0] = hour/10;                           //取时十位

  69.     buffer[7] = day % 10;
  70.     buffer[6] = day / 10;
  71.     buffer[5] = month % 10;
  72.     buffer[4] = month / 10;
  73.     buffer[3] = year % 10;
  74.     buffer[2] = year / 10;
  75.     buffer[1] = 20 % 10;
  76.     buffer[0] = 20 / 10;
  77. }


  78. /************************************************************************
  79. 函数名称:void main(void)
  80. 函数功能:主函数
  81. 输入参数:无
  82. 返回参数:无
  83. ************************************************************************/
  84. void main(void)
  85. {
  86.     uchar dat[132];
  87.     uint i=0,k=0;

  88.     DDRA = 0xff;
  89.     PORTA =0xff;
  90.     DDRB = 0xff;
  91.     PORTB =0xff;

  92.     DDRC &= ~(BIT(PC0) | BIT(PC1));                  //初始仳SCL,SDA引脚
  93.     PORTC |= BIT(PC0)|BIT(PC1);

  94.     TWCR=0;                                          //初始化I2C
  95.     TWBR=12;                                         //set bit rate   TWBR应大于10
  96.     TWSR=0;                                          //set prescale

  97.     PCF8563_set(0x14,0x08,0x16,0x01,0x11,0x25,0x45); //写入时间

  98.     while(1)
  99.     {
  100.         PCF8563_read(dat);
  101.         if(k<50)
  102.         for(i=0;i<8;i++)
  103.         {
  104.             PORTB=~table[i];
  105.             PORTA=seg[buf[i]];
  106.             delay(500);
  107.         }
  108.         if(k>=50)
  109.         for(i=0;i<8;i++)
  110.         {
  111.             PORTB=~table[i];
  112.             if(i==3||i==5)
  113.             {
  114.                 PORTA=(seg[buffer[i]] | 0x80);
  115.             }
  116.             else
  117.             {
  118.                     PORTA=seg[buffer[i]];
  119.             }
  120.             delay(500);
  121.         }
  122.         if(++k>70)k=0;
  123.     }
  124. }
复制代码


回复 支持 反对

使用道具 举报

地板
发表于 2014-8-16 16:54:38 | 只看该作者
楼主给力啊,32个赞
回复 支持 反对

使用道具 举报

4#
发表于 2014-8-17 15:19:16 | 只看该作者
太牛了,我看移植是太困难了
回复 支持 反对

使用道具 举报

5#
 楼主| 发表于 2014-8-18 11:17:54 | 只看该作者
杨玉玺 发表于 2014-8-17 15:19
太牛了,我看移植是太困难了

不用移植的。。51的程序有好多
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表