零、目录

零、目录

一、硬件和参考对象

二、STC32G 的 LCM

三、简要的初始化流程

四、代码的移植和修改

五、引脚接线

六、运行结果

七、总结和注意事项


一、硬件和参考对象

  1. 本次将使用 STC32G12K128 芯片的 LCM 对 8080 接口的液晶屏(该液晶屏为野火指南者STM32F103开发板的 3.2寸 TFTLCD)进行驱动,目的是成功点亮并在液晶屏中输出英文字符串和绘图
  2. 硬件接线、液晶屏驱动和测试程序均来自野火指南者STM32F103开发板 ,有关的资料可以在野火官网下载。
  3. 用到的参考图文为 STC32G 的库函数手册、STC32G 芯片手册、野火液晶屏原理图。

二、STC32G 的 LCM

STC32G 系列单片机内部集成了一个 LCM 接口控制器,可驱动 I8080 接口和 M6800 接口,支持 8位 和 16位 数据宽度。

        本文将使用到 STC 官方提供的库函数来控制 LCM,对于 LCM 的初始化,将使用库文件: STC32G_LCM.H;LCM 的功能引脚切换,将使用库文件:STC32G_Switch().H。

STC32G 的库函数可以在 STC32G 官网下载。对于 LCM,STC32G_LCM.H 的主要内容如下:

/* 引脚定义 */
sbit LCD_RS     = P4^5;        // 数据/命令切换
sbit LCD_RD     = P4^4;        // 读控制
sbit LCD_WR     = P4^2;        // 写控制sbit LCD_CS   = P4^0;        // 片选
sbit LCD_RESET  = P4^3;        // 复位
sbit LCD_BK     = P4^1;            // 背光控制/* 数据/指令触发宏定义 */
#define LCM_WRITE_CMD()                 LCMIFCR = ((LCMIFCR & ~0x07) | 0x84)
#define LCM_WRITE_DAT()                 LCMIFCR = ((LCMIFCR & ~0x07) | 0x85)
#define LCM_READ_CMD()                  LCMIFCR = ((LCMIFCR & ~0x07) | 0x86)
#define LCM_READ_DAT()                  LCMIFCR = ((LCMIFCR & ~0x07) | 0x87)/* 接口类型和数据宽度类型 */
#define MODE_I8080          0   //I8080模式
#define MODE_M6800          1   //M6800模式#define    BIT_WIDE_8          0   //8位数据宽度
#define BIT_WIDE_16         2   //16位数据宽度/* 初始化结构体 */
typedef struct
{u8 LCM_Enable;                 //LCM接口使能   ENABLE,DISABLEu8    LCM_Mode;                       //LCM接口模式   MODE_I8080,MODE_M6800u8 LCM_Bit_Wide;               //LCM数据宽度   BIT_WIDE_8,BIT_WIDE_16u8    LCM_Setup_Time;         //LCM通信数据建立时间   0~7u8   LCM_Hold_Time;          //LCM通信数据保持时间   0~3
} LCM_InitTypeDef;/* 接口函数 */
void LCM_Inilize(LCM_InitTypeDef *LCM);

LCD_RS、LCD_RD、LCD_WR 的引脚定义受到 LCM 寄存器的控制,具体设置可参考官方手册,如下图所示。本文使用 LCMIFCPS[1:0] = 00 时的功能引脚。

LCD_CS、LCD_RESET、LCD_BK 可任意定义,主要用于 LCD 的片选、复位和背光控制。

触发数据和指令的宏定义用于触发 LCM 模块将数据寄存器中的数据通过端口发送给 LCD,仅用于触发,数据需要在触发前写入数据寄存器

接口类型和数据宽度类型将在 LCM 的初始化结构体里被使用,本次使用的 LCD 的类型是 I8080 接口 和 16位数据宽度。16位 LCM 接口数据脚选择参考官方手册,如下图所示。本文使用的是 LCMIFDPS[1:0] = 11 时的引脚。

