0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【GD32F303红枫派开发板使用手册】第二十一讲 I2C-EEPROM读写实验

聚沃科技 2024-06-21 10:23 次阅读
wKgaomZVdiiAfR9BAB3mDFhHnZc972.png

21.1实验内容

通过本实验主要学习以下内容:

21.2实验原理

21.2.1AT24C16 EEPROM的工作原理

下图为AT24CXX系列EEPROM相关参数,由该图可知,AT24C16的存储容量为16Kbit,共2048字节,共128页,每页为16字节。

wKgaomZ04vaAOmljAAJCtLMn3ng636.png

由下图可知,AT24C16由8块组成,每块256字节。

wKgaomZ04vWAUgYXAACvFtpHgTY105.png

I2C开始信号后,第一个字节为器件地址,由1010+3位块地址+1位读写标志组成,3位块地址刚好可以表示8个块, 所以一次写完256字节,换到下一下块的时候,要重新更改器件地址。

wKgZomZ04vWANv5yAACovDz5C1E070.png

AT24C16支持页写入模式,一次最多可支持写入16字节。主机每发送一个字节,24c16收到确认,内部地址递增(仅限低4bit,所以1次可写16字节)。

21.2.2IIC接口原理

GD32F30X系列MCU的I2C接口模块实现了I2C协议的标速模式,快速模式以及快速+模式,具备CRC计算和校验功能、支持SMBus(系统管理总线)和PMBus(电源管理总线),此外还支持多主机I2C总线架构,其主要特性如下:

◼并行总线至I2C总线协议的转换及接口;
◼同一接口既可实现主机功能又可实现从机功能;
◼主从机之间的双向数据传输;
◼支持7位和10位的地址模式和广播寻址;
◼支持I2C多主机模式;
◼支持标速(最高100 KHz),快速(最高400 KHz)和快速+模式(最高1MHz);
◼从机模式下可配置的SCL主动拉低;
◼支持DMA模式;
◼兼容SMBus 2.0和PMBus;
◼两个中断:字节成功发送中断和错误事件中断;
◼可选择的PEC(报文错误校验)生成和校验。

IIC模块结构框图如下所示。

wKgZomZ04vWAOgFSAAFrZaX0CtE876.png

21.3硬件设计

EEPROM硬件电路图如下所示,IIC引脚使用PB10和PB11引脚,SDA和SCL总线通过4.7K电阻上拉,且对地接30pf电容以及100欧姆串阻滤波。

wKgZomZ04vWAaaaLAAC4RSlhMDg168.pngwKgaomZ04vWAI7sJAADJKEKLg00314.png

21.4代码解析

21.4.1EEPROM初始化配置函数

EEPROM初始化配置函数如下,主要实现对IIC总线引脚配置以及IIC模块配置。

C
void bsp_eeprom_init_AT24C16(void)
{
driver_i2c_init(&EEPROM_I2C);
}
void driver_i2c_init(typdef_i2c_struct *i2cx)
{
rcu_periph_clock_enable(i2cx->rcu_i2c_x);

i2c_deinit(i2cx->i2c_x);

driver_gpio_general_init(i2cx->i2c_scl_gpio);
driver_gpio_general_init(i2cx->i2c_sda_gpio);

/* I2C clock configure */
i2c_clock_config(i2cx->i2c_x, i2cx->frequency, I2C_DTCY_2);
/* I2C address configure */
i2c_mode_addr_config(i2cx->i2c_x, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, i2cx->slave_addr);
/* enable I2C0 */
i2c_enable(i2cx->i2c_x);
/* enable acknowledge */
i2c_ack_config(i2cx->i2c_x, I2C_ACK_ENABLE);
}

21.4.2EEPROM buf写入接口函数

EEPROM buf写入接口函数实现如下,通过该函数可实现对AT24C16任意地址的多字节写入。内部已根据地址和写入长度自动识别从机地址以及对应的块,然后写入正确的地址空间。

