单片机学习小组
直播中

周必镜

7年用户 930经验值
私信 关注

12864的原理是什么?12864的使用方法是什么

12864的原理是什么?12864的使用方法是什么?

回帖(1)

杜元晓

2022-1-21 15:29:39
最近在做有关51的电子密码锁实验,正巧用到了12864与24C04。想在网上找找相关资料,要么讲的含糊不清,看的一知半解;要么太过复杂,难以理解。花了几天搞明白之后,把自己的看法简单分享一下。下面使用了我自己的代码进行讲解,但是各位朋友要能够真正的明白原理,而不是只会用我的代码。文中可能会有认识不全面的地方,请大家多多指教。
12864原理

所谓12864,顾名思义,为128x64的点阵组。在实际使用时,通常会把它分为左半屏和右半屏,每个半屏为64x64点阵。这里先扔掉我们的固有思维,不要用平日里的阅读习惯(从左到右,从上到下)去理解其显示方法,否则只会越学越糊涂。
需要知道的是,12864中使用了页这个概念。什么是页呢?以右半屏为例,我们应该都知道行和列的概念,在我的代码中,从第一行开始,往下数8个行,这8个行所构成的8x64点阵就是一页。虽然不同的操作函数设置的页的大小会有差别,但总体构成原理是相似的。话不多说,直接上图:

可以看到,每个半屏由8页组成,从上至下编号为0~7,一块完整的屏幕由16个页组成。而这些页的容量便取决于你的汉字字符有多大。说到这里,需要先重复一个常识:汉字(包括中文输入法下的标点符号)所占用的空间是英文字母、数字的2倍。知道了这一点,下面就比较好理解了。
在我写的代码中,一个页最多可以排列4个汉字,或是8个数字、字母。也就是说,一个汉字要占用8x16大小的点阵,四个汉字便占满了8x64的点阵。注意,这里我没有说一个汉字的大小是8x16,而是说一个汉字需要8x16大小的点阵来表示,要注意这两种说法的区别。
看到这里大家应该就明白了,在12864上显示的内容实际上是由不同的页里面的内容组合、拼凑而成的。有些朋友可能会问,那如果在屏幕的中间位置显示字符的话,不就涉及到了左右两块半屏了吗?没错,如果想要在屏幕的中间位置显示的话,左右半屏就需要各自显示内容的左半部分和右半部分。虽然这样听起来有些别扭,但既然是这样设计的,我们就只能这样去使用。
12864使用方法

下面直接把我用的12864的C文件代码贴上来,如果你是认真读到这里的,那么12864的基本原理应该理解得差不多了,只要我对函数的参数稍加解释,很快就可以理解并上手。至于代码是如何实现显示功能的就不讨论了,毕竟对于大多数人而言,只要能够使用便足矣。

#include
#include
#include "12864header.h"
//直接往下翻到标有使用方法注释的操作函数部分,前面可以不用看
void busy()//忙检测函数,不用管
{
        P0=0X00;
        RS=0;
        RW=1;
        EN=1;
        while(P0&0X80);
        EN=0;
}


void wcmd(uchar cmd)
{
        busy();
        RS=0;
        RW=0;
        P0=cmd;
        EN=1;_nop_();_nop_();
        EN=0;
}


void wdata(uchar dat)
{
        busy();
        RS=1;
        RW=0;
        P0=dat;
        EN=1;_nop_();_nop_();
        EN=0;
}


void set_page(uchar page)
{
        page=0xb8|page;
        wcmd(page);
}


void set_line(uchar line)
{
        line=0xc0|line;
        wcmd(line);
}


void set_column(uchar column)
{
        column=0x40|column;
        wcmd(column);
}


void set_onoff(uchar onoff)
{
        onoff|=0x3e;
        wcmd(onoff);
}


void select_screen(uchar screen)
{       
        switch(screen)       
        {
                  case 0:CS1=0;CS2=0;break;
                  case 1:CS1=0;CS2=1;break;
                  case 2:CS1=1;CS2=0;break;
                default:break;
        }
}


void clear_screen(uchar screen)
{
         uchar i,j;
         select_screen(screen);
         for(i=0;i<8;i++)?
         {
                  set_page(i);   
                  set_column(0);
                  for(j=0;j<64;j++)
                          wdata(0x00);  
         }
}


void init() //这里是12864初始化,需要在使用前调用1次
{
         busy();
         select_screen(0);
         set_onoff(0);
         select_screen(0);
         set_onoff(1);
         select_screen(0);
         clear_screen(0);
         set_line(0);   
}


void Show(uchar screen,uchar page,uchar column,uchar *p)//显示汉字的函数,各参数的含义在下面讲解  
{
         uchar i;
         select_screen(screen); //选择要操作的是左半屏还是右半屏,1为左半屏,2为右半屏
         set_page(page);    //选择要操作的页,范围为0~7
         set_column(column);//选择从哪个地方开始写,这个在下文中解释
         for(i=0;i<8;i++)
                 wdata(p);//p为指针,指向待写入内容的起始位置,这里推荐用数组
         set_page(page+1);
         set_column(column);
         for(i=0;i<16;i++)
                  wdata(p[i+16]);
}


void Show1(uchar screen,uchar page,uchar column,uchar *p)//显示数字或字母的函数,参数含义与上一个函数相同,不做赘述
{
         uchar i;
         select_screen(screen);
         set_page(page);
         set_column(column);
         for(i=0;i<8;i++)
                 wdata(p);  
         set_page(page+1);
         set_column(column);
         for(i=0;i<8;i++)
                   wdata(p[i+8]);  
}
那么,这个函数要怎么使用呢?举个例子,假设在一个名为start的数组中,有如下两个汉字:“通”,编码如下(利用字模软件生成):
0x40,0x42,0xCC,0x00,0x00,0xE2,0x22,0x2A,0x2A,0xF2,0x2A,0x26,0x22,0xE0,0x00,0x00,
0x80,0x40,0x3F,0x40,0x80,0xFF,0x89,0x89,0x89,0xBF,0x89,0xA9,0xC9,0xBF,0x80,0x00,
“信”,编码如下:
0x00,0x80,0x60,0xF8,0x07,0x00,0x04,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x04,0x00,
0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0xF9,0x49,0x49,0x49,0x49,0x49,0xF9,0x00,0x00,
现在我的左半屏第1页中的第一个字为“通”,我想紧跟其后的显示“信”这个字,就可以这样来写:
Show(1,1,2*8,start+1*32);

(因为文本显示问题,下面都用乘来代替*)
这里面,第一个1表示在左半屏,第二个1表示在第1页,2乘8表示从第16位写起,因为第一个汉字“通”已经占据了8x16大小的点阵,也就是在横向的方向占据了2x8个点(纵向方向的不用在意,因为它们都占满了8个点),即0-15,那么下一个汉字就要从横向方向从左往右数的第16个点开始写起。而start+1乘32,则表示将指针指向数组中第二个字的起始位置,为什么是1乘32呢?观察一下上面每个字的编码,这里假设每个十六进制数占用一个数位,不难发现每个字的大小便是32个数位,那么就可以知道,第一个汉字“通”占用了数组的0-31数位,所以指针就需要指到第32个数位处,即1乘32。
12864就写到这里,过几天应该会把24C04的相关操作也写出来(最近陆陆续续的有考试,大概率会咕咕咕)。第一次写博客,不知道怎么写比较好,就随便写了一点,希望能够帮到大家,也欢迎大家来找我探讨交流电子类方面的问题。
举报

更多回帖

×
20
完善资料,
赚取积分