STM32CubeMx入门教程(7):I2C的读写应用

控制/MCU

1882人已加入

描述

导语“本次 教程使用CubeMx配置I2C进行I2C总线设备的数据读写操作,使用EEPROM作为实验对象”

01第一节 系统要求

•硬件

野火指南者开发板

•软件

CubeMx & MDK & 串口调试助手

•原理图

I2C总线

我们可以从原理图中得到使用的I2C1,AT24C02的设备地址的第三位是000,容量是256个字节。设备地址从下图得到:

I2C总线

不带读写方向的使用左移得到的地址为0b10100000->0xA0, 读地址为:0xA1,写地址为0xA0;

注意:(1) 操作ATC02的时候,多字节写入的时候没写入一个字节,延时最小5ms, 多字节读的时候没有要求,页写入的时候每8个字节为一页,共32页。

02第二节 CubeMx的配置

我们依然使用之前的USART的项目,在此基础上进行I2C的配置,串口的使用是进行EEPROM读写数据显示在控制台上,使用CubeMx进行I2C的配置:

I2C总线

I2C的配置很简单,完成上述配置后生成代码。

03第三节MDK的代码编写

使用MDK打开CubeMx生成的代码进行应用代码编写。

(1)在main.c 中进行AT24C02的相关宏定义和变量定义:

#define ADDR_AT24C_Write 0xA0
#define ADDR_AT24C_Read  0xA1
#define DEV_ADDR_ATC02   0xA0 //0x50 左移得到的。
#define ATC02_BufferSize 256   // 256
#define I2C_TIMEOUT                0xFF
#define AT_I2C              hi2c1
uint8_t AT24_WriteBuffer[ATC02_BufferSize],AT24_ReadBuffer[ATC02_BufferSize];

( 2 ) 应用函数申明:

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

I2CWriteBuffer()是自定义的任意字节写入I2C-AT24C02的函数,I2CReadBuffer()是任意字节读写函数。这两个函数的实现采用HAL库的这两个函数:

1)HALStatusTypeDef HALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);

参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,写的数据,数据大小,超时时间)

2)HALStatusTypeDef HALI2CMemRead(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress, uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);

参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,读出数据,数据大小,超时时间)

为什么不直接使用库函数呢?是因为在测试中AT24C02读写不正常,查看AT24C02的手册发现,单个字节写入没问题,多字节的写入需要每个字节延时5ms, 其实多字节的读没有问题,这个从新实现了下。可以连续8个字节的页写入,这个不需要延时。

(3)多字节的读写函数:

/*这里自己实现多字节的ATC02的写操作*/
HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
{
       uint16_t count=0;
       for(count=0;count
       {
              if(HAL_I2C_Mem_Write(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)
              {
                     MemAddress ++;
                     pData ++;
                     HAL_Delay(5);
              }
              else
              {
                     printf("i2c write is error tn");
                     return HAL_ERROR;
              }
       }
       return HAL_OK;
}
/*这里自己实现多字节的ATC02的读操作*/
HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,
uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t *pData, uint16_t Size,
uint32_t Timeout)
{
       uint16_t count=0;
       for(count=0;count< Size;count ++)
       {
              if(HAL_I2C_Mem_Read(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)
              {
                     MemAddress ++;
                     pData ++;
                     //HAL_Delay(5);
              }
              else
              {
                     printf("i2c read is error n");
                     return HAL_ERROR;
              }
       }
       return HAL_OK;
}

(4)在main函数中添加测试代码:

uint16_t num_atc=0;
       printf("this is test for I2C device read and write in ATC02rn");
       printf("/**--------------------开始I2C-------------------------**/rn");
       for( num_atc=0;num_atc
       {
              AT24_WriteBuffer[num_atc]=num_atc;
              printf("0x%xt",AT24_WriteBuffer[num_atc]);       
       }
       if(I2C_Write_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_WriteBuffer,ATC02_BufferSize, I2C_TIMEOUT) == HAL_OK)
       {
              printf("write i2c lots bytes is oktn");
       }
       if(HAL_I2C_Mem_Read(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
       {
              printf("rn EEPROM 24C02 read data Test OK rn");
       }
       else
       {
              printf("rn EEPROM 24C02 read data Test False rn");
       }
/*这里使用自定义多字节读函数也是正常的*/
/*
       if(I2C_Read_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0,               I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
       {
              printf("i2c read lots is oktn");
       }
*/
       for(num_atc=0; num_atc< ATC02_BufferSize; num_atc++)
       {
              printf("0x%xt",AT24_ReadBuffer[num_atc]);
       }
       if(memcmp(AT24_WriteBuffer,AT24_ReadBuffer,ATC02_BufferSize) == 0 ) /* check date */
       {
              printf("rn EEPROM 24C02 Read and write Test OKrn");
       }
       else
       {
    printf("rn EEPROM 24C02 Read and write Test Falsern");
       }       
       printf("/**--------------------结束I2C-------------------------**/rn");

编译上述程序后下载。

04第四节效果演示

使用串口观察写入的数据和读出的数据是否一致?

I2C总线

可以看到I2C操作EEPROM进行读写都是正常的。

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分