【I2C协议】

规格和从机地址传输

1、I2C的信号

2、数据的有效性(I2C是电平触发采样)

SDA的可变化时机数据线(SDA)上的数据只能在时钟线(SCL)为低电平时进行改变。

SDA的稳定性SCL为高电平期间,SDA必须保持稳定。

在SCL为高电平时,SDA上的数据被视为有效,接收方会在这个时刻对SDA的状态进行采样。

3、数据的传输单元(单位)

I²C总线以字节(8位)为单位传输数据,每次传输一个字节。

4、数据的传输顺序(MSBor LSB)

在I²C数据传输中,数据的传输顺序是MSB(Most Significant Bit,最高有效位)先传输。

5、数据传输方向(读or写)

主机是要给从机发送数据,还是要读取从机的数据。

从机地址传输

7 位从机地址(最常用)

这是 I2C 总线的标准地址格式,支持最多 128 个从机地址(27=128),但其中部分地址被预留为特殊用途(如广播地址),实际可用地址约 112 个。

  • 地址字节结构 :1 个字节共 8 位,高 7 位为真正的从机地址最低位(第 0 位)为读写控制位(R/W)
    • 当最低位为 0 时:表示主设备接下来要向从机写入数据(写操作)
    • 当最低位为 1 时:表示主设备接下来要从从机读取数据(读操作)

10 位从机地址(扩展格式)

当系统需要挂载超过 128 个从设备时,会采用 10 位从机地址格式,支持最多 1024 个独立地址

  • 地址字节结构 :10 位地址需要分两个字节发送
    • 第 1 个字节(地址字节 1):高 5 位固定为 11110(10 位地址的标志位),接下来 2 位为 10 位地址的高 2 位 ,最低位为读写控制位(R/W)
    • 第 2 个字节(地址字节 2):完整的 8 位为 10 位地址的低 8 位
  • 选通过程:主设备发送完两个地址字节后,只有 10 位地址完全匹配的从设备才会应答,后续通信流程与 7 位地址一致。

数据读取

特性 未移位从机地址 移位从机地址
位数 7 位(0x00~0x7F) 8 位(0x00~0xFE)
定义 芯片手册标注的原始地址 未移位地址左移 1 位(×2)
用途 配置硬件寄存器、代码中表示从机身份 实际通信中发送的 8 位地址字节(含读写位)
编程使用 直接写入硬件寄存器(库函数自动处理) 仅用于底层通信函数的手动实现

有寄存器区分的通信流程:

写操作

复制代码
起始信号 → 从机地址(写) → ACK → 寄存器地址 → ACK → 数据 → ACK → 停止信号

读操作

复制代码
起始信号 → 从机地址(写) → ACK → 寄存器地址 → ACK → 
重新起始 → 从机地址(读) → ACK → 数据 → NACK/ACK → 停止信号

无寄存器区分的通信流程:

写操作:一般不会使用这种情况,无内存地址无意义。

复制代码
起始信号 → 从机地址(写) → ACK → 数据 → ACK → 停止信号

读操作

复制代码
起始信号 → 从机地址(读) → ACK → 数据 → NACK/ACK → 停止信号

关键差异:有寄存器设备必须先发送寄存器地址告知从机操作位置;无寄存器设备直接进行数据交互,无中间寻址环节。

软件I2C(IO模拟I2C)

函数封装

cs 复制代码
#include "delay.h"   
 
//IO操作函数      
#define CT_IIC_SCL_1     HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, GPIO_PIN_SET) //SCL
#define CT_IIC_SCL_0     HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, GPIO_PIN_RESET) //SCL
#define CT_IIC_SDA_1     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_SET) //SCL
#define CT_IIC_SDA_0     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET) //SCL
 
#define CT_READ_SDA     HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)   //输入SDA 
 
//控制I2C速度的延时
void CT_Delay(void)
{
    delay_us(2);
} 
 
//电容触摸芯片IIC接口初始化
void CT_IIC_Init(void)
{           
    GPIO_InitTypeDef  GPIO_InitStruct;  
     
    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
     
    /* SCL */
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;     /* 开漏输出 */
    GPIO_InitStruct.Pull = GPIO_PULLUP;             /* 内部上拉 */
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, GPIO_PIN_SET);    /* 拉高SCL */
     
    /* SDA */
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;         /* 开漏输出 */
    GPIO_InitStruct.Pull = GPIO_PULLUP;                 /* 内部上拉 */
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_SET);   /* 拉高SDA */
}
 
