硬件驱动篇 | STM8驱动 触摸控制芯片IQS263

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 线从高电平向低电平切换

软件模拟协议实现如下:

 1 /**************************************
 2 起始信号
 3 **************************************/
 4 void Touch_Sen_Start()
 5 {
 6     SDA_H;                    //拉高数据线
 7     SCL_H;                    //拉高时钟线
 8     I2C_DELAY;                 //延时
 9     SDA_L;                    //产生下降沿
10     I2C_DELAY;                 //延时
11     SCL_L;                    //拉低时钟线
12 }

停止信号: 当 SCL 是高电平时 SDA 线由低电平向高电平切换

 软件模拟协议实现如下:

 1 /**************************************
 2 停止信号
 3 **************************************/
 4 void Touch_Sen_Stop()
 5 {
 6     SDA_L;                    //拉低数据线
 7     SCL_H;                    //拉高时钟线
 8     I2C_DELAY;                 //延时
 9     SDA_H;                    //产生上升沿
10     I2C_DELAY;                 //延时
11 }

 注:I2C的延迟函数一般设置为5us以上

  • 应答和非应答

传输时主机产生时钟,在第9个时钟时,数据发送端会释放SDA的控制权,由数据接收端控制SDA,若SDA为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)

应答信号(ACK):SDA为低电平

非应答信号(NACK):SDA为高电平

  软件模拟协议实现如下:

 1 /**************************************
 2 发送应答信号
 3 入口参数:ack (0:ACK 1:NAK)
 4 **************************************/
 5 void Touch_Sen_SendACK(u8 ack)
 6 {
 7     
 8     
 9     if (ack)//写应答信号
10     {
11       SDA_H;      
12     }
13     else
14     {
15       SDA_L;   
16     }           
17     
18     
19     SCL_H;                    //拉高时钟线
20     I2C_DELAY;                 //延时
21     SCL_L;                    //拉低时钟线
22     I2C_DELAY;                 //延时
23 }
24 
25 /**************************************
26 接收应答信号
27 **************************************/
28 u8 Touch_Sen_RecvACK()
29 {
30     I2C_PORT->DDR &= ~I2C_SDA_PIN; //Set as input mode
31     SCL_H;                    //拉高时钟线
32     I2C_DELAY;             //延时
33     
34     if(I2C_PORT->IDR & I2C_SDA_PIN)
35     {
36       ack = 1;    //读应答信号
37     }
38     else
39     {
40        ack = 0;    //读应答信号
41     }
42     
43     I2C_PORT->DDR |= I2C_SDA_PIN; //Set as output mode
44     
45     
46     SCL_L;                    //拉低时钟线
47     I2C_DELAY;                 //延时
48 
49     return ack;
50 }
  • I2C读写
 1 /**************************************
 2 向I2C总线发送一个字节数据
 3 **************************************/
 4 void Touch_Sen_SendByte(u8 dat)
 5 {
 6     u8 i;
 7 
 8     for (i=0; i<8; i++)         //8位计数器
 9     {
10         if (dat & 0x80)
11         {
12           SDA_H;
13         }
14         else
15         {
16           SDA_L;
17         }
18         
19         dat <<= 1;              //移出数据的最高位          
20         I2C_DELAY;             //延时
21         
22         SCL_H;                //拉高时钟线
23         I2C_DELAY;             //延时
24         SCL_L;                //拉低时钟线
25         I2C_DELAY;             //延时
26     }
27     Touch_Sen_RecvACK();
28 }
29 
30 /**************************************
31 从I2C总线接收一个字节数据
32 **************************************/
33 u8 Touch_Sen_RecvByte()
34 {
35     u8 i;
36     u8 dat = 0;
37 
38     SDA_H;                    //使能内部上拉,准备读取数据,
39     I2C_PORT->DDR &= ~I2C_SDA_PIN; //Set as input mode
40     
41     for (i=0; i<8; i++)         //8位计数器
42     {
43         dat <<= 1;
44         SCL_H;                //拉高时钟线
45         I2C_DELAY;             //延时
46         if (I2C_PORT->IDR & I2C_SDA_PIN)//读数据   
47         {
48           dat |=1;
49         } //esle curret bit is 0       
50                                  
51         SCL_L;                //拉低时钟线
52         I2C_DELAY;             //延时
53     }
54     
55     I2C_PORT->DDR |= I2C_SDA_PIN; //Set as output mode
56     return dat;
57 }
 1 //******单字节写入*******************************************
 2 
 3 void Single_Write_Touch_Sen(u8 REG_Address,u8 REG_data)
 4 {
 5     Touch_Sen_Start();                  //起始信号
 6     Touch_Sen_SendByte(I2C_SLAVE_ADDR_WR);   //发送设备地址+写信号
 7     Touch_Sen_SendByte(REG_Address);    //内部寄存器地址
 8     Touch_Sen_SendByte(REG_data);       //内部寄存器数据
 9     Touch_Sen_Stop();                   //发送停止信号
10 }
11 
12 //********单字节读取*****************************************
13 
14 u8 Single_Read_Touch_Sen(u8 REG_Address)
15 {  
16     u8 REG_data;
17     
18     Touch_Sen_Start();                          //起始信号
19     Touch_Sen_SendByte(I2C_SLAVE_ADDR_WR);           //发送设备地址+写信号
20     Touch_Sen_SendByte(REG_Address);                   //发送存储单元地址,从0开始    
21     Touch_Sen_Start();                          //起始信号
22     Touch_Sen_SendByte(I2C_SLAVE_ADDR_RD);         //发送设备地址+读信号
23     REG_data=Touch_Sen_RecvByte();              //读出寄存器数据
24     Touch_Sen_SendACK(1);   
25     Touch_Sen_Stop();                           //停止信号
26     
27     return REG_data; 
28 }

三、Touch Slide测试及结果

   注:IQS263芯片的一个地址对应好几个字节的寄存器,对IQS263 IC进行I2C读写时,需要进行多字节读写,I2C的多字节读写可参考上面的单字节读写部分代码。

  滑动Touch Slide,STM Studio动态显示读数变化。

 

 

 

 

原文地址:https://www.cnblogs.com/Tuple-Joe/p/9534350.html