液晶显示屏驱动(KD014QQTBN001、STC12C5A60S2)

lianxian连线 2017-06-06 08:41:17
前文汇编码、机器码、十六进制码相互转换阐述了在各种码字之间进行相互转换的方法。本文将使用此法实现一个液晶显示屏驱动。

以 宏晶 STC12C5A60S2 与 液晶显示屏 KD014QQTBN001(ST7735S) 为例。

1. 连线

首先将 STC12C5A60S2 连接 PL2303



然后连接 KD014QQTBN001:



图中 KD014QQTBN001 的 IM2IM0 引脚都接 高电平 5.0V,SPI4W 接 低电平 地,表示 ”MCU 16-bit
Parallel“,即 ”16位 并行接口“。
同时 STC12C5A60S2 的 P2P0 16 位 接 KD014QQTBN001 的数据总线 DB 16 位。P1 前 5 位 接 KD014QQTBN001 的控制线 RDDCXRESETCSWR

2. 启动

STC 芯片的 引脚 和 地址 有如下 对应关系:



我们可以通过操作地址,以某种方式,达到控制引脚电平的目的。例如我们在 P0.0 脚接了一个 发光二极管,那么点亮即可用 汇编码:CLR 0x80。功能是将 P0.0 脚置 低电平,在 发光二极管 上产生一个 电压 从而导通发光。

而现在我们要控制的是一个 液晶显示屏,这就需要 控制引脚电平 产生一定波形,因此必须参见 KD014QQTBN001 芯片手册。可以看到它的波形图:



我们首先根据 波形图 写出 写一个字节 和 读一个字节 的 汇编码:

2.1 写一个字节

根据时序图,可以写出 汇编码:



0x91P1.1 对应 DCX0x94P1.4 对应 WR0x80P0 对应 DB7-0

P0 的一个字节 在 WR上升沿 写入 液晶显示屏。
也就是说, 0x80 的一个字节 在 执行 SETB 0x94 时 写入 液晶显示屏。

2.2 读一个字节

同理可以写出 汇编码:



0x90P1.0 对应 RD

RD下降沿 读取 液晶显示屏 一个字节 到 P0
也就是说,在 执行 CLR 0x90 时 读取 液晶显示屏 一个字节 到 0x80

2.3 函数

我们将 上述两组指令 写成 函数 的形式:



这样 写一个字节 的功能,用一个 ACALL 指令 调用,就完成了。

它的执行方式是这样的:ACALL 0x0003,长跳转 到 0x0009,执行 写一个字节,执行到 0x0011 然后返回。

2.4 唤醒

我们调用 写一个字节 函数 实现 唤醒 0x11 指令:



这样应该就 唤醒 了。当然前提必须是已 重置 的(RESET 有一个 高-低-高 电平)。

还有一个命令,也是一定必须在 启动代码 中给出的。那就是 设置像素格式 命令 0x3a,它的 数据 0x06 表示我们前述的 16位 并行接口。
还有 开显示 0x29 命令,不过 好的驱动 会考虑到 使用缓存 来消除 视觉可见的 刷新,也就是在 写内存 0x2c 命令 进行时 关显示 0x28,等完成后再 开显示。
还有许多命令例如 局部刷新 也是很有用的,可以参见 KD014QQTBN001(ST7735S) 的芯片手册。

3. 驱动

液晶显示屏 KD014QQTBN001 的分辨率为 128x128。对于 16位 并行接口 模式,颜色编码如图:



3.1 时钟数

可以看到 每 3 个时钟 传送 6 个 颜色分量 也就是 2 个 像素。平均每 1 个像素 需要 1.5 个时钟。

这样,128x128 个像素需要的时钟数就是 128x128x1.5。

要 写内存 这么多的数据,是一定要通过 循环 进行的。先来看一个 小循环:

3.2 小循环

因为 液晶显示屏 像素个数一定非 0,因此写循环不会是 0 次的。所以我们可以 先执行一次循环体,然后对寄存器数值减一,减到 0 时表示这层循环完成。这样寄存器初值为 0 表示循环 1 次,...,初值为 255 表示循环 256 次。

熟悉 C 语言 的读者 可以很清楚地理解到,这就是 do 循环 的汇编码。这样做的一个好处是,充分地应用了 8位寄存器 的表数能力,使循环的最大次数增加了 1 次。

我们用 汇编码 实现循环,如图:



我们依 2.4节 的说明 在循环前 调用 写一个字节 功能 传送 写内存 0x2c 命令(0x80 = 0x2c0x91 = 0),然后 在循环体中 将 NOP 指令换成 同样 调用 写一个字节 功能 传送 数据(0xa00x80 = 数据,0x91 = 1)。

它一共循环了 0xff(256) 次,这已是 8位寄存器 表数范围的 极限 了。要进行更多次数的循环,必须用 多重循环。

3.3 大循环

芯片 STC12C5A60S2 字长是 8位 的,每个 寄存器 都是 8位,表数范围只有 0~255,太小。因此需要一个 多重循环 来表示 128x128x1.5 这个数字。

多重循环 可用 多个寄存器,甚至 还可以用 寄存器外的内存,因此循环次数是 接近 无限 的,表示 这个数字 当然是没有问题的。

如何确定循环的 层数 和 每层次数 呢?

设循环层数 n,第 i 层循环次数 ti+1,ti 为寄存器初值。那么循环总次数可按如下公式计算:



我们可以设置各层循环次数如下:



因为



大循环是多个小循环的嵌套,实现是类似的,这里就不细说。详细可以参考资源:

http://www.pudn.com/Download/item/id/3186010.html
http://download.csdn.net/detail/elecfans2csdn/9861717

这样就完成了 一个屏幕 的显示。

4. 操作系统

启动代码 运行完成后 跳转 或 将 操作系统 加载到 内存中 执行。操作系统 调用 驱动 完成显示。

4.1 代码投影

如果用 STC12C5A60S2 芯片,就只能 跳转 而 不能 将 操作系统 加载到 内存,这是由 指令集 决定了的,因为这个指令集 不能支持 “代码投影(Code Shadowing)” 技术。我们看一个指令集 是否支持代码投影 其实也不难,只要看 PCMOV 指令是否指向同一片内存空间 就行了。

我们先用 跳转 到 操作系统 的方法。

4.2 分页

在 汇编程序设计 过程中,可以用到 STC12C5A60S2 芯片 指令集 支持的一种技术: “分页(Page)” 技术。分页 有很多应用,我们这里将其应用于 模块化程序设计。

我们将 2.节 的 启动、3.节 的 驱动、4.节 的 操作系统 以及我们的显示数据,分别部署在 内存 的 4 个页中:



每页首部都是跳转指令(AJMPLJMP)。驱动中,居于首部的一个(也可多个)AJMP 页内跳转指令 指向一个 驱动功能,是为 操作系统 LJMP 长跳转 准备的;然后的几个 AJMP 页内跳转指令 指向一些 读写操作,是为 驱动自己 准备的。

这个方法好处很明显。一方面,驱动的改动 不会影响到 操作系统,因为首部地址总是不动的;另一方面,操作系统的 调用 也变得简单,因为只需一个 ACALL 页内首地址 就行。

5. 实物图

用前文汇编码、机器码、十六进制码相互转换所述方法,将本文 汇编码 生成 十六进制码,同时指定每个 页 的地址。发一张 烧写入 STC12C5A60S2 成功的实物图:

...全文
836 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
lianxian连线 2017-07-04
  • 打赏
  • 举报
回复
引用 7 楼 qq_39192077 的回复:
“我们看一个指令集 是否支持代码投影 其实也不难” 难道你想自己实现指令集?
等着瞧吧,我一定能实现它的。
qq_39192077 2017-07-04
  • 打赏
  • 举报
回复
“我们看一个指令集 是否支持代码投影 其实也不难”
难道你想自己实现指令集?
lianxian连线 2017-06-26
  • 打赏
  • 举报
回复
引用 5 楼 qq_39192077 的回复:
do 循环 ? 是 do-while 循环 吧?
简单一点的说法。
qq_39192077 2017-06-20
  • 打赏
  • 举报
回复
do 循环 ? 是 do-while 循环 吧?
lianxian连线 2017-06-20
  • 打赏
  • 举报
回复
引用 3 楼 baidu_39207891 的回复:
看你电路图上为何只有 STC12C5A60S2 标签在右边?
哦,是这样:我原想用显式连线画出电路的,上面加共电源下面加共地,因此左下留以空位过接地线。后来换成以接口形式表示连线更为一目了然。
baidu_39207891 2017-06-20
  • 打赏
  • 举报
回复
看你电路图上为何只有 STC12C5A60S2 标签在右边?
lianxian连线 2017-06-07
  • 打赏
  • 举报
回复
引用 1 楼 fatalromeo 的回复:
看楼主ID,是从电子发烧友投奔CSDN的?
你知道电子发烧友论坛!哈哈,是的啊。一开始在那做硬件,也常来CSDN写软件!硬件链接
hello_mcu 2017-06-06
  • 打赏
  • 举报
回复
看楼主ID,是从电子发烧友投奔CSDN的?
基于NRF24L01的PID电机转速控制器,采用51单片机控制,有发送端和接收端的完整图纸和程序代码 实物图: 原理图: 项目介绍: 在过程控制中,按偏差的比例(P)、积分(I)和微分(D)进行控制的PID控制器(亦称PID调节器)是应用最为广泛的一种自动控制器。它具有原理简单,易于实现,适用面广,控制参数相互独立,参数的选定比较简单等优点;而且在理论上可以证明,对于过程控制的典型对象──“一阶滞后+纯滞后”与“二阶滞后+纯滞后”的控制对象,PID控制器是一种最优控制。PID调节规律是连续系统动态品质校正的一种有效方法,它的参数整定方式简便,结构改变灵活(PI、PD、PID)。 然而PID算法在工业发展中也占据不小的地位,例如,液位,压力,温度,流量的控制都能利用PID算法进行精准控制。本项目将PID的算法用在了直流电机的控制当中,用于精准控制电机转速,简化电机控制难度。为了使操作者能够简单,方便,实时,快捷的控制电机的转速,我又在此基础上加上了无线模块,使得操作者能够更加简单的操作本产品,操作者只需简单改变主控板的设定值,接收机即可将电机转速控制在设定值以内,误差范围控制在正负20r/s(转/秒)。 功能设计要点 1.控制核心:接收和发射核心控制部分均采用STC12C5A60S2单片机进行控制 2.显示部分:接收机显示采用普通的12864液晶显示,发射部分为了减小其体积采用OLED液晶,功耗低,体积小,显示效果好 3.电机驱动部分:采用的是L298N电机驱动模块,价格低,抗干扰能力强,安全性高,可靠性强,大大提高了电机的效率。 4.速度检测部分:采用44E开关型霍尔传感器,成本低,电路简单,可与单片机IO口直接连接,操作方便。 5.无线数据传输采用NRF24L01无线模块,工作在 2.4~2.5GHz 世界通用 ISM 频段,工作电流只有 10.5mA, 接收时工作电流只有 18mA, 多种低功率工作模式, 功耗低。 6.核心控制算法PID:此电路采用的是PID算法里的增量式算法, pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last); 增量式算法不需做累加, 计算误差和计算精度问题对控制量的计算影响较小; 系统工作原理方框图:

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