正点原子 发表于 3 小时前

《ESP32-S3使用指南—MicroPython版 V1.0》第三十一章 RGB触摸实验


1)实验平台:正点原子ESP32S3开发板
2)购买链接:https://detail.tmall.com/item.htm?id=768499342659
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-347618-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子手把手教你学ESP32S3快速入门视频教程:https://www.bilibili.com/video/BV1sH4y1W7Tc
6)正点原子FPGA交流群:132780729


第三十一章 RGB触摸实验

       本章,作者将介绍如何使用ESP32-S3来驱动触摸屏,我们通过外接带触摸屏的LCD模块(比如正点原子RGBLCD模块),来实现触摸屏控制。在本章中,我们将向大家介绍ESP32-S3控制正点原子RGBLCD模块,实现触摸屏驱动(电容触摸),最终实现一个手写板的功能。
       本章分为如下几个小节:
       31.1 Touch C模块解析
       31.2 硬件设计
       31.3 软件设计
       31.4 下载验证

       31.1 Touch C模块解析
       RGB屏相关内容,可参考正点原子提供的《ATK-MD0430R模块用户手册_V1.0》和《ATK-MD0430R模块使用说明_V1.0》,在这两个手册中,已经详细说明了RGB的工作原理及相关参数信息。
       温馨提示:正点原子ATK-MD0430R 模块搭载了GT9147电容式触摸屏IC,我们可通过IIC协议读取显示屏的触摸点。

       31.1.1 C模块解析
       本章的Touch C模块组件可在资料A盘6,软件资料1,软件2,MicroPython开发工具01-Windows2,正点原子MicroPython驱动CModules_LibRGBLCD目录下找到。下面作者将简要介绍正点原子Touch C模块驱动。这个讲解内容会分为几个部分:Touch模块初始化、扫描触摸屏、获取x坐标、获取y坐标和获取触摸状态。

       1,Touch模块初始化模块方法
_m_tp_dev tp_dev =
{{
    tp_init,
    0,
    0,
    0,
    0,
    0,
}};

/**
* @brief       触摸屏初始化
* @param       无
* @retval      0,没有进行校准
*            1,进行过校准
*/
uint8_t tp_init(void)
{
    tp_dev.touchtype = 0;                                 /* 默认设置(电阻屏 & 竖屏) */
    tp_dev.touchtype |= ltdc_self->dir & 0X01;         /* 根据LCD判定是横屏还是竖屏 */

    if (ltdc_self->id == 0X4342 || ltdc_self->id == 0X4384)
    {
      gt9xxx_init();
      tp_dev.scan = gt9xxx_scan;               /* 扫描函数指向GT9147触摸屏扫描 */
      tp_dev.touchtype |= 0X80;                   /* 电容屏 */
      return 0;
    }

    return 1;
}

/**
* @brief       触摸初始化
* @param       无
* @retval      无
*/
STATIC mp_obj_t mp_touch_init(void)
{
    tp_dev.init();
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(touch_init_obj, mp_touch_init);
       在上述源代码中,我们首先初始化tp_dev结构体的成员变量。然后,在tp_init函数中,我们判断RGB显示屏的ID是否为0x4342和0x4384,这两款是RGB屏幕。接着,我们执行触摸IC的初始化操作,并将tp_dev.scan函数指针指向gt9xxx_scan函数,该函数用于扫描触摸,最后,将mp_touch_init函数注册至模块列表当中,使得在MicroPython环境下调用此模块的方法。
       请注意,gt9xxx.c/.h文件与正点原子STM32F429以上开发板提供的触摸IC驱动完全一致,只是将IIC协议通信替换为硬件IIC通信。

       2,扫描触摸屏模块方法
       上述作者提到,RGB显示屏的扫描函数由tp_dev结构体中的tp_dev.scan函数指针指向。因此,如果MicroPython想调用扫描触摸屏方法,可以将tp_dev.scan函数指针注册到模块列表中。如下源代码所示:
/**
* @brief       扫描触摸屏(采用查询方式)
* @param       mode : 电容屏未用到次参数, 为了兼容电阻屏
* @retval      当前触屏状态
*   @arg       0, 触屏无触摸;
*   @arg       1, 触屏有触摸;
*/
STATIC mp_obj_t mp_touch_scan(mp_obj_t mode)
{
    int ct_mode = mp_obj_get_int(mode);
    tp_dev.scan(ct_mode);
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(touch_scan_obj, mp_touch_scan);       可以看到,此方法需要传入一个形参,用来设置触摸屏的状态,若此入参为0时,则触摸屏并没有触摸,反次,有触摸。

       3,获取x/y坐标模块方法
/**
* @brief       获取X轴坐标
* @param       无
* @retval      无
*/
STATIC mp_obj_t mp_touch_get_x(void)
{
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t)
* MP_ARRAY_SIZE(tp_dev.x), tp_dev.x);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(touch_get_x_obj, mp_touch_get_x);

/**
* @brief       获取Y轴坐标
* @param       无
* @retval      无
*/
STATIC mp_obj_t mp_touch_get_y(void)
{
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t)
* MP_ARRAY_SIZE(tp_dev.y), tp_dev.y);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(touch_get_y_obj, mp_touch_get_y);       上述模块方法中,我们使用MicroPython字节数组来存储触摸屏的X和Y轴坐标,然后,把字节数组返回给用户,这样就可以得到当前触摸的X与Y轴坐标了。

       4,获取触摸状态模块方法