C
EEPROM_STATE eeprom_buffer_write_AT24C16(uint8_t* p_buffer, uint16_t write_address, uint16_t number_of_byte)
{
uint8_t number_of_page = 0, number_of_single = 0, address = 0, count = 0;
uint8_t deviceId;
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+write_address>EEPROM_SIZE)
{
return EEPROM_ERROR;
}
/* if write_address is I2C_PAGE_SIZE aligned */
if(0 == address){
while(number_of_page--){

deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer,I2C_PAGE_SIZE) == DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C) == EEPROM_ERROR)
{
return EEPROM_ERROR;
}
write_address += I2C_PAGE_SIZE;
p_buffer += I2C_PAGE_SIZE;
}
if(0 != number_of_single){
deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer, number_of_single)==DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C) == EEPROM_ERROR)
{
return EEPROM_ERROR;
}
}
return EEPROM_SUCCESS;
}else{
/* if write_address is not I2C_PAGE_SIZE aligned */
if(number_of_byte < count){ 
deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer, number_of_byte)==DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C)==EEPROM_ERROR)
{
return EEPROM_ERROR;
}

}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){
deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer, count)==DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C)==EEPROM_ERROR)
{
return EEPROM_ERROR;
}
write_address += count;
p_buffer += count;
}
/* write page */
while(number_of_page--){
deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer, I2C_PAGE_SIZE)==DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C)==EEPROM_ERROR)
{
return EEPROM_ERROR;
}
write_address += I2C_PAGE_SIZE;
p_buffer += I2C_PAGE_SIZE;
}
/* write single */
if(0 != number_of_single){
deviceId=(write_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((write_address>>7)&0x0E)):EEPROM_ADDR ;
if(driver_i2c_mem_poll_write(&EEPROM_I2C,deviceId,write_address,MEM_ADDRESS_8BIT,p_buffer, number_of_single)==DRV_ERROR)
{
return EEPROM_ERROR;
}
if(eeprom_wait_standby_state(&EEPROM_I2C)==EEPROM_ERROR)
{
return EEPROM_ERROR;
}
}
}
return EEPROM_SUCCESS;
}
}

21.4.3EEPROM buf读取接口函数

EEPROM buf读取接口函数实现如下,通过该函数可实现对EEPROM任意地址的多字节数据读取,内部也对读取的地址进行自动识别从机地址。

C
EEPROM_STATE eeprom_buffer_read_AT24C16(uint8_t* p_buffer, uint16_t read_address, uint16_t number_of_byte)
{
uint8_t rNum=0; //读取的数据长度
uint16_t lenLeft=number_of_byte;//剩余的数据长度
uint8_t deviceId;//读取的器件地址
if(read_address+number_of_byte>EEPROM_SIZE)//如果读取的长度加上读取地址超过了EEPROM的空间大小,则报错误
{
return EEPROM_ERROR;
}
/*calculate the current read position to know how many word can read continully*/
rNum=16-read_address & 0x0F;
if(rNum == 0) rNum=16;
rNum = lenLeft>=rNum ? rNum : lenLeft;//剩余未读字节数如果大于rNum, 则读rNum个,如果小于rNum,则一次读完了
/*read the data from e2prom*/
while(lenLeft)
{
//这里计算页地址,当地址小于256时,右移8位会小于0,所以器件地址为基地址A1
//如果读取的地址大于256时,右移8位则不会小于0,所以器件地址为 基地址A1 | 3位页地址
deviceId=(read_address>>8)>0 ? (EEPROM_ADDR | (uint8_t)((read_address>>7)&0x0E)):EEPROM_ADDR ;

if(driver_i2c_mem_poll_read(&EEPROM_I2C,deviceId,read_address,MEM_ADDRESS_8BIT,p_buffer,rNum)==DRV_ERROR)
{
// printf("i2c read error\r\n");
return EEPROM_ERROR;
}
read_address+=rNum;//已经读了rNum个了,所以地址后移rNum个
lenLeft-=rNum;//剩余未读数据减少rNum个
p_buffer+=rNum;
rNum=lenLeft>16? 16 : lenLeft;//如果剩余大于16个,则下次再读16个,如果小于,则一次读完
}
return EEPROM_SUCCESS;
}

