在Proteus中模拟了89C52操作HDG12864F-1液晶屏,原理图如下:

一、HDG12864F-1官网信息

  该液晶屏是Hantronix的产品,官网上搜索出这个型号是系列型号中的一种,各种型号间的区别主要是尺寸不同、有无背光、背光颜色等等。

  下面是官网中几个手册的链接:

二、基本操作函数

  根据几个手册提供的信息,“写命令”和“写数据”函数如下:

 sbit cs = P1^;//-cs,片选,低电平有效
sbit rst = P1^;//-rst,复位,低电平有效
sbit a0 = P1^;//写命令、写数据控制位。1=Display data; 0=Control data;
sbit wr = P1^;//-Write serial data,写串口数据,低电平有效
sbit rd = P1^;//-Read serial data,读串口数据,低电平有效
sbit scl = P1^;//Shift clock input,时钟输入
sbit si = P1^;//Serial data input,串口数据输入
//手册中说了,各种操作都是ns级,不用各种等待命令,下面操作也没有写入等待功能
//写命令
void wrt_cmd(unsigned char command)
{
unsigned char i = ;
cs = ;
a0 = ;//0=Control data,命令置0
wr = ;
rd = ;
while(i--){
  scl = ;
  si = (bit) (command & 0x80);//先写高位
  scl = ;
  command <<= ;
}
scl = ;
}
//写数据
void wrt_dt(unsigned char data_)
{
unsigned char i = ;
cs = ;
wr = ;
a0 = ;//1=Display data,写数据置1
rd = ;
while(i--){
  scl = ;
  si = (bit) (data_ & 0x80);
  scl = ;
  data_ <<= ;
}
scl = ;
}

三、显存和屏幕的对应关系

  手册中有描述,不太好理解,网上也查了不少,还是用自己的方法好理解一些。

  在详细说明对应关系前,必须提到该芯片有正、反两种写入方向,ADC Select (Segment Driver Direction Select),见完整版手册第50页。厂家居然把“从屏幕右边开始写”称为“正”,看着别扭。不过我先看的是“正”的,下面就先“正”着说。手册中对正反的描述如下:

  1. 屏幕从左到右分成128列,分别是column0~column127,后面简称c0~c127,每一列对应着屏幕上纵向的一串点,相当于屏幕的x坐标值;同时,屏幕从上到下分成8个Page,每个Page对应着一个字节,恰好8个bit,每个bit对应着屏幕上横向的一串点,8个Page一共8*8=64个点,每个bit的位置相当于屏幕的y坐标值。这样,就将屏幕分成了128*64个点。“使用注意事项”中给出了图示:

  2. 大格局说清楚了,再来说说写RAM的顺序,我在这里绕了好长时间,利用下面的图形反复校对终于搞清楚了。图中:1-代表亮点,空白(0)-代表暗点。

  下图一共有8*8的点阵4个,形成了一个16*16的大点阵,一个16*16的大点阵可以显示一个汉字。

  如果从屏幕右上角开始显示汉字,则有:

  • 右上角的点阵代表汉字的右上角,其中每一列8个点构成一个Byte,下面的点是高位,上面的点是低位,例如:代表C0列的Byte为1010 1011B=abH。
  • 因为写数据的时候是从右边开始,所以字模数组的顺序也是从右边开始的。例如右上角8*8点阵形成的数组为:N[0],N[1],N[2],N[3],N[4],N[5],N[6],N[7]。
  • 写完一个Byte后,控制器将列坐标自动加1,因此按0~7的顺序写完这个数组后,在屏幕的右上角就完成了一个汉字右上四分之一的显示。
  • 接着连续写汉字左上四分之一,就是写N[8]~N[15]共8个字节。到这里一个汉字的上半部分就写完了。
  • 接下来就是更改Page了(相当于更改纵向位置)。刚才写汉字的上半部分时,纵坐标是在Page=0的位置,现在需要将纵坐标设置成Page=1;同时,也要将列重新设置为0。这样再连续写N[16]~N[31]共16个Byte后,一个完整的汉字就在屏幕上写好了。

  这段功能的主程序和实际效果如下:

 #include "HDG12864F1.h"
