STM32F103驱动GT911
0x00 引脚连接:
// SCL-------PB10
// SDA-------PB11
// INT--------PB1
// RST--------PB2
IIC的SCL与SDA需要接上拉电阻!
0x01 模拟IIC:
在模拟IIC的头文件中:
定义所需的IO操作宏:
//IO操作函数
#define IIC_SCL PBout(10) //SCL
#define IIC_SDA PBout(11) //SDA
#define READ_SDA PBin(11) //输入SDA
宏定义模拟IIC的引脚:
#define GT911_PIN_SCL GPIO_Pin_10
#define GT911_PIN_SDA GPIO_Pin_11
在模拟IIC的C源文件中实现相关函数:
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SCL|GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GT911_PIN_SCL|GT911_PIN_SDA);
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
//IIC_SDA=(txd&0x80)>>7;
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
0x02 初始化GT911:
查阅《GT911编程指南》:
IIC通信地址选择 0x28/0x29,在头文件中加入相关声明和定义:
//I2C读写命令
#define GT_CMD_WR 0X28 //写命令
#define GT_CMD_RD 0X29 //读命令
//GT911 部分寄存器定义
#define GT_CTRL_REG 0X8040 //GT911控制寄存器
#define GT_CFGS_REG 0X8047 //GT911配置起始地址寄存器
#define GT_CHECK_REG 0X80FF //GT911校验和寄存器
#define GT_PID_REG 0X8140 //GT911产品ID寄存器
#define GT_GSTID_REG 0X814E //GT911当前检测到的触摸情况
#define GT911_PIN_INT GPIO_Pin_1
#define GT911_PIN_RST GPIO_Pin_2
typedef struct _POINT{
u16 x;
u16 y;
}POINT, *PPOINT;
typedef struct _GT911_POINT_DATA{
u8 cnt;
POINT points[5];
}GT911_POINT_DATA, *PGT911_POINT_DATA;
extern GT911_POINT_DATA gt911_data;
在C源文件中添加GT911初始化所需要的准备函数:
void GT911_INT_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_INT(u8 cmd)
{
if(cmd) GPIO_SetBits(GPIOB, GT911_PIN_INT);
else GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_INT_Change(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_RST_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_RST;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}
void GT911_RST(u8 cmd)
{
if(cmd) GPIO_SetBits(GPIOB, GT911_PIN_RST);
else GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}
按照时序GT911上电初始化大致流程如下(IIC通信地址选择 0x28/0x29):
GT911_RST_Init();
GT911_INT_Init();
IIC_Init();GT911_RST(0);
GT911_INT(1);
delay_us(200);
GT911_RST(1);
delay_ms(6);
GT911_INT(0);
delay_ms(55);
GT911_INT_Change();
delay_ms(50);
在C源文件中添加读写GT911寄存器以及修改配置的相关函数:
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:写数据长度
//返回值:0,成功;1,失败.
u8 GT911_WR_Reg(u16 reg,u8 *buf,u8 len)
{
u8 i;
u8 ret=0;
IIC_Start();
IIC_Send_Byte(GT_CMD_WR); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(reg>>8); //发送高8位地址
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF); //发送低8位地址
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
IIC_Send_Byte(buf[i]); //发数据
ret=IIC_Wait_Ack();
if(ret)break;
}
IIC_Stop(); //产生一个停止条件
return ret;
}
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:读数据长度
void GT911_RD_Reg(u16 reg,u8 *buf,u8 len)
{
u8 i;
IIC_Start();
IIC_Send_Byte(GT_CMD_WR); //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(reg>>8); //发送高8位地址
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF); //发送低8位地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(GT_CMD_RD); //发送读命令
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
buf[i]=IIC_Read_Byte(i==(len-1)?0:1); //发数据
}
IIC_Stop();//产生一个停止条件
}
//发送配置参数
//mode:0,参数不保存到flash
// 1,参数保存到flash
u8 GT911_Send_Cfg(u8 mode)
{
u8 buf[2];
u8 i=0;
buf[0]=0;
buf[1]=mode; //是否写入到GT911 FLASH? 即是否掉电保存
for(i=0;i<sizeof(GT911_Cfg);i++)buf[0]+=GT911_Cfg[i];//计算校验和
buf[0]=(~buf[0])+1;
GT911_WR_Reg(GT_CFGS_REG,(u8*)GT911_Cfg,sizeof(GT911_Cfg));//发送寄存器配置
GT911_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
return 0;
}
其中GT911_Cfg为寄存器配置数据,一般由厂商直接提供
完整的GT911初始化代码如下:
void GT911_Init(void)
{
GT911_RST_Init();
GT911_INT_Init();
IIC_Init();
GT911_RST(0);
GT911_INT(1);
delay_us(200);
GT911_RST(1);
delay_ms(6);
GT911_INT(0);
delay_ms(55);
GT911_INT_Change();
delay_ms(50);
u8 tmp[4]={0};
//读取PID
GT911_RD_Reg(GT_PID_REG, tmp, 4);
//修改配置
tmp[0] = 0x02;
GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
GT911_RD_Reg(GT_CFGS_REG, tmp, 1);
if(tmp[0] < 0x60){
printf("Default Ver:0x%X\r\n",tmp[0]);
GT911_Send_Cfg(1);
}
delay_ms(10);
tmp[0] = 0x00;
GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
EXTIX_Init();
}
0x03 中断接收GT911坐标数据:
GT911所连引脚外部中断初始化(PB1):
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
中断服务函数:
查阅《GT911编程指南》:
void EXTI1_IRQHandler(void)
{
u8 tmp;
GT911_RD_Reg(0x8140, data, 0x40);
tmp = data[0x0E];
if((tmp&0x80) && ((tmp&0x0f)>0)){
GetPointData(tmp&0x0f, data);
ShowPointData();
}
tmp = 0;
GT911_WR_Reg(0x814E, &tmp, 1);
delay_ms(10);
EXTI_ClearITPendingBit(EXTI_Line1);
}
data为全局数据(0x8140-0x8180一共0x40个数据),直接一次性读出所有的数据
其中获取和打印坐标的相关函数:
在GT911的头文件中:extern GT911_POINT_DATA gt911_data;
void GetPointData(u8 cnt, u8 data[])
{
gt911_data.cnt = 0;
switch(cnt){
case 5:
gt911_data.points[4].x = data[0x31]<<8 | data[0x30];
gt911_data.points[4].y = data[0x33]<<8 | data[0x32];
case 4:
gt911_data.points[3].x = data[0x29]<<8 | data[0x28];
gt911_data.points[3].y = data[0x2B]<<8 | data[0x2A];
case 3:
gt911_data.points[2].x = data[0x21]<<8 | data[0x20];
gt911_data.points[2].y = data[0x23]<<8 | data[0x22];
case 2:
gt911_data.points[1].x = data[0x19]<<8 | data[0x18];
gt911_data.points[1].y = data[0x1B]<<8 | data[0x1A];
case 1:
gt911_data.points[0].x = data[0x11]<<8 | data[0x10];
gt911_data.points[0].y = data[0x13]<<8 | data[0x12];
break;
default:
break;
}
gt911_data.cnt = cnt;
}
void ShowPointData(void)
{
u8 cnt = gt911_data.cnt;
for(u8 i=0; i<cnt; i++){
printf("Point%d(%d,%d)\t", i+1, gt911_data.points[i].x, gt911_data.points[i].y);
}
printf("\r\n");
memset(>911_data, 0, sizeof(gt911_data));
}
0x04 验证结果:
烧录程序至MCU,接线、上电,打开串口调试助手查看打印信息(最多同时五点触摸):
STM32F103驱动GT911的更多相关文章
- STM32F103驱动ADS1118
ADS1118 作为常用温度测量芯片被越来越多的开发者熟知,TI官方给出的是基于 MSP430 的驱动测试程序,由于 STM32 的普及,闲暇中移植了 MSP430 的 ADS1118 驱动程序到 S ...
- 全志A33驱动GT911触摸屏
0x00 环境说明: 所使用的开发板为锐尔威视的插针版A33_Vstar 触摸屏驱动IC为GT911 接线参照开发板的TP线路 0x01 修改系统配置文件: 笔者所使用的A33开发板的系统配置文件路径 ...
- 电赛总结(四)——波形发生芯片总结之AD9834
一.特性参数 1.2.3V~5.5V供电 2.输出频率高达37.5MHz 3.正弦波.三角波输出 4.提供相位调制和频率调制功能 5.除非另有说明,VDD = 2.3 V至5.5 V,AGND = D ...
- FLASH 存储学习-串行SPI NOR FLASH
1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率:50MHz: l 低功耗模式下电流消耗:5uA ...
- FLASH 存储学习-串行SPI nor
1.1 SST25VF080B简介 1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. 容量:8MBit: 最高SPI时钟频率:50MHz: 低功耗模式下电流消耗:5uA,正常读模 ...
- STM32-串行SPI nor
源:FLASH 存储学习-串行SPI nor 1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率: ...
- 从FPGA搞定OV7670 VGA显示 移植到 STM32F10x TFT显示 总结及疑问(高手请进)
OV7670不愧是最便宜的摄像头了最大显示像素:640*480(在VGA显示器上显示效果还不赖,用usb模块采集显示依然显著) 第一步:VGA显示 视频图像(实时)FPGA+SDRAM+OV7670= ...
- STM32F103 USB虚拟串口 驱动例程移植
1)驱动下载及安装.目前ST公司支持WIN7版本号为:VCP_V1.3.1_Setup.exe (在官网上搜索stsw-stm32102即是了):先安装驱动后再插入USB不然安装不成功. 2)固件下载 ...
- 如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)
六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...
随机推荐
- ios 在工程中使用字体
1.将字体拖入项目 2.在info.plist 文件中加入 3.使用 self.label.font = [UIFont fontWithName: @"FZ XingHei" s ...
- .net core 设置访问静态资源
- 模拟select,隐藏下拉列表的几种实现
前言 平时开发过程中,出于各种原因模拟原生slect的要求并不算少见. 在实现的过程中,点击其他区域隐藏下拉列表,又是一个必备的功能, 最近在一次开发的过程中引发了点思考,做下总结. 现象 实际中的实 ...
- CSS-Sass
什么是css预处理器
- JAVA篇<一> 继承extends(已转移到JAVA总结篇)
前题:如果不经过指出继承,那么所有的类都继承了JAVA中的Object类. 正文: 继承的关键字是:extends,是所有面向对象语言的重要特性. 例public class TestExtends ...
- RAID 0 ~ RAID 7
一.RAID解析1.RAID 0(1)将几块磁盘并行组合,横向写数据(2)并发IO,写数据最快缺点:不提供数据冗余,如果其中一块磁盘废掉,则数据全毁详细:条带深度大时,一次IO只能从一块磁盘上读取,无 ...
- rsyslog 移植与配置方案介绍
rsyslog介绍 rsyslog是一个 syslogd 的多线程增强版.它提供高性能.极好的安全功能和模块化设计.虽然它基于常规的 syslogd,但 rsyslog 已经演变成了一个强大的工具,可 ...
- JavaScript的几种克隆(clone)方式【转】
一:在Javascript里,如果克隆对象是基本类型,我们直接赋值就可以了: var sStr = "kingwell"; var cStr = sStr; alert(cStr) ...
- 从构建分布式秒杀系统聊聊Lock锁使用中的坑
前言 在单体架构的秒杀活动中,为了减轻DB层的压力,这里我们采用了Lock锁来实现秒杀用户排队抢购.然而很不幸的是尽管使用了锁,但是测试过程中仍然会超卖,执行了N多次发现依然有问题.输出一下代码吧,可 ...
- 一个bat病毒分析(part1)
之前没学过bat,这里借分析顺便学一波,分析过程可能有点啰嗦 这里的@echo off关闭回显,病毒一般都是隐秘的执行的,然后setlocal enabledelayedexpansion是设置本地变 ...