21.4.4EEPROM读写实验主函数

EEPROM读写实验主函数如下所示。通过该实验实现对AT24C16任意地址256字节的写入、读取以及校验测试。

C
int main(void)
{
uint16_t i;
uint8_t i2c_buffer_write[BUFFER_SIZE];
uint8_t i2c_buffer_read[BUFFER_SIZE];

bsp_eeprom_init_AT24C16();
/* initialize i2c_buffer_write */
for(i = 0;i < BUFFER_SIZE;i++){ 
i2c_buffer_write[i]=i;
// printf("0x%02X ",i2c_buffer_write[i]);
// if(15 == i%16){
// printf("\r\n");
// }
}

if(eeprom_buffer_write_AT24C16(i2c_buffer_write,0x0153,BUFFER_SIZE)==EEPROM_SUCCESS)
{
__nop();
}
if(eeprom_buffer_read_AT24C16(i2c_buffer_read,0x0153,BUFFER_SIZE)==EEPROM_SUCCESS)
{
__nop();
}
/* compare the read buffer and write buffer */
for(i = 0;i < BUFFER_SIZE;i++){
if(i2c_buffer_read[i] != i2c_buffer_write[i]){
__nop();
// printf("0x%02X ", i2c_buffer_read[i]);
// printf("Err:data read and write aren't matching.\n\r");
// return I2C_FAIL;
}
//printf("0x%02X ", i2c_buffer_read[i]);
// if(15 == i%16){
// printf("\r\n");
// }
}
__nop();
// printf("I2C-AT24C02 test passed!\n\r");
while (1)
{
}
}

21.5实验结果

将本实验历程烧录到红枫派开发板中,运行后,可通过串口打印测试结果,可实现对于AT24C16任意地址写入、读取以及校验。

wKgaomZ04vWAdP5HAABu6KXZb68775.png

教程GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6035

    文章

    44554

    浏览量

    634690
  • 嵌入式
    +关注

    关注

    5082

    文章

    19107

    浏览量

    304834
  • EEPROM
    +关注

    关注

    9

    文章

    1019

    浏览量

    81562
  • I2C
    I2C
    +关注

    关注

    28

    文章

    1484

    浏览量

    123627
  • 开发板
    +关注

    关注

    25

    文章

    5033

    浏览量

    97378
