×
单片机 > 单片机程序设计 > 详情

STM32HAL库学习笔记--硬件I2C读写AT24C512

发布时间:2020-06-06 发布时间:
|

一、CubeMx配置

开启I2C1,其余参数默认

在旧版本的CubeMx中,HAL库实现的I2C初始化带有一些BUG,比如需要在I2C引脚复用GPIO配置前加上I2C的时钟使能,不过这些BUG在新版本的CubeMx中似乎得到了解决,直接使用其生成的初始化程序和HAL库的I2C接口就可以实现成功的读写操作

二、读AT24C512DataSheet

AT24Cxx系列芯片内存大小各异,页数和每页字节数也不同,要根据数据手册来确定该型号芯片的内存结构(Memory Organization)

由DS可知AT24C512的内存一共有 512 Pages x 128 Bytes = 65536 Bytes = 512 kbits,同时地址是16位数据字,范围是0x0000~0xFFFF

和同系列其他芯片一样,器件地址为8位,前5位固定,最低位为读/写标志,第二、三位为总线地址。电路中A0、A1引脚接地,故读、写的器件地址分别为0xA1,0xA0

三、调用HAL库接口实现读写

HAL库将I2C操作封装后提供了直接操作EEPROM的接口:


//EEPORM写函数

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

//EEPORM读函数

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)


参数表

参数类型含义
hi2cI2C_HandleTypeDef *HAL库I2C结构体指针
DevAddressuint16_t器件地址
MemAddressuint16_t内存地址
MemAddSizeuint16_t内存地址大小(8或16)
pDatauint8_t *缓冲区头指针
Sizeuint16_t缓冲区大小
Timeoutuint32_t超时时间

返回值

HAL_OK成功
HAL_TIMEOUT等待超时
HAL_BUSY总线繁忙
HAL_ERROR其他错误

读写的实现


#define ADDR_AT24C02_Write 0xA0

#define ADDR_AT24C02_Read 0xA1

 

int16_t AT24C512_Write_nBytes(uint8_t *data, uint16_t addr, uint16_t length)

{

    if( HAL_I2C_Mem_Write( &hi2c1, ADDR_AT24C02_Write, addr, I2C_MEMADD_SIZE_16BIT, data, length, 1000 ) == HAL_OK )

        return 0;

    else

        return -1;

}

 

int16_t AT24C512_Read_nBytes(uint8_t *data, uint16_t addr, uint16_t length)

{

    if( HAL_I2C_Mem_Read( &hi2c1, ADDR_AT24C02_Write, addr, I2C_MEMADD_SIZE_16BIT, data, length, 1000 ) == HAL_OK )

        return 0;

    else

        return -1;

}

1

连续读写测试


void E2PROMTestTask(void const * argument)

{

    uint8_t write_buff[18] = "read & write test";

    uint8_t read_buff[18] = {0};

    

    AT24C512_Write_nBytes( &write_buff[0], 0, 10 );

    HAL_Delay( 10 ); //这里的延时是必要的

    AT24C512_Write_nBytes( &write_buff[10], 10, 8 );

    HAL_Delay( 10 );

    AT24C512_Read_nBytes( read_buff, 0, 18 );

 

    printf( "%srn", read_buff );

 

    uint8_t long_write_buff[256];

    uint8_t long_read_buff[256] = {0};

    for( size_t i = 0; i < 256; ++i )

    {

        long_write_buff[i] = i;

    }

 

    //写入有页限制

    AT24C512_Write_nBytes( &long_write_buff[0], 0, 128 );

    HAL_Delay( 10 );

    AT24C512_Write_nBytes( &long_write_buff[128], 128, 128 );

    HAL_Delay( 10 );

    //读出没有页限制

    AT24C512_Read_nBytes( long_read_buff, 0, 256 );

 

    for( size_t i = 0; i < 256; ++i )

    {

        printf("0x%02X  ",long_read_buff[i]);

    }

 

}


四、需要注意的问题

1. 写操作结束后,MCU会向EEPROM发送一个停止位,在发出下一个起始位之前,EEPORM芯片会进入写周期(internally-timed write cycle),这段时间内不能进行任何输入,所以在两个写操作或写操作与读操作之间需要有一个保证wirte cycle的延时,一般5~10ms即可

2. 调用HAL库自带的HAL_I2C_Mem_Write函数时,需要注意一次写入的字节数不能大于EEPROM芯片的页字节数,否则会回滚覆盖低位地址的数据





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机中断源的扩展方法