在我们日常开发过程中,常用到EEPROM作为数据存储。今天我以AT24C32为例,给大家接一下EEPROM的使用。1、在我们编写代码前,需要先确定EEPROM的连接STM32的I2C接口。 2、我们需要确定EEPROM的设备地址,在技术手册中找到Device Address,如下图所示。我们介绍使用A2 A1 A0均连接到GND。因此我们使用的Device Address为0xA0。R/W这一位由我们操作I2C读写时再填入。 3、确定EEPROM的内部地址访问规则,如下图所示,AT24C32的访问地址为16位,我们在发送start信号以后,需要连续写入两个字节的地址,再进行后续操作。需要确定2字节的内容存储的格式:AT24C32的页最大容量为32byte,bit0-4用来存写入页内地址,bit5-11填写页地址。比如访问AT24C32的地址为:35,输入页地址为addr=35%32 | ((uint16_t)(35/32)<<5)。换算后的结果为0x0023。 4、EEPROM写时序如下图,通过时序图我们确定写入是,需要先写入硬件地址0xA0,再写入两字节页内地址,后面写入的是数据内容。注意数据内容长度要小于等于32-页内起始地址。# \2 @1 |4 n5 N5 C 5、EEPROM读时序如下图,通过时序图我们发现,读写操作是不一样的。读操作需要先写入设备地址,两字节页地址后,需要重新发送一个读取的start信号,然后就可以读取数据了。读数据时不需要考虑读的长度,但也不能超出EEPROM的范围。6 J; L: @1 B) j, \1 p I 6、结合上面的介绍,我们来看一下EEPROM的代码操作。首先我们需要对I2C进行初始化,初始化时需要考虑I2C的复用功能,407和103的使用方法不同,需要注意。我们以407为例,代码初始化如下所示: /* Peripheral clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);% I, U/ X( \% s' o( O /**I2C2 GPIO Configuration PB8 ------> I2C1_SCL PB9 ------> I2C1_SDA */( T! w2 j! `3 a" q) u8 _ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);: v0 @5 O2 R- ~9 @ GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); /*!< Configure I2C2 pins: SCL,SDA */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;% j4 S" r$ |6 _' N" L GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;" `- U$ v8 F* N' L A1 h GPIO_Init(GPIOB, &GPIO_InitStructure); / M4 H. U% b/ W. y3 N9 A3 ~4 f Std_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0); Std_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);7、读操作代码 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));( m2 k- n5 P6 j, m8 ~ I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5 * o1 U. T" u) O5 e! i1 y I2C_Send7bitAddress(I2C1, addr_dev, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //EV6# @. _' n# i |; t, ]9 B. } I2C_SendData(I2C1,addr>>8]); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));//EV8% C8 Q1 ~/ R# O" W$ D* d " C, X: C' j) z( L' u I2C_SendData(I2C1, addr); while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);//EV8- T* B/ B- _/ F+ b* A # e: y# w0 N3 m I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5 I2C_Send7bitAddress(I2C1, addr_dev|0x01, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//EV6 while(Num --> 1)) \0 i6 u' K0 V* I- P% V0 N {: w5 E) i5 l0 | while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET); *pBuffer++ = I2C_ReceiveData(I2C1); }2 D; E* _3 z" b u3 o& n I2C_AcknowledgeConfig(I2C1, DISABLE);# c) X; B4 z; ^; ]1 {) ]9 f' C I2C_GenerateSTOP(I2C1, ENABLE); while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET); *pBuffer++ = I2C_ReceiveData(I2C1);' M: z( x% X6 X$ a* @ 8、写操作代码4 U" O j7 s# ?3 A2 X5 Q 5 z* \3 e& U' w while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));( y& [5 h3 ?3 ] I2C_GenerateSTART(I2C1, ENABLE);0 h" Z8 U. z! F. B: \4 S while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5+ f% R' Y/ [6 M7 c3 {+ r6 m8 w I2C_Send7bitAddress(I2C1, addr_dev, I2C_Direction_Transmitter);; G: q6 x n: K! t9 y8 m) n while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //EV6 t. r1 w+ K, i# |5 y (void)I2C1->SR1;//EV6+ d! n& y- ^4 x/ _8 d ( s) v P4 y8 @) |7 c I2C_SendData(I2C1, addr>>8]); //EV8-1( z& U2 B/ m8 W% W! U7 U while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV87 [6 `: U% ~4 T$ P9 I( Y) s8 W5 T I2C_SendData(I2C1, addr); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8( [0 Q- A7 S+ W2 x% I/ }" d: r2 y while(Num-->0), h' [9 b7 w2 z8 y8 [( I {8 t6 G' B: d5 D9 u, _ I2C_SendData(I2C1,*pBuffer++); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8 }* G- J, S0 Y) a* O" Y; {$ u8 a- u I2C_GenerateSTOP(I2C1,ENABLE);0 q) q% K- W2 |) z( X8 ] while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //EV8-2 - Y8 _* Q: r7 l- F9 D+ C . |! e0 J8 _6 g" L8 | 1 F2 B9 C4 ^/ N9 P& g" [ ( t8 t* @" B5 W, M5 J2 f! Z1 O, j 0 a7 y! o1 B' Z9 l1 I* p: \2 B$ @( q |
【NUCLEO-WB09KE评测】使用I2C点亮一个OLED
【NUCLEO-WB09KE评测】USART的printf和GPIO的使用
【STM32H7S78-DK评测】使用FatFs文件系统读取SD卡文件
【NUCLEO-H533RE评测】+04 串口中断使用心得
【NUCLEO-H533RE评测】+03 printf输出调试
传感器为什么需要智能?
关于STM32的SWD引脚错误配置,“No Target Connected”导致程序不能下载问题解决
【年中粉丝节】+18B20温度传感器
【年中粉丝节】STM32L476开发板-基于rtthread读取加速度传感器KX224数据
STM32F401CCU6快速移植littleVGL