IIC通讯

几个原则:
IIC通信,高位在先,低位在后

开始信号
在时钟信号线为为高时,拉低SDA
在这里插入图片描述

结束信号
在时钟信号线为为高时,拉高SDA
在这里插入图片描述

Ack信号
ACK信号为每次传输8bit(1字节)数据后,必须要有的响应信号,由接收方来发出
在SCK为高时(一个脉冲内),将SDA拉低(管脚开漏输出只能拉低,来表示回复)

NACK信号
在SCK为高时(一个脉冲内),将SDA置高(管脚开漏输出只能拉低,不操作时默认为高电平)

写数据
设备地址:设备地址为7位,发送的数据中一共八位,前七位是设备地址,最后一位是读写控制位,0是写,1是读
在这里插入图片描述

从设备写取数据的过程如下:

  1. 发送起始信号
  2. 输出从机的地址(写位),获取从机的应答信号,没有应答则发送STOP信号,释放总线
  3. 先发送要写入的寄存器高八位的地址,获取从机的应答信号,同上
  4. 再发送要写入的寄存器低八位的地址,获取应答信号
  5. 接下来发送要写入的数据,字节数任意
  6. 不想发的时候,发送STOP信号,结束通信
    在这里插入图片描述
    在这里插入图片描述

读数据

  1. 发送开始信号
  2. 发送设备地址(写命令),并获取设备的应答信号
  3. 发送设备的高八位地址,等待应答信号
  4. 发送设备的低八位地址,等待应答信号
  5. 发送停止信号
  6. 重新发送开始信号(重启通信)
  7. 发送设备地址(读命令),等待设备应答信号
  8. 读取数据,读到数据后主机回复ACK信号
  9. 若主机不想接收数据了,给设备回复NACK 或者 发送停止信号
    在这里插入图片描述

底层驱动函数有:

  1. IIC_Start
  2. IIC_Stop
  3. IIC_SendAck
  4. IIC_SendNack
  5. IIC_ReadAck:读取不到ACK信号时,要发送IIC_Stop
  6. IIC_WriteByte
  7. IIC_ReadByte

接收Ack

void delay(unsigned int t)
{//延时函数
    while(t){t--;};                    //延时循环计数
}
//-------------------------------------------------------------------
void delay_IIC(void)    
{//IIC总线限速延时函数。
//该函数是空函数,延时4个机器周期。
;;
}
//-------------------------------------------------------------------
void IIC_Init(void)
{//IIC总线初始化函数
    IIC_SDA=1;//释放IIC总线的数据线。
    IIC_SCL=1;//释放IIC总线的时钟线。
}
//-------------------------------------------------------------------
void IIC_start(void)
{//IIC总线产生起始信号函数  
    IIC_SDA=1;//拉高数据线
     IIC_SCL=1;//拉高时钟线
     delay_IIC();
     IIC_SDA=0;//在时钟线为高电平时,拉低数据线,产生起始信号。
     delay_IIC();
    IIC_SCL=0;//拉低时钟线
}
//-------------------------------------------------------------------
void IIC_stop(void) 
{//IIC总线产生停止信号函数
    IIC_SDA=0;//拉低数据线
    delay_IIC();
    IIC_SCL=1;//拉高时钟线。
    delay_IIC();
    IIC_SDA=1;//时钟时线为高电平时,拉高数据线,产生停止信号。
    delay_IIC();
}
//-------------------------------------------------------------------
bit IIC_Tack(void)
{//接收应答信号函数
    bit ack;//定义一个位变量,来暂存应答状态。
    IIC_SDA=1;//释放数据总线,准备接收应答信号。
    delay_IIC();
    IIC_SCL=1;//拉高时钟线。
    delay_IIC();
    ack=IIC_SDA;//读取应答信号的状态。
    delay_IIC();
    IIC_SCL=0;//拉低时钟线。
    delay_IIC();
    return ack;//返回应答信号的状态,0表示应答,1表示非应答。
}
//-------------------------------------------------------------------
void IIC_write_byte(unsigned char Data)
{//向IIC总线写入一个字节的数据函数 
    unsigned char i;
     for(i=0;i<8;i++)//有8位数据
    {
        IIC_SDA=Data&0x80;//写最高位的数据
          delay_IIC();
          IIC_SCL=1; //拉高时钟线,将数写入到设备中。
        delay_IIC();
        IIC_SCL=0;//拉低时钟线,允许改变数据线的状态
        delay_IIC();
        Data=Data<<1;//数据左移一位,把次高位放在最高位,为写入次高位做准备
    }
}
//-------------------------------------------------------------------
unsigned char IIC_read_byte()
{//从IIC总线读取一个字节的数据函数
    unsigned char i;
    unsigned char Data;       //定义一个缓冲寄存器。
    for(i=0;i<8;i++)//有8位数据
    {
        IIC_SCL=1;//拉高时钟线,为读取下一位数据做准备。
        delay_IIC();
        Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。
        delay_IIC();
        
        if(IIC_SDA)//如果数据线为高平电平。
            Data=Data|0x1;//则给缓冲字节的最低位写1。
        IIC_SCL=0;//拉低时钟线,为读取下一位数据做准备。
        delay_IIC();
    }
    return Data;//返回读取的一个字节数据。
}
//-------------------------------------------------------------------
void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data)
{//向任意地址写入一个字节数据函数
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    IIC_Tack();//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    IIC_Tack();//等待设备的应答。
    IIC_write_byte(Data);//写入数据。
    IIC_Tack();//等待设备的应答。
    IIC_stop();//产生停止符号。
}
//-------------------------------------------------------------------
unsigned char IIC_single_byte_read(unsigned char Daddr,unsigned char Waddr)
{//从任意地址读取一个字节数据函数
    unsigned char Data;//定义一个缓冲寄存器。

    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    IIC_Tack();//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    IIC_Tack();//等待设备的应答。
    
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr+1);//写入设备地址(读)。
    IIC_Tack();//等待设备的应答。 
    Data=IIC_read_byte();//写入数据。
    IIC_stop();//产生停止符号。
    //-------------------返回读取的数据--------------------
    return Data;//返回读取的一个字节数据。
}

读取触摸坐标分为 中断方式 和 轮询方式
1. 中断方式
TP的INT引脚接在芯片的中断引脚上,触摸后,TP的INT引脚会输出高电平,触发芯片的中断,芯片进入中断服务函数ISR,ISR中读取TP指定寄存器的数据,将数据存在栈存储结构中,中断外再处理数据

2. 轮询方式
不使用TP的INT引脚,使用空闲任务读取TP的坐标等信息,可以在程序中处理数据

IIC最多支持多少个设备地址?
127个,八位中的最后一位是读写位,读1,写0

上拉电阻的阻值
4.7K,10K

一般TP初始化过程

  1. 通过RESET引脚硬件复位
  2. 延时一段时间
  3. 结束复位
  4. 通过INT引脚的电平设置设备地址
  5. 延时
  6. 软复位
  7. 若需要则要更新配置(分辨率等)
  8. 结束软复位

某些TP读寄存器坐标之后,要对其寄存器清零

猜你喜欢

转载自blog.csdn.net/Hao_Zhen/article/details/83826022
IIC