void main(void)
{ unsigned char i;
unsigned char chinachar[] = {
  0xab,0xab,0xab,0xab, 0xab,0xab,0xab,0xab,
  0x55,0x55,0x55,0x55, 0x55,0x55,0x55,0x55,
  0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,
  0xd5,0xd5,0xd5,0xd5, 0xd5,0xd5,0xd5,0xff
};
//HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);
HDG12864F1_SetColumnAddress();//设开始写的横向坐标为C0
HDG12864F1_SetPageAddress();//设开始写的纵向坐标为Page0
for(i=; i<; i++){
  HDG12864F1_WriteData(chinachar[i]);//连续写汉字的上半部分
}
HDG12864F1_SetColumnAddress();//再将横向坐标设为C0
HDG12864F1_SetPageAddress();//将纵向坐标设为Page1
for(i=; i<; i++){
  HDG12864F1_WriteData(chinachar[i]);//连续写汉字的下半部分
}
}

  其中,用到的几个函数如下。设置纵向位置、列位置两个函数,分别根据手册要求编写,见下图中(3)Page address set和(4)Column address set。

 //设置列位置,其中参数address:0~127
void HDG12864F1_SetColumnAddress(unsigned char address)
{  //写列要分成两步走,先写高四位,再写低四位
wrt_cmd(0x10 + (address >> & 0x0f));//C中右移是算术右移,必须&0x0f去掉高4位才能得到正确的结果
wrt_cmd(address & 0x0f);
}
//设置纵向位置,其中参数pageAddress:0~8
void HDG12864F1_SetPageAddress(unsigned char pageAddress)
{
wrt_cmd(0xb0 + pageAddress);
}
//写数据
void HDG12864F1_WriteData(unsigned char data_)
{
wrt_dt(data_);
}

  3. 上面说的内容都是以“从右侧开始写入”为条件的,也就是厂家所说的“正”着来,这不太符合我们日常的习惯,厂家也考虑到了这一点,并且提供了一个功能,让用户决定从左还是从右开始写起,就是上图中(9)Display normal/reverse。为了更加清楚,定义了两个宏,使用的时候直接把参数direction换成需要的宏即可。

 #define DISPLAY_LEFT_TO_RIGHT    1 //从左边数计算列位置,每写完一个字节,列数自动向右移动一个
#define DISPLAY_RIGHT_TO_LEFT 0 //从右边数计算列位置,每写完一个字节,列数自动向左移动一个
void HDG12864F1_Direction(unsigned char direction)
{
wrt_cmd(0xa0+direction);
}

  将main()函数第10行注释的“//”去掉,再次运行程序得到字形呈镜面对称。

  4. 另外,还验证了上2图中功能(2)Display start line set,该功能的作用是对写好的屏幕内容向上滚屏,滚出上边的部分会从屏幕下边冒出来,我设置了一个循环,对该函数的参数从0~63逐次加1,刚刚开始运行后截屏得到的图形如下。

 //参数line取值范围0~63