收藏 人收藏

    评论

    相关推荐

    明德扬视频分享点拨FPGA课程--第二十一章  矩阵键盘工程

    第二十一章矩阵键盘工程1. 矩阵扫描模块2. 数码显示模块3. for循环的使用4. 统计模块5. generate的使用6. 进制转换模块7. 顶层模块http://yunpan.cn/cjZTiDA9pY56x访问密码 c3
    发表于 11-09 08:47

    GD32F303】星空介绍

    一、开发板介绍星空GD开发板是由旗点科技推出的一款GD32开发板,板载
    发表于 09-11 17:55

    【星空GD32F303开发板试用体验】开箱+环境搭建

    开发板。感谢旗点科技创始人 连志安提供资料及视频 。SF速运包含开发板及电源适配器(5v2A).我准备采用适配器供电,需将电源切换开关置于右侧(VDD5V 侧)看下资源,使用此 星空
    发表于 10-18 14:15

    【星空GD32F303开发板试用体验】开箱+环境搭建

    GD32F303开发板。感谢旗点科技创始人 连志安提供资料及视频 。顺风速运包含开发板及电源适配器(5v2A).我准备采用适配器供电,需将
    发表于 11-02 15:36

    【星空GD32F303开发板试用体验】+板卡概览

    完整地进行外设开发,包括:JTAG、RTC、I2C、UART、SPI、SDIO、EXMC、DAC、ADC、USB、TFT-LCD等。GD32F303系列片上集成了丰富的创新外设资源,包括:Cortex
    发表于 11-06 21:05

    【星空GD32F303开发板试用体验】文件读写与数码相框的实现 (兼结题报告)

    本帖最后由 jinglixixi 于 2021-11-27 01:23 编辑 星空开发板是旗点科技推出的一款以GD32F303ZET6为核心的开发板,该
    发表于 11-26 12:05

    迅为iMX6ULL开发板使用手册资料下载

    按键例程第十三章 GPT定时器延时例程第十四章 串口通信例程第十五章 串口格式化函数例程第十六章 LCD屏幕显示例程第十七章 SRTC实时时钟例程第十八章 I2C操作第十九章 电容触摸实验第二十章 屏幕背光调节例程
    发表于 12-02 14:13

    星空GD32F303开发板的相关资料下载

    eeprom等,支持3.2寸的TFT - LCD屏幕。所有IO口均引出,可完整地进行外设开发,包括:JTAG、RTC、I2C、UART、SPI、SDIO、EXMC、DAC、ADC、USB、TFT-LCD等。二、
    发表于 12-10 08:27

    第二十一讲 组合逻辑电路中的竞争冒险

    第二十一讲 组合逻辑电路中的竞争冒险 6.7.1 竞争冒险现象及其产生的原因一、竞争、冒险1.理想情况2.实际情况3.竞
    发表于 03-30 16:25 3072次阅读
    <b class='flag-5'>第二十一讲</b> 组合逻辑电路中的竞争冒险

    STM32F4 I2C-EEPROM实验例程

    STM32F4 I2C-EEPROM实验例程(嵌入式开发专业课程)-STM32F4 I2C-EEPROM
    发表于 07-30 16:02 19次下载
    STM32<b class='flag-5'>F</b>4 <b class='flag-5'>I2C-EEPROM</b><b class='flag-5'>实验</b>例程

    GD32F303固件库开发

    /qq_24312945/article/details/124325797] GD32F303固件库开发2)----读保护与写保护 芯片读保护以后,flash将不可以从外部读取,这样可以防止别人读取或者盗取芯片代码,如果想再
    的头像 发表于 07-27 09:27 1163次阅读
    <b class='flag-5'>GD32F303</b>固件库<b class='flag-5'>开发</b>

    GD32F303红枫开发板使用手册第二讲 GPIO-流水灯实验

    GD32F303系列MCU最多可支持 112 个通用I/O 引脚(GPIO),分别为 PA0 ~ PA15, PB0 ~ PB15, PC0 ~ PC15,PD0 ~ PD15, PE0
    的头像 发表于 05-29 10:02 1632次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】<b class='flag-5'>第二</b>讲 GPIO-流水灯<b class='flag-5'>实验</b>

    GD32F303红枫开发板使用手册第二十讲 SPI-SPI NAND FLASH读写实验

    通过本实验主要学习以下内容: •SPI通信协议,参考19.2.1东方红开发板使用手册GD32F303 SPI操作方式,参考19.2.2东方红
    的头像 发表于 06-20 09:50 886次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】<b class='flag-5'>第二十</b>讲 SPI-SPI NAND FLASH<b class='flag-5'>读写实验</b>

    GD32F303红枫开发板使用手册第二十三讲 SDIO-SD卡读写实验

    通过本实验主要学习以下内容: •SDIO操作原理 •SD卡读写实
    的头像 发表于 06-23 10:49 619次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】<b class='flag-5'>第二十</b>三讲 SDIO-SD卡<b class='flag-5'>读写实验</b>

    GD32F303红枫开发板使用手册第二十七讲 USB-虚拟键盘实验

    ,传输速度也很快,这些特性使支持USB接口的电子设备更易用、更大众化。GD32F303系列MCU集成了USB2.0全速设备USBD模块,可以满足作为USB设备与主机
    的头像 发表于 06-27 09:42 828次阅读
    【<b class='flag-5'>GD32F303</b><b class='flag-5'>红枫</b><b class='flag-5'>派</b><b class='flag-5'>开发板</b><b class='flag-5'>使用手册</b>】<b class='flag-5'>第二十</b>七讲  USB-虚拟键盘<b class='flag-5'>实验</b>