/**
* @brief       获取触摸状态
* @param       无
* @retval      无
*/
STATIC mp_obj_t mp_touch_get_sta(void)
{
    sta = tp_dev.sta;
   
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t)
*MP_ARRAY_SIZE(sta), sta);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(touch_get_sta_obj, mp_touch_get_sta);       同理,触摸状态方法也是利用MicroPython的字节数组来存储触摸状态数值,然后,返回给用户,来判断当前RGB显示屏触摸状态。

       31.1.2 C模块构造与类的方法
       在上小节中,作者已介绍了RGB触摸C模块的方法,下面是MicroPython引用这些模块方法的原型,如下所示:

       ①:初始化触摸驱动
       其方法原型如下:
touch.init()       返回值:无。

       ②:扫描触摸
       其方法原型如下:
touch.scan(0)       返回值:无。

       ③:获取X轴坐标
       其方法原型如下:
touch.get_x()       返回值:X坐标。

       ④:获取Y轴坐标
       其方法原型如下:
touch.get_y()       返回值:Y坐标。

       ⑤:获取触摸状态
       其方法原型如下:
touch.get_sta()       返回值:触摸状态。
       温馨提示:调用触摸模块的方法之前,必须先导入atk_touch模块,后调用此模块的方法,如下是导入模块示例:
import atk_touch as touch
       31.2 硬件设计

       1. 例程功能
       本章实验功能简介:经过一系列的初始化之后,进入电容触摸屏测试程序,用户可在画板上绘画字符、线条等,在测试界面的右上角会有一个清空的操作区域(RST),点击这个地方就会将输入全部清除,恢复白板状态。

       2. 硬件资源

       1)LED灯
              LED-IO1

       2)XL9555
              IIC_INT-IO0(需在P5连接IO0)
              IIC_SDA-IO41
              IIC_SCL-IO42

       3)RGBLCD
              LCD_BL-IO1_3(XL9555)
              LCD_DE-IO4
              LCD_VSYNC-NC
              LCD_HSYNC-NC
              LCD_PCLK-IO5
              LCD_R3-IO45
              LCD_R4-IO48
              LCD_R5-IO47
              LCD_R6-IO21
              LCD_R7-IO14
              LCD_G2-IO10
              LCD_G3-IO9
              LCD_G4-IO46
              LCD_G5-IO3
              LCD_G6-IO8
              LCD_G7-IO18
              LCD_B3-IO17
              LCD_B4-IO16
              LCD_B5-IO15
              LCD_B6-IO7
              LCD_B7-IO6

       3. 原理图
       RGB接口与ESP32-S3的连接关系,如下图所示:

图31.2.1 RGB接口与ESP32-S3的连接电路图
       31.3 软件设计

       31.3.1 程序流程图
       程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图。

图31.3.1.1 程序流程图
       31.3.2 程序解析
       本书籍的代码都在main.py脚本下编写的,读者可在光盘资料下找到对应的源码。RGB触摸实验main.py源码如下:
from machine import Pin,I2C
import atk_xl9555 as io_ex
import atk_ltdc as ltdc
import atk_touch as touch
import time


# 设置屏幕横竖屏:0为竖屏;1为横屏
atk_dir = 1

if atk_dir == 1:
    LCD_WIDTH= 800
    LCD_HEIGHT = 480
else:
    LCD_WIDTH= 480
    LCD_HEIGHT = 800

