STM32CubeMx入门教程(7) I2C的读写应用
导语“本次 教程使用CubeMx配置I2C进行I2C总线设备的数据读写操作,使用EEPROM作为实验对象” 01 ------------第一节 系统要求----------
•硬件 野火指南者开发板
•软件
CubeMx & MDK & 串口调试助手
•原理图
我们可以从原理图中得到使用的I2C1,AT24C02的设备地址的第三位是000,容量是256个字节。设备地址从下图得到:
不带读写方向的使用左移得到的地址为0b10100000->0xA0, 读地址为:0xA1,写地址为0xA0;
注意:(1) 操作ATC02的时候,多字节写入的时候没写入一个字节,延时最小5ms, 多字节读的时候没有要求,页写入的时候每8个字节为一页,共32页。
02 ------------第二节 CubeMx的配置----------
我们依然使用之前的USART的项目,在此基础上进行I2C的配置,串口的使用是进行EEPROM读写数据显示在控制台上,使用CubeMx进行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)HALStatusTypeDefHALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress,uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,写的数据,数据大小,超时时间)
2)HALStatusTypeDefHALI2CMemRead(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 \t\n");
- 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 ATC02\r\n");
- printf("/**--------------------开始I2C-------------------------**/\r\n");
- for( num_atc=0;num_atc
- {
- AT24_WriteBuffer[num_atc]=num_atc;
- printf("0x%x\t",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 ok\t\n");
- }
- if(HAL_I2C_Mem_Read(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
- {
- printf("\r\n EEPROM 24C02 read data Test OK \r\n");
- }
- else
- {
- printf("\r\n EEPROM 24C02 read data Test False \r\n");
- }
- /*这里使用自定义多字节读函数也是正常的*/
- /*
- 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 ok\t\n");
- }
- */
- for(num_atc=0; num_atc<ATC02_BufferSize; num_atc++)
- {
- printf("0x%x\t",AT24_ReadBuffer[num_atc]);
- }
- if(memcmp(AT24_WriteBuffer,AT24_ReadBuffer,ATC02_BufferSize) == 0 ) /* check date */
- {
- printf("\r\n EEPROM 24C02 Read and write Test OK\r\n");
- }
- else
- {
- printf("\r\n EEPROM 24C02 Read and write Test False\r\n");
- }
- printf("/**--------------------结束I2C-----------------**/\r\n");
复制代码
编译上述程序后下载。 04 ------------第四节效果演示----------
使用串口观察写入的数据和读出的数据是否一致?
可以看到I2C操作EEPROM进行读写都是正常的。 文章出处: 小鸟的早晨
|