CPU作为老板,发钱需要自己转帐,收钱需要自己看信息,是一种悲哀。
上一篇《STM32 使用IO口模拟I2C时序》,我们讲述了“论老板如何自己发钱和收钱”。
这一篇《STM32 使用硬件I2C接口读写EEPROM》,我们来讲述“论老板如何雇佣员工帮忙发钱和收钱”。
我们先来招聘一个职位:
岗位职责:
1、自动产生I2C时序,向其他芯片发送(发钱)或者接收(收钱)数据。
任职要求:
1、CPU只需发指令便行,无须关心时序。(老板只要告诉发多少钱就行了,不需要知道怎么发)。
经过层层筛选,I2C bus interface 刚好符合这个要求,他的简历在 RM0033文档 553页,记得多读读喔。
它还能与搬砖小能手DMA配合,把钱当砖头搬,相当强大。
这就是业内人称:硬件I2C,它会自动产生SCL/SDA的时序,不需要通过CPU对IO口拉高拉低。
接下来,写代码了,Stm32Cube这一块,就不再多叙述,简单说一下就行了。
对EEPROM操作,速度,选择100K就够了,如果要选择更牛逼的速度,要把Speed Mode变成Fast Mode。
这里值得一提的是,为什么有个Slave Features呢?
因为Stm32的I2C也可以做从设备,让另一个MCU做主设备,对它进行操作。在这里,我们是对EEPROM操作,是做主设备,这个Slave,就不用管它。
另外,不建议Mcu间的通信用I2C,一般用RS232/RS485,简单通用。
还有,Stm32 I2C同样是支持DMA方式的,我们这里,就不用DMA了。
生成代码,看看都生成了些啥?
i2c.c/i2c.h 文件,还有在main里面调用 MX_I2C1_Init() 配置I2C
我们把它添加到上一篇的工程里,同样用@cmd命令测试它。
PS: stm32cube生成代码时,自已添加修改的代码,会被覆盖。这让人很恼火。解决方法有4个:
1. 在项目初期,规划好所有用到的外设,一次性配置好;
2. 将自己的代码添加在 /* USER CODE BEGIN */和/* USER CODE END*/之间(这让人更恼火,还让不让人自由自在地写代码了?程序员追求自由自在的心灵,叔可忍,婶不可忍!);
3. 自己调用HAL库配置(要stm32cube干嘛?总得做点事吧?);
4. 用stm32cube配置好,生成代码后,把相关的代码拷到对应的项目上(我就是这么做的。)。
对了,记得务必要把i2c.c加进编译里面,加在User里面。
对了,记得务必要把stm32_hal_i2c.c也加进编译里面,加在 Drivers里面。
对了,还要把 stm32f2xx_hal_conf.h里面的 #define HAL_I2C_MODULE_ENABLED 打开。
对了,还要记得io口__HAL_RCC_GPIOB_CLK_ENABLE()。
接下来,
在main里面,#include "i2c.h"
在初始化代码里增加 MX_I2C1_Init();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_UART4_Init();
MX_TIM1_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
USR_UartInit();
// IOI2C_GpioInit(); // 上一节的IO口,要去掉啊。
MX_I2C1_Init(); // 看这里,看这里!
接下来,调用这两个函数,一个是写,一个是读。
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)
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);
上一节的工程基础上,在at24c02.c/at24c02.h 里,把 I2C 读写的接口改一下:
static uint8_t I2C_READBUF(uint8_t *pAddr, uint8_t *pData, uint16_t len)
{
// return IOI2C_ReadBlock(AT24C02_DEVICE, pAddr, 1, pData, len);
uint16_t addr = *pAddr;
if(HAL_I2C_Mem_Read(&hi2c1, AT24C02_DEVICE|I2C_RD, addr, I2C_MEMADD_SIZE_8BIT, pData, len, 500) != HAL_OK)
return IOI2C_BUSY;
return IOI2C_OK;
}
static uint8_t I2C_WRITEBUF(uint8_t *pAddr, uint8_t *pData, uint16_t len)
{
// return IOI2C_WriteBlock(AT24C02_DEVICE, pAddr, 1, pData, len);
uint16_t addr = *pAddr;
if(HAL_I2C_Mem_Write(&hi2c1, AT24C02_DEVICE|I2C_WR, addr, I2C_MEMADD_SIZE_8BIT, pData, len, 500) != HAL_OK)
return IOI2C_BUSY;
return IOI2C_OK;
}
编译、烧录、运行、测试:
写字节:
@cmd 0x1 2 0 0x13
@cmd 0x1 2 1 0x14
@cmd 0x1 2 2 0x34
读字节:
@cmd 0x1 0 0
@cmd 0x1 0 1
@cmd 0x1 0 2
3. 写一串,就往0x3存储单元写14个字节吧。
@cmd 0x1 3 0x3 14
4、读一串,就从0x0读18个字节吧。
@cmd 0x1 1 0x0 18
0x13、0x14、0x34,是写字节时写进去的;
0x3~0x10,是写一串的时候写进去的,刚好14个字节。
整个工程及代码呢,请上百度网盘上下载:
链接:https://pan.baidu.com/s/19usUcgZPX8cCRTKt_NPcfg
密码:07on
文件夹:\Stm32CubeMx\Code\I2c.rar
上一篇:《STM32 使用IO口模拟I2C时序》
下一篇:《》
回目录:《目录》