本文针对淘宝所购买的1.69寸LCD触摸屏驱动进行讲解。
屏幕购买链接如下:
1.69寸全视角IPSTFT彩屏 液晶显示屏SPI位接口ST7789V驱动工业屏-淘宝网 (taobao.com)
我们先搞一下IIC驱动
#define CST816_SCL_Clr() HAL_GPIO_WritePin(TP_SCL_GPIO_Port,TP_SCL_Pin, GPIO_PIN_RESET)//SCL=SCLK
#define CST816_SCL_Set() HAL_GPIO_WritePin(TP_SCL_GPIO_Port,TP_SCL_Pin, GPIO_PIN_SET)
#define CST816_SDA_IN() GPIO_InitStruct.Pin = TP_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(TP_SDA_GPIO_Port, &GPIO_InitStruct)
#define CST816_SDA_Get() HAL_GPIO_ReadPin(TP_SDA_GPIO_Port,TP_SDA_Pin)
#define CST816_SDA_OUT() GPIO_InitStruct.Pin = TP_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(TP_SDA_GPIO_Port, &GPIO_InitStruct)
#define CST816_SDA_Clr() HAL_GPIO_WritePin(TP_SDA_GPIO_Port,TP_SDA_Pin, GPIO_PIN_RESET)
#define CST816_SDA_Set() HAL_GPIO_WritePin(TP_SDA_GPIO_Port,TP_SDA_Pin, GPIO_PIN_SET)
由于我所用到的是HAL库,所以这里针对IIC驱动做了宏定义。
用标准库的开发者可以根据需要进行改动。
//模拟IIC部分的函数声明
void CST816_IIC_ACK(void);
void CST816_IIC_NACK(void);
unsigned char CST816_IIC_Wait_ACK(void);
void CST816_IIC_Start(void);
void CST816_IIC_Stop(void);
void CST816_IIC_SendByte(unsigned char byte);
void CST816_IIC_WriteREG(unsigned char reg,unsigned char date);
unsigned char CST816_IIC_ReadREG(unsigned char reg);
unsigned char CST816_IIC_RecvByte(void);
我们IIC的目的是对CST816的寄存器进行读写,所以根据手册内容,我们做出下面的寄存器声明
//CST816寄存器
#define GestureID 0x01 //手势寄存器
#define FingerNum 0x02 //手指数量
#define XposH 0x03 //x高四位
#define XposL 0x04 //x低八位
#define YposH 0x05 //y高四位
#define YposL 0x06 //y低八位
#define ChipID 0xA7 //芯片型号
#define MotionMask 0xEC //触发动作
#define AutoSleepTime 0xF9 //自动休眠
#define IrqCrl 0xFA //中断控制
#define AutoReset 0xFB //无手势休眠
#define LongPressTime 0xFC //长按休眠
#define DisAutoSleep 0xFE //使能低功耗模式
多数寄存器我们是不需要去打理的,我们最关心的是XposH、XposL、YposH、YposL用于读取手指触摸位置的坐标,以及FingerNum用于读取触摸状态。
typedef struct
{
unsigned char chipID;
unsigned int X_Pos; //X坐标
unsigned int Y_Pos; //Y坐标
unsigned char Sta; //记录触摸状态
}CST816_Info;
接下来我们创建触摸屏实例,用于触摸屏的信息管理,内容包括芯片ID,X\Y坐标,以及触摸状态等。
下面是函数实现
//IIC驱动实现
#include "CST816.h"
#include "math.h"
CST816_Info CST816_Instance; //创建CST816实例。
#define delay_num 4 //宏定义延时时间
GPIO_InitTypeDef GPIO_InitStruct = {0};
//IIC起始信号
void CST816_IIC_Start(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
CST816_SDA_OUT();
CST816_SDA_Set();
CST816_SCL_Set();
delay_us(delay_num);
CST816_SDA_Clr();
delay_us(delay_num);
CST816_SCL_Clr();
}
//IIC停止信号
void CST816_IIC_Stop(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
CST816_SDA_OUT();
CST816_SCL_Clr();
CST816_SDA_Clr();
delay_us(delay_num);
CST816_SCL_Set();
CST816_SDA_Set();
delay_us(delay_num);
}
//发送ACK应答
void CST816_IIC_ACK(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
CST816_SDA_OUT();
CST816_SCL_Clr();
CST816_SDA_Clr();
delay_us(delay_num);
CST816_SCL_Set();
delay_us(delay_num);
CST816_SCL_Clr();
}
//发送NACK不应答
void CST816_IIC_NACK(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
CST816_SDA_OUT();
CST816_SCL_Clr();
CST816_SDA_Set();
delay_us(delay_num);
CST816_SCL_Set();
delay_us(delay_num);
CST816_SCL_Clr();
}
//等待IIC应答信号
unsigned char CST816_IIC_Wait_ACK(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
unsigned char t = 0;
CST816_SDA_IN();
CST816_SDA_Set();
delay_us(delay_num);
CST816_SCL_Set();
delay_us(delay_num);
while(CST816_SDA_Get())
{
t++;
if(t>250)
{
CST816_IIC_Stop();
return 1;
}
}
CST816_SCL_Clr();
return 0;
}
//IIC发送一字节数据
void CST816_IIC_SendByte(unsigned char byte)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
unsigned char BitCnt;
CST816_SDA_OUT();
CST816_SCL_Clr();
for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位
{
if(byte&0x80) CST816_SDA_Set();//判断发送位
else CST816_SDA_Clr();
byte<<=1;
delay_us(delay_num);
CST816_SCL_Set();
delay_us(delay_num);
CST816_SCL_Clr();
delay_us(delay_num);
}
}
//IIC接收一字节数据
unsigned char CST816_IIC_RecvByte(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
unsigned char retc;
unsigned char BitCnt;
retc=0;
CST816_SDA_IN();//置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
CST816_SCL_Clr();
delay_us(delay_num);
CST816_SCL_Set();//置时钟线为高使数据线上数据有效
retc=retc<<1;
if(CST816_SDA_Get()) retc++;//读数据位,接收的数据位放入retc中
delay_us(delay_num);
}
return(retc);
}
//IIC写入指定寄存器数据
void CST816_IIC_WriteREG(unsigned char reg,unsigned char date)
{
CST816_IIC_Start();
CST816_IIC_SendByte(0x2A);
CST816_IIC_Wait_ACK();
CST816_IIC_SendByte(reg);
CST816_IIC_Wait_ACK();
CST816_IIC_SendByte(date);
CST816_IIC_Wait_ACK();
CST816_IIC_Stop();
HAL_Delay(10);
}
//IIC读取指定寄存器数据
unsigned char CST816_IIC_ReadREG(unsigned char reg)
{
unsigned char date;
CST816_IIC_Start();
CST816_IIC_SendByte(0x2A);
CST816_IIC_Wait_ACK();
CST816_IIC_SendByte(reg);
CST816_IIC_Wait_ACK();
CST816_IIC_Start();
// delay_us(4);
CST816_IIC_SendByte(0x2B);
CST816_IIC_Wait_ACK();
date=CST816_IIC_RecvByte();
CST816_IIC_ACK();
CST816_IIC_Stop();
// delay_us(5);
return date;
}
IIC协议部分不展开介绍,我们来看有关CST816寄存器的读取
void CST816_Init(void)
{
//我自己不需要做任何操作,由于习惯就写了Init函数。
//可根据自己需求进行修改
}
unsigned char CST816_Get_ChipID()
{
return CST816_IIC_ReadREG(ChipID); //读取芯片ID
}
void CST816_Get_XY()
{
//这个函数非常值得注意,为什么我没有使用上面提到的直接读取指定寄存器的函数,
//因为这个CST816芯片的原因,当读取过XY坐标四个寄存器之中的任意一个之后,其他寄存器会被清空,得到的数据不准确。
//因此必须连续读取,这样也可以学习下IIC总线的读取逻辑嘛对不对。
unsigned char temp[4];
unsigned int x,y;
CST816_IIC_Start();
CST816_IIC_SendByte(0x2A);
CST816_IIC_Wait_ACK();
CST816_IIC_SendByte(0x03);
CST816_IIC_Wait_ACK();
CST816_IIC_Start();
// delay_us(4);
CST816_IIC_SendByte(0x2B);
CST816_IIC_Wait_ACK();
temp[0]=CST816_IIC_RecvByte();
CST816_IIC_ACK();
temp[1]=CST816_IIC_RecvByte();
CST816_IIC_ACK();
temp[2]=CST816_IIC_RecvByte();
CST816_IIC_ACK();
temp[3]=CST816_IIC_RecvByte();
CST816_IIC_ACK();
CST816_IIC_Stop();
x=(unsigned int)((temp[0]&0x0F)<<8)|temp[1];//(temp[0]&0X0F)<<4|
y=(unsigned int)((temp[2]&0x0F)<<8)|temp[3];//(temp[2]&0X0F)<<4|
if(x<240&&y<280)
{
CST816_Instance.X_Pos = x;
CST816_Instance.Y_Pos = y;
}
}
unsigned char CST816_Get_Sta()
{
unsigned char sta;
CST816_IIC_Start();
CST816_IIC_SendByte(0x2A);
CST816_IIC_Wait_ACK();
CST816_IIC_SendByte(0x01);
CST816_IIC_Wait_ACK();
CST816_IIC_Start();
// delay_us(4);
CST816_IIC_SendByte(0x2B);
CST816_IIC_Wait_ACK();
CST816_IIC_RecvByte();
CST816_IIC_ACK();
sta=CST816_IIC_RecvByte();
CST816_IIC_ACK();
CST816_IIC_Stop();
if(sta!=255&sta!=0)return 1;
else return 0;
}
剩下的寄存器用到的情况很少,如果有需要可以自己去定义一个函数。
类似这样,仅做展示,作者并没有测试是否可行,就不帖出来喽~文章来源:https://www.toymoban.com/news/detail-553366.html
unsigned char CST816_Get_Sta(void); //更新触摸状态
void CST816_Set_MotionMask(unsigned char Motion);
void CST816_Set_IrqCtrl(unsigned char IRQCtrl);
void CST816_Set_AutoRST(unsigned char time); //设置多长时间无触摸自动复位,默认5s,写0则禁用功能
void CST816_Set_LongPressRST(unsigned char time); //设置长按多长时间复位,默认为10s,写0禁用功能
void CST816_Set_AutoSleep(unsigned char en); //是否使能自动进入低功耗模式
unsigned char CST816_Get_Gesture(void);
文章来源地址https://www.toymoban.com/news/detail-553366.html
到了这里,关于CST816S触摸驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!