void CT_SDA_IN(void)  
{
    GPIO_InitTypeDef GPIO_InitStruct;
     
    //PB15设置为输入模式
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}   
 
void CT_SDA_OUT(void) 
{
    GPIO_InitTypeDef GPIO_InitStruct;
     
    //PB15设置为开漏输出模式
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
 
 
//产生IIC起始信号
void CT_IIC_Start(void)
{
 
    CT_SDA_OUT();     //sda线输出
    CT_IIC_SDA_1;         
    CT_IIC_SCL_1;
    delay_us(5);
    CT_IIC_SDA_0;//START:when CLK is high,DATA change form high to low 
    delay_us(5);
    CT_IIC_SCL_0;//钳住I2C总线,准备发送或接收数据 
     
}   
   
//产生IIC停止信号
void CT_IIC_Stop(void)
{
    CT_SDA_OUT();//sda线输出
    CT_IIC_SCL_1;
    CT_IIC_SDA_0;//STOP:when CLK is high DATA change form low to high
    delay_us(5);
    CT_IIC_SDA_1;//发送I2C总线结束信号  
}
 
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uint8_t CT_IIC_Wait_Ack(void)
{
    uint8_t ucErrTime=0;
    CT_SDA_IN();      //SDA设置为输入  
    CT_IIC_SDA_1;      
    delay_us(2);    
    CT_IIC_SCL_1;
    delay_us(2);    
    //CT_Delay();
    while(CT_READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            CT_IIC_Stop();
            return 1;
        } 
        CT_Delay();
    }
    CT_IIC_SCL_0;//时钟输出0       
    return 0;  
} 
 
//产生ACK应答
void CT_IIC_Ack(void)
{
    CT_IIC_SCL_0;
    CT_SDA_OUT();
    CT_Delay();
    CT_IIC_SDA_0;
    CT_Delay();CT_Delay();
    CT_IIC_SCL_1;
    CT_Delay();CT_Delay();
    CT_IIC_SCL_0;
}
 
//不产生ACK应答          
void CT_IIC_NAck(void)
{
    CT_IIC_SCL_0;
    CT_SDA_OUT();
    CT_Delay();
    CT_IIC_SDA_1;
    CT_Delay();
    CT_IIC_SCL_1;
    CT_Delay();
    CT_IIC_SCL_0;
}   
                                      
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答           
void CT_IIC_Send_Byte(uint8_t txd)
{ 
     
    uint8_t t;   
    CT_SDA_OUT();       
    CT_IIC_SCL_0;//拉低时钟开始数据传输
    CT_Delay();
    for(t=0;t<8;t++)
    {              
        if(((txd&0x80)>>7)==1)CT_IIC_SDA_1;
            else if(((txd&0x80)>>7)==0)CT_IIC_SDA_0;
        txd<<=1;      
            delay_us(5);      
        CT_IIC_SCL_1; 
            delay_us(5);
        CT_IIC_SCL_0;   
            delay_us(5);
    }    
}   
     
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
uint8_t CT_IIC_Read_Byte(unsigned char ack)
{
    uint8_t i,receive=0;
    CT_SDA_IN();//SDA设置为输入
    //delay_us(30);
    for(i=0;i<8;i++ )
    { 
        CT_IIC_SCL_0;              
        delay_us(4);
        CT_IIC_SCL_1;    
        receive<<=1;
        if(CT_READ_SDA)receive++;  
        delay_us(4);  
    }                    
    if (!ack)CT_IIC_NAck();//发送nACK
    else CT_IIC_Ack(); //发送ACK   
    return receive;
}
相关推荐
Vizio<2 小时前
STM32HAL库开发笔记-STM32CubeMX点灯
笔记·stm32·嵌入式硬件
Rorsion2 小时前
第七章:串行总线与接口技术
单片机·嵌入式硬件·串口通信·通信协议·备考ing
anghost1502 小时前
基于MSP430单片机的老人睡眠质量监测系统设计
单片机·嵌入式硬件
一杯原谅绿茶2 小时前
单片机的软件串口通信
单片机·嵌入式硬件
d111111111d3 小时前
在STM32中,中断服务函数的命名有什么要求?
笔记·stm32·单片机·嵌入式硬件·学习·c#
易水寒陈3 小时前
MultiTimer源码分析
stm32·单片机
白羽陌3 小时前
STM32入门教程
stm32·单片机·嵌入式硬件
高工智能汽车4 小时前
车规MCU,开启“巨变”
单片机·嵌入式硬件
TEL136997627504 小时前
PTCB818A说明书 配套PL27A1芯片MCU参数说明
网络·单片机·嵌入式硬件