文章内容根据野火学习教程进行整理,仅仅是学习记录。
开发板: 野火STM32F429-挑战者V2
官方固件库版本: STM32F4xx_DSP_StdPeriph_Lib_V1.8.0
这里以与EEPROM进行通讯的代码作为例子。
一、看电路图
1、要得知那些信息
从电路图上主要是要知道3点关键信息
- I2C设备挂载在I2C1、I2C2、I2C3的哪一个总线上
- SDA、SCL接的是哪两个GPIO
- I2C设备地址(有的是可以选择的,比如这个EEPROM)
2、挂在哪个I2C总线以及哪个GPIO
从电路图上可以看出:
- 挂载在I2C1上的
- SDA接的是PB7引脚
- SCL接的是PB6引脚
这个一般硬件工程师都会在电路图上标出来吧。
另外如果只标出了使用的GPIO引脚,也可以通过 《STM32F4xx中文数据手册》 查找相关GPIO的复用得知所挂的I2C总线。
3、I2C设备地址
查看EPPROM的参考手册可以得知设备地址是由1010 A2A1A0一共位组合而成,而从电路图可以得知A2=0、A1=0、A0=0,所以最终的I2C地址位101 0000(0x50)。
其实在I2C总线上只要设备地址是唯一的就可以了。
二、开始编码
由于是使用I2C对EEPROM进行读写,所以编码主要是分为I2C配置和对EEPROM读写两个部分。
1、I2C配置
(1)宏定义声明
根据电路连接情况就可以知道GPIO引脚以及哪个I2C总线啦。
#define I2C1_OwnAddress 0X0A /* STM32的I2C1设备自身地址,自定义,与其他I2C设备地址不同即可 */
#define I2C1_Speed 400000 /* I2C1设备速率400KHz */
#define I2C1_GPIO_PORT GPIOB /* I2C1所接GPIO的端口 */
#define I2C1_SCL_PIN GPIO_Pin_6 /* I2C1的SCL所接的GPIO引脚 */
#define I2C1_SDA_PIN GPIO_Pin_7 /* I2C1的SDA所接的GPIO引脚 */
#define I2C1_SCL_SOURCE GPIO_PinSource6 /* I2C1的SCL所接的GPIO引脚序号 */
#define I2C1_SDA_SOURCE GPIO_PinSource7 /* I2C1的SDA所接的GPIO引脚序号 */
#define I2C1_GPIO_AF GPIO_AF_I2C1 /* I2C1的SDA、SCL的GPIO引脚复用功能 */
- I2C速率:有三种,标准模式(100kbit/s)、快速模式(400kbit/s)、Hs模式(3.4Mbit/s)。我自己试了一下速率过低是会有问题的,过高似乎没有什么问题,一般就填400K好了。
(2)使能GPIO和I2C总线时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* 初始化GPIO端口时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); /* 初始化I2C1的外围时钟 */
不管是使用GPIO还是I2C,相应的总线时钟都是要使能的。
(3)初始化GPIO
/**************************************************************************************************
** 函数名称: gpio_cfg
** 功能描述: I2C的GPIO配置
** 输入参数: 无
** 输出参数: 无
** 返回参数: 无
**************************************************************************************************/
static void gpio_cfg(void)
{
GPIO_InitTypeDef GPIO_def;
GPIO_def.GPIO_Pin = I2C1_SCL_PIN | I2C1_SDA_PIN; /* 要配置的GPIO的PIN脚 */
GPIO_def.GPIO_Mode = GPIO_Mode_AF; /* 要配置的GPIO模式(复用) */
GPIO_def.GPIO_Speed = GPIO_Speed_50MHz; /* 要配置的GPIO速率(50MHz) */
GPIO_def.GPIO_OType = GPIO_OType_OD; /* 输出类型(开漏) */
GPIO_def.GPIO_PuPd = GPIO_PuPd_UP; /* 引脚默认状态(上拉) */
GPIO_Init(I2C1_GPIO_PORT, &GPIO_def);
GPIO_PinAFConfig(I2C1_GPIO_PORT, I2C1_SCL_SOURCE, I2C1_GPIO_AF); /* 配置复用类型 */
GPIO_PinAFConfig(I2C1_GPIO_PORT, I2C1_SDA_SOURCE, I2C1_GPIO_AF); /* 配置复用类型 */
}
- GPIO类型必须配置成 开漏输出 ,因为这样I2C设备才能输出 低电平 和 高阻态。因为 SCL 和 SDA 连接上拉电阻到电源,那么GPIO输出低电平则拉低,输出高阻态则拉高。高阻态可类似看为开路。
(4)初始化I2C
/**************************************************************************************************
** 函数名称: i2c_cfg
** 功能描述: I2C配置
** 输入参数: 无
** 输出参数: 无
** 返回参数: 无
**************************************************************************************************/
static void i2c_cfg(void)
{
I2C_InitTypeDef I2C_def;
I2C_def.I2C_Mode = I2C_Mode_I2C;