"""
* @brief       清空屏幕并在右上角显示"RST"
* @param       无
* @retval      无
"""
def load_draw_dialog():
   
    display.clear(ltdc.WHITE)
    display.string(LCD_WIDTH - 30, 0, 200, 16, 16, "RST", ltdc.BLUE)


"""
* @brief       画粗线
* @param       x1,y1: 起点坐标
* @param       x2,y2: 终点坐标
* @param       size : 线条粗细程度
* @param       color: 线的颜色
* @retval      无
"""
def lcd_draw_bline(x1,y1,x2,y2,size,color):
   
    t = 0
    xerr = 0
    yerr = 0
    delta_x = 0
    delta_y = 0
    distance = 0
    incx = 0
    incy = 0
    row = 0
    col = 0

    delta_x = x2 - x1                     # 计算坐标增量
    delta_y = y2 - y1
    row = x1
    col = y1

    if delta_x > 0:
      incx = 1                            # 置单步方向
    elif delta_x == 0:
      incx = 0                            # 垂直线
    else:
      incx = -1
      delta_x = -delta_x

    if delta_y > 0:
      incy = 1
    elif delta_y == 0:
      incy = 0                            # 水平线
    else:
      incy = -1
      delta_y = -delta_y

    if delta_x > delta_y:
      distance = delta_x;               # 选取基本增量坐标轴
    else:
      distance = delta_y

    for t in range(0,distance + 1):         # 画线输出
      display.circle(row, col, size, color)   # 画点
      xerr += delta_x
      yerr += delta_y

      if xerr > distance:
            xerr -= distance
            row += incx

      if yerr > distance:
            yerr -= distance
            col += incy

"""
* @brief       电容屏测试
* @param       无
* @retval      无
"""
def ctp_test():
   
    t = 0
    i = 0
    lastpos = [, ]    #最后一次的数据

    while True:
      
      touch.scan(0)
      
      x_data = touch.get_x()
      y_data = touch.get_y()
      sta_data = touch.get_sta()
      
      x = (x_data << 8) | x_data
      y = (y_data << 8) | y_data
      sta = (sta_data << 8) | sta_data
      
      for t in range(0,5):
            
            if sta & (1 << t):
               
                if (x < LCD_WIDTH and y < LCD_HEIGHT):
                  
                  if lastpos == 0xFFFF:
                        
                        lastpos = x
                        lastpos = y
                  
                  lcd_draw_bline(lastpos, lastpos,x,y,2,ltdc.RED);
                  lastpos = x
                  lastpos = y
                  
                  if (x > (LCD_WIDTH - 30) and y < 20):
                        
                        load_draw_dialog()
                else:
                  lastpos = 0xFFFF
               
      time.sleep_ms(5)
      
      i += 1
      
      if (i % 20 == 0):
            
            led_state = led.value()
            led.value(not led_state)

"""
* @brief       程序入口
* @param       无
* @retval      无
"""
if __name__ == '__main__':
   
    x = 0
    # 初始化LED并输出高电平
    led = Pin(1,Pin.OUT,value = 1)
    # IIC初始化
    i2c0 = I2C(0, scl = Pin(42), sda = Pin(41), freq = 400000)
    # XL9555初始化
    xl9555 = io_ex.init(i2c0)
   
   
    # 初始化RGB
    display = ltdc.init(dir = atk_dir)
    # 打开RGB屏背光
    xl9555.write_bit(io_ex.LCD_BL,1)
    time.sleep_ms(100)
   
    # 复位触摸芯片
    xl9555.write_bit(io_ex.CT_RST,0)
    time.sleep_ms(10)
    xl9555.write_bit(io_ex.CT_RST,1)
    time.sleep_ms(10)
   
    # 初始化触摸驱动
    touch.init()
   
    # 清空屏幕并在右上角显示"RST"
    load_draw_dialog()
   
    while True:
      
      ctp_test()       该示例经过一些列初始化之后,执行ctp_test函数创建白色的画板,用户可在画板上涂鸦,如果xiang 清除画板上的涂鸦,可点击右上角的“RST”按键清除。

       31.4 下载验证
       在代码编译成功之后,我们通过下载代码到开发板上,触摸屏测试如下图所示界面:

图31.4.1 触摸屏测试界面
       图中,作者在触摸板绘画“ALIENTEK”字符串。按右上角的RST标志,可以清屏。
页: [1]
查看完整版本: 《ESP32-S3使用指南—MicroPython版 V1.0》第三十一章 RGB触摸实验