LCM 结构体公有 5个成员函数,STC 在注释中给出了可设置的范围。结构体配置完成后通过函数 LCM_Inilize() 对 LCM 进行初始化。

功能引脚切换使用 STC32G_Switch() 中提供的宏定义:

#define  LCM_CTRL_SW(Pin)            LCMIFCFG2 = (LCMIFCFG2 & ~0x60) | (Pin << 5)
#define  LCM_DATA_SW(Pin)           LCMIFCFG = (LCMIFCFG & ~0x0C) | (Pin << 2)

三、简要的初始化流程

  1. 野火程序的简单分析。下图为笔者对野火液晶屏参考示例的程序运行简单摘要(如有错误或理解有误可以在评论区指出)。
  2. STM32 与 STC32G 的异同点比较
    STM32 STC32G
    GPIO 都是对需要的 GPIO 进行初始化

        驱动 LCD 的外设

    采用 FSMC 控制 采用 LCM 控制
    液晶屏配置 对于液晶屏的配置函数,只要基本的读写函数能够实现,基本不需要做修改
    读写函数 基于 FSMC 的读写触发 基于 LCM 的读写触发
    LCD 控制引脚 通过 FSMC ,自动控制的对应的引脚实现控制 需要用户来手动控制引脚的高低电平

四、代码的移植和修改

提前准备好需要的库函数和驱动程序,本文的中断函数将使用 STC32G 库函数自带 ISR 函数。具体使用到的有关文件请参考下表:

STC32G 库函数 STM32 参考程序

STC32G_Delay

STC32G_GPIO

STC32G_LCM

STC32G_NVIC

STC32G_SWITCH

STC32G_UART

bsp_ili9341_lcd

font

创建 KEIL C251 项目,先将 STC32G 的文件导入到项目中,并实现通过串口发送 Hello World 的程序,以此确保 STC32G 的库函数移植无误。

接下来添加 STM32 的液晶屏驱动程序和字模 到工程项目中。在 bsp_ili9341_lcd.h 中删除有关 FSMC 的所有定义,并针对 bsp_ili9341_lcd.c 的需要,补充基本的类型定义,并包含下表所需要的头文件:

头文件 作用
STC32G_GPIO 对引脚进行初始化
STC32G_LCM 提供对 LCM 的控制
STC32G_NVIC 中断嵌套配置,用于配置外设中断
STC32G_Delay 延时函数
STC32G_Switch 提供功能引脚切换

接下来对需要修改的函数进行重定义。

需要重定义的函数 函数功能
ILI9341_Write_Cmd() 向 ILI9341 写指令
ILI9341_Write_Data() 向 ILI9341 写数据
ILI9341_Read_Data() 向 ILI9341 读数据

ILI9341_Delay()

延时函数

ILI9341_GPIO_Config()

GPIO 初始化

ILI9341_FSMC_Config()

LCM 初始化

ILI9341_Init()

初始化外设并对液晶屏进行基本配置

ILI9341_BackLed_Control()

背光控制

ILI9341_Rst()

复位控制

首先对 ILI9341_Write_Cmd()、ILI9341_Write_Data()、ILI9341_Read_Data() 和 ILI9341_Delay() 进行重定义,如下:

/*** @brief  向ILI9341写入命令* @param  usCmd :要写入的命令(表寄存器地址)* @retval 无*/
void ILI9341_Write_Cmd(uint16_t usCmd)
{//* ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_CMD ) = usCmd;LCD_RS = 0;LCMIFDATL = usCmd & 0x00ff;LCMIFDATH = (usCmd >> 8) & 0x00ff;LCM_WRITE_CMD();
}/*** @brief  向ILI9341写入数据* @param  usData :要写入的数据* @retval 无*/
void ILI9341_Write_Data(uint16_t usData)
{//* ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) = usData;LCD_RS = 0;LCMIFDATL = usData & 0x00ff;LCMIFDATH = (usData >> 8) & 0x00ff;LCM_WRITE_DAT();
}/*** @brief  从ILI9341读取数据* @param  无* @retval 读取到的数据*/
uint16_t ILI9341_Read_Data(void)
{// return ( * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) );LCD_RS = 1;LCM_READ_DAT();return (LCMIFDATH << 8) | LCMIFDATL;
}/*** @brief  用于 ILI9341 简单延时函数* @param  nCount :延时计数值* @retval 无*/
static void ILI9341_Delay(uint16_t ms)
{delay_ms(ms);
}

重定义 GPIO 初始化函数,具体的初始化端口依据实际用到的端口来决定。

/*** @brief  初始化ILI9341的IO引脚* @param  无* @retval 无*/
static void ILI9341_GPIO_Config(void)
{GPIO_InitTypeDef gpio;// 选用 P7 P6 作为数据/指令发送信号线,16线制gpio.Mode = GPIO_PullUp;gpio.Pin = GPIO_Pin_All;GPIO_Inilize(GPIO_P6, &gpio);GPIO_Inilize(GPIO_P7, &gpio);// LCD 控制信号线配置gpio.Pin = GPIO_Pin_All;GPIO_Inilize(GPIO_P4, &gpio);
}

重定义 LCM 初始化函数,此处函数名没有修改。

/*** @brief  LCD  FSMC 模式配置* @param  无* @retval 无*/
static void ILI9341_FSMC_Config(void)
{LCM_InitTypeDef lcm;lcm.LCM_Bit_Wide = BIT_WIDE_16;lcm.LCM_Enable = ENABLE;lcm.LCM_Hold_Time = 1;lcm.LCM_Setup_Time = 1;lcm.LCM_Mode = MODE_I8080;LCM_Inilize(&lcm);NVIC_LCM_Init(ENABLE, Priority_1);LCM_CTRL_SW(LCM_CTRL_P45_P44_P42);LCM_DATA_SW(LCM_D16_P6_P7);
}

重定义 ILI9341 复位函数。

/*** @brief  ILI9341G 软件复位* @param  无* @retval 无*/
void ILI9341_Rst(void)
{// digitalL( GPIOE,GPIO_PIN_1);     //低电平复位LCD_RESET = 0;ILI9341_Delay(50);// digitalH( GPIOE,GPIO_PIN_1);LCD_RESET = 1;ILI9341_Delay(50);
}

重定义 ILI9341 背光控制函数。

