📄 i2c.c
字号:
//PCF8583的宏定义
#define TDATA_H 0x0008 //FLOATS DATA LINE (IOPF3=1)
#define TDATA_L 0xFFF7 //DRIVES DATA LINE LOW(IOPF3=0)
#define TCLOCK_H 0x0004 //FLOATS CLOCK LINE (IOPF2=1)
#define TCLOCK_L 0xFFFB //DRIVES CLOCK LINE LOW(IOPF2=0)
#define TDATACLOCK_H 0x000C //FLOATS CLOCK AND DATA LINE(IOPF2 IOPF3=11)
#define TDATACLOCK_L 0xFFF3 //DRIVE CLOCK AND DATA LINE LOW(IOPF2,IOPF3=00)
#define TDATA_INPUT 0xF7FF //PFDATDIR.11=0
#define TDATA_OUTPUT 0x0800 //PFDATDIR.11=1
#define TSHIFTNUM 5
#define TNUMBER 6 //读写PCF8583的参数个数
/****************************************/
void delay(int x)
{ int count;
for(count=0;count<x;count++)
;
}
/*;======== I2C发送一字节子程序 ====================
; 描述:通过SDA线向EEPROM器件发送一个字节
;=================================================*/
void pcf_transmit(unsigned int pcfdata)
{ unsigned int i;
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*SCL=0*/
delay(72);
*PFDATDIR=*PFDATDIR|TDATA_OUTPUT; /*SDA output*/
for(i=0;i<8;i++)
{
if(pcfdata&0x0080)
*PFDATDIR=*PFDATDIR|TDATA_H; /*SDA=1*/
else
*PFDATDIR=*PFDATDIR&TDATA_L; /*SDA=0*/
delay(72); //64
*PFDATDIR=*PFDATDIR|TCLOCK_H; /*SCL=1*/
delay(72);
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*SCL=0*/
delay(24); //8添加的!!!!!!!!!!!
pcfdata=pcfdata<<1;
}
}
/*;======== I2C接收一字节子程序 ====================
; 描述:通过SDA线从EEPROM器件读入一个字节
;=================================================*/
unsigned int pcf_receive()
{ unsigned int i,temp;
unsigned int pcfdata=0x0000;
*PFDATDIR=*PFDATDIR&TDATA_INPUT;/*SDA INPUT*/
*PFDATDIR=*PFDATDIR&TDATACLOCK_L; //SCL=0,?????
delay(72);
for(i=0;i<8;i++)
{
pcfdata=pcfdata<<1;
*PFDATDIR=*PFDATDIR|TCLOCK_H; /*SCL=1*/
delay(72);
temp=*PFDATDIR&TDATA_H;
if(temp==0)
pcfdata=pcfdata&0XFFFE;/*如果数据位为0,则R_DATA最低位清0*/
else
pcfdata=pcfdata|0x0001;
//pcfdata=(pcfdata+((*PFDATDIR&TDATA_H)>>TSHIFTNUM))<<1; /*input DATA need change(>>)*/
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*SCL=0*/
delay(72);
}
*PFDATDIR=*PFDATDIR|TDATA_OUTPUT; /*SDA output*/
delay(24); //添加的!!!!!!!!!!!
//pcfdata=pcfdata>>1;
return(pcfdata);
}
/*;======== I2C 启动子程序 =========================
; 描述:启动I2C总线
;=================================================*/
void pcf_start()
{
*PFDATDIR=*PFDATDIR|TDATACLOCK_H; /*SDA=1,SCL=1*/
delay(72);
*PFDATDIR=*PFDATDIR&TDATA_L; /*SDA=0*/
delay(72);
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*SCL=0*/
delay(24); //添加的!!!!!!!!!!!
}
/*;======== I2C 结束子程序 =========================
; 描述:结束 I2C 总线
;=================================================*/
void pcf_stop()
{
*PFDATDIR=*PFDATDIR&TDATA_L; //SDA=0
delay(24); //16*/
*PFDATDIR=*PFDATDIR|TCLOCK_H; /*SCL=1*/
delay(24); //8添加的!!!!!!!!!!!
*PFDATDIR=*PFDATDIR|TDATA_H; /*SDA=1*/
delay(24);
}
/*;======== I2C 从机应答子程序 =====================
; 描述:从机发应答信号
;=================================================*/
unsigned int pcf_slave_ack()
{ unsigned int k;
*PFDATDIR=*PFDATDIR|TDATA_H; /* SDA=1*/
delay(24); //8
*PFDATDIR=*PFDATDIR&TDATA_INPUT; /* SDA设为输入*/
delay(24);
*PFDATDIR=*PFDATDIR|TCLOCK_H; /*SCL=1*/
delay(24);
if(*PFDATDIR&TDATA_H)
k=1; //失败
else
k=0;
*PFDATDIR=(*PFDATDIR|TDATA_OUTPUT)&TDATACLOCK_L;/*SDA设为输出,SDA=0,SCL=0*/
delay(24); //后来加的!!!!
return(k);
}
/*;======== I2C 主机不发应答子程序 =====================
; 描述:主机不发应答信号
;=================================================*/
void pcf_no_ack()
{
*PFDATDIR=*PFDATDIR|TCLOCK_H; /*SCL=1 */
delay(24); //8
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*Scl=0 */
delay(24); //添加的!!!!!!!!!!!
}
/*;======== I2C 主机应答子程序 =====================
; 描述:主机发应答信号
;=================================================*/
void pcf_master_ack()
{
*PFDATDIR=*PFDATDIR&TCLOCK_L; //SCL=0
*PFDATDIR=*PFDATDIR&TDATA_L; /*SDA=0 */
*PFDATDIR=*PFDATDIR|TCLOCK_H; //SCL=1
delay(24); //8添加的!!!!!!!!!!!
*PFDATDIR=*PFDATDIR&TCLOCK_L; /*Scl=0 */
}
/*;======== 向I2C 写1个字节子程序 =====================
; 描述:入口为要写入数据的地址ADDR,数据DATA
; 出口为0表示操作成功;为1表示操作失败
;=================================================*/
unsigned int byte_wr(unsigned int addr,unsigned int data)
{ unsigned int k;
pcf_start();
pcf_transmit(0x0A0); //送写控制字
k=pcf_slave_ack(); //从机应答
if(k==0)
{ pcf_transmit(addr); //送地址
k=pcf_slave_ack();
}
if(k==0)
{ pcf_transmit(data);
k=pcf_slave_ack();
}
if(k==0)
pcf_stop();
return(k);
}
/*;======== 从I2C 读1个字节子程序 =====================
; 描述:入口为要读数据的地址ADDR,
; 出口为数据DATA
;=================================================*/
unsigned int byte_rd(unsigned int addr)
{ unsigned int data=0,k;
pcf_start(); //启动I2C总线
pcf_transmit(0x0A0); //送写控制字
k=pcf_slave_ack(); //从机应答
if(k==0)
pcf_transmit(addr); //送地址
k=pcf_slave_ack();
if(k==0)
{ pcf_start();
pcf_transmit(0x0A1); //送读控制字
}
k=pcf_slave_ack();
if(k==0)
{ data=pcf_receive();
pcf_no_ack();
pcf_stop();
}
if(k==0)
return(data);
else
return(0x0FFFF);
}
/*;======== 连续页写子程序 ===========================
; 描述:向EEPROM写入1~TNUMBER个字,最多为TNUMBER个字(由EEPROM器件决定)
; 入口:要写的起始地址ADDR,要写数据的数组首址ARRAY
; 出口:返回0或1。为0表示操作成功;为1表示操作失败
;=================================================*/
unsigned int pcf_wr(unsigned int addr,unsigned int *array)
{ unsigned int k,i; /*page write subroutine*/
//delay(7500);
pcf_start();
pcf_transmit(0x0A0); //送写控制字
k=pcf_slave_ack();
if(k==0)
{ pcf_transmit(addr);
}
k=pcf_slave_ack();
if(k==0)
{ for(i=0;i<TNUMBER;i++)
{
/*pcf_transmit((*array>>8)&0xff); //送高8位
k=pcf_slave_ack();
if(k==1)
break;
array++;*/
pcf_transmit(*array); //送低8位
k=pcf_slave_ack();
if(k==1)
break;
array++;
}
}
pcf_stop();
return(k);
}
/*;======== 页读子程序 ===========================
; 描述:从EEPROM读出1~TNUMBER个字,最多为TNUMBER个字(由EEPROM器件决定)
; 入口:要读的起始地址ADDR,读出数据存放数组的首址ARRAY
; 出口:返回0或1。为0表示操作成功;为1表示操作失败
;=================================================*/
unsigned int pcf_rd(unsigned int addr,unsigned int *array)
{
unsigned int k,i,temp;
pcf_start();
pcf_transmit(0x0A0);
k=pcf_slave_ack();
if(k==0)
pcf_transmit(addr);
k=pcf_slave_ack();
if(k==0)
{ pcf_start();
pcf_transmit(0x0A1);
}
k=pcf_slave_ack();
if(k==0)
{ for(i=0;i<(TNUMBER-1);i++)
{
temp=pcf_receive();
/**array=temp;*/
*array=temp&0x00ff;
pcf_master_ack();
array++;
}
temp=pcf_receive();
/**array|=(temp&0x00ff); */
*array=temp&0x00ff;
pcf_no_ack();
pcf_stop();
}
return(k);
}
/**********从8583中读时间子程序------------------**********/
void time_read()
{
pcf_rd(0x02,&pcf_data[0]);
time[0]=year_base+((pcf_data[3]&0x00c0)>>6);//year
time[1]=((pcf_data[4]&0x001f)<<8)|(pcf_data[3]&0x003f); //month,date
time[2]=((pcf_data[4]&0x00e0)<<3)|pcf_data[2]; //week.hour
time[3]=(pcf_data[1]<<8)|pcf_data[0]; //minute,second
}
/***********----------------*********/
void time_write()
{
pcf_data[0]=0x0; //ms
pcf_data[1]=chtime[3]&0x00ff; //second
pcf_data[2]=(chtime[3]&0xff00)>>8; //minute
pcf_data[3]=chtime[2]&0x00ff; //hour;
pcf_data[4]=((chtime[0]&0x03)<<6)|(chtime[1]&0x003f); //year/date
pcf_data[5]=((chtime[2]&0x0700)>>3)|((chtime[1]&0x1f00)>>8); //week/month
pcf_wr(0x01,&pcf_data[0]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -