开发板

K210开发板

基于K210开发板LCD触摸屏读取坐标数据测试_触摸板

实验目的

主要学习 K210 通过 I2C 读取触摸屏的坐标,并打印出来,显示在 LCD上。

实验准备

实验元件

LCD 显示屏+触摸板

基于K210开发板LCD触摸屏读取坐标数据测试_#define_02

元件特性

K210 开发板自带 2.0 寸触摸屏,其实是 LCD 显示屏上贴一个触摸板组成,LCD显示屏上一节课已经学过,而触摸板为电容触摸板,与手机上使用的电容屏原理一样,可以直接用手指触摸,而不像电阻屏一样要用指甲按。电容屏具有相应时间短,精确度高,使用寿命长,操作简单方便等特点。触摸板使用的是 I2C 通讯,能够稳定传输数据,并且支持与其他 I2C 设备并联到同一个 I2C 接口上通讯。

硬件连接

K210 开发板出厂默认已经安装好 LCD 显示屏和触摸板,其中 LCD 显示屏的LCD_D0~D7 总共八个引脚连接到 SPI0_D0~D7 上,LCD_CS 连接到 IO36 上,LCD_RST连接到 IO37 上,LCD_RS 连接 IO3 上,LCD_WR 连接 IO39 上;触摸板的 I2C_SCL连接到 IO9,I2C_SDA 连接到 IO10,FT_INT 连接到 IO12,FT_RST 连接到 IO37,与 LCD 显示屏共用使用一个 RST 接口。

基于K210开发板LCD触摸屏读取坐标数据测试_#define_03

基于K210开发板LCD触摸屏读取坐标数据测试_初始化_04

SDK 中对应 API 功能

以头文件 i2c.h为例

  • I2C 总线用于和多个外部设备进行通信。多个外部设备可以共用一个 I2C总线。
  • I2C 模块具有独立的 I2C 设备封装外设相关参数,自动处理多设备总线争用的功能。
  • K210 芯片集成电路总线有 3个 I2C总线接口,都可以作为 I2C 主机(MASTER)模式或从机(SLAVE)模式来使用。
  • I2C 接口支持标准模式(0 到 100kb/s),快速模式(<=400kb/s),7 位或10 位寻址模式,批量传输模式,中断或轮询模式操作。
• i2c_init:初始化 I2C,配置从机地址、寄存器位宽度和 I2C 速率。
• i2c_init_as_slave:配置 I²C 为从模式。
• i2c_send_data:I2C 写数据。
• i2c_send_data_dma:I2C 通过 DMA 写数据。
• i2c_recv_data:I2C 通过 CPU 读数据。
• i2c_recv_data_dma:I2C 通过 dma 读数据。
• i2c_handle_data_dma:I2C 使用 dma 传输数据。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

实验原理

  • 电容式触摸屏技术是利用人体的电流感应进行工作的。电容式触摸屏是一块 四层复合玻璃屏,玻屏的内表面和夹层各涂有一层 ITO,最外层是一薄层矽土 玻璃保护层,夹层 ITO 涂层作为工作面,角上引出四个电极,内层ITO 为屏 蔽层以保证良好的工作环境。当手指触摸在金属层上时,由于人体电场,用户 和触摸屏表面形成以一个耦合电容,对于高频电流来说,电容是直接导体,于是手指从接触点吸走一个很小的电流。这个电流分别从触摸屏的四角上的电极中流出,并且流经这四个电极的电流与手指到四角的距离成正比,控制器通过对这四 个电流比例的精确计算,得出触摸点的位置。
  • I2C 是一种总线式结构,它只需要 SCL 时钟信号线与 SDA 数据线,两根线就能将连接与总线上设备实现数据通信,由于它的简便的构造设计,于是成为一种较为常用的通信方式。由于 I2C 采用的是主从式通信方式,所以,通信的过程完全由主设备仲裁。在通信之前,必须由主设备发送一个起始信号,决定数据是否可以开始传送,并且在结束通信时,必须再由主设备发送一个结束信号,以表示通信已经结束。 I2C 向寄存器写入数据的过程:I2C 从寄存器读取数据的过程:

基于K210开发板LCD触摸屏读取坐标数据测试_#define_05

实验过程

  1. 首先初始化 K210 的硬件引脚和软件功能使用的是 FPIOA 映射关系
#define PIN_LCD_CS             (36)
#define PIN_LCD_RST            (37)
#define PIN_LCD_RS             (38)
#define PIN_LCD_WR             (39)

#define PIN_FT_RST             (37)
#define PIN_FT_INT             (12)
#define PIN_FT_SCL             (9)
#define PIN_FT_SDA             (10)

/*****************************SOFTWARE-GPIO********************************/
// 软件GPIO口,与程序对应
#define LCD_RST_GPIONUM        (0)
#define LCD_RS_GPIONUM         (1)

#define FT_INT_GPIONUM         (2)
#define FT_RST_GPIONUM         (3)

