搜索
bottom↓
回复: 5

【转】硬件TWI控制PCF8563的程序

[复制链接]

出0入0汤圆

发表于 2011-7-30 00:35:49 | 显示全部楼层 |阅读模式
几个月前,在古欣的指导下,我完成了这个程序。目前,这个程序是我在项目上用得很多的。现将有关硬件TWI控制PCF8563的部分贴出,供大家参考。其中时钟数组的定义请在主函数里完成。

/*******************************************
*     PCF8563的I2C(TWI)操作函数       *
* 文 件 名:TWI_8563.h               *
* 函数功能:利用CPU的硬件TWI接口操作     *
* 设   计:铜河                   *
* 修改日期:2007年04月09日             *
* 版   本:V1.0                   *
* 主控芯片:Mega16                   *
*******************************************/
#include <iom16v.h>
#include <macros.h>
//宏定义
//状态寄存器TWSR各种状态定义
//主模式启动状态
#define START         0x08     //启动总线
#define RESTART         0x10     //重新启动总线

//主发送模式各种状态
#define MT_SLA_ACK     0x18     //SLA_W写地址已发送,收到应答位
#define MT_SLA_NACK     0x20     //SLA_W写地址已发送,收到非应答位
#define MT_DATA_ACK     0x28     //写入数据已发送,收到应答位
#define MT_DATA_NACK   0x30     //写入数据已发送,收到应答位
#define MT_ARB_LOST     0x38     //SLA_W或数据仲裁失败

//主接收模式各种状态
#define MR_ARB_LOST     0x38     //
#define MR_SLA_ACK     0x40     //SLA_R已发送,收到应答位
#define MR_SLA_NACK     0x48     //SLA_R已发送,收到非应答位
#define MR_DATA_ACK     0x50     //接收到数据,应答位已返回
#define MR_DATA_NACK   0x58     //接收到数据,非应答位已返回

#define SLA_W         0xA2       //PCF8563写从地址
#define SLA_R         0xA3     //PCF8563读从地址

#define start()         (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define stop()         (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define waitack()     {while(!(TWCR&(1<<TWINT)));}
#define chkack()       (TWSR&0xf8)             //check ack
#define sendack()     (TWCR|=(1<<TWEA))
#define sendnack()     (TWCR&=~(1<<TWEA))
#define sendbyte(x)     {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
#define rcvnckbyte()   (TWCR=(1<<TWINT)|(1<<TWEN))
#define rcvackbyte()   (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA))

/* I2C Config */
#define I2C_ERR         0
#define I2C_CRR         1

//简化宏定义
#define uchar unsigned char
#define uint unsigned int


//TWI初始化
void Twi_Init(void)
  {
  TWBR=14;
  TWSR=0;
  }

//写入时间函数
uchar write_tim(uchar a)
  {   
  sendbyte(a);             //发送
  waitack();                 //等待写完成
  if(chkack()!=MT_SLA_ACK)return I2C_ERR; //检查是否正确写入
  else return I2C_CRR;
  }
//读出时间函数
uchar read_tim(void)
  {
  rcvackbyte();               //接收一字节并返回应答
  waitack();                 //等待接收完成
  if(chkack()!=MR_DATA_ACK)return I2C_ERR;       //检查是否接收成功
//     return I2C_ERR;
  else
    return(TWDR);             //读出时钟数据
  }

/**********************************
*       读出数据函数         *
**********************************/
uchar read_timer(void)
  {
  start();                   //启动总线
  waitack();                 //等待启动完成
  if(chkack()!=START)return I2C_ERR;       //检查是否启动成功
  write_tim(SLA_W);             //发送写地址
  write_tim(0x02);             //写数据地址
  
  start();
  waitack();                 //等待启动完成
  if(chkack()!=RESTART)return I2C_ERR;     //检查是否启动成功
  write_tim(SLA_R);             //发送读地址
  
  timer[0]=read_tim()&0x7F;       //读出秒数据
  timer[1]=read_tim()&0x7F;       //读出分数据
  timer[2]=read_tim()&0x3F;       //读出时数据
  timer[3]=read_tim()&0x3F;       //读出日数据
  timer[4]=read_tim()&0x07;       //读出周数据
    if(timer[4]==0)timer[4]=7;
  timer[5]=read_tim();           //读出月数据
    if((timer[5]&0x80)==0)
        timer[7]=0x20;           //世纪位为0,是21世纪
    else timer[7]=0x19;         //世纪位不为0,是20世纪
  timer[5]=timer[5]&0x1F;
  timer[6]=read_tim();         //读出年数据
  stop();
  return I2C_CRR;
  }

/**********************************
*       写入时钟函数         *
**********************************/
uchar write_timer(void)
  {
  start();                   //启动总线
  waitack();                 //等待启动完成
  if(chkack()!=START)return I2C_ERR;       //检查是否启动成功
  write_tim(SLA_W);             //发送写地址
  write_tim(0x00);             //写数据首地址
  write_tim(0x20);             //写控制/状态寄存器1,暂停计时
  write_tim(0x00);             //写控制/状态寄存器2
  write_tim(0x00);             //写秒数据为0
  write_tim(timer[1]);         //写分数据
  write_tim(timer[2]);         //写时数据
  write_tim(timer[3]);         //写日数据
  write_tim(timer[4]);         //写周数据
  write_tim(timer[5]);         //写月数据
  write_tim(timer[6]);         //写年数据
  stop();
  return I2C_CRR;
  }
  
/**********************************
*       启动时钟函数         *
**********************************/
uchar start_timer(void)
  {
  start();                   //启动总线
  waitack();                 //等待启动完成
  if(chkack()!=START)return I2C_ERR;       //检查是否启动成功
  write_tim(SLA_W);             //发送写地址
  write_tim(0x00);             //写数据首地址
  write_tim(0x00);             //写控制/状态寄存器1,暂停计时
  stop();
  return I2C_CRR;
  }

完整的工作项目文件如下:
点击此处下载 ourdev_662050Z55IX3.rar(文件大小:71K) (原文件名:1602_time.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2011-8-19 08:12:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-26 10:32:20 | 显示全部楼层
谢谢,不过附件无法下载,不知是否是改版的原因

出0入0汤圆

发表于 2012-3-26 10:37:31 | 显示全部楼层
下不了,我发贴,上传图片准是失败

出0入0汤圆

发表于 2012-5-15 11:41:55 | 显示全部楼层

出0入0汤圆

发表于 2012-9-5 18:24:20 | 显示全部楼层
HAOTIE,DING
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-15 10:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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