一.使用寄存器编程写入EEPROM
EEPROM 写入的完整过程本质上是一次标准的 I2C Memory Write 时序:首先配置并使能 STM32 的 I2C 外设,随后依次发送 START 信号、EEPROM 器件地址(写方向)、待写入的 EEPROM 内部存储地址,紧接着将 1 字节(或多字节)数据通过 I2C 数据寄存器(DR)发送出去(这一时刻数据才真正进入 EEPROM),最后发送 STOP 信号结束总线通信;但由于 EEPROM 接收到数据后还需进行内部 Flash 写操作(tWR),此时它会暂时停止响应 I2C 总线,因此必须通过一个“轮询 ACK”的过程(即不断发送 START 和器件地址直到收到 ACK)来等待 EEPROM 内部写完成,只有完成这一步,一次 EEPROM 写入才算彻底结束。
uint32_t I2C_EE_ByteWrite(uint8_t* pBuffer, uint8_t WriteAddr)
{
uint32_t timeout;
/*--------------------------------------------------
* 1. 发送 START
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
/*--------------------------------------------------
* 2. 发送 EEPROM 器件地址(写)
*--------------------------------------------------*/
I2C1->DR = EEPROM_ADDRESS; // 0xA0
while (!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2; // 清 ADDR
/*--------------------------------------------------
* 3. 发送 EEPROM 内部地址
*--------------------------------------------------*/
I2C1->DR = WriteAddr;
while (!(I2C1->SR1 & I2C_SR1_TXE));
/*--------------------------------------------------
* 4. 发送数据
*--------------------------------------------------*/
I2C1->DR = *pBuffer;
while (!(I2C1->SR1 & I2C_SR1_TXE));
/*--------------------------------------------------
* 5. 发送 STOP
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_STOP;
/*--------------------------------------------------
* 6. 等待 EEPROM 内部写完成 这里,EEPROM在写入时不会应答地址,写入完成后才会应答地址
* 等价于 HAL_I2C_IsDeviceReady()
*--------------------------------------------------*/
timeout = EEPROM_MAX_TRIALS;
do
{
/* 发送 START */
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB) && timeout);
/* 发送 EEPROM 地址(写) */
I2C1->DR = EEPROM_ADDRESS;
timeout--;
while (!(I2C1->SR1 & I2C_SR1_ADDR) && timeout);
(void)I2C1->SR2;
I2C1->CR1 |= I2C_CR1_STOP;
}
while (timeout == 0);
return (timeout ? HAL_OK : HAL_TIMEOUT);
}
二.读EEPROM:
uint32_t I2C_EE_BufferRead(
uint8_t* pBuffer,
uint8_t ReadAddr,
uint16_t NumByteToRead
)
{
uint16_t i;
/*--------------------------------------------------
* 1. 发送 START
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
/*--------------------------------------------------
* 2. 发送 EEPROM 器件地址(写)
*--------------------------------------------------*/
I2C1->DR = EEPROM_ADDRESS; // 0xA0
while (!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2; // 清 ADDR
/*--------------------------------------------------
* 3. 发送 EEPROM 内部地址
*--------------------------------------------------*/
I2C1->DR = ReadAddr;
while (!(I2C1->SR1 & I2C_SR1_TXE));
/*--------------------------------------------------
* 4. 发送 ReSTART
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
/*--------------------------------------------------
* 5. 发送 EEPROM 器件地址(读)
*--------------------------------------------------*/
I2C1->DR = EEPROM_ADDRESS | 0x01;
while (!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2;
/*--------------------------------------------------
* 6. 连续读数据
*--------------------------------------------------*/
for (i = 0; i < NumByteToRead; i++)
{
/* 最后一个字节前给 ACK,最后一个给 NACK */
if (i == NumByteToRead - 1)
I2C1->CR1 &= ~I2C_CR1_ACK; // NACK
else
I2C1->CR1 |= I2C_CR1_ACK; // ACK
while (!(I2C1->SR1 & I2C_SR1_RXNE));
pBuffer[i] = I2C1->DR;
}
/*--------------------------------------------------
* 7. 发送 STOP
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_STOP;
return HAL_OK;
}
二.读EEPROM
uint32_t I2C_EE_BufferRead(
uint8_t* pBuffer,
uint8_t ReadAddr,
uint16_t NumByteToRead
)
{
uint16_t i;
/*--------------------------------------------------
* 1. 发送 START
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
/*--------------------------------------------------
* 2. 发送 EEPROM 器件地址(写)
*--------------------------------------------------*/
I2C1->DR = EEPROM_ADDRESS; // 0xA0
while (!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2; // 清 ADDR
/*--------------------------------------------------
* 3. 发送 EEPROM 内部地址
*--------------------------------------------------*/
I2C1->DR = ReadAddr;
while (!(I2C1->SR1 & I2C_SR1_TXE));
/*--------------------------------------------------
* 4. 发送 ReSTART
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB));
/*--------------------------------------------------
* 5. 发送 EEPROM 器件地址(读)
*--------------------------------------------------*/
I2C1->DR = EEPROM_ADDRESS | 0x01;
while (!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2;
/*--------------------------------------------------
* 6. 连续读数据
*--------------------------------------------------*/
for (i = 0; i < NumByteToRead; i++)
{
/* 最后一个字节前给 ACK,最后一个给 NACK */
if (i == NumByteToRead - 1)
I2C1->CR1 &= ~I2C_CR1_ACK; // NACK
else
I2C1->CR1 |= I2C_CR1_ACK; // ACK
while (!(I2C1->SR1 & I2C_SR1_RXNE));
pBuffer[i] = I2C1->DR;
}
/*--------------------------------------------------
* 7. 发送 STOP
*--------------------------------------------------*/
I2C1->CR1 |= I2C_CR1_STOP;
return HAL_OK;
}

7496

被折叠的 条评论
为什么被折叠?



