赞
踩
1、AT24C04 、AT24C08、AT24C016应该都适应这份代码,他们每一页的大小都是16字节。如果是AT24C02的话,每一页的大小为8个字节,修改一下#define I2C_PAGE_SIZE 8 应该也可以正常换页读取。
2、关于代码的宏定义配置
Application目录的Makefile中 ENABLE_I2C_TEST = yes才会编译I2C1的相关代码。
同时修改i2c.h文件,定义I2C1_MODE为I2C1_MODE_POLL,at24c08 .c 相关代码才会编译进去。
3、At24C08.c 核心就是一个换页写入的操作,因为eeprom连续写入时不支持自动换页,但是连续读取时,是可以自动换页的。
#include "gd32f30x.h"
#include "systick.h"
#include "at24c08.h"
#include "i2c.h"
#if I2C1_MODE == I2C1_MODE_POLL
#define I2C1_SPEED 100000
#define EE_ADDR 0xA0
#define I2C_PAGE_SIZE 16
/*!
\brief write one byte to the I2C EEPROM
\param[in] p_buffer: pointer to the buffer containing the data to be written to the EEPROM
\param[in] write_address: EEPROM's internal address to write to
\param[out] none
\retval none
*/
void eeprom_byte_write(uint8_t Data, uint8_t write_address)
{
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, EE_ADDR, I2C_TRANSMITTER);
/* wait until ADDSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
/* clear the ADDSEND bit */
i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
/* wait until the transmit data buffer is empty */
while(SET != i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* send the EEPROM's internal address to write to : only one byte address */
i2c_data_transmit(I2C1, write_address);
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* send the byte to be written */
i2c_data_transmit(I2C1, Data);
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* wait until the stop condition is finished */
while(I2C_CTL0(I2C1)&0x0200);
}
/*!
\brief write more than one byte to the EEPROM with a single write cycle
\param[in] p_buffer: pointer to the buffer containing the data to be written to the EEPROM
\param[in] write_address: EEPROM's internal address to write to
\param[in] number_of_byte: number of bytes to write to the EEPROM
\param[out] none
\retval none
*/
void eeprom_page_write(uint8_t* p_buffer, uint8_t write_address, uint8_t number_of_byte)
{
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, EE_ADDR, I2C_TRANSMITTER);
/* wait until ADDSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
/* clear the ADDSEND bit */
i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
/* wait until the transmit data buffer is empty */
while( SET != i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* send the EEPROM's internal address to write to : only one byte address */
i2c_data_transmit(I2C1, write_address);
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* while there is data to be written */
while(number_of_byte--){
i2c_data_transmit(I2C1, *p_buffer);
/* point to the next byte to be written */
p_buffer++;
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
}
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* wait until the stop condition is finished */
while(I2C_CTL0(I2C1)&0x0200);
}
/*!
\brief read data from the EEPROM
\param[in] p_buffer: pointer to the buffer that receives the data read from the EEPROM
\param[in] read_address: EEPROM's internal address to start reading from
\param[in] number_of_byte: number of bytes to reads from the EEPROM
\param[out] none
\retval none
*/
void eeprom_buffer_read(uint8_t* p_buffer, uint8_t read_address, uint16_t number_of_byte)
{
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
if(2 == number_of_byte){
i2c_ackpos_config(I2C1,I2C_ACKPOS_NEXT);
}
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, EE_ADDR, I2C_TRANSMITTER);
/* wait until ADDSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
/* clear the ADDSEND bit */
i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
/* wait until the transmit data buffer is empty */
while(SET != i2c_flag_get( I2C1 , I2C_FLAG_TBE));
/* enable I2C1*/
i2c_enable(I2C1);
/* send the EEPROM's internal address to write to */
i2c_data_transmit(I2C1, read_address);
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, EE_ADDR, I2C_RECEIVER);
if(number_of_byte < 3){
/* disable acknowledge */
i2c_ack_config(I2C1,I2C_ACK_DISABLE);
}
/* wait until ADDSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
/* clear the ADDSEND bit */
i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
if(1 == number_of_byte){
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
}
/* while there is data to be read */
while(number_of_byte){
if(3 == number_of_byte){
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* disable acknowledge */
i2c_ack_config(I2C1,I2C_ACK_DISABLE);
}
if(2 == number_of_byte){
/* wait until BTC bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_BTC));
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
}
/* wait until the RBNE bit is set and clear it */
if(i2c_flag_get(I2C1, I2C_FLAG_RBNE)){
/* read a byte from the EEPROM */
*p_buffer = i2c_data_receive(I2C1);
/* point to the next location where the byte read will be saved */
p_buffer++;
/* decrement the read bytes counter */
number_of_byte--;
}
}
/* wait until the stop condition is finished */
while(I2C_CTL0(I2C1)&0x0200);
/* enable acknowledge */
i2c_ack_config(I2C1,I2C_ACK_ENABLE);
i2c_ackpos_config(I2C1,I2C_ACKPOS_CURRENT);
}
/*!
\brief wait for EEPROM standby state
\param[in] none
\param[out] none
\retval none
*/
void eeprom_wait_standby_state(void)
{
__IO uint32_t val = 0;
while(1){
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus */
i2c_master_addressing(I2C1, EE_ADDR, I2C_TRANSMITTER);
/* keep looping till the Address is acknowledged or the AE flag is set (address not acknowledged at time) */
do{
/* get the current value of the I2C_STAT0 register */
val = I2C_STAT0(I2C1);
}while(0 == (val & (I2C_STAT0_ADDSEND | I2C_STAT0_AERR)));
/* check if the ADDSEND flag has been set */
if(val & I2C_STAT0_ADDSEND){
/* clear ADDSEND flag */
i2c_flag_clear(I2C1,I2C_FLAG_ADDSEND);
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* exit the function */
return ;
}else{
/* clear the bit of AE */
i2c_flag_clear(I2C1,I2C_FLAG_AERR);
}
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* wait until the stop condition is finished */
while(I2C_CTL0(I2C1)&0x0200);
}
}
/*!
\brief write buffer of data to the I2C EEPROM
\param[in] p_buffer: pointer to the buffer containing the data to be written to the EEPROM
\param[in] write_address: EEPROM's internal address to write to
\param[in] number_of_byte: number of bytes to write to the EEPROM
\param[out] none
\retval none
*/
void eeprom_buffer_write(uint8_t* p_buffer, uint8_t write_address, uint16_t number_of_byte)
{
uint8_t number_of_page = 0, number_of_single = 0, address = 0, count = 0;
address = write_address % I2C_PAGE_SIZE;
count = I2C_PAGE_SIZE - address;
number_of_page = number_of_byte / I2C_PAGE_SIZE;
number_of_single = number_of_byte % I2C_PAGE_SIZE;
/* if write_address is I2C_PAGE_SIZE aligned */
if(0 == address){
while(number_of_page--){
eeprom_page_write(p_buffer, write_address, I2C_PAGE_SIZE);
eeprom_wait_standby_state();
write_address += I2C_PAGE_SIZE;
p_buffer += I2C_PAGE_SIZE;
}
if(0 != number_of_single){
eeprom_page_write(p_buffer, write_address, number_of_single);
eeprom_wait_standby_state();
}
}else{
/* if write_address is not I2C_PAGE_SIZE aligned */
if(number_of_byte < count){
eeprom_page_write(p_buffer, write_address, number_of_byte);
eeprom_wait_standby_state();
}else{
number_of_byte -= count;
number_of_page = number_of_byte / I2C_PAGE_SIZE;
number_of_single = number_of_byte % I2C_PAGE_SIZE;
if(0 != count){
eeprom_page_write(p_buffer, write_address, count);
eeprom_wait_standby_state();
write_address += count;
p_buffer += count;
}
/* write page */
while(number_of_page--){
eeprom_page_write(p_buffer, write_address, I2C_PAGE_SIZE);
eeprom_wait_standby_state();
write_address += I2C_PAGE_SIZE;
p_buffer += I2C_PAGE_SIZE;
}
/* write single */
if(0 != number_of_single){
eeprom_page_write(p_buffer, write_address, number_of_single);
eeprom_wait_standby_state();
}
}
}
}
#endif //#if I2C1_MODE == I2C1_MODE_POLL
at24c08.h
/*
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
********************************************************************************************************/
#ifndef __24C08_H
#define __24C08_H
#include "i2c.h"
#if I2C1_MODE == I2C1_MODE_POLL
/* Private function prototypes -----------------------------------------------*/
void eeprom_buffer_read(uint8_t* p_buffer, uint8_t read_address, uint16_t number_of_byte);
void eeprom_buffer_write(uint8_t* p_buffer, uint8_t write_address, uint16_t number_of_byte);
#endif //#if I2C1_MODE == I2C1_MODE_POLL
#endif //__24C08_H
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
i2c1de 初始化在 i2c1.c中
/**
* PB10 PB11 config I2C1
*/
void i2c1_config(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* enable I2C1 clock */
rcu_periph_clock_enable(RCU_I2C1);
/* connect PB10 to I2C1_SCL */
/* connect PB11 to I2C2_SDA */
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11);//配置PB10,PB11为复用功能
/* configure I2C clock */
i2c_clock_config(I2C1, I2C1_SPEED, I2C_DTCY_2);
/* configure I2C address */
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C1_SLAVE_ADDR);
/* enable I2C1 */
i2c_enable(I2C1);
/* enable acknowledge */
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
}
4、主函数调用,我们连续写入一个字符串,超过16个字节,然后读取,看是否一致
char r_buff[48] = {0};
char *buff = "hello world,GD32F330RCT6!";
eeprom_buffer_write(r_buff,0,sizeof(r_buff)); //清零
delay_1ms(200);
eeprom_buffer_write(buff,0,strlen(buff));
delay_1ms(200);
eeprom_buffer_read(r_buff,0,48);
printf("read data form eeprom = %s\r\n",r_buff);
5、开机打印信息如下:
6 、代码路径:https://gitee.com/xiaoguo-tec_0/gd32-iap-code.git
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。