1.基本原理:
上图是I2C的总线图和通讯协议图(就是I2C是怎么实现设备之间读写数据的)
下面主要介绍通讯协议的每一步:
1.发出开始信号: 一开始都为高电平为空闲状态。当SCL为高电平时,主机将SDA拉低即为发出开始信号,从机设备检测到开始信号后会开始监听总线,总线进入繁忙状态
2.地址传输
主设备向总线发送一个字节数据:7位设备地址+1位读写数据帧。
每个从机都会将主机发送的地址与自己的地址进行比较,成功匹配地址的从设备通过拉低 SDA 线返回 ACK(应答)信号。至此主从机配对成功。接下来,无论谁是接收方,在接受到数据后必须向发送方返回成功接收的应答信号“ACK",或者接收失败的应答信号”NACK"
而后面数据传输的方向由 “ R/W读写位 ” 决定
0(写) = 主机 → 从机
1 (读)= 从机 → 主机
3.数据传输
根据读写位,主机开始发送/接收数据,接下来就是正常返回应答,还有编写自己的传输协议就行了。最后记得拉高SDA发出停止信号,代表数据传输结束
注:
因为写数据一直是”一个方向“,所以不用重写读写数据帧
但是读数据需要在配对后更改传输方向,所以需要重写读写数据帧
2.软件IIC / 硬件I2C
首先一般我们要编写I2C驱动,然后再编写通讯协议
I2C驱动指的就是定义接口、读写指令、发出应答等指令函数
通讯协议就是传感器的数据传输函数
而关于软硬件驱动:
硬件I2C驱动编写:
1.用CUBEMX配置的HAL库I2C,自动生成的i2c.h就是驱动
2.不用CUBEMX配置的HAL库I2C,自己用HAL库去编写驱动,会比纯软少一点代码(
#ifndef __BSP_I2C_H
#define __BSP_I2C_H#include "stm32f1xx.h"
#include "./usart/bsp_debug_usart.h"/*等待超时时间*/
#define Delay HAL_Delay#define I2Cx_FLAG_TIMEOUT ((uint32_t) 1000) //0x1100
#define I2Cx_LONG_TIMEOUT ((uint32_t) (300 * I2Cx_FLAG_TIMEOUT)) //was300
/**************************I2C参数定义,I2C1或I2C2********************************/
#define I2C_OWN_ADDRESS 0x00#define SENSORS_I2C I2C1
#define SENSORS_I2C_RCC_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
#define SENSORS_I2C_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define SENSORS_I2C_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()/*引脚定义*/
#define SENSORS_I2C_SCL_GPIO_PORT GPIOB
#define SENSORS_I2C_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define SENSORS_I2C_SCL_GPIO_PIN GPIO_PIN_6#define SENSORS_I2C_SDA_GPIO_PORT GPIOB
#define SENSORS_I2C_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define SENSORS_I2C_SDA_GPIO_PIN GPIO_PIN_7#define SENSORS_I2C_AF GPIO_AF4_I2C1/*信息输出*/
#define I2C_DEBUG_ON 1
#define I2C_DEBUG_FUNC_ON 0#define I2C_INFO(fmt,arg...) printf("<<-I2C-INFO->> "fmt"\n",##arg)
#define I2C_ERROR(fmt,arg...) printf("<<-I2C-ERROR->> "fmt"\n",##arg)
#define I2C_DEBUG(fmt,arg...) do{\if(I2C_DEBUG_ON)\printf("<<-I2C-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\}while(0)#define I2C_DEBUG_FUNC() do{\if(I2C_DEBUG_FUNC_ON)\printf("<<-I2C-FUNC->> Func:%s@Line:%d\n",__func__,__LINE__);\}while(0)void I2cMaster_Init(void);
unsigned short Get_I2C_Retry(void);int Sensors_I2C_ReadRegister(unsigned char slave_addr,unsigned char reg_addr,unsigned short len, unsigned char *data_ptr);
int Sensors_I2C_WriteRegister(unsigned char slave_addr,unsigned char reg_addr,unsigned short len, unsigned char *data_ptr);#endif /* __BSP_I2C_H */
而软件