必须能够从触摸控制器读取触摸坐标,以便用户与应用程序进行交互。 此处开发的代码将被用于以后开发TouchGFX抽象层。
由于开发板触摸芯片没有连接在I2C接口上,因此本节采用普通IO口模拟I2C接口
1.配置IO口
2.配置定时器
3.编写延时函数
delay.c
#include "delay.h"
#include "tim.h"
void delay_init(void)
{
__HAL_TIM_ENABLE(&htim16);
}
void delay_us(uint16_t us)
{
uint16_t cnt = TIM16->CNT;
while(TIM16->CNT - cnt < us)
{
}
}
void delay_ms(uint32_t ms)
{
for(uint32_t i = 0; i < ms; i++)
delay_us(1000);
}
tim.c
/* USER CODE BEGIN TIM16_MspInit 1 */
delay_init();
/* USER CODE END TIM16_MspInit 1 */
4.模拟I2C接口
i2c.c
#include "i2c.h"
#include "main.h"
#include "delay.h"
#define SDA_IN() {GPIOI->MODER &= ~(3 << (3 * 2)); GPIOI->MODER |= 0 << 3 * 2;}
#define SDA_OUT() {GPIOI->MODER &= ~(3 << (3 * 2)); GPIOI->MODER |= 1 << 3 * 2;}
#define i2c_scl(n) (n ? HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOH, GPIO_PIN_6, GPIO_PIN_RESET))
#define i2c_sda(n) (n ? HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3, GPIO_PIN_RESET))
#define READ_SDA HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_3)
void i2c_delay(void)
{
delay_us(2);
}
void i2c_start(void)
{
i2c_sda(1);
i2c_scl(1);
i2c_delay();
i2c_sda(0);
i2c_delay();
i2c_scl(0);
i2c_delay();
}
void i2c_stop(void)
{
i2c_sda(0);
i2c_delay();
i2c_scl(1);
i2c_delay();
i2c_sda(1);
i2c_delay();
}
uint8_t i2c_wait_ack(void)
{
uint8_t ucErrTime = 0;
uint8_t rack = 0;
i2c_sda(1);
i2c_delay();
i2c_scl(1);
i2c_delay();
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime > 250)
{
i2c_stop();
rack = 1;
break;
}
i2c_delay();
}
i2c_scl(0);
i2c_delay();
return rack;
}
void i2c_ack(void)
{
i2c_sda(0);
i2c_delay();
i2c_scl(1);
i2c_delay();
i2c_scl(0);
i2c_delay();
i2c_sda(1);
i2c_delay();
}
void i2c_nack(void)
{
i2c_sda(1);
i2c_delay();
i2c_scl(1);
i2c_delay();
i2c_scl(0);
i2c_delay();
}
void i2c_send_byte(uint8_t txd)
{
uint8_t t;
for(t = 0; t < 8; t++)
{
i2c_sda((txd & 0x80) >> 7);
i2c_delay();
i2c_scl(1);
i2c_delay();
i2c_scl(0);
txd <<= 1;
}
i2c_sda(1);
}
uint8_t i2c_read_byte(unsigned char ack)
{
uint8_t i, receive = 0;
for(i = 0; i < 8; i++)
{
receive <<= 1;
i2c_scl(1);
i2c_delay();
if(READ_SDA)
receive++;
i2c_scl(0);
i2c_delay();
}
if(!ack)
i2c_nack();
else
i2c_ack();
return receive;
}
5.GT9147驱动
gt9147.c
#include "gt9147.h"
#include "i2c.h"
#include "delay.h"
#define GT_RST(n) (n ? HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_RESET))
//I2C读写命令
#define GT_CMD_WR 0X28 //写命令
#define GT_CMD_RD 0X29 //读命令
//GT9147 部分寄存器定义
#define GT_CTRL_REG 0X8040 //GT9147控制寄存器
#define GT_CFGS_REG 0X8047 //GT9147配置起始地址寄存器
#define GT_CHECK_REG 0X80FF //GT9147校验和寄存器
#define GT_PID_REG 0X8140 //GT9147产品ID寄存器
#define GT_GSTID_REG 0X814E //GT9147当前检测到的触摸情况
#define GT_TP1_REG 0X8150 //第一个触摸点数据地址
#define GT_TP2_REG 0X8158 //第二个触摸点数据地址
#define GT_TP3_REG 0X8160 //第三个触摸点数据地址
#define GT_TP4_REG 0X8168 //第四个触摸点数据地址
#define GT_TP5_REG 0X8170 //第五个触摸点数据地址
uint8_t GT9147_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t i;
uint8_t ret = 0;
i2c_start();
i2c_send_byte(GT_CMD_WR); //发送写命令
i2c_wait_ack();
i2c_send_byte(reg >> 8); //发送高8位地址
i2c_wait_ack();
i2c_send_byte(reg & 0XFF); //发送低8位地址
i2c_wait_ack();
for(i=0; i < len; i++)
{
i2c_send_byte(buf[i]); //发数据
ret = i2c_wait_ack();
if(ret)
break;
}
i2c_stop(); //产生一个停止条件
return ret;
}
void GT9147_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t i;
i2c_start();
i2c_send_byte(GT_CMD_WR); //发送写命令
i2c_wait_ack();
i2c_send_byte(reg >> 8); //发送高8位地址
i2c_wait_ack();
i2c_send_byte(reg & 0XFF); //发送低8位地址
i2c_wait_ack();
i2c_start();
i2c_send_byte(GT_CMD_RD); //发送读命令
i2c_wait_ack();
for(i=0; i < len; i++)
{
buf[i] = i2c_read_byte(i == (len - 1) ? 0 : 1); //发数据
}
i2c_stop();//产生一个停止条件
}
uint8_t CIP[5];
uint8_t GT9147_Init(void)
{
uint8_t cmd;
GT_RST(0); //复位
delay_ms(20);
GT_RST(1); //释放复位
delay_ms(50);
GT9147_RD_Reg(GT_PID_REG, CIP, 4); //读取产品ID
cmd = 0x02;
GT9147_WR_Reg(GT_CTRL_REG, &cmd, 1); //软复位GT9XXX
GT9147_RD_Reg(GT_CFGS_REG, &cmd, 1); //读取GT_CFGS_REG寄存器
delay_ms(10);
cmd= 0x00;
GT9147_WR_Reg(GT_CTRL_REG, &cmd, 1); //结束复位, 进入读坐标状态
return 0;
}
uint8_t GT9147_Scan(uint16_t *x, uint16_t *y)
{
uint8_t cmd;
uint8_t mode;
uint8_t buf[4];
GT9147_RD_Reg(GT_GSTID_REG, &mode, 1);
if(mode & 0x80)
{
GT9147_RD_Reg(GT_TP1_REG, buf, 4); //读取XY坐标值
*x = (((uint16_t)buf[1] << 8) + buf[0]);
*y = (((uint16_t)buf[3] << 8) + buf[2]);
cmd = 0;
GT9147_WR_Reg(GT_GSTID_REG, &cmd, 1); //清标志
return 1;
}
return 0;
}
6.循环采集触摸坐标
main.c
/* USER CODE BEGIN PV */
//uint16_t framebuffer[1024 * 200]; //16 bpp framebuffer
uint16_t *framebuffer = (uint16_t *)0xC0000000; //16 bpp framebuffer
uint16_t touch_x, touch_y;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
GT9147_Init();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
HAL_LTDC_SetAddress(&hltdc, (uint32_t)framebuffer, LTDC_LAYER_1);
hdma2d.Init.Mode = DMA2D_R2M;
hdma2d.Init.ColorMode = DMA2D_RGB565;
MODIFY_REG(hdma2d.Instance->CR, DMA2D_CR_MODE, DMA2D_R2M);
MODIFY_REG(hdma2d.Instance->OPFCCR, DMA2D_OPFCCR_CM, DMA2D_RGB565);
MODIFY_REG(hdma2d.Instance->OOR, DMA2D_OOR_LO, 0);
hdma2d.LayerCfg[1].InputColorMode = CM_RGB565;
hdma2d.LayerCfg[1].InputOffset = 0;
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_Start_IT(&hdma2d, 0xF800, (unsigned int)framebuffer, 1024, 600);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
GT9147_Scan(&touch_x, &touch_y);
HAL_Delay(60);
}
/* USER CODE END 3 */
7.烧录程序,运行检查触摸坐标