|
在我们日常开发过程中,常用到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。/ \$ z7 }" [. L7 R' @- Q1 G
4、EEPROM写时序如下图,通过时序图我们确定写入是,需要先写入硬件地址0xA0,再写入两字节页内地址,后面写入的是数据内容。注意数据内容长度要小于等于32-页内起始地址。 b) @9 F, [7 ]7 D3 F
5、EEPROM读时序如下图,通过时序图我们发现,读写操作是不一样的。读操作需要先写入设备地址,两字节页地址后,需要重新发送一个读取的start信号,然后就可以读取数据了。读数据时不需要考虑读的长度,但也不能超出EEPROM的范围。8 y. m) b! ?- c6 ^/ \
6、结合上面的介绍,我们来看一下EEPROM的代码操作。首先我们需要对I2C进行初始化,初始化时需要考虑I2C的复用功能,407和103的使用方法不同,需要注意。我们以407为例,代码初始化如下所示: /* Peripheral clock enable */. Y& h4 G# b8 G% F RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); G% t1 g7 |( q /**I2C2 GPIO Configuration PB8 ------> I2C1_SCL PB9 ------> I2C1_SDA7 w( R9 C. y/ y */- X3 }6 V" ^3 I5 W( F: _" V RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);1 c/ J3 E; @/ _3 a- j6 V+ Z GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);$ K ]7 ~3 i! Y0 _. J( T GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); . m1 B; J. h A* A* H& {6 M /*!< Configure I2C2 pins: SCL,SDA */0 M. @4 ^ e$ D3 k GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;% G3 l+ `- x9 \* {( D3 ?) x& d GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;; Z6 }: A; `! F/ A) m1 v2 H8 C GPIO_Init(GPIOB, &GPIO_InitStructure);1 ]1 J( v1 c2 w' q Std_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0); Std_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);7、读操作代码 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));1 o- n k) _" p: A$ H+ z I2C_GenerateSTART(I2C1, ENABLE); S' O0 b+ y6 [ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5" W2 {4 T; ^" L8 M+ r$ p6 G 3 R( ^+ t( _/ y4 b I2C_Send7bitAddress(I2C1, addr_dev, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //EV64 W+ @5 W9 u& {8 Z& _* |# t' J - o. P5 g5 A8 ^: l I2C_SendData(I2C1,addr>>8]);% N% v& R1 \" i! `, n while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));//EV8 I2C_SendData(I2C1, addr); while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);//EV8, \* @" ^' v/ q3 X( z$ S( C/ d; X 7 d5 n( |9 O: d8 H' L I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5 6 m4 V2 {0 A0 R: m5 I Z I2C_Send7bitAddress(I2C1, addr_dev|0x01, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//EV62 o& h/ x5 A9 T ?; ?! _ while(Num --> 1)8 g' J! B- ^* W8 U4 t2 [ {9 E1 }8 |0 w9 Z3 K( K& j+ q! @ while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET); *pBuffer++ = I2C_ReceiveData(I2C1);7 X4 ?! T6 h& Z2 }0 L }4 Z3 ^% }& f3 b! f/ M1 } I2C_AcknowledgeConfig(I2C1, DISABLE);/ y* D0 B5 u# A. G! W- P { I2C_GenerateSTOP(I2C1, ENABLE); while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);+ p8 g0 M" m& @3 i% X; e *pBuffer++ = I2C_ReceiveData(I2C1); 8、写操作代码 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));, C1 \) c" d; j- L ! |# J3 P; m( Y r I2C_GenerateSTART(I2C1, ENABLE);0 Q. C& r% n+ k( B while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //EV5' v8 |; Z5 y. ~$ F0 q I2C_Send7bitAddress(I2C1, addr_dev, I2C_Direction_Transmitter);8 H# ?% c$ }- p; R/ ], t O/ `: l. n while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //EV6 (void)I2C1->SR1;//EV6 I2C_SendData(I2C1, addr>>8]); //EV8-1 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8 I2C_SendData(I2C1, addr); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8; n4 g2 O' d7 M1 s& ] while(Num-->0)3 T- i3 W) h3 c8 `0 B# \* _+ o { I2C_SendData(I2C1,*pBuffer++); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); //EV8! Q" S2 R3 z* f: E' j$ }, K } I2C_GenerateSTOP(I2C1,ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //EV8-2: o0 X4 ]8 N0 A) X + |! c" U( L0 v3 k& x( ` % ?" B2 {* p! P' A: o ; d# x2 b" t: s {: K0 F / ]* Y$ o, E0 i h: r1 V7 u* o Q" S' ~ |
【NUCLEO-WBA65RI评测】物联网 LED
【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数据
微信公众号
手机版