首页 > 代码库 > AT24C02/04/08 地址理解
AT24C02/04/08 地址理解
该类器件要通过iic总线操作,读写过程中都要先寻址,这类器件地址有两个字节组成,如下表,1010是固定的,A表示器件地址,可以拉高和拉低,iic总线上可以并接2的几次方个器件。P表示具体的内部地址数,比如at24c02共有256个字节,第二个地址字节完全可以满足,不用P。但是at24c04一个有512个字节,需要9位地址线,第一个字节中的p就表示地址线了,p=0表示低256字节,1表示高256字节。
注意:一般页写可以连续写8个数据。主机每发送一个字节都要接受从机的应答信号。该类器件是采用iic总线进行操作的,器件地址根据容量的不同稍有不同,如下
对于芯片的A0,A1,A2脚:
24C01/02,A0,A1,A2都是从设备地址。
24C04,A1,A2是从设备地址,A0没用
24C08,A2是从设备地址,A0,A1没用
24C16及以上,A0,A1,A2都没用了。
其中,A表示期间地址,p表示也地址,在读写的时候首先是起始条件+器件地址
器件地址如上所示在16k中,需要两个字节表示内部地址,正是p2/1/0 和8位具体的地址
AT24C08为例子
//端口定义 #define SCL_L GPIOB->BSRR |= 1<<(16+6) #define SCL_H GPIOB->BSRR |= 1<<6 #define SDA_L GPIOB->BSRR |= 1<<(16+7) #define SDA_H GPIOB->BSRR |= 1<<7 #define SDA_RED GPIOB->IDR & 1<<7 //sda #define AT24C08Address 0xA0 // 8k 1010 A_2 P_1 P_0 R/W 数据地址 p1,p2+8位 共十个地址位 // p1 p0 4块(256字节) 一块16页 一页16字节 void GPIO_Init(void); //初始化 u8 IIC_ReadByte(void); u8 IIC_WriteByte(u8 SendByte); u8 IIC_STOP(void ); u8 IIC_START(void); u8 AT24C02Read(u8 RomAddr); u8 AT24C02Write(u8 RomAddr,u8 RegData); u8 IIC_NACK(void); u8 IIC_ACK(void) ; u8 IIC_WaitAck(void) ; u8 InitAT24C02(void); /初始化PB6和PB7 PC13为输出口.并使能这两个口的时钟 void GPIO_Init(void) { RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<4; //使能PORTC时钟 GPIOB->CRL&=0X00FFFFFF; GPIOB->CRL|=0X77000000; //PB6 PB7 开漏输出 //led GPIOC->CRH &=0XFF0FFFFF; GPIOC->CRH |=0X00300000; //PC13推挽输出 GPIOC->ODR |=1<<13; } u8 IIC_START() { SCL_L; //准备 SDA_H; SCL_H; //scl 高电平 此时改变sda 结束或开始的标志 if(!SDA_RED) //测试sda有没占用 若sda 被从机接地拉低 主机无法拉高 return 0; SDA_L; if(SDA_RED) //总线出错 return 0; SDA_L; //主机钳住I2C总线,准备发送或接收数据 return 1; } u8 IIC_STOP() { SCL_L; SDA_L; delay_us(4); SCL_H; delay_us(4); SDA_H; //发送I2C总线结束信号 delay_us(4); if(!SDA_RED) //sda 被从机接地拉低 主机无法拉高 return 0; return 1; } u8 IIC_WriteByte(u8 SendByte) { u8 i =8; SCL_L; //拉低时钟开始数据传输 while(i--) { SCL_L; if(SendByte & 0x80) SDA_H; else SDA_L; SendByte<<=1; delay_us(4); //scl 产生脉冲 SCL_H; delay_us(4); } SCL_L; } u8 IIC_ReadByte(void) { u8 i =8,ReceiveByte; // SDA_H; while(i--) { SCL_L; delay_us(4); //先给个脉冲 SCL_H; //拉高时钟开始数据接收 sda交给从机 ReceiveByte <<=1; if(SDA_RED) ReceiveByte |=1; delay_us(4); } SCL_L; return ReceiveByte; } u8 IIC_WaitAck(void) /*stm32 发送时用*/ { SCL_L; //scl 低 主机方能改变sda delay_us(4); SDA_H; //主机置高sda 等待回复 从机将拉低 sda delay_us(2); SCL_H; //产生脉冲 if(SDA_RED) //从机不拉低sda 即不回复 return 0; SCL_L; return 1; } u8 IIC_ACK(void) //主机必须在从机发出最后一个字节时产生一个响应 只讲主发送从接收 //从机发送器通知数据结束 “知道吗” /****stm32接收时用*/ { SCL_L; __nop(); SDA_L; //从机stm32响应 scl低时 拉低sda delay_us(4); SCL_H; delay_us(4); SCL_L; } u8 IIC_NACK(void) /****stm32接收时用*/ { SCL_L; __nop(); SDA_H; //从机stm32不响应 sda置高 delay_us(4); SCL_H; delay_us(4); SCL_L; } /******** AT24C02读写操作 ********/ u8 AT24C02Write(u8 RomAddr,u8 RegData) { if(! IIC_START()) return 0; IIC_WriteByte(AT24C08Address); //写模式 if(!IIC_WaitAck()) { IIC_STOP(); return 0; } IIC_WriteByte(RomAddr); if(!IIC_WaitAck()) { IIC_STOP(); return 0; } IIC_WriteByte(RegData); if(!IIC_WaitAck()) { IIC_STOP(); return 0; } IIC_STOP(); return 1; } u8 AT24C02Read(u8 RomAddr) { u8 receive; if(!IIC_START()) { IIC_STOP(); return 0; } IIC_WriteByte(AT24C08Address); if(! IIC_WaitAck()) { IIC_STOP(); return 0; } IIC_WriteByte(RomAddr); if(! IIC_WaitAck()) { IIC_STOP(); return 0; } IIC_START(); IIC_WriteByte(AT24C08Address+1); //配置成读模式 if(! IIC_WaitAck()) { IIC_STOP(); return 0; } receive=IIC_ReadByte(); IIC_NACK(); IIC_STOP(); return receive; } u8 H; int main(void) { Stm32_Clock_Init(9); //系统时钟设置 delay_init(72); //延时初始化 GPIO_Init(); //初始化与LED连接的硬件接口 AT24C02Write(0x00,0xf5); H=AT24C02Read(0x00); if(H==0xf5) { while(1) { GPIOC->ODR &=0<<13; delay_ms(500); GPIOC->ODR |=1<<13; delay_ms(500); } } else GPIOC->ODR |=1<<13; } //数据一致 led闪烁
AT24C02/04/08 地址理解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。