I2C 与 Touch slide
最近做了一个与触摸滑条相关的测试,利用I2C通讯协议来配置触摸控制芯片的相关寄存器,读取触摸读数,并通过STM Studio动态显示触摸读数的变化过程。这个测试相对简单,只要搞定I2C通讯协议,后面的触摸控制芯片的相关寄存器配置就变得很简单了,所以我就简单地总结一下I2C通讯部分笔记。
实验平台:IAR 及 STM Studio
实验主芯片:自制STM8L051/101评估板
触摸控制芯片:ProxSense IQS263
使用硬件触摸滑条(Touch slide),如下图:
一、触摸控制芯片IQS263简介
IQS 263 ProxSense IC是一种3通道投影(或自)电容接近和触摸控制器,具有最佳的类灵敏度,信噪比和功耗。
- 硬件原理图
其中,通信线为RDY,SDA,SCL,都接有上拉电阻。RDY是通讯使能脚,当RDY为低电平时才支持I2C通信。
二、I2C软件模拟协议的实现:
- 自定义宏定义
#define I2C_PORT GPIOC
#define I2C_SCL_PIN GPIO_Pin_1
#define I2C_SDA_PIN GPIO_Pin_0 #define SCL_H I2C_PORT->ODR |= I2C_SCL_PIN
#define SCL_L I2C_PORT->ODR &= ~I2C_SCL_PIN
#define SDA_H I2C_PORT->ODR |= I2C_SDA_PIN
#define SDA_L I2C_PORT->ODR &= ~I2C_SDA_PIN
- 起始信号和停止信号
起始信号:当 SCL 线是高电平时 SDA 线从高电平向低电平切换
软件模拟协议实现如下:
/**************************************
起始信号
**************************************/
void Touch_Sen_Start()
{
SDA_H; //拉高数据线
SCL_H; //拉高时钟线
I2C_DELAY; //延时
SDA_L; //产生下降沿
I2C_DELAY; //延时
SCL_L; //拉低时钟线
}
停止信号: 当 SCL 是高电平时 SDA 线由低电平向高电平切换
软件模拟协议实现如下:
/**************************************
停止信号
**************************************/
void Touch_Sen_Stop()
{
SDA_L; //拉低数据线
SCL_H; //拉高时钟线
I2C_DELAY; //延时
SDA_H; //产生上升沿
I2C_DELAY; //延时
}
注:I2C的延迟函数一般设置为5us以上
- 应答和非应答
传输时主机产生时钟,在第9个时钟时,数据发送端会释放SDA的控制权,由数据接收端控制SDA,若SDA为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)
应答信号(ACK):SDA为低电平
非应答信号(NACK):SDA为高电平
软件模拟协议实现如下:
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void Touch_Sen_SendACK(u8 ack)
{ if (ack)//写应答信号
{
SDA_H;
}
else
{
SDA_L;
} SCL_H; //拉高时钟线
I2C_DELAY; //延时
SCL_L; //拉低时钟线
I2C_DELAY; //延时
} /**************************************
接收应答信号
**************************************/
u8 Touch_Sen_RecvACK()
{
I2C_PORT->DDR &= ~I2C_SDA_PIN; //Set as input mode
SCL_H; //拉高时钟线
I2C_DELAY; //延时 if(I2C_PORT->IDR & I2C_SDA_PIN)
{
ack = ; //读应答信号
}
else
{
ack = ; //读应答信号
} I2C_PORT->DDR |= I2C_SDA_PIN; //Set as output mode SCL_L; //拉低时钟线
I2C_DELAY; //延时 return ack;
}
- I2C读写
/**************************************
向I2C总线发送一个字节数据
**************************************/
void Touch_Sen_SendByte(u8 dat)
{
u8 i; for (i=; i<; i++) //8位计数器
{
if (dat & 0x80)
{
SDA_H;
}
else
{
SDA_L;
} dat <<= ; //移出数据的最高位
I2C_DELAY; //延时 SCL_H; //拉高时钟线
I2C_DELAY; //延时
SCL_L; //拉低时钟线
I2C_DELAY; //延时
}
Touch_Sen_RecvACK();
} /**************************************
从I2C总线接收一个字节数据
**************************************/
u8 Touch_Sen_RecvByte()
{
u8 i;
u8 dat = ; SDA_H; //使能内部上拉,准备读取数据,
I2C_PORT->DDR &= ~I2C_SDA_PIN; //Set as input mode for (i=; i<; i++) //8位计数器
{
dat <<= ;
SCL_H; //拉高时钟线
I2C_DELAY; //延时
if (I2C_PORT->IDR & I2C_SDA_PIN)//读数据
{
dat |=;
} //esle curret bit is 0 SCL_L; //拉低时钟线
I2C_DELAY; //延时
} I2C_PORT->DDR |= I2C_SDA_PIN; //Set as output mode
return dat;
}
//******单字节写入******************************************* void Single_Write_Touch_Sen(u8 REG_Address,u8 REG_data)
{
Touch_Sen_Start(); //起始信号
Touch_Sen_SendByte(I2C_SLAVE_ADDR_WR); //发送设备地址+写信号
Touch_Sen_SendByte(REG_Address); //内部寄存器地址
Touch_Sen_SendByte(REG_data); //内部寄存器数据
Touch_Sen_Stop(); //发送停止信号
} //********单字节读取***************************************** u8 Single_Read_Touch_Sen(u8 REG_Address)
{
u8 REG_data; Touch_Sen_Start(); //起始信号
Touch_Sen_SendByte(I2C_SLAVE_ADDR_WR); //发送设备地址+写信号
Touch_Sen_SendByte(REG_Address); //发送存储单元地址,从0开始
Touch_Sen_Start(); //起始信号
Touch_Sen_SendByte(I2C_SLAVE_ADDR_RD); //发送设备地址+读信号
REG_data=Touch_Sen_RecvByte(); //读出寄存器数据
Touch_Sen_SendACK();
Touch_Sen_Stop(); //停止信号 return REG_data;
}
三、Touch Slide测试及结果
注:IQS263芯片的一个地址对应好几个字节的寄存器,对IQS263 IC进行I2C读写时,需要进行多字节读写,I2C的多字节读写可参考上面的单字节读写部分代码。
滑动Touch Slide,STM Studio动态显示读数变化。