STM32CubeMX学习教程之十:硬件I2C读写AT24C02

您所在的位置:网站首页 校园即景作文450字动静结合描写冬天 STM32CubeMX学习教程之十:硬件I2C读写AT24C02

STM32CubeMX学习教程之十:硬件I2C读写AT24C02

#STM32CubeMX学习教程之十:硬件I2C读写AT24C02| 来源: 网络整理| 查看: 265

完整源码下载:

https://github.com/simonliu009/STM32CubeMX-hardware-I2C-AT24C02

网上有流传已久一种说法,就是STM的I2C有bug,不好用。确实很多人在实际应用中都遇到了各种问题,所以绝大部分人都是在用软件模拟IIC。

有了STM32CubeMX,我们可以尝试使用硬件I2C了,官方的优化总不会有错了吧?(其实还是有个小bug,不过可以改过来的)。本文的目标就是使用STM32CubeMX的硬件I2C对麒麟座板载的AT24C02 EEPROM进行完整的读写操作。

软件版本:

STM32CubeMX V4.25.0  

 

System Workbench V2.4

固件库版本: STM32Cube FW_F1 V1.6.1

固件库版本:

STM32Cube FW_F1 V1.6.1

硬件:OneNet 麒麟座V2.3

在STM32CubeMX中新建项目,选择正确的MCU型号(或者旧项目另存一下也可以)。

首先设置RCC和SYS,如下图

然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M),如下图

设置I2C2,麒麟座V2.3 的 AT24C02是接在I2C2上的,I2C的设置不需要改,用默认的值就好。

打开串口USART1,串口设置也不需要修改,默认115200波特率。

引脚设置如下:

 

Project - setting ,ToolChain/IDE选择 SW4STM32,注意项目名称这里不能有空格,最好不要用中文。

 

勾选这里

 

 

保存以后,点击任务栏的生成代码图标

生成完毕以后在弹出的对话框点击"Open Project", System Workbench自动打开Eclipse并导入和打开了项目,然后展开项目树,

 

双击Src文件夹下的i2c.c, 把I2C时钟初始化提前到GPIO前面(这个就是我们需要修改的那个bug):

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct; if(i2cHandle->Instance==I2C2) { /* USER CODE BEGIN I2C2_MspInit 0 */ __HAL_RCC_I2C2_CLK_ENABLE(); //默认情况下这句时钟初始化代码放在了GPIO初始化之后,需要调整到这里,即GPIO初始化前 /* USER CODE END I2C2_MspInit 0 */ /**I2C2 GPIO Configuration PB10 ------> I2C2_SCL PB11 ------> I2C2_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* I2C2 clock enable */ // __HAL_RCC_I2C2_CLK_ENABLE();//默认情况下这句时钟初始化代码放在了这里,这里需要注释掉 /* USER CODE BEGIN I2C2_MspInit 1 */ /* USER CODE END I2C2_MspInit 1 */ } }

然后编辑main.c,首先我们需要用printf输出一些信息并重定向到串口,参考前面的教程,我们做如下修改:

另外不要忘记把STM32Cube_FW_F1_V1.6.0\Projects\STM3210C_EVAL\Examples\UART\UART_Printf\syscalls.c 文件复制到src目录

/* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END 0 */

 

AT24C02是一个具有256 Byte (即2Kbit)的EEPROM。首先定义器件地址和读写变量

/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ #define ADDR_AT24C02_Write 0xA0 #define ADDR_AT24C02_Read 0xA1 uint8_t I2C_Buffer_Write[256]; uint8_t I2C_Buffer_Read[256]; uint16_t i; /* USER CODE END PV */

256个字节我们按顺序填充0x00 到 0xFF, 我们使用如下函数进行写入

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),含义如下:

 I2C_HandleTypeDef *hi2c --IIC的句柄  uint16_t DevAddress -- IIC设备的外部地址  uint16_t MemAddress --IIC设备的内部地址  uint16_t MemAddSize --读写内部地址的方式,一般使用I2C_MEMADD_SIZE_8BIT方式,                                    注意只有两种选择:I2C_MEMADD_SIZE_8BIT 或者 I2C_MEMADD_SIZE_16BIT  uint8_t *pData --写入的数组或者指针  uint16_t Size --写入的字节数! uint32_t Timeout -- 超时时间

阅读AT24C02的规格书我们可以看到,AT24C02的2Kbit分为32页,每页8个字节。而EEPROM有一种写入方式就是按页写入,而不是按字节写入。所以我们的例子使用了按页写入的方式,分32次写入。注意每次写入完毕需要延时5ms,这是AT24C02的要求。

所以参数应该如下选择:

 I2C_HandleTypeDef *hi2c -- &hi2c2 // I2C2

 uint16_t DevAddress --ADDR_AT24C02_Write //即0xA0,这是写地址,读地址就是写地址+1  uint16_t MemAddress --i //每次写入8个字节,所以从0开始递增8  uint16_t MemAddSize --I2C_MEMADD_SIZE_8BIT //读写内部地址的方式,上面规格书的截图也说明了是8BIT方式     uint8_t *pData --I2C_Buffer_Write+i ,因为数组即指针,所以也可以用(uint8_t*)(&(I2C_Buffer_Write[i]))                                                         或者&(I2C_Buffer_Write[i])

 uint16_t Size -- 8//一次写入一页,上文说过了,是8个字节

uint32_t Timeout -- 1000//1000或者以上,有人也用0xFFFF。

每页写完以后串口打印成功信息。

/* USER CODE BEGIN 3 */ /* USER CODE BEGIN 2 */ printf("\r\n \r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n"); printf("\r\n I2C Write Buffer:\r\n"); for(i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3