搜索
bottom↓
回复: 0

《ESP32-S3使用指南—MicroPython版 V1.0》第十六章 SPILCD实验

[复制链接]

出0入234汤圆

发表于 4 天前 | 显示全部楼层 |阅读模式
2.jpg
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
1.png
3.png

第十六章 SPILCD实验


       在本章实验中,我们将通过编写MicroPython驱动程序来实现SPILCD显示。在开发板上,我们已经预留了SPILCS模块接口,因此需要准备一个SPILCD显示模块。我们将一起点亮SPILCS,并实现字符的显示。
       16.1 SPILCD模块简介
       16.2 SPILCD C模块解析
       16.3 硬件设计
       16.4 软件设计
       16.5 下载验证

       16.1 SPILCD模块简介
       本例程仅支持两种屏幕,一种是ATK-MD0130的1.3寸显示模块,另一种是ATK-MD0240的2.4寸显示模块。这两种显示模块是由正点原子推出的高性能LCD显示模块。这两个显示模块的LCD分辨率为240*240和320*240像素,支持16位真彩色显示。模块采用ST7789V作为LCD的驱动芯片,该芯片自带RAM,无需外加驱动器或存储器。使用外接的主控芯片时,仅需使用SPI接口就可以轻松地驱动这两个显示模块。
       ATK-MD0130和ATK-MD0240 模块的各项基本参数,如下表所示。

1.png
表16.1.1 ATK-MD0130和ATK-MD0240 模块基本参数

       ATK-MD0130和ATK-MD0240模块通过2*4的排针(2.54mm 间距)同外部相连接,该模块可直接与正点原子DNESP32-S3开发板和正点原子MiniSTM32H750开发板等开发板的WIRELESS接口(SPI 接口)连接,而对于没有板载WIRELESS接口的开发板,可以通过杜邦线连接。正点原子大部分的STM32开发板,我们都提供了本模块相应的例程,用户可以直接在这些开发板上,对模块进行测试。
       ATK-MD0130模块的外观,如下图所示。

第十六章 SPILCD实验911.png
图16.1.1 ATK-MD0130模块实物图

       ATK-MD0130和ATK-MD0240模块的原理图,如下图所示。

第十六章 SPILCD实验972.png
图16.1.2 ATK-MD0130模块原理图

       ATK-MD0130和ATK-MD0240模块通过一个2*4的排针(2.54mm间距)同外部电路连接,各引脚的详细描述,如下表所示。

2.png
表16.1.2 ATK-MD0130和ATK-MD0240模块引脚说明

       16.1.1 模块SPI时序介绍
       ATK-MD0130和ATK-MD0240模块在四线SPI通讯模式下,最少仅需四根信号线(CS、SCK、SDA、WR(DC))就能够完成与这两个显示模块的通讯,四线SPI接口时序如下图所示。

第十六章 SPILCD实验1399.png
图16.1.1.1 四线SPI接口时序图

       上图中各个时间参数,如下图所示。

第十六章 SPILCD实验1439.png
图16.1.1.2 四线SPI接口时序时间参数

       从上图中可以看出,ATK-MD0130和ATK-MD0240模块四线SPI的写周期是非常快的(TSCYCW = 66ns),而读周期就相对慢了很多(TSCYCR = 150ns)。
       更详细的时序介绍,可以参考ST7789V的数据手册《ST7789V_SPEC_V1.4.pdf》。

       16.1.2 模块驱动说明
       ATK-MD0130和ATK-MD0240模块采用ST7789V作为LCD驱动器,LCD的显存可直接存放在ST7789V的片上RAM中,ST7789V的片上RAM有240*320*3字节,并且ST7789V会在没有外部时钟的情况下,自动将其片上RAM的数据显示至LCD上,以最小化功耗。
       在每次初始化显示模块之前,必须先通过RST引脚对显示模块进行硬件复位,硬件复位要求RST至少被拉低10微秒,拉高RST结束硬件复位后,须延时120毫秒等待复位完成后,才能够往显示模块传输数据。
       PWR引脚用于控制显示模块的LCD背光,该引脚自带下拉电阻,当PWR引脚被拉低或悬空时,ATK-MD0130模块的LCD背光都处于关闭状态,当PWR引脚被拉高时,显示模块的LCD背光才会点亮。
       ST7789V最高支持18位色深(262K色),但一般在希纳是模块上使用16位色深(65K色)的RGB565格式,这样可以在16位色深下达到最快的速度。在16位色深模式下,ST7789V采用RGB565格式传输、存储颜色数据,如下图所示。

