Rbb666 před 2 roky
revize
a75cf1f963
5 změnil soubory, kde provedl 565 přidání a 0 odebrání
  1. 13 0
      SConscript
  2. 351 0
      lcd_ili9341.c
  3. 77 0
      lcd_ili9341.h
  4. binární
      libraries/ILI9341.pdf
  5. 124 0
      readme.md

+ 13 - 0
SConscript

@@ -0,0 +1,13 @@
+
+from building import *
+
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd]
+
+if GetDepend(['PKG_USING_ILI9341']):
+    src += Glob('lcd_ili9341.c')
+
+group = DefineGroup('ili9341', src, depend = [], CPPPATH = CPPPATH)
+
+Return('group')

+ 351 - 0
lcd_ili9341.c

@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2023-03-23     Rbb666        First version
+ */
+#include "lcd_ili9341.h"
+
+#define DBG_TAG "ili9341"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#ifdef PKG_USING_ILI9341
+
+_lcd_dev lcddev;
+static struct rt_spi_device *lcd_dev;
+
+static void LCD_RESET(void)
+{
+    LCD_RES_CLR;
+    DELAY(100);
+    LCD_RES_SET;
+    DELAY(100);
+}
+
+static void LCD_WR_REG(uint8_t reg)
+{
+    LCD_DC_CLR;
+    rt_spi_send(lcd_dev, &reg, 1);
+    LCD_DC_SET;
+}
+
+static void LCD_WR_DATA(uint8_t data)
+{
+    LCD_DC_SET;
+    rt_spi_send(lcd_dev, &data, 1);
+}
+
+static void LCD_ReadData(uint8_t *data, uint16_t length)
+{
+    LCD_DC_SET;
+    rt_spi_transfer(lcd_dev, RT_NULL, &data, length);
+}
+
+static void LCD_WriteReg(uint8_t reg, uint16_t regdata)
+{
+    LCD_WR_REG(reg);
+    LCD_WR_DATA(regdata);
+}
+
+static void LCD_WriteRAM_Prepare(void)
+{
+    LCD_WR_REG(lcddev.wramcmd);
+}
+
+static void LCD_WriteData_16Bit(uint16_t Data)
+{
+    uint8_t buf[2];
+    LCD_DC_SET;
+    buf[0] = Data >> 8;
+    buf[1] = Data & 0xff;
+    rt_spi_send(lcd_dev, buf, 2);
+}
+
+void LCD_direction(uint8_t direction)
+{
+    lcddev.setxcmd = 0x2A;
+    lcddev.setycmd = 0x2B;
+    lcddev.wramcmd = 0x2C;
+    switch (direction)
+    {
+    case 0:
+        lcddev.width = LCD_W;
+        lcddev.height = LCD_H;
+        LCD_WriteReg(0x36, (1 << 3) | (0 << 6) | (0 << 7)); /* BGR==1,MY==0,MX==0,MV==0 */
+        break;
+    case 1:
+        lcddev.width = LCD_H;
+        lcddev.height = LCD_W;
+        LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) | (1 << 5)); /* BGR==1,MY==1,MX==0,MV==1 */
+        break;
+    case 2:
+        lcddev.width = LCD_W;
+        lcddev.height = LCD_H;
+        LCD_WriteReg(0x36, (1 << 3) | (1 << 6) | (1 << 7)); /* BGR==1,MY==0,MX==0,MV==0 */
+        break;
+    case 3:
+        lcddev.width = LCD_H;
+        lcddev.height = LCD_W;
+        LCD_WriteReg(0x36, (1 << 3) | (1 << 7) | (1 << 5)); /* BGR==1,MY==1,MX==0,MV==1 */
+        break;
+    default:
+        break;
+    }
+}
+
+void LCD_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd)
+{
+    LCD_WR_REG(lcddev.setxcmd);
+    LCD_WR_DATA(xStar >> 8);
+    LCD_WR_DATA(0x00FF & xStar);
+    LCD_WR_DATA(xEnd >> 8);
+    LCD_WR_DATA(0x00FF & xEnd);
+
+    LCD_WR_REG(lcddev.setycmd);
+    LCD_WR_DATA(yStar >> 8);
+    LCD_WR_DATA(0x00FF & yStar);
+    LCD_WR_DATA(yEnd >> 8);
+    LCD_WR_DATA(0x00FF & yEnd);
+
+    LCD_WriteRAM_Prepare();
+}
+
+void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
+{
+    LCD_SetWindows(Xpos, Ypos, Xpos, Ypos);
+}
+
+void LCD_Clear(uint16_t Color)
+{
+    unsigned int i, m;
+    uint8_t buf[80];
+
+    for (i = 0; i < 40; i++)
+    {
+        buf[2 * i] = Color >> 8;
+        buf[2 * i + 1] = Color & 0xff;
+    }
+
+    LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1);
+
+    LCD_DC_SET;
+    for (i = 0; i < lcddev.height; i++)
+    {
+        for (m = 0; m < lcddev.width;)
+        {
+            m += 40;
+            rt_spi_send(lcd_dev, buf, 80);
+        }
+    }
+}
+
+void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color)
+{
+    uint16_t i, j;
+    LCD_SetWindows(xsta, ysta, xend - 1, yend - 1);
+    for (i = ysta; i < yend; i++)
+    {
+        for (j = xsta; j < xend; j++)
+        {
+            LCD_WriteData_16Bit(color);
+        }
+    }
+}
+
+void lcd_fill_array_spi(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, void *Image)
+{
+    rt_uint32_t size = 0;
+
+    size = (Xend - Xstart + 1) * (Yend - Ystart + 1) * 2;/*16bit*/
+    LCD_SetWindows(Xstart, Ystart, Xend, Yend);
+    LCD_DC_SET;
+
+    rt_spi_send(lcd_dev, Image, size);
+}
+
+static void _ili9341_init(void)
+{
+    LCD_WR_REG(0xCF);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0X83);
+    LCD_WR_DATA(0X30);
+
+    LCD_WR_REG(0xED);
+    LCD_WR_DATA(0x64);
+    LCD_WR_DATA(0x03);
+    LCD_WR_DATA(0X12);
+    LCD_WR_DATA(0X81);
+
+    LCD_WR_REG(0xE8);
+    LCD_WR_DATA(0x85);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x79);
+
+    LCD_WR_REG(0xCB);
+    LCD_WR_DATA(0x39);
+    LCD_WR_DATA(0x2C);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x34);
+    LCD_WR_DATA(0x02);
+
+    LCD_WR_REG(0xF7);
+    LCD_WR_DATA(0x20);
+
+    LCD_WR_REG(0xEA);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x00);
+
+    LCD_WR_REG(0xC0);   /* Power control */
+    LCD_WR_DATA(0x26);  /* VRH[5:0] */
+
+    LCD_WR_REG(0xC1);   /* Power control */
+    LCD_WR_DATA(0x11);  /* SAP[2:0];BT[3:0] */
+
+    LCD_WR_REG(0xC5);   /* VCM control */
+    LCD_WR_DATA(0x35);
+    LCD_WR_DATA(0x3E);
+
+    LCD_WR_REG(0xC7);   /* VCM control2 */
+    LCD_WR_DATA(0XBE);
+
+    LCD_WR_REG(0x36);   /* Memory Access Control */
+    LCD_WR_DATA(0x28);
+
+    LCD_WR_REG(0x3A);
+    LCD_WR_DATA(0x55);
+
+    LCD_WR_REG(0xB1);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x1B);
+
+    LCD_WR_REG(0xB6);   /* Display Function Control */
+    LCD_WR_DATA(0x0A);
+    LCD_WR_DATA(0xA2);
+
+    LCD_WR_REG(0xF2);   /* 3Gamma Function Disable */
+    LCD_WR_DATA(0x08);
+
+    LCD_WR_REG(0x26);   /* Gamma curve selected */
+    LCD_WR_DATA(0x01);
+
+    LCD_WR_REG(0xE0);   /* set Gamma */
+    LCD_WR_DATA(0X1F);
+    LCD_WR_DATA(0X1A);
+    LCD_WR_DATA(0X18);
+    LCD_WR_DATA(0X0A);
+    LCD_WR_DATA(0X0F);
+    LCD_WR_DATA(0X06);
+    LCD_WR_DATA(0X45);
+    LCD_WR_DATA(0X87);
+    LCD_WR_DATA(0X32);
+    LCD_WR_DATA(0X0A);
+    LCD_WR_DATA(0X07);
+    LCD_WR_DATA(0X02);
+    LCD_WR_DATA(0X07);
+    LCD_WR_DATA(0X05);
+    LCD_WR_DATA(0X00);
+
+    LCD_WR_REG(0xE1);   /* set Gamma */
+    LCD_WR_DATA(0X00);
+    LCD_WR_DATA(0X25);
+    LCD_WR_DATA(0X27);
+    LCD_WR_DATA(0X05);
+    LCD_WR_DATA(0X10);
+    LCD_WR_DATA(0X09);
+    LCD_WR_DATA(0X3A);
+    LCD_WR_DATA(0X78);
+    LCD_WR_DATA(0X4D);
+    LCD_WR_DATA(0X05);
+    LCD_WR_DATA(0X18);
+    LCD_WR_DATA(0X0D);
+    LCD_WR_DATA(0X38);
+    LCD_WR_DATA(0X3A);
+    LCD_WR_DATA(0X2F);
+
+    LCD_WR_REG(0x29);
+}
+
+static void LCD_Init(void)
+{
+    LCD_RESET();        /* LCD Hardware Reset */
+    LCD_WR_REG(0x11);   /* Sleep out */
+    DELAY(120);         /* Delay 120ms */
+    _ili9341_init();    /* IlI9341 init */
+    LCD_BLK_CLR;        /* Open Backlight */
+
+    LCD_direction(USE_DIRECTION);
+}
+
+rt_err_t spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
+{
+    RT_ASSERT(bus_name != RT_NULL);
+    RT_ASSERT(device_name != RT_NULL);
+
+    rt_err_t result = RT_EOK;
+    struct rt_spi_device *spi_device;
+
+    /* attach the device to spi bus*/
+    spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
+    RT_ASSERT(spi_device != RT_NULL);
+
+    result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);
+    if (RT_EOK != result)
+    {
+        LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
+    }
+    else
+    {
+        LOG_I("%s attach to %s done", device_name, bus_name);
+    }
+
+    return result;
+}
+
+rt_err_t spi_lcd_init(uint32_t freq)
+{
+    rt_err_t res = RT_EOK;
+
+    spi_device_attach(PKG_ILI_9341_SPI_BUS_NAME, PKG_ILI_9341_SPI_DEVICE_NAME, PKG_ILI_9341_CS_PIN);
+    lcd_dev = (struct rt_spi_device *)rt_device_find(PKG_ILI_9341_SPI_DEVICE_NAME);
+    if (lcd_dev != RT_NULL)
+    {
+        struct rt_spi_configuration spi_config;
+        spi_config.data_width = 8;
+        spi_config.max_hz = freq * 1000 * 1000;
+        spi_config.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
+        rt_spi_configure(lcd_dev, &spi_config);
+    }
+    else
+    {
+        res = -RT_ERROR;
+    }
+
+    LCD_Init();
+
+    return res;
+}
+
+static uint16_t color_array[] =
+{
+    WHITE, BLACK, BLUE, BRED,
+    GRED, GBLUE, RED, YELLOW
+};
+
+static int lcd_spi_test(void)
+{
+    uint8_t index = 0;
+    for (index = 0; index < sizeof(color_array) / sizeof(color_array[0]); index++)
+    {
+        LCD_Clear(color_array[index]);
+        LOG_I("lcd clear color: %#x", color_array[index]);
+        DELAY(200);
+    }
+
+    return RT_EOK;
+}
+MSH_CMD_EXPORT(lcd_spi_test, lcd_spi_test);
+#endif

+ 77 - 0
lcd_ili9341.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author        Notes
+ * 2023-03-23     Rbb666        First version
+ */
+#ifndef __LCD_ILI9341_H__
+#define __LCD_ILI9341_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <stdint.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drivers/spi.h"
+
+typedef struct
+{
+    uint16_t width;   /* LCD width */
+    uint16_t height;  /* LCD high */
+    uint32_t id;      /* LCD ID */
+    uint8_t dir;      /* 0:Vertical | 1:Vertical */
+    uint16_t wramcmd; /* gram cmd */
+    uint16_t setxcmd; /* set x cmd */
+    uint16_t setycmd; /* set y cmd */
+} _lcd_dev;
+
+/* LCD param */
+extern _lcd_dev lcddev;
+
+/* 0-0 angle|1-90 angle|2-180 angle|-270 angle */
+#define USE_DIRECTION   0
+
+/* lcd size */
+#define LCD_W PKG_ILI_9341_WIDTH
+#define LCD_H PKG_ILI_9341_HEIGHT
+
+#define LCD_DC_CLR  rt_pin_write(PKG_ILI_9341_DC_PIN, PIN_LOW)
+#define LCD_DC_SET  rt_pin_write(PKG_ILI_9341_DC_PIN, PIN_HIGH)
+#define LCD_RES_CLR rt_pin_write(PKG_ILI_9341_RES_PIN, PIN_LOW)
+#define LCD_RES_SET rt_pin_write(PKG_ILI_9341_RES_PIN, PIN_HIGH)
+#define LCD_BLK_CLR rt_pin_write(PKG_ILI_9341_BLK_PIN, PIN_HIGH)
+#define DELAY       rt_thread_mdelay
+
+#define WHITE 0xFFFF
+#define BLACK 0x0000
+#define BLUE 0x001F
+#define BRED 0XF81F
+#define GRED 0XFFE0
+#define GBLUE 0X07FF
+#define RED 0xF800
+#define MAGENTA 0xF81F
+#define GREEN 0x07E0
+#define CYAN 0x7FFF
+#define YELLOW 0xFFE0
+#define BROWN 0XBC40
+#define BRRED 0XFC07
+#define GRAY 0X8430
+
+void LCD_Clear(uint16_t Color);
+void LCD_direction(uint8_t direction);
+void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos);
+void LCD_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd);
+void LCD_Fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color);
+void lcd_fill_array_spi(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, void *pcolor);
+
+rt_err_t spi_lcd_init(uint32_t freq);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

binární
libraries/ILI9341.pdf


+ 124 - 0
readme.md

@@ -0,0 +1,124 @@
+#  ILI9341
+
+## 简介
+
+本软件包是 TFT-LCD-ILI9341 SPI接口屏幕的驱动包,本软件包已经对接到 SPI 框架。通过 SPI 框架 API,开发者可以快速的将此屏幕驱动起来。
+
+##  使用说明
+
+### 依赖
+
+- RT-Thread 5.0.0+
+- SPI 驱动:ILI9341 屏幕使用 SPI 进行数据通讯,需要系统SPI 驱动支持;
+
+###  获取软件包
+
+使用 ILI9341 软件包需要在 RT-Thread 的包管理中选中它,具体路径如下:
+
+```shell
+RT-Thread online packages  --->
+  peripheral libraries and drivers  --->
+    TFT-LCD ILI9341 SPI screen driver software package --->
+        (spi0) spi bus name
+        (spi00) spi device name
+        (240) Width of the LCD display
+        (320) Height of the LCD display
+        (-1) DC pin connected to the LCD display
+		(-1) RESET pin connected to the LCD display
+		(-1) CS pin connected to the LCD display
+		(-1) Backlight pin connected to the LCD display
+        	Version (latest)  --->
+```
+
+**spi bus name**:连接 LCD 所使用的 SPI 总线名称
+
+**spi device name**:连接 LCD 所使用的 SPI 设备名称
+
+**Width of the LCD display**: LCD  屏幕宽度参数
+
+**Height of the LCD display**: LCD 屏幕高度参数
+
+**DC pin connected to the LCD display**: LCD 屏幕数据引脚
+
+**RESET pin connected to the LCD display**: LCD 屏幕复位引脚
+
+**CS pin connected to the LCD display**: LCD 屏幕片选引脚(若硬件无CS引脚则填写 -1)
+
+**Backlight pin connected to the LCD display**: LCD 屏幕背光引脚
+
+###  使用软件包
+
+ILI9341 软件包初始化函数如下所示:
+
+```c
+rt_err_t spi_lcd_init(uint32_t freq)
+```
+
+该函数需要由用户调用,函数主要完成的功能有:
+
+- 设备配置和初始化(根据传入的配置信息,配置 SPI 的频率,初始化 LCD 参数);
+- 注册相应的传感器设备,完成 SPI 设备的注册;
+
+> 参数:SPI 的频率。例如:单片机的 SPI 外设频率为 20 MHZ,则填写 20
+
+```c
+void lcd_fill_array_spi(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend, void *Image)
+```
+
+该函数需要由用户调用,函数主要完成的功能有:
+
+- 填充颜色数组到 LCD 显存
+
+> 参数:要填充的x起始坐标,y起始坐标,x终止坐标,y终止坐标,颜色数组
+
+####  初始化示例
+
+```c
+#include "lcd_ili9341.h"
+
+int rt_hw_ili9341_port(void)
+{
+    /* LCD init by 20MHZ SPI */
+    spi_lcd_init(20);
+    /* LCD fill blue color */
+    LCD_Clear(0x001F);
+    rt_thread_mdelay(1000);
+    /* LCD fill red color */
+    LCD_Clear(0xF800);
+    return 0;
+}
+INIT_APP_EXPORT(rt_hw_ili9341_port);
+```
+
+#### LVGL V8.2.0 接口示例
+
+```c
+#include "lcd_ili9341.h"
+
+static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
+{
+    lcd_fill_array_spi(area->x1, area->y1, area->x2, area->y2, color_p);
+    lv_disp_flush_ready(disp_drv);
+}
+
+void lv_port_disp_init(void)
+{
+    spi_lcd_init(20);
+    ...
+    /*Set the resolution of the display*/
+    disp_drv.hor_res = PKG_ILI_9341_WIDTH;
+    disp_drv.ver_res = PKG_ILI_9341_HEIGHT;
+    ...
+}
+```
+
+## 注意事项
+
+暂无
+
+## 联系人信息
+
+维护人:
+
+- [Rbb66](https://github.com/Rbb666)
+- 主页:[TFT-LCD-ILI9341](https://github.com/Rbb666/ILI9341)