logo资料库

12864DDRAM入门.docx

第1页 / 共15页
第2页 / 共15页
第3页 / 共15页
第4页 / 共15页
第5页 / 共15页
第6页 / 共15页
第7页 / 共15页
第8页 / 共15页
资料共15页,剩余部分请下载后查看
DDRAM: 笔者使用的这块 12864 内部有 4 行×32 字节的 DDRAM 空间。但 是某一时刻,屏幕只能显示 2 行×32 字节的空间,那么剩余的这些空间 呢?它们可以用于缓存,在实现卷屏显示时这些空间就派上用场了。 DDRAM 结构如下所示: 80H、81H、82H、83H、84H、85H、86H、87H、88H、89H、8AH、8BH、8CH、8DH、8EH、8FH 90H、91H、92H、93H、94H、95H、96H、97H、98H、99H、9AH、9BH、9CH、9DH、9EH、9FH A0H、A1H、A2H、A3H、A4H、A5H、A6H、A7H、A8H、A9H、AAH、ABH、ACH、ADH、AEH、AFH B0H、B1H、B2H、B3H、B4H、B5H、B6H、B7H、B8H、B9H、BAH、BBH、BCH、BDH、BEH、BFH 地址与屏幕显示对应关系如下: 第一行:80H、81H、82H、83H、84H、85H、86H、87H 第二行:90H、91H、92H、93H、94H、95H、96H、97H 第三行:88H、89H、8AH、8BH、8CH、8DH、8EH、8FH 第四行:98H、99H、9AH、9BH、9CH、9DH、9EH、9FH 说明:红色部分的数据归上半屏显示,绿色部分的数据归下半屏显示。 一般我们用于显示字符使用的是上面两行的空间,也就是 80H~8FH, 90H~9FH,每个地址的空间是 2 个字节,也就是 1 个字,所以可以用于 存储字符编码的空间总共是 128 字节。因为每个汉字的编码是 2 个字节, 所以每个地址需要使用 2 个字节来存储一个汉字。当然如果将 2 个字节 拆开来使用也可以,那就是显示 2 个半宽字符。 DDRAM 内部存储的数据是字符的编码,可以写入的编码有 ASCII 码、GB2312 码、BIG5 码。笔者使用的 12864 字库貌似不太全,字符“数” 都无法显示,而是显示其他字符。如果显示长篇汉字文章就不太适合吧。
DDRAM 数据读写: 所有的数据读写都是先送地址,然后进行读写。对 DDRAM 写数 据时,确保在基本指令集下(使用指令 0x30 开启),然后写入地址, 之后连续写入两个字节的数据。读数据时,在基本指令集下先写地址, 然后假读一次,之后再连续读 2 个字节的数据,读完之后地址指针自动 加一,跳到下一个字,若需要读下一个字的内容,只需再执行连续读 2 个字节的数据。这里的假读需要注意,不光是读 CGRAM 需要假读,读其 他的 GDRAM、DDRAM 都需要先假读一次,之后的读才是真读,假读就是 读一次数据,但不存储该数据,也就是说送地址之后第一次读的数据时 错误的,之后的数据才是正确的。(dummy 为假读) 关于编码在 DDRAM 中的存储需要说明事项如下: 1)、每次对 DDRAM 的操作单位是一个字,也就是 2 个字节, 当往 DDRAM 写入数据时,首先写地址,然后连续送入 2 个字节的数据,
先送高字节数据,再送低字节数据。读数据时也是如此,先写地址,然 后读出高字节数据,再读出低字节数据(读数据时注意先假读一次)。 2)、显示 ASCII 码半宽字符时,往每个地址送入 2 个字节的 ASCII 编码,对应屏幕上的位置就会显示 2 个半宽字符,左边的为高字 节字符,右边的为低字节字符。 3)、显示汉字时,汉字编码的 2 个字节必须存储在同一地址 空间中,不能分开放在 2 个地址存放,否则显示的就不是你想要的字符。 每个字中的 2 个字节自动结合查找字模并显示字符。所以,如果我们往 一个地址中写入的是一个汉字的 2 字节编码就会正确显示该字符,编码 高字节存放在前一地址低字节,编码低字节存放在后一地址高字节,显 然他们就不会结合查找字模,而是与各地址相应字节结合查找字模。 4)、因为控制器 ST7920 提供了 4 个自定义字符,所以这 4 个 自定义字符也是可以显示出来的,同样这 4 个自定义字符也是采用编码 的方式,但是这 4 个字符的编码是固定的,分别是 0000H,0002H,0004H,0006H。如下图所示:
上图只是把 2 个字符的 CGRAM 空间画出来,后续还有 2 个字符。可以看 到每个字符都有 16 行 16 列,每一行使用 2 个字节,因此一个字符占用 的空间是 32 字节,地址是 6 位的,4 个字符的地址分别是:00H~0FH、 10H~1FH、20H~2FH、30H~3FH。编码使用 2 个字节,可以看到有 2 个位
是任意的,说明其实这 4 个字符的编码可以有多个,只是我们常用前面 列举的 4 个编码。 3)、12864 全屏卷动的实现方法 首先需要明确的要点: DDRAM 的结构如下: 80H、81H、82H、83H、84H、85H、86H、87H、88H、89H、8AH、8BH、8CH、8DH、 8EH、8FH 90H、91H、92H、93H、94H、95H、96H、97H、98H、99H、9AH、9BH、9CH、9DH、 9EH、9FH A0H、A1H、A2H、A3H、A4H、A5H、A6H、A7H、A8H、A9H、AAH、ABH、ACH、 ADH、AEH、AFH B0H、B1H、B2H、B3H、B4H、B5H、B6H、B7H、B8H、B9H、BAH、BBH、BCH、 BDH、BEH、BFH 卷屏是分上下屏个各自卷动的,上半屏卷动左边红色区域的内容,下半屏卷动右边绿色区域 的内容。 为了实现全屏卷动显示,必须使用拼接的方法实现。 笔者花了几个小时研究了下算法,然后第二天实现了。现讲述如下: 细心观察 DDRAM 的结构发现,如果在卷动过程中,在同一时刻屏幕显示的内容最多涉及 3 行 DDRAM 的内容,而另一行是没有显示的,那么这一行就是用来缓存的数据的。 当屏幕显示如下 2 行时开始卷动(一): 80H、81H、82H、83H、84H、85H、86H、87H、88H、89H、8AH、8BH、8CH、8DH、 8EH、8FH 90H、91H、92H、93H、94H、95H、96H、97H、98H、99H、9AH、9BH、9CH、9DH、 9EH、9FH 则屏幕同时出现以下 3 行 DDRAM 内容(二): 80H、81H、82H、83H、84H、85H、86H、87H、88H、89H、8AH、8BH、8CH、8DH、 8EH、8FH
90H、91H、92H、93H、94H、95H、96H、97H、98H、99H、9AH、9BH、9CH、9DH、 9EH、9FH A0H、A1H、A2H、A3H、A4H、A5H、A6H、A7H、A8H、A9H、AAH、ABH、ACH、 ADH、AEH、AFH 需要注意的是,左边是上半屏显示,右边是下半屏显示。 在程序的开始处往 DDRAM 对应区域填写如下内容: 第一行字符 第三行字符--> 开始显示 第二行字符 第四行字符 第三行字符 第五行字符--> 即将显示 第四行字符 第六行字符 这样在开始卷动之后,就可以实现拼接的效果了。当卷动了 16 次之后, 也就是第一行字符已经移出屏幕,屏幕显示的 DDRAM 如下: 第一行字符 第三行字符 第二行字符 第四行字符 第三行字符 第五行字符 第四行字符 第六行字符 此时,屏幕接着滚动,显示内容涉及 3 行的 DDRAM,如下: 第一行字符 第三行字符--> 已显示完毕 第二行字符 第四行字符 第三行字符 第五行字符 第四行字符 第六行字符--> 即将显示
第一行 DDRAM 是空余的,下次就该往第一行写数据,写完后 DDRAM 内容如下: 第五行字符 第七行字符 第二行字符 第四行字符 第三行字符 第五行字符 第四行字符 第六行字符 经过又一次的 16 次卷屏之后屏幕显示内容如下: 第五行字符 第七行字符--> 即将显示 第二行字符 第四行字符--> 显示完毕 第三行字符 第五行字符 第四行字符 第六行字符 然后接下来又卷动 16 次,笔者的算法是,在每一次卷动后写一个字到 显示完毕的那一行中,卷完 16 次,显示完毕的那一行也就写完了。然 后接下来的 16 次卷动又写刚刚显示完毕的那一行,而刚被写完的那一 行将在后面 16 次卷动中显示。 原理就是如此,然后从中提取出规律,设计出算法,并编程实现: 下面是程序实现: void main(void){ unsigned char code ser[] = {"一一一一一一一一二二二二二二二二 叁叁叁叁叁叁叁叁四四四四四四四四中国中国中国中国"}; //这是要显 示的字符串
//没有检测换行符功能,只能显示一长串的汉字或一串 ASCII 码字符。 unsigned char i,addr,flag,hang,over,*ptdat; //addr 用于存储写入地址 //flag 存储卷动地址,名字没取好! //hang 存储下一行要写入数据的行号(1~4) //over 记录写入的空字符数 //ptdat 存储字符串的指针 delay_12864(1000); initial_12864(); ptdat = ser; over = 0; //写入空字符数 //这里先把前面 DDRAM 中的前 3 行的字符数据写入 //如果字符不足<=4 行,那么不卷动,之后字符>4 行才卷动 //一直到末行显示完毕则停止卷动 wrtcom_12864(0x80); //写屏幕第一行字符 for(i = 0; i < 16; i++){ if(*ptdat != '\0'){ wrtdat_12864(*ptdat++); }else{
分享到:
收藏