void HDG12864F1_SetStartLine(unsigned char line)
{
wrt_cmd(0x40 + line);
}

  5. 其他功能还有很多,没有逐个试验,下面贴出功能表的下半部分,需要时可参考。

  6. 这款芯片没有汉字库,英文字库我也没有找到。出于试验目的,利用字模小软件“拓”了几个汉字和数字,汉字占4个8*8点阵,数字占上下2个8*8点阵。代码和实际效果如下:

 void main(void)
{
unsigned char code cCharCai[]={0x4, 0x4, 0x24, 0x64, 0xA4, 0x2F, 0x64, 0xA4, 0x24, 0x2F, 0x94, 0x54, 0x14, 0x6, 0x4, 0x0, 0x2, 0x42, 0x42, 0x22, 0x12, 0xA, 0x6, 0xFF, 0x6, 0xA, 0x12, 0x12, 0x22, 0x63, 0x22, 0x0};//菜
unsigned char code cCharDan[]={0x0, 0x0, 0xF8, 0x49, 0x4A ,0x4C ,0x48 ,0xF8 ,0x48 ,0x4C, 0x4A, 0x49 ,0xFC, 0x8 ,0x0, 0x0 ,0x10, 0x10 ,0x17 ,0x12 ,0x12 ,0x12, 0x12, 0xFF, 0x12 ,0x12 ,0x12, 0x12, 0x13 ,0x18 ,0x10, 0x0};//单
unsigned char code cCharRen[]={0x0, 0x0 ,0x0, 0x0, 0x0, 0x0, 0x80 ,0x7F, 0x80 ,0x0 ,0x0 ,0x0 ,0x0 ,0x0, 0x0, 0x0 ,0x0, 0x80, 0x40, 0x20, 0x10, 0xC ,0x3 ,0x0, 0x3, 0xC ,0x10 ,0x20, 0x40 ,0xC0, 0x40, 0x0};//人
unsigned char code cCharYuan[]={0x0, 0x0, 0xC0, 0x5E, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x5F, 0xE2 ,0x40, 0x0, 0x0, 0x0, 0x80, 0x9F, 0x40, 0x40, 0x20, 0x10, 0xF ,0x0, 0x20, 0x20, 0x40 ,0x5F, 0x80, 0x0 ,0x0};//员
unsigned char code eCharColon[]={0x0, 0x0, 0x0, 0xC0, 0xC0, 0x0, 0x0, 0x0 ,0x0, 0x0 ,0x0, 0x30 ,0x30, 0x0, 0x0, 0x0 };//:
unsigned char code eChar0[]={0x0, 0xE0, 0xF0, 0x8, 0x8, 0x18, 0xF0, 0x80, 0x0 ,0xF ,0x1F, 0x20, 0x20, 0x30 ,0x1F ,0x3};//
unsigned char code eChar1[] = {0x0, 0x0, 0x10, 0xF0, 0xF8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x3F, 0x3F, 0x20, 0x0, 0x0};//
unsigned char code eChar2[]={0x0, 0x30, 0x78, 0x8 ,0x8 ,0x98, 0xF0, 0x0 ,0x0, 0x30 ,0x28 ,0x24, 0x22, 0x21, 0x38 ,0x0 };//
unsigned char code eChar3[]={0x0, 0x30, 0x38, 0x8, 0x88, 0xF8, 0x70, 0x0, 0x0, 0x18, 0x38, 0x21, 0x21, 0x33, 0x1E, 0x0};//
unsigned char code eChar4[]={0x0,0x0,0x80,0x40,0x30,0xF8,0x0,0x0,0x0,0x6,0x5,0x24,0x24,0x3F,0x24,0x0};//
unsigned char code eChar5[]={0x0, 0xC0, 0xF8, 0x88, 0x88 ,0x88, 0x8, 0x0 ,0x0, 0x19, 0x39, 0x20, 0x20 ,0x31, 0x1F, 0x4};//
unsigned char code eChar6[]={0x0, 0xE0, 0xF0, 0x88, 0x88, 0x98, 0x10, 0x0, 0x0 ,0xF, 0x1F, 0x20, 0x20, 0x20, 0x1F, 0xE };//
unsigned char code eChar7[]={0x0, 0x30, 0x18, 0x8, 0x88, 0xE8, 0x18, 0x0,0x0, 0x0 ,0x0 ,0x3C, 0x3F, 0x0, 0x0 ,0x0};//
unsigned char code eChar8[]={0x0 ,0x70, 0xF8, 0x88, 0x8 ,0x88, 0x70, 0x0 ,0x0, 0x1E, 0x23, 0x21, 0x21, 0x23, 0x1E, 0x8 };//
unsigned char code eChar9[]={0x0, 0xF0, 0xB8, 0x8 ,0x8 ,0x18, 0xF0, 0xC0 ,0x0 ,0x11, 0x33, 0x22, 0x22, 0x19, 0xF, 0x3 };//
unsigned char code **number[] = {eChar0,eChar1,eChar2,eChar3,eChar4,eChar5,eChar6,eChar7,eChar8,eChar9};
HDG12864F1_WriteChineseChar(cCharRen, , );
HDG12864F1_WriteChineseChar(cCharYuan, , );
HDG12864F1_WriteEnglishChar(eCharColon, , );
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[], , );
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[], , );
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteEnglishChar(number[], , );
HDG12864F1_WriteEnglishChar(number[],,);
HDG12864F1_WriteChineseChar(cCharCai, , );
HDG12864F1_WriteChineseChar(cCharDan, , );
}

  其中HDG12864F1_WriteChineseChar()和HDG12864F1_WriteEnglishChar()两个函数分别用于写16*16点阵的汉字和8*16的数字。具体代码实现和效果图如下:

void HDG12864F1_WriteChineseChar(unsigned char *pCChar, unsigned char column, unsigned char page)
{
unsigned char i;
HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);//DISPLAY_LEFT_TO_RIGHT是一个宏,值为1,代表从屏幕左侧写入
HDG12864F1_SetColumnAddress(column);//设开始写的横向坐标
HDG12864F1_SetPageAddress(page);//设开始写的纵向Page
for(i=; i<; i++){
  HDG12864F1_WriteData(*(pCChar + i));//连续写汉字的上半部分
}
HDG12864F1_SetColumnAddress(column);//再将横向坐标复原
HDG12864F1_SetPageAddress(page + );//将纵向Page加1
for(i=; i<; i++){
  HDG12864F1_WriteData(*(pCChar + i));//连续写汉字的下半部分
}
}
void HDG12864F1_WriteEnglishChar(unsigned char *pEChar, unsigned char column, unsigned char page)
{
unsigned char i;
HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);//DISPLAY_LEFT_TO_RIGHT是一个宏,值为1,代表从屏幕左侧写入
HDG12864F1_SetColumnAddress(column);//设开始写的横向坐标
HDG12864F1_SetPageAddress(page);//设开始写的纵向Page
for(i=; i<; i++){
  HDG12864F1_WriteData(*(pEChar + i));//连续写英文的上半部分
}
HDG12864F1_SetColumnAddress(column);//再将横向坐标复原
HDG12864F1_SetPageAddress(page + );//将纵向Page加1
for(i=; i<; i++){
  HDG12864F1_WriteData(*(pEChar + i));//连续写英文的下半部分
}
}

使用Proteus模拟操作HDG12864F-1液晶屏的更多相关文章

  1. Arduino 1602液晶屏实验和程序

    在Arduino IDE中, 项目->加载库->管理库中搜索LiquidCrystal,然后安装即可 1.接线图 2.引脚图 3.最简单程序 #include <LiquidCrys ...

  2. 拓普微小尺寸TFT液晶屏-高性价比

    智能模块(Smart LCD)是专为工业显示应用而设计的TFT液晶显示模块. 模块自带主控IC.Flash存储器.实时嵌入式操作系统,客户主机可把要存储的数据(如背景图.图标等)存储到屏的flash中 ...

  3. 单片机中不带字库LCD液晶屏显示少量汉字

    单片机中不带字库LCD液晶屏如何显示少量汉字,一般显示汉字的方法有1.使用带字库的LCD屏,2.通过SD 卡或者外挂spi flash存中文字库,3.直接将需要的汉字取模存入mcu的flash中. 第 ...

  4. 51单片机 | 实现SMC1602液晶屏显示实例

    ———————————————————————————————————————————— LCD1602 - - - - - - - - - - - - - - - - - - - - - - - - ...

  5. 使用Python控制1602液晶屏实时显示时间(附PyCharm远程调试)

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文介绍一下UP板的GPIO资源使用,以及一个使用Python演示一个简单的demo. 本文使用Markdown写成,为获得更好的 ...

  6. s3c2440液晶屏驱动 (内核自带) linux-4.1.24

    自带有一部分驱动的配置信息,只要修改这部分就能支援 不同的液晶屏 - /arch/arm/mach-s3c24xx/mach-smdk2440.c 另一部分在 /drivers/video/fbdev ...

  7. jquery模拟操作——trigger()函数

    在页面中很多效果需要触发才能实现,比如click后的弹窗.但有时我们无法点击或是跳过用户触发,就像网页中那些可恶的广告弹窗 trigger函数可以实现模拟操作.譬如常用的点击动作,我们可以这样, $( ...

  8. jQuery中的模拟操作

    jQuery中的模拟操作主要是通过trigger来触发,相当于页面加载完成后不需要用户点击按钮,就可以自动触发页面中的相关事件. trigger(type,[data])可以用来模拟触发自定义事件的触 ...

  9. adb模拟操作之event

    首语: 我们都知道,adb可以对模拟器和root过的真机进行很多操作,例如:模拟点击,输入,截图,手机和PC,数据互传等.这篇要说的就是adb操作模拟器或者真机的输入输出. 0x01 问题 使用adb ...

随机推荐

  1. 选择IT行业的自我心得,希望能帮助到各位!(二)

    在前面说道的一,希望大家能喜欢,这也只是自己的一种经历,每个人都有年轻的时候,谁的年级都有自以为是,谁的年轻都有风华正茂,谁的年轻都让自己的内涵给我们自己摔了一个狠狠的道理,人外有人天外有天.我记得当 ...

  2. Python 分析后告诉你闲鱼上哪些商品抢手?

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:[Airpython] PS:如有需要Python学习资料的小伙伴可以 ...

  3. OpenCV 之 基本绘图

    OpenCV 虽是开源的计算机视觉库,但里面也有一些基础的绘图函数,本文将介绍几种常用绘图函数:直线.圆.椭圆.长方形.多边形等. 1  数据结构 1.1  二维向量 cv::Point 代表的是二维 ...

  4. V - Largest Rectangle in a Histogram HDU - 1506

    两种思路: 1 单调栈:维护一个单调非递减栈,当栈为空或者当前元素大于等于栈顶元素时就入栈,当前元素小于栈顶元素时就出栈,出栈的同时计算当前值,当前值所包含的区间范围为从当前栈顶元素到当前元素i的距离 ...

  5. Python巩固 - 第N天

    一.函数解释: def fact(n, m = 1): s = 1 for j in range(1, n+1): s = s*j return n, m, s//m print(fact(10, 5 ...

  6. python白帽子/黑客/实战编程教程

    Python搜索爬虫抓取超高清视频教程_第一期Python搜索爬虫抓取超高清视频教程_第二期Python搜索爬虫抓取视频教程_第三期Python搜索爬虫抓取视频教程_第四期Python搜索引擎爬虫抓取 ...

  7. 谈谈MySQL的索引

    目录 索引 前言 是什么 B树 B+树 B树和B+树结构上异同 有什么用 怎么用 索引 前言 总所周知,数据库查询是数据库的最主要功能之一.我们都希望查询数据的速度能尽可能的快.而支撑这一快速的背后就 ...

  8. 任意用户密码重置的十种姿势=====>学习笔记!

    原学习视频链接:https://www.butian.net/School/content?id=214%E2%80%98 1.验证码不失效 原因:获取的验证码缺少时间限制,仅判断验证码是否不正确而未 ...

  9. 4、flink自定义source、sink

    一.Source 代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 1.1.flink内置数据源 1.基于文件 env.readTextFile(" ...

  10. 3、flink架构,资源和资源组

    一.flink架构 1.1.集群模型和角色 如上图所示:当 Flink 集群启动后,首先会启动一个 JobManger 和一个或多个的 TaskManager.由 Client 提交任务给 JobMa ...