第十六章 SPILCD实验2078.png
图16.1.2.1 16位色深模式(RGB565)传输颜色数据

       如上图所示,一个像素的颜色数据需要使用16比特来传输,这16比特数据中,高5比特用于表示红色,低5比特用于表示蓝色,中间的6比特用于表示绿色。数据的数值越大,对应表示的颜色就越深。
       ST7789V支持连续读写RAM中存放的LCD上颜色对应的数据,并且连续读写的方向(LCD的扫描方向)是可以通过命令0x36进行配置的,如下图所示。

第十六章 SPILCD实验2278.png
图16.1.2.2 命令0x36

       从上图中可以看出,命令0x36可以配置6个参数,但对于配置LCD的扫描方向,仅需关心MY、MX和MV这三个参数,如下表所示。

3.png
表16.1.2.1 命令0x36配置LCD扫描方向

       这样一来,就能够大大地提高ATK-MD0130和ATK-MD0240模块在刷屏时的效率,仅需设置一次坐标,然后连续地往ATK-MD0130和ATK-MD0240模块传输颜色数据即可。
       在往ATK-MD0130和ATK-MD0240模块写入颜色数据前,还需要设置地址,以确定随后写入的颜色数据对应LCD上的哪一个像素,通过命令0x2A和命令0x2B可以分别设置ATK-MD0130和ATK-MD0240模块显示颜色数据的列地址和行地址,命令0x2A的描述,如下图所示。

第十六章 SPILCD实验2791.png
图2.3.3 命令0x2A

       命令0x2B的描述,如下图所示。

第十六章 SPILCD实验2824.png
图2.3.4 命令0x2B

       以默认的LCD扫描方式(从左到右,从上到下)为例,命令0x2A的参数XS和XE和命令0x2B的参数YS和YE就在LCD上确定了一个区域,在连读读写颜色数据时,ST7789V就会按照从左到右,从上到下的扫描方式读写设个区域的颜色数据。

       16.2 SPILCD C模块解析

       16.2.1 C模块解析
       作者将简要介绍正点原子SPILCD C模块驱动。这个讲解内容会分为几个部分:SPILCD构造函数、写数据、写命令。SPILCD C模块驱动可在A盘6,软件资料1,软件2,MicroPython开发工具01-Windows2,正点原子MicroPython驱动CModules_LibLCD路径下找到。

       1,SPILCD构造函数
  1. mp_obj_t lcd_make_new(const mp_obj_type_t *type,size_t n_args,size_t n_kw
  2. ,const mp_obj_t *all_args )
  3. {
  4.     /* 创建对象的参数 */
  5.     enum
  6.     {
  7.         ARG_spi, ARG_reset, ARG_dc, ARG_cs,
  8.         ARG_backlight, ARG_dir,ARG_lcd,
  9.     };
  10.     /* 创建对象参数的默认值 */
  11.     static const mp_arg_t allowed_args[] = {
  12.         { MP_QSTR_spi, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} },
  13.         { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
  14.         { MP_QSTR_dc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
  15.         { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
  16.         { MP_QSTR_backlight, MP_ARG_KW_ONLY|MP_ARG_OBJ,{.u_obj = MP_OBJ_NULL} },
  17.         { MP_QSTR_dir, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
  18.         { MP_QSTR_lcd, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
  19.     };
  20.         
  21.     mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
  22. mp_arg_parse_all_kw_array(n_args, n_kw, all_args,
  23.                           MP_ARRAY_SIZE(allowed_args), allowed_args, args);

  24.     /* 创建对象 */
  25.     self = m_new_obj(lcd_obj_t);
  26.     self->base.type = &lcd_type;

  27.     /* 设置对象参数 */
  28. mp_obj_base_t *spi_obj  = (mp_obj_base_t*)
  29. MP_OBJ_TO_PTR(args[ARG_spi].u_obj);
  30.     self->spi_obj           = spi_obj;
  31.     self->dir               = args[ARG_dir].u_int;
  32.     self->lcd               = args[ARG_lcd].u_int;
  33.    
  34.     /* SPI控制块是否为空 */
  35.     if (spi_obj == MP_OBJ_NULL)
  36.     {
  37.         mp_raise_ValueError(MP_ERROR_TEXT("SPI init ???"));
  38.     }
  39.     /* 屏幕方向只能横屏和竖屏 */
  40.     if (self->dir != 1 && self->dir != 0)
  41.     {
  42.         mp_raise_ValueError(MP_ERROR_TEXT("Not horizontal and
  43. vertical screens"));
  44.     }
  45.     /* LCD类型选择 */
  46.     if (self->lcd != 1 && self->lcd != 0)
  47.     {
  48.         mp_raise_ValueError(MP_ERROR_TEXT("Only supports 320x240(0)
  49. and 240x240(1)"));
  50.     }
  51.     /* DC命令/数据选择管脚 */
  52.     if (args[ARG_dc].u_obj == MP_OBJ_NULL) {
  53.         mp_raise_ValueError(MP_ERROR_TEXT("must specify dc pin"));
  54.     }
  55.     /* 背光管脚 */
  56.     if (args[ARG_backlight].u_obj != MP_OBJ_NULL) {
  57.         self->backlight = mp_hal_get_pin_obj(args[ARG_backlight].u_obj);
  58.     }
  59.     /* 复位管脚 */
  60.     if (args[ARG_reset].u_obj != MP_OBJ_NULL) {
  61.         self->reset = mp_hal_get_pin_obj(args[ARG_reset].u_obj);
  62.     }
  63.     /* 获取DC管脚号 */
  64.     self->dc = mp_hal_get_pin_obj(args[ARG_dc].u_obj);
  65.     /* 片选管脚 */
  66.     if (args[ARG_cs].u_obj != MP_OBJ_NULL) {
  67.         self->cs = mp_hal_get_pin_obj(args[ARG_cs].u_obj);
  68.     }
  69.     /* 执行LCD初始化序列 */
  70.     lcd_dv_init();
  71.    
  72.     return MP_OBJ_FROM_PTR(self);
  73. }
复制代码
       根据上述源代码可以看出,作者首先创建了一个LCD对象控制块,然后设置了LCD对象的属性。接着,系统判断SPI控制块、LCD类型、LCD扫描方向和各个管脚是否满足相关条件。如果不满足条件,系统将不再执行下去,并在Shell交互窗口下提示错误信息。最后,系统调用了lcd_dv_init函数来初始化LCD序列,并返回LCD对象。

       2,SPILCD写命令函数
  1. /**
  2. * @brief       发送命令到LCD,使用轮询方式阻塞等待传输完成(由于数据传输量很少,
  3. 因此在轮询方式处理可提高速度。使用中断方式的开销要超过轮询方式)
  4. * @param       cmd 传输的8位命令数据
  5. * @retval      无
  6. */
  7. STATIC void lcd_write_cmd(const uint8_t cmd)
  8. {
  9.     CS_LOW();
  10.     DC_LOW();
  11.     mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(lcd_self->spi_obj);
  12. mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)
  13. MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
  14.     spi_p->transfer(s, 1, &cmd, NULL);
  15.     CS_HIGH();
  16. }
复制代码
       上述源码中,作者首先拉低DC数据/命令和CS片选管脚的电平,接着根据传入的SPI控制块,调用了SPI收发函数来发送SPILCD命令。发送完成后,拉高CS片选管脚的电平。

       3,SPILCD写数据函数
  1. /**
  2. * @brief       发送数据到LCD,使用轮询方式阻塞等待传输完成(由于数据传输量很少,
  3. 因此在轮询方式处理可提高速度。使用中断方式的开销要超过轮询方式)
  4. * @param       data 传输的8位数据
  5. * @retval      无
  6. */
  7. STATIC void lcd_write_data(const uint8_t *data, int len){
  8.     CS_LOW();
  9.     DC_HIGH();
  10.     mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(lcd_self->spi_obj);
  11. mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)
  12. MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
  13.     spi_p->transfer(s, len, data, NULL);
  14.     CS_HIGH();
  15. }
复制代码
       上述源码中,作者首先拉高DC数据/命令和拉低CS片选管脚的电平,接着,调用了SPI收发函数来发送SPILCD数据。发送完成后,拉高CS片选管脚的电平。其他函数,如画线、画点等,请参考lcd.c/.h文件。

       16.2.2 C模块构造与类的方法

       1,atk_lcd类与SPI构造函数
       Lcd和SPI的构造对象方法如下:
  1. class atk_lcd.init(spi,reset,dc,cs,backlight,dir,lcd)
  2. 使用示例:
  3. spi=SPI(2,baudrate=80000000, sck = Pin(12), mosi = Pin(11), miso = Pin(13))
  4. lcd=atk_lcd.init(spi,dc=Pin(40,Pin.OUT),cs=Pin(21,Pin.OUT,value=1),dir=1,lcd=0)
复制代码
       该构造方法的参数描述,如下表所示。

4.png
表16.2.2.1 atk_lcd.init构造函数参数描述

       返回值:LCD对象。

       2,lcd类的方法

       ①:打开LCD背光。
       其函数原型如下:
  1. lcd.on()
复制代码

       ②:关闭LCD背光。
       其函数原型如下:
  1. lcd.off()
复制代码

       ③:LCD清屏。
       其函数原型如下:
  1. lcd.clear(color)
复制代码
       该函数的参数描述,如下表所示。

5.png
表16.2.2.2 lcd.clear函数参数描述

       ④:LCD画点。
       其函数原型如下:
  1. lcd.pixel(x,y,colot)
复制代码
       该函数的参数描述,如下表所示。


6.png
表16.2.2.3 lcd.clear函数参数描述

       ⑤:LCD画线。
       其函数原型如下:
  1. lcd.line(x1,y1,x2,y2,color)
复制代码
       该函数的参数描述,如下表所示。

7.png
表16.2.2.4 lcd.line函数参数描述

       ⑥:LCD画一个矩形。
       其函数原型如下:
  1. lcd.rectangle (x0,y0,x1,y1,color)
复制代码
       该函数的参数描述,如下表所示。

8.png
表16.2.2.5 lcd.rectangle函数参数描述

       ⑦:LCD画一个圆。
       其函数原型如下:
  1. lcd.circle (x0,y0,x1,y1,color)
复制代码
       该函数的参数描述,如下表所示。

9.png
表16.2.2.6 lcd.circle函数参数描述

       ⑧:LCD显示字符。
       其函数原型如下:
  1. lcd.char(x,y,chr,size,mode,color)
复制代码
       该函数的参数描述,如下表所示。

10-2.png
表16.2.2.7 lcd.char函数参数描述

       ⑨:LCD显示len个数字。
       其函数原型如下:
  1. lcd.num(x,y,num,len,size,color)
复制代码
       该函数的参数描述,如下表所示。

11.png
表16.2.2.7 lcd.num函数参数描述

       ⑩:LCD显示字符串。
       其函数原型如下:
  1. lcd.string(x,y,width,heught,size,p,color)
复制代码
       该函数的参数描述,如下表所示。

12.png
表16.2.2.8 lcd.string函数参数描述

       11:LCD填充区域。
       其函数原型如下:
  1. lcd.fill(x0,y0,x1,y1,color)
复制代码
       该函数的参数描述,如下表所示。

13.png
表16.2.2.9 lcd.fill函数参数描述

       12,RGB888转RGB565,返回RGB565颜色数值。
       其函数原型如下:
  1. atk_lcd.color565(r,g,b)
复制代码
       该函数的参数描述,如下表所示。

14.png
表16.2.2.10 atk_lcd.color565函数参数描述

       16.3 硬件设计

       1. 例程功能
       本章实验功能简介:使用开发板的SPI接口连接正点原子 SPILCD模块(仅限SPI显示模块),实现SPILCD模块的显示。通过把LCD模块插入底板上的WIRELESS接口(SPI 接口),按下复位之后,就可以看到SPILCD模块不停的显示一些信息并不断切换底色。LED闪烁用于提示程序正在运行。

       2. 硬件资源
       1)LED灯
              LED-IO1

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

       3)SPILCD
              CS-IO21
              SCK-IO12
              SDA-IO11
              DC-IO40(在P5端口,使用跳线帽将IO_SET和LCD_DC相连)
              PWR- IO1_3(XL9555)
              RST- IO1_2(XL9555)

       3. 原理图
       SPILCD硬件部分的原理图,如下图所示。

第十六章 SPILCD实验9381.png
图16.3.1 SPILCD接口原理图

       16.4 软件设计

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


第十六章 SPILCD实验9513.png
图16.3.1.1 程序流程图

       16.4.2 程序解析
       本书籍的代码都在main.py脚本下编写的,读者可在光盘资料下找到对应的源码。SPILCD实验main.py源码如下:
  1. from machine import Pin,SPI,I2C
  2. import atk_xl9555 as io_ex
  3. import atk_lcd as lcd
  4. import time
  5. """
  6. * @brief       程序入口
  7. * @param       无
  8. * @retval      无
  9. """
  10. if __name__ == '__main__':
  11.     x = 0
  12.     # IIC初始化
  13.     i2c0 = I2C(0, scl = Pin(42), sda = Pin(41), freq = 400000)
  14.     # XL9555初始化
  15.     xl9555 = io_ex.init(i2c0)
  16.     # 复位LCD
  17.     xl9555.write_bit(io_ex.SLCD_RST,0)
  18.     time.sleep_ms(100)
  19.     xl9555.write_bit(io_ex.SLCD_RST,1)
  20.     time.sleep_ms(100)
  21.     # 初始化SPI
  22.     spi=SPI(2,baudrate=80000000, sck = Pin(12), mosi = Pin(11), miso = Pin(13))
  23.     # 初始化LCD,lcd = 0为正点原子2.4寸屏幕;lcd = 1为正点原子1.3寸SPILCD屏幕;
  24.     display=lcd.init(spi,dc=Pin(40,Pin.OUT),cs=Pin(21, Pin.OUT),dir = 1,lcd = 0)
  25.     # 打开背光
  26.     xl9555.write_bit(io_ex.SLCD_PWR,1)
  27.     time.sleep_ms(100)
  28.     while True:
  29.         #创建字典
  30.         seasondict = {
  31.         0: lcd.BLACK,
  32.         1: lcd.BLUE,
  33.         2: lcd.RED,
  34.         3: lcd.GREEN,
  35.         4: lcd.CYAN,
  36.         5: lcd.MAGENTA,
  37.         6: lcd.YELLOW}
  38.         #刷新颜色
  39.         display.clear(seasondict[x])
  40.         #显示字体
  41.         display.string(0, 5, 240, 32, 32, "ESP32-S3",lcd.RED)
  42.         display.string(0, 34, 240, 16, 16, "SPI LCD Test",lcd.RED)
  43.         display.string(0, 50, 240, 16, 16, "ATOM@ALIENTEK",lcd.RED)
  44.         x += 1
  45.         if x == 7:
  46.             x = 0
  47.         time.sleep(1)
复制代码
       这示例代码使用SPI和I2C接口与外部设备进行通信,并通过特定的库函数控制2.4寸LCD显示屏的显示内容。具体来说,代码中初始化了I2C和SPI接口,然后使用这些接口与XL9555芯片通信,以控制LCD显示屏的复位和背光。接着,它通过调用特定库(atk_lcd)提供的函数在LCD屏幕上显示文本和颜色。在循环中,它使用一个变量x来循环显示不同的颜色,并在屏幕上显示固定的文本。当变量x的值达到7时,它会被重置为0,从而循环显示。

       16.5 下载验证
       下载代码后,LED不停的闪烁,提示程序已经在运行了。同时可以看到SPILCD模块的显示实验信息,并且背景色不停切换,如下图所示。

第十六章 SPILCD实验11221.png
图16.5.1 SPILCD显示效果图

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-25 06:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表