/*调试通过20130202
24c256连续读取多个数据.多写,可单读单写
*/
#include #include //数据类型预定义 8位,16位整数 #define INT8U unsigned char #define INT16U unsigned int # define F_CPU 7372800UL /* TWSR values (not bits) */ /* Master */ #define I2C_START 0x08 #define I2C_RESTART 0x10 /* Master Transmitter */ #define I2C_MT_SLA_ACK #define I2C_MT_SLA_NACK #define I2C_MT_DATA_ACK #define I2C_MT_DATA_NACK #define I2C_MT_ARB_LOST /* Master Receiver */ #define I2C_MR_ARB_LOST #define I2C_MR_SLA_ACK #define I2C_MR_SLA_NACK #define I2C_MR_DATA_ACK #define I2C_MR_DATA_NACK /* Slave Transmitter */ 0x18 //? 0x20 //? 0x28 0x30 //? 0x38 //? 0x38 //? 0x40 0x48 //? 0x50 //? 0x58 //? #define I2C_ST_SLA_ACK 0xA8 //? #define I2C_ST_ARB_LOST_SLA_ACK 0xB0 //? #define I2C_ST_DATA_ACK 0xB8 //? #define I2C_ST_DATA_NACK 0xC0 //? #define I2C_ST_LAST_DATA 0xC8 //? /* Slave Receiver */ #define I2C_SR_SLA_ACK 0x60 //? #define I2C_SR_ARB_LOST_SLA_ACK 0x68 //? #define I2C_SR_GCALL_ACK 0x70 //? #define I2C_SR_ARB_LOST_GCALL_ACK 0x78//? #define I2C_SR_DATA_ACK 0x80 //? #define I2C_SR_DATA_NACK 0x88 //? #define I2C_SR_GCALL_DATA_ACK 0x90 //? #define I2C_SR_GCALL_DATA_NACK 0x98 //? #define I2C_SR_STOP 0xA0 //? /* Misc */ #define I2C_NO_INFO 0xF8 //? #define I2C_BUS_ERROR 0x00 //? /* * The lower 3 bits of TWSR are reserved on the ATmega163. * The 2 LSB carry the prescaler bits on the newer ATmegas. */ #define I2C_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) #define I2C_STATUS (TWSR & I2C_STATUS_MASK) /* * R/~W bit in SLA+R/W address field. */ #define I2C_READ 1 #define I2C_WRITE 0 #define I2CStart() (TWCR=(1< #define I2CSendAck() (TWCR|=(1< #define I2C_Stop() I2CStop() #define I2C_SendAck() I2CSendAck() #define I2C_SendNoAck() I2CSendNoAck() #define I2C_WaitAck() I2CWaitAck() /* I2C Config */ #define I2C_ERR 0 #define I2C_CRR 1 //char data1;//为观察读取的数据的临时观察变量 #ifndef WR_DADR #define WR_DADR 0xa0 //write device-address #endif #ifndef RD_DADR #define RD_DADR 0xa1 //read device-address #endif //#define AT24CXX_ERR 0 //#define AT24CXX_CRR 1 //****************************** twi 初始化************************************* // TWCR: 控制寄存器,用来控制TWI操作,说明如下: // Bit 7-TWINT:中断标志位,Bit 6-TWEA:使能应答位,Bit 5-TWSTA:START状态位 // Bit 4-TWSTO:STOP状态位,Bit 3-TWWC: 写冲突标志,Bit 2-TWEN:TWI使能位 // Bit 1-RES:保留,Bit 0-TWIE:中断使能 // TWSR: 状态寄存器,Bits 7..3:表示了TWI总线的当前状态,读取时需屏蔽低三位的值,Bits 1..0-TWPS:TWI预分频位 // TWBR: 比特率寄存器,用来设置TWI的工作频率,计算公式为:SCL=CPU频率/(16+2*(TWBR)*4TWPS),TWPS在4的指数位置 // TWAR: 从机地址寄存器,Bits 7..1:存放从机地址,Bit 0:最低位为广播识别使能位 // TWDR: 数据寄存器,用来存放接收或要发送的地址和数据 //****************************************************************************** void twi_init(void) { TWBR=1; TWSR=0; TWCR=0x44; } /*-------------------------------------------------------------------- 程序名称:I2C Start 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_Start() { I2CStart(); I2CWaitAck(); //202页第二步等待 if( I2CChkAck()!=I2C_START ) //202页第三步 开始启动传输 return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C ReStart 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_Restart() { I2CStart(); I2CWaitAck(); if( I2CChkAck()!=0x10 ) return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)发送 7位 器件写地址: XXXX XXX0 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_SendWrDAdr(INT8U wrDAdr) //wrDAdr相当于202页表中提到的sla_w { I2CSendByte(wrDAdr); //202页第四步1 .将SLA_W载入到TWDR 寄存器,TWINT位清零,启动发送地址设置 器件写地址 I2CWaitAck(); //202页第四步2 等待TWINT 置位,TWINT置位表示总线命令SLA+W 已发出,及收到应答信号ACK/NACK if((TWSR&0xf8) != 0x18) //202页表 中第5步 检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理 return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)发送 10位 器件写地址: 1111 0XX0, XXXX XXXX 程序功能: 注意事项: 提示说明:兼容 发送 7位 器件写地址: XXXX XXX0 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_SendWrDAdr_(INT16U wrDAdr) { if((wrDAdr & 0xf000) == 0xF000) //判断是否为 10位 器件地址 if(I2C_SendWrDAdr((INT8U)wrDAdr>>8 )==I2C_ERR) //设置 (高位)器件写地址 return I2C_ERR; if( I2C_SendWrDAdr((INT8U)wrDAdr)==I2C_ERR) //设置 (低位)器件写地址 return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)发送 7位 器件读地址: XXXX XXX1 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_SendRdDAdr(INT8U rdDAdr) { I2CSendByte(rdDAdr); //设置 器件读地址 I2CWaitAck(); if( I2CChkAck()!=I2C_MR_SLA_ACK )//I2C_MR_SLA_ACK=0x40 return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)发送 10位 器件读地址: 1111 0XX0, XXXX XXXX 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_SendRdDAdr_(INT8U rdDAdr) { if( rdDAdr&0xf000 ==0xf000 ) //判断是否为 10位 器件地址 if( I2C_SendWrDAdr((INT8U)rdDAdr>>8)==I2C_ERR) //设置 (高位)器件读地址 return I2C_ERR; if( I2C_SendWrDAdr((INT8U)rdDAdr)==I2C_ERR) //设置 (低位)器件读地址 return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)发送数据 程序功能: 注意事项: 提示说明: 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_SendDat(INT8U configDat) //原先位16位 { I2CSendByte(configDat); I2CWaitAck(); if( I2CChkAck()!=I2C_MT_DATA_ACK ) return I2C_ERR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)接收数据且不产生应答 程序功能:只读一个字节,然后停止读取 注意事项: 提示说明:读取一个字节后,发送不响应,用于读取1个字节 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_RcvNAckDat(INT8U *pRdDat) { I2CRcvNckByte(); I2CWaitAck(); if(I2CChkAck()!=I2C_MR_DATA_NACK)//接收到数据0x58 return I2C_ERR; *pRdDat=TWDR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)接收数据且产生应答 程序功能:用于连续读取,读取单个字节后,在读下一个字节.最后读取n个字节后,再停止. 注意事项: 提示说明:读取一个字节后,发送响应,用于读取多个字节 输 入: 返 回: --------------------------------------------------------------------*/ INT8U I2C_RcvAckDat(INT8U *pRdDat) { I2CRcvAckByte(); I2CWaitAck(); if( I2CChkAck()!=0x50) return I2C_ERR; *pRdDat=TWDR; return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)写器件,写一个数据 程序功能: 注意事项: 提示说明: 输 入:wrDAdr: write device-address 写器件地址 wordAdr: word address 字地址 dat: data 数据 返 回: --------------------------------------------------------------------*/ INT8U I2CWriteByte(INT8U wrDAdr,INT16U wordAdr,INT8U dat) { if( I2C_Start()==I2C_ERR ) return I2C_ERR; if( I2C_SendWrDAdr_(wrDAdr)==0) return I2C_ERR; if( I2C_SendDat((wordAdr&0xff00)>>8)==I2C_ERR ) return I2C_ERR; if( I2C_SendDat(wordAdr&0x00ff)==I2C_ERR ) return I2C_ERR; if( I2C_SendDat(dat)==0 ) return I2C_ERR; I2C_Stop(); return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)写器件,写N个数据 程序功能: 注意事项: 提示说明: 输 入:wrDAdr: write device-address 写器件地址 wordAdr: word address 存储数据的起始地址 *pWrDat: p->write data 写入数据指针 num: number 写入数据个数 返 回: --------------------------------------------------------------------*/ INT8U I2CWriteStr(INT8U wrDAdr,INT16U wordAdr,INT8U *pWrDat,INT8U num) { INT16U i; if( I2C_Start()==I2C_ERR ) return I2C_ERR; if( I2C_SendWrDAdr_(wrDAdr)==0) return I2C_ERR; if( I2C_SendDat((wordAdr&0xff00)>>8)==I2C_ERR ) return I2C_ERR; if( I2C_SendDat(wordAdr&0x00ff)==I2C_ERR ) return I2C_ERR; for (i=0;i return I2C_ERR; I2C_Stop(); return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)读器件,读一个数据 程序功能: 注意事项: 提示说明: 输 入:wrDAdr: write device-address 写器件地址 wordAdr: word address 字地址 rdDAdr: read device-address 读器件地址 *pRdDat: p->read data 读取数据指针 返 回: --------------------------------------------------------------------*/ INT8U I2CReadByte(INT8U wrDAdr,INT16U wordAdr,INT8U rdDAdr,INT8U *pRdDat) { if( I2C_Start()==I2C_ERR ) return I2C_ERR; if( I2C_SendWrDAdr_(wrDAdr)==I2C_ERR ) return I2C_ERR; ////16位地址拆分 if( I2C_SendDat((wordAdr&0xff00)>>8)==I2C_ERR ) return I2C_ERR; if( I2C_SendDat(wordAdr&0x00ff)==I2C_ERR ) return I2C_ERR; if( I2C_Restart()==I2C_ERR ) return I2C_ERR; if( I2C_SendRdDAdr(rdDAdr)==I2C_ERR ) return I2C_ERR; if( I2C_RcvNAckDat(pRdDat)==I2C_ERR ) return I2C_ERR; I2C_Stop(); return I2C_CRR; } /*-------------------------------------------------------------------- 程序名称:I2C(TWI)读器件,读N个数据 程序功能: 注意事项: 提示说明: 输 入:wrDAdr: write device-address 写器件地址 wordAdr: word address 存储数据的起始地址 rdDAdr: read device-address 读器件地址 *pRdDat: p->read data 读取数据指针 num: number 读取数据个数 返 回: --------------------------------------------------------------------*/ INT8U I2CReadStr(INT8U wrDAdr,INT16U wordAdr,INT8U rdDAdr,INT8U *pRdDat,INT8U num) { INT8U i; if( I2C_Start()==I2C_ERR ) return I2C_ERR; if( I2C_SendWrDAdr_(wrDAdr)==I2C_ERR ) return I2C_ERR; //16位24c256存储空间地址拆分 if( I2C_SendDat((wordAdr&0xff00)>>8)==I2C_ERR ) return I2C_ERR; if( I2C_SendDat(wordAdr&0x00ff)==I2C_ERR ) return I2C_ERR; if( I2C_Restart()==I2C_ERR ) return I2C_ERR; if( I2C_SendRdDAdr(rdDAdr)==I2C_ERR ) return I2C_ERR; for(i=0;i return I2C_ERR; if( I2C_RcvNAckDat(pRdDat+i)==I2C_ERR ) return I2C_ERR; I2C_Stop(); return I2C_CRR; } // int main(void) { int i; INT8U data2[256]={0}; INT8U data21[256]={0}; INT8U data3[]={ 0x11,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x2e, 0x65,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x3e, 0x75,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x4e, 0x85,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x5e, 0x95,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x6e, 0x05,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x11, 0x54,0x88,0x1,0x1, 0x11,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x2e, 0x65,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x3e, 0x75,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x4e, 0x85,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x5e, 0x95,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x6e, 0x05,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x11, 0x54,0x88,0x1,0x1, 0x11,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x2e, 0x65,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x3e, 0x75,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x4e, 0x85,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x5e, 0x95,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x6e, 0x05,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x11, 0x54,0x88,0x1,0x1, 0x11,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x2e, 0x65,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x3e, 0x75,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x4e, 0x85,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x5e, 0x95,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x6e, 0x05,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x11, 0x54,0x88,0x1,0x1 //0x14,0x1a,0x1b,0x1c,0x1d,0x1e }; INT8U data4[64]={ 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa, 0x11,0x22,0x33,0x44 //0x14,0x1a,0x1b,0x1c,0x1d,0x1e }; INT8U data5[64]={ 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xaa,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11, 0xbb,0xcc,0xdd,0xee //0x14,0x1a,0x1b,0x1c,0x1d,0x1e }; INT8U data6[64]={ 0x55,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x2e, 0x65,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x3e, 0x75,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x4e, 0x85,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x5e, 0x95,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x6e, 0x05,0x68,0xde,0xab,0xc4,0xaa,0xbb,0xcc,0xdd,0x7e, 0x55,0x12,0x4,0x4 //0x14,0x1a,0x1b,0x1c,0x1d,0x1e }; INT8U dat1[1]; char c; while(1) { twi_init(); _delay_ms(400); I2CWriteStr(0xa0,0x0000,data4,64); _delay_ms(400); I2CWriteStr(0xa0,0x0040,data5,64); _delay_ms(400); I2CWriteStr(0xa0,0x0080,data6,64); _delay_ms(400); I2CReadStr(0xa0,0x0000,0xa1,data2,64);//多读 _delay_ms(400); I2CReadStr(0xa0,0x0040,0xa1,data2,64);//多读 _delay_ms(400); I2CReadStr(0xa0,0x0080,0xa1,data2,64);//多读 _delay_ms(400); I2CReadStr(0xa0,0x0000,0xa1,data2,64);//多读 _delay_ms(400); for (i=0;i<192;i++) { I2CWriteByte(0xa0,0x2000+i,0x05);//写入地址0x0001中一个数据0x64 _delay_ms(250);//延时十分必要 } I2CReadStr(0xa0,0x2000,0xa1,data2,192);//多读 _delay_ms(400); I2CReadStr(0xa0,0x2000,0xa1,data2,256);//多读 _delay_ms(400); I2CReadStr(0xa0,0x2000,0xa1,data2,256);//多读 _delay_ms(400); } } 因篇幅问题不能全部显示,请点此查看更多更全内容