/*****************************FUNC-GPIO************************************/
// GPIO口的功能,绑定到硬件IO口
#define FUNC_LCD_CS             (FUNC_SPI0_SS3)
#define FUNC_LCD_RST            (FUNC_GPIOHS0 + LCD_RST_GPIONUM)
#define FUNC_LCD_RS             (FUNC_GPIOHS0 + LCD_RS_GPIONUM)
#define FUNC_LCD_WR             (FUNC_SPI0_SCLK)

#define FUNC_FT_RST             (FUNC_GPIOHS0 + FT_RST_GPIONUM)
#define FUNC_FT_INT             (FUNC_GPIOHS0 + FT_INT_GPIONUM)
#define FUNC_FT_SCL             (FUNC_I2C0_SCLK)
#define FUNC_FT_SDA             (FUNC_I2C0_SDA)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
void hardware_init(void)
{
    /**
    *lcd_cs	    36
    *lcd_rst	37
    *lcd_rs	    38
    *lcd_wr 	39
    **/
    fpioa_set_function(PIN_LCD_CS, FUNC_LCD_CS);
    fpioa_set_function(PIN_LCD_RST, FUNC_LCD_RST);
    fpioa_set_function(PIN_LCD_RS, FUNC_LCD_RS);
    fpioa_set_function(PIN_LCD_WR, FUNC_LCD_WR);
    
    /* 使能SPI0和DVP */
    sysctl_set_spi0_dvp_data(1);

    /* I2C FT6236 */
    // fpioa_set_function(PIN_FT_RST, FUNC_FT_RST);
    fpioa_set_function(PIN_FT_INT, FUNC_FT_INT);
    fpioa_set_function(PIN_FT_SCL, FUNC_FT_SCL);
    fpioa_set_function(PIN_FT_SDA, FUNC_FT_SDA);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  1. 设置 LCD 的 IO 口电平电压为 1.8V。
void io_set_power(void)
{
    sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18);
}
  • 1.
  • 2.
  • 3.
  • 4.
  1. 由于触摸板需要使用中断来判断屏幕是否有触摸,所有需要初始化中断并使能全局中断。
/* 系统中断初始化,并使能全局中断 */
    plic_init();
    sysctl_enable_irq();
  • 1.
  • 2.
  • 3.
  1. 初始化 LCD 显示屏,并显示图片和字符串欢迎语
/* 初始化LCD */
    lcd_init();

    /* 显示图片 */
    uint16_t * img = &gImage_logo; 
    lcd_draw_picture_half(0, 0, 320, 240, img);
    sleep(1);
    lcd_draw_string(16, 40, "Hello Yahboom", RED);
    lcd_draw_string(16, 60, "Nice to meet you!", BLUE);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  1. 初始化触摸板,并通过 LCD 显示和串口打印触摸提示。
/* 初始化触摸板 */
    ft6236_init();
    printf("Hi!Please touch the screen to get coordinates!\n");
    lcd_draw_string(16, 180, "Please touch the screen to get coord!", RED);
  • 1.
  • 2.
  • 3.
  • 4.

触摸板 FT6236 的初始化比较简单,分为硬件初始化和软件初始化,软件初始化主要是设置 FT6236 的寄存器,唤醒 FT6236 设置触摸灵敏度和扫描周期。

/* 初始化ft6236 */
void ft6236_init(void)
{
    ft6236.touch_state = 0;
    ft6236.touch_x = 0;
    ft6236.touch_y = 0;

    /* 硬件初始化 */
    ft6236_hardware_init();

    /* 软件初始化 */
    i2c_hardware_init(FT6236_I2C_ADDR);
    ft_i2c_write(FT_DEVIDE_MODE, 0x00);
    /* 设置触摸有效值,越小越灵敏,def=0xbb */
    ft_i2c_write(FT_ID_G_THGROUP, 0x12);    // 0x22
    /* 工作扫描周期,用于控制报点率,def=0x08, 0x04~0x14 */
    ft_i2c_write(FT_ID_G_PERIODACTIVE, 0x06);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  1. 硬件引脚初始化,主要是修改触摸板复位引脚的电平,这里与屏幕使用同一个复位引脚,所以不需要再复位操作。再设置 FT_INT 中断引脚为输入,中断回调函数为 ft6236_isr_cb,并在中断函数中修改触摸屏的状态。
void ft6236_hardware_init(void)
{
    /* 与屏幕使用不同复位引脚时设置为1 */
    #if (0) 
    {
        gpiohs_set_drive_mode(FT_RST_GOIONUM, GPIO_DM_OUTPUT);
        ft6236_reset_pin(LEVEL_LOW);
        msleep(50);
        ft6236_reset_pin(LEVEL_HIGH);
        msleep(120);
    }
    #endif

    gpiohs_set_drive_mode(FT_INT_GPIONUM, GPIO_DM_INPUT);
    gpiohs_set_pin_edge(FT_INT_GPIONUM, GPIO_PE_RISING);
    gpiohs_irq_register(FT_INT_GPIONUM, FT6236_IRQ_LEVEL, ft6236_isr_cb, NULL);
    msleep(5);
    
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  1. FT6236通过I2C通讯的方式来读和写数据,以下是触摸板 I2C控制的函数:
/* I2C写数据 */
static void ft_i2c_write(uint8_t reg, uint8_t data)
{
    i2c_hd_write(FT6236_I2C_ADDR, reg, data);
}

/* I2C读数据 */
static void ft_i2c_read(uint8_t reg, uint8_t *data_buf, uint16_t length)
{
    i2c_hd_read(FT6236_I2C_ADDR, reg, data_buf, length);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

初始化 I2C,设置从机地址,数据位宽度,I2C 通讯速率等,

static uint16_t _current_addr = 0x00;

/* 硬件初始化I2C,设置从机地址,数据位宽度,I2C通讯速率 */
void i2c_hardware_init(uint16_t addr)
{
    i2c_init(I2C_DEVICE_0, addr, ADDRESS_WIDTH, I2C_CLK_SPEED);
    _current_addr = addr;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

向寄存器 reg 写入一个数据 data ,写入成功返回 0,失败则返回非 0,

/* 向寄存器reg写入一个数据data ,写入成功返回0,失败则返回非0*/
uint16_t i2c_hd_write(uint8_t addr, uint8_t reg, uint8_t data)
{
    if (_current_addr != addr)
    {
        i2c_hardware_init(addr);
    }
    uint8_t cmd[2];
    cmd[0] = reg;
    cmd[1] = data;
    uint16_t error = 1;
    error = i2c_send_data(I2C_DEVICE_0, cmd, 2);
    return error;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

从寄存器 reg 读取 length 个数据保存到 data_buf,读取成功返回 0,失败则返回非 0。

/* 从寄存器reg读取length个数据保存到data_buf,读取成功返回0,失败则返回非0 */
uint16_t i2c_hd_read(uint8_t addr, uint8_t reg, uint8_t *data_buf, uint16_t length)
{
    if (_current_addr != addr)
    {
        i2c_hardware_init(addr);
    }
    uint16_t error = 1;
    error = i2c_recv_data(I2C_DEVICE_0, ®, 1, data_buf, length);
    return error;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  1. main 函数里最后是一个 while(1)循环,读取触摸屏的坐标 XY 值,然后通过串口打印出来,再显示到 LCD 显示屏上。每次显示完成后都需要刷新以下显示的位置,否则旧数据会重叠到一起,所以 lcd_clear_coord 函数就是清除坐标的作用。
while (1)
    {
        /* 刷新数据位,清空上次显示的数据 */
        if (is_refresh)
        {
            lcd_clear_coord();
            is_refresh = 0;
        }
        
        /* 如果触摸到触摸屏的时候 */
        if (ft6236.touch_state & TP_COORD_UD)
        {
            ft6236.touch_state &= ~TP_COORD_UD;
            /* 扫描触摸屏 */
            ft6236_scan();
            /* 串口打印X Y 坐标 */
            printf("X=%d, Y=%d \n ", ft6236.touch_x, ft6236.touch_y);
            sprintf(coord, "(%d, %d)", ft6236.touch_x, ft6236.touch_y);

            lcd_draw_string(120, 200, coord, BLUE);
            is_refresh = 1;
        }
        /* 延迟80毫秒保证屏幕数据正常刷新 */
        msleep(80);
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  1. 先使用 lcd_set_area 函数设定显示坐标的区域,然后再写入白色的值(0XFFFFFFFF),以此来刷新显示的内容。如果背景图片的坐标区域不是空白的,则无法使用此方法来刷新。
void lcd_clear_coord(void)
{
    uint32_t color = 0xFFFFFFFF;
    uint8_t x1 = 120;
    uint8_t y1 = 200;
    uint8_t width = 100;
    uint8_t height = 16;
    
    lcd_set_area(x1, y1, x1 + width - 1, y1 + height - 1);
    tft_fill_data(&color, width * height / 2);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

10.编译调试,烧录运行进入自己项目 build目录,运行以下命令编译。

cmake .. -DPROJ=watchdog -G "MinGW Makefiles"
make
  • 1.
  • 2.

实验现象

烧录完成固件后,系统会弹出一个终端界面,如果没有弹出终端界面的可以打开串口助手显示调试内容。

基于K210开发板LCD触摸屏读取坐标数据测试_初始化_06

基于K210开发板LCD触摸屏读取坐标数据测试_触摸板_07

同时 LCD 显示屏上也会显示当前触摸的坐标,当松开手时,坐标也会消失。每次移动手指,改变触摸的位置,对应的触摸点坐标也会改变。

实验总结

  • K210 开发板的触摸屏是电容式触摸屏,可以使用手指直接触摸使用。
  • 触摸板使用的是 I2C 通讯,读取数据后需要转化计算一下才能得到实际的触摸 坐标。
  • 触摸板的相关寄存器放在项目的  README.md 文件中,具体寄存器功能请查看硬 件相关资料中触摸屏资料