/*** @brief  ILI9341G背光LED控制* @param  enumState :决定是否使能背光LED*   该参数为以下值之一:*     @arg ENABLE :使能背光LED*     @arg DISABLE :禁用背光LED* @retval 无*/
void ILI9341_BackLed_Control(FunctionalState enumState)
{if (enumState){// digitalL( GPIOD, GPIO_PIN_12);LCD_BK = 0;       // 用的 PNP 型三极管做开关,因此低电平点亮}else{// digitalH( GPIOD, GPIO_PIN_12);LCD_BK = 1;}
}

在 ILI9341 初始化函数中补上 LCD 片选控制。

/*** @brief  ILI9341初始化函数,如果要用到lcd,一定要调用这个函数* @param  无* @retval 无*/
void ILI9341_Init(void)
{ILI9341_GPIO_Config();ILI9341_FSMC_Config();LCD_CS = 0;ILI9341_BackLed_Control(ENABLE); // 点亮LCD背光灯ILI9341_Rst();ILI9341_REG_Config();// 设置默认扫描方向,其中 6 模式为大部分液晶例程的默认显示方向ILI9341_GramScan(LCD_SCAN_MODE);ILI9341_Clear(0, 0, ILI9341_LESS_PIXEL, ILI9341_MORE_PIXEL);
}

将 bsp_ili9341_lcd.h 包含到 main.c 中。编写测试程序。其中 gpio_init() 和 uart_init() 是针对串口输出做的初始化。

void main(void)
{__STC32G_DRIVER_INIT();gpio_init();uart_init();ILI9341_Init();LCD_SetTextColor(BLACK);ILI9341_DrawRectangle(0, 0, ILI9341_LESS_PIXEL, ILI9341_MORE_PIXEL, 1);LCD_SetFont(&Font8x16);LCD_SetColors(YELLOW, BLACK);EA = 1;while(1){printf("Hello world\r\n");LCD_SetColors(YELLOW, BLACK);ILI9341_DispStringLine_EN(LINE(0), "Hello LCM I8080!");delay_ms(1000);// 画线LCD_ClearLine(LINE(4)); /* 清除单行文字 */LCD_SetColors(YELLOW, BLACK);ILI9341_DispStringLine_EN(LINE(4), "Draw line:");LCD_SetColors(RED, BLACK);ILI9341_DrawLine(50, 170, 210, 230);ILI9341_DrawLine(50, 200, 210, 240);LCD_SetColors(GREEN, BLACK);ILI9341_DrawLine(100, 170, 200, 230);ILI9341_DrawLine(200, 200, 220, 240);LCD_SetColors(BLUE, BLACK);ILI9341_DrawLine(110, 170, 110, 230);ILI9341_DrawLine(130, 200, 220, 240);delay_ms(2500);ILI9341_Clear(0, 16 * 8, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 8); /* 清屏,显示全黑 */// 画矩形LCD_ClearLine(LINE(4)); /* 清除单行文字 */LCD_SetColors(GREEN, BLACK);ILI9341_DispStringLine_EN(LINE(4), "Draw Rectangle:");LCD_SetColors(RED, BLACK);ILI9341_DrawRectangle(50, 200, 100, 30, 1);LCD_SetColors(GREEN, BLACK);ILI9341_DrawRectangle(160, 200, 20, 40, 0);LCD_SetColors(BLUE, BLACK);ILI9341_DrawRectangle(170, 200, 50, 20, 1);delay_ms(2500);ILI9341_Clear(0, 16 * 8, LCD_X_LENGTH, LCD_Y_LENGTH - 16 * 8); /* 清屏,显示全黑 */// 画圆LCD_ClearLine(LINE(4)); /* 清除单行文字 */LCD_SetColors(GREEN, BLACK);ILI9341_DispStringLine_EN(LINE(4), "Draw Circle:");LCD_SetColors(RED, BLACK);ILI9341_DrawCircle(100, 200, 20, 0);LCD_SetColors(GREEN, BLACK);ILI9341_DrawCircle(100, 200, 10, 1);LCD_SetColors(BLUE, BLACK);ILI9341_DrawCircle(140, 200, 20, 0);delay_ms(2500);ILI9341_Clear(0, 0, LCD_X_LENGTH, LCD_Y_LENGTH); /* 清屏,显示全黑 */}
}

编译项目,若无报错则说明文件移植没有语法错误。


五、引脚接线

已经接线对照表如下。

实物接线图如下。


六、运行结果

烧录后,液晶屏正常点亮并显示测试程序:首先显示字符串 “Hello LCM I8080”,然后显示字符串“Draw Line”,绘制测试直线,之后显示字符串“Draw Rectangle”,绘制测试矩形,最后显示字符串“Draw Circle”,绘制测试圆形。运行结果如下图所示。


七、总结

1. BUG 汇总

问题 可能的原因 解决方法
程序卡死 未开启外设或中断

1. 使能外设

2. 开启中断,STC32G 的库函数开启外设中断的方式是使用 NVIC 提供的接口

未定义正确的中断函数或未清空标志位 本文使用 STC32G 库函数提供的默认中断函数,可用于参考
使用 printf 时未正确指定串口 确定 printf 使用的串口是连接到电脑端的串口
未正确初始化相关外设 确认 GPIO、LCM、UART 等外设初始化正确
串口有输出,屏幕没有点亮 LCB_BK 接线不正确或电平值不正确 检查 LCB_BK 电平值是否正确,或检查引脚是否接线正确
可能是因为片选引脚 LCB_CS 电平不对 LCB_CS 处于低电平时 LCD 被选中
GPIO 未正确初始化 检查 GPIO 的引脚配置是否正确
屏幕点亮,没有显示字符串和图像 接线错误或未正确指定功能引脚 检查接线是否正常,检查是否进行了正确的功能引脚切换
驱动程序未正确重定义 检查需要重定义的函数是否都正确重定义
数据建立时间和数据保存时间数值不正确 初始化 LCM 时,依据实际情况赋值进行测试,笔者的两个值都为 1
清屏函数仅清屏部分区域

ILI9341_FillColor() 的传参不正确

ILI9341_FillColor() 第一个参数是 uint32_t 类型,调用该函数时,需要将参数进行强制类型转换到 uint32_t,建议将 bsp_ili9341_lcd.c 中所有用到 ILI9341_FillColor() 的地方都手动补上强制类型转换的语句。
屏幕输出字符串像素点不完整 数据建立时间和数据保存时间数值不正确 初始化 LCM 时,依据实际情况赋值进行测试,笔者的两个值都为 1
填充区块时出现白屏闪烁问题 数据建立时间和数据保存时间数值不正确 初始化 LCM 时,依据实际情况赋值进行测试,笔者的两个值都为 1
调用了 ILI9341_FillColor() 该问题目前暂未解决,除了黑色填充外,其他颜色进行填充时都会导致白色屏闪的情况,推测可能和 STC32G 的执行速度有关系。

2. LCM 使用感受

STC32G 提供的 LCM 对驱动 TFTLCD 提供了便利的帮助,官方库函数的提供让使用这一外设变得更加简单。STC8A8K64D4 也具有 LCM 功能,通用官方也提供了相应的库函数,而 STC8A8K64D4 的时钟频率能调节到 45MHz,比 STC32G 在 ISP 上能调节的范围更广,也许用起来会比 STC32G 更好吧(可能)。

可惜适配 51 的 GUI 太少了,虽然 STC 完成了 FreeRTOS 的移植(据说可以尝试 uC/GUI,没试过不清楚)。

利用 STC32G12K128 的 LCM 驱动 8080 接口的液晶屏相关推荐

  1. ZYNQ7020(黑金)纯verilog驱动4.3寸RGB接口TFT液晶屏(AN430)显示彩条

    ZYNQ7020(黑金)纯verilog驱动4.3寸RGB接口TFT液晶屏(AN430)显示彩条 简介 像素(Pixel):像素是指由图像的小方格组成的,这些小方快都有一个明确的位置和被分配的色彩数值 ...

  2. 联盛德 HLK-W806 (六): I2C驱动SSD1306 128x64 OLED液晶屏

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  3. 【嵌入式】MCU(HC32F460)+SPI接口LCD液晶屏ILI9341 移植emWin记录1----点亮LCD屏

    目录 一 SPI屏的接线 二 SPI屏驱动初始化 三 SPI屏点亮 四 附录 一 SPI屏的接线 SPI屏的特点在于接线简单,只需要四根SPI线以及几个GPIO口即可驱动工作,但是由于非并口的,所以当 ...

  4. 基于STM32F103ZET6主控平台实现(SPI接口)OLED液晶屏驱动

    一个热爱代码的工程师,唯有凭借双手不断敲打,才可以快速提升实力! 本文谨以记录,日后相忘时再作复习,代码没有贵贱,既来之则安之. OLED液晶屏产品图和效果图 由上图我们知道:OLED液晶屏分别有GN ...

  5. Arduino驱动I2C接口12864LCD大屏液晶模块方法及库文件

    关键词:Arduino显示,12864液晶模块,中文显示,IIC接口,I2C接口,12864驱动程序 液晶显示模块目前在中国发展已经有30多个年头了,市场上应用最广泛的要属于128*64点阵的显示屏, ...

  6. TTL接口笔记本液晶屏改液晶显示器

    一.所有TFT-LCD的数据接口种类:         单TTL6位(8位)         双TTL6位(8位)         单LVDS6位(8位)         双LVDS6位(8位)    ...

  7. 树莓派GPIO驱动ST7735S主控TFT液晶屏显示图片和文字

    本文使用1.8''128*160RGB_TFT ST7735S主控的液晶屏来操作 参考blog:http://blog.mangolovecarrot.net/2017/03/05/raspi-stu ...

  8. 全志melis系统 - 8080接口CPU屏调试

    全志melis系统8080接口CPU屏调试 一.准备工作 二.点屏步骤 三.核验资料 1. 查看屏规格书确认其为8080接口的CPU屏 2.查看驱动IC型号 四.确认硬件 1.8080接口18位.16 ...

  9. 液晶屏 -- 驱动板 -- 屏线 -- 高压条 -- LVDS接口知识

    1.液晶屏 先说液晶屏,只要不是太特殊的笔记本,绝大多数都是LVDS接口的,极少是TTL的,这个看液晶屏的针脚可以大致判断出来(注意是看液晶屏上的接口,不是已经引出的屏线),LVDS的一般是14.20 ...

最新文章

  1. 关系数据库非关系数据库_如何与关系数据库最佳配合
  2. oracle 备份格式dmp解析,Oracle 数据导入备份(dmp格式)
  3. 科沃斯擦窗机器人擦不干净怎么办_家用自动擦玻璃机器人哪种好呢?玻妞和科沃斯擦窗机器人能干净吗...
  4. libevent安装总结 - jinfg2008的专栏 - 博客频道 - CSDN.NET
  5. ITK:迷你管道MiniPipeline
  6. Oracle数据库设计要做到五戒
  7. Chrome开发者工具对Vue应用的支持
  8. websocket wss_使用wss和HTTPS / TLS保护WebSocket的安全
  9. android tag的作用,Android中的Context的作用(2)
  10. html标签info,HtmlTrInfo 元素
  11. Rust性能分析-迭代器的enumerate方法是否会影响程序性能
  12. 【算法】斐波那契(黄金分割法) 查找算法
  13. 苹果XR信号差,可否要求苹果公司召回?
  14. java锁的粗化,锁优化(自旋锁,锁消除,锁粗化,轻量级锁,偏向锁)(深入理解JAVA虚拟机-学习记录)...
  15. jquery.uploadify php,jquery组件Uploadify的使用
  16. 华为----园区网络三层架构实验
  17. 由于找不到MSVCR100.dll,无法继续执行代码解决方法
  18. 音频加速 foobar_如何使用Foobar2000将音频CD翻录到FLAC
  19. php单页菜单,纯CSS3单页切换导航菜单界面设计
  20. Guava学习笔记(转)

热门文章

  1. 摩尔斯 (Morse )编码
  2. 13.python的文件操作
  3. mvn打包springboot项目,打包时报错:子模块找不到找不到父模块所配置的信息,<relativePath /> 所引发的问题
  4. MySQL怎么导出想要的数据_mysql怎么导出数据
  5. SQLZOO more JOIN
  6. 2019武大国重考研地理信息(GIS,资源与环境)复试上机题目分享
  7. 苹果app商品定价_刚刚,苹果爆料“差异定价”猫腻,原来App商家也挖坑!
  8. Elasticsearch 7.x版本重大改变(Breaking changes in 7.x)
  9. 信息化 + 个性化再造学习生命力
  10. 光宇游戏软件测试面试,[腾讯][急招][缺人][光速面试] IEG 天美游戏测试开发工程师...