硬件I2C(TWI)读写PCF8563和24CXX程序

2019-04-15 14:53发布

//ICC-AVR application builder : 2010-3-5 13:51:50 // Target : M88 // Crystal: 8.0000Mhz #include #include #include //I2C(TWI)基本指令 #define I2C_START() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTA) #define I2C_STOP() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWSTO) #define I2C_ACK() TWCR = BIT(TWINT)|BIT(TWEN)|BIT(TWEA) #define I2C_NAK() TWCR = BIT(TWINT)|BIT(TWEN) #define I2C_CHECK_STATUS(X) {while(!(TWCR&BIT(TWINT))); if((TWSR&0xF8)!=(X)) return 0;} #define I2C_WRITE(X) TWDR = (X) #define I2C_READ(X) (X) = TWDR //TWSR&0xF8 状态码 #define START 0x08 #define RE_START 0x10 #define MT_SLA_ACK 0x18 #define MT_SLA_NAK 0x20 #define MT_DATA_ACK 0x28 #define MT_DATA_NAK 0x30 #define SLA_DATA_FAIL 0x38 #define MR_SLA_ACK 0x40 #define MR_SLA_NAK 0x48 #define MR_DATA_ACK 0x50 #define MR_DATA_NAK 0x58 //器件地址及参数 #define SLA_R_24C64 0xA1 #define SLA_W_24C64 0xA0 #define PAGE_SIZE_24C64 32 #define NUM_PAGE_24C64 256 #define SLA_R_PCF8563 0xA3 #define SLA_W_PCF8563 0xA2 #define PAGE_SIZE_PCF8563 16 #define NUM_PAGE_PCF8563 1 //毫秒级延时 void delay_ms(unsigned int x) { int i,j; for(j=0;j>8); I2C_NAK(); I2C_CHECK_STATUS(MT_DATA_ACK); } I2C_WRITE((unsigned char)ADDR); I2C_NAK(); I2C_CHECK_STATUS(MT_DATA_ACK); for(i=0;i>8); I2C_NAK(); I2C_CHECK_STATUS(MT_DATA_ACK); } I2C_WRITE((unsigned char)ADDR); I2C_NAK(); I2C_CHECK_STATUS(MT_DATA_ACK); I2C_START(); I2C_CHECK_STATUS(RE_START); I2C_WRITE(SLA_R); I2C_NAK(); I2C_CHECK_STATUS(MR_SLA_ACK); if(N>1) { for(i=0;iNUM_PAGE-1) { //not enough memory return; } PAGE=ADDR/PAGE_SIZE; NBYTES[0]=(PAGE+1)*PAGE_SIZE-ADDR; NBYTES[1]=(ADDR+N)-(END_PAGE*PAGE_SIZE); if(NBYTES[0]) { i2c_write_n_bytes(SLA_W,ADDR,NBYTES[0],DAT); //delay_ms(10);//仿真时用延时代替器件忙检测 while(i2c_check_busy(SLA_W));//器件忙检测 } if(END_PAGE>PAGE) { i=0; while(END_PAGE>++PAGE) { i2c_write_n_bytes(SLA_W,(PAGE*PAGE_SIZE),PAGE_SIZE,(DAT+NBYTES[0]+(i++)*PAGE_SIZE)); //delay_ms(10);//仿真时用延时代替器件忙检测 while(i2c_check_busy(SLA_W));//器件忙检测 } if(NBYTES[1]) { i2c_write_n_bytes(SLA_W,(PAGE*PAGE_SIZE),NBYTES[1],(DAT+NBYTES[0]+i*PAGE_SIZE)); //delay_ms(10);//仿真时用延时代替器件忙检测 while(i2c_check_busy(SLA_W));//器件忙检测 } } } /************************************************************************ I2C主机从从器件(EEPROM)读N字节数据 编程:许工 QQ11520389 时间:2010.03.05 参数说明: SLA_R: 从器件读地址 PAGE_SIZE: EEPROM页大小(单位:字节) NUM_PAGE: EEPROM总页数 ADDR: 从器件内部读数据起始地址 N: 读数据字节数 DAT: 目标数据起始地址 ************************************************************************/ void SEEPROM_read_n_bytes(unsigned char SLA_R,unsigned int PAGE_SIZE,unsigned int NUM_PAGE, unsigned int ADDR,unsigned int N,unsigned char *DAT) { unsigned int PAGE,END_PAGE,NBYTES[2],i; END_PAGE=(ADDR+N)/PAGE_SIZE; if(END_PAGE>NUM_PAGE-1) { //not enough memory return; } PAGE=ADDR/PAGE_SIZE; NBYTES[0]=(PAGE+1)*PAGE_SIZE-ADDR; NBYTES[1]=(ADDR+N)-(END_PAGE*PAGE_SIZE); if(NBYTES[0]) { i2c_read_n_bytes(SLA_R,ADDR,NBYTES[0],DAT); } if(END_PAGE>PAGE) { i=0; while(END_PAGE>++PAGE) { i2c_read_n_bytes(SLA_R,(PAGE*PAGE_SIZE),PAGE_SIZE,(DAT+NBYTES[0]+(i++)*PAGE_SIZE)); } if(NBYTES[1]) { i2c_read_n_bytes(SLA_R,(PAGE*PAGE_SIZE),NBYTES[1],(DAT+NBYTES[0]+i*PAGE_SIZE)); } } } //PCF8563时钟停止指令 void PCF8563_stop(void) { unsigned char stopcode=0x20; i2c_write_n_bytes(SLA_W_PCF8563,0,1,&stopcode); } //PCF8563时钟启动指令 void PCF8563_start(void) { unsigned char startcode=0x00; i2c_write_n_bytes(SLA_W_PCF8563,0,1,&startcode); } /************************************************************************ PCF8563时钟设置 编程:许工 QQ11520389 时间:2010.03.05 参数说明:(BCD码) yy: 年(0x00到0x99) mm: 月(0x01到0x12) dd: 日(0x01到0x31) hh: 时(0x00到0x23) mi: 分(0x00到0x59) ss: 秒(0x00到0x59) da: 星期(0x01到0x07) ************************************************************************/ void PCF8563_set(unsigned char yy,unsigned char mm,unsigned char dd, unsigned char da,unsigned char hh,unsigned char mi,unsigned char ss) { unsigned char time[7]; time[6]=yy; //年 time[5]=mm;//月 time[4]=da; //星期 time[3]=dd; //日 time[2]=hh;//时 time[1]=mi;//分 time[0]=ss;//秒 PCF8563_stop(); i2c_write_n_bytes(SLA_W_PCF8563,2,7,time); PCF8563_start(); } /************************************************************************ PCF8563时钟读取 编程:许工 QQ11520389 时间:2010.03.05 参数说明:(BCD码) time: 存放读出时间的数组名 time[6]: 年(0x00到0x99) time[5]: 月(0x01到0x12) time[3]: 日(0x01到0x31) time[2]: 时(0x00到0x23) time[1]: 分(0x00到0x59) time[0]: 秒(0x00到0x59) time[4]: 星期(0x01到0x07) ************************************************************************/ void PCF8563_read(unsigned char *time) { i2c_read_n_bytes(SLA_R_PCF8563,2,7,time); //time[6] //年 time[5] &= 0x1F;//月 time[4] &= 0x07;//星期 time[3] &= 0x3F;//日 time[2] &= 0x3F;//时 time[1] &= 0x7F;//分 time[0] &= 0x7F;//秒 } void main(void) { unsigned char dat[132]; unsigned int i; DDRD|=3;//RED ON PORTD|=1; DDRC&=~(BIT(PC4)|BIT(PC5));//Pull up the pin SDA and SCL PORTC|=BIT(PC4)|BIT(PC5); TWCR=0; TWBR=12; //set bit rate TWSR=0; //set prescale /* PCF8563_set(0x10,0x03,0x04,0x04,0x11,0x25,0x45); delay_ms(1000); PCF8563_read(dat); //*/ //* for(i=0;i<132;i++) dat=i; for(i=0;i<2;i++) SEEPROM_write_n_bytes(SLA_W_24C64,PAGE_SIZE_24C64,NUM_PAGE_24C64,i*66+4,66,dat); //*/ //* for(i=0;i<132;i++) dat=255; SEEPROM_read_n_bytes(SLA_R_24C64,PAGE_SIZE_24C64,NUM_PAGE_24C64,4,132,dat); //*/ EEPROM_WRITE(0, dat); PORTD&=~1; PORTD|=2;//GREEN ON }