单片机GD32F303RCT6 (Macos环境)开发 (十六)—— Eeprom AT24C08的读取

本文主要是介绍单片机GD32F303RCT6 (Macos环境)开发 (十六)—— Eeprom AT24C08的读取,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

这篇关于单片机GD32F303RCT6 (Macos环境)开发 (十六)—— Eeprom AT24C08的读取的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/205586

相关文章

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

解决Java中基于GeoTools的Shapefile读取乱码的问题

《解决Java中基于GeoTools的Shapefile读取乱码的问题》本文主要讨论了在使用Java编程语言进行地理信息数据解析时遇到的Shapefile属性信息乱码问题,以及根据不同的编码设置进行属... 目录前言1、Shapefile属性字段编码的情况:一、Shp文件常见的字符集编码1、System编码

利用Python实现添加或读取Excel公式

《利用Python实现添加或读取Excel公式》Excel公式是数据处理的核心工具,从简单的加减运算到复杂的逻辑判断,掌握基础语法是高效工作的起点,下面我们就来看看如何使用Python进行Excel公... 目录python Excel 库安装Python 在 Excel 中添加公式/函数Python 读取

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并