从零开始构建计算机系统——二维图形库(字符串输出、键盘输入)

四、输出字符串

对于字符串的输出,我们需要思考两个问题,一个是输出的位置,一个是输出的大小。

首先,我们假设屏幕的像素栅格总共有256行、512列,那么屏幕的像素就是:256×512。听起来很耳熟吧,对这就是我们经常说的屏幕的像素。

一般对于字符,我们假设其字模空间定为11×8点阵,也就是11行、8列,如下图所示,为字符A的字模示意图:

从零开始构建计算机系统——二维图形库(字符串输出、键盘输入)_第1张图片

因此,字符A的字模数组为:

{0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc}

类似的,我们实现对所有的字符都做好计算,并按照一定的编码顺序保存到数组中,那么我们就可以在需要使用的时候以字符的编码为索引,从数组中取出字模文件。这样的库就叫做字体库。这里我们说一下字符编码。

①汉字的区位码与内码

国家标准的汉字字符集(GB2312-80)在汉字操作系统中是以汉字库的形式提供的。汉字库结构有统一规定,即将汉字库分成94个区,每个区有94个汉字(以位作区别),每个汉字在汉字库中有确定的区和位编号(用两个字节),这就是所谓的区位码。区位码的第一个字节表示区号,第二个字节表示位号,因而只要知道了区位码,就可以知道该汉字在字库中的地址。每个汉字在字库中是以点阵字模形式存储的,当用存储单元存储该字模信息时,将需要32字节。在计算机内,英文字符是用一个字节的ASCII码表示的,而对于众多的汉字,需用两个字节才能代表,国家为此制定了统一标准,称为国标码。又规定国标码在机内表示汉字时,将每个字节的最高位置1。这些国标码的两字节最高位加1后的代码称为机器内的汉字代码,简称内码。

②内码转换为区位码与取字模

汉字内码与区位码有固定的转换关系,即若汉字内码为十六进制数aaff,则区号qh和位号wh分别为 qh= aa-0xa0,wh=ff-0xa0。由于在中文DOS下,输入汉字时,其相应的内码即已在程序中存在,如同在西文DOS下,输入英文字符时,其对应的ASCII也在程序中存在一样。因而得知汉字内码,将其转换为区位码,这样就可以找出该汉字字模在字库中存放的地址,由此地址调出该32字节汉字的内容(字模)。

综合上述分析看,我们采用C语言代码进行简要实现:

DrawCHS( x, y, QW)

x:绘制的起始横坐标

y:绘制的起始纵坐标

QW:要绘制的汉字编码

a获取字模数组:

pZK = &__CHS[ (  ( (QW >> 8) - 1 )*94 + (QW & 0x00FF)- 1 )*32 ];  

b逐行逐个点进行绘制

mask = 0x80;  

for( i = 0 ; i < 11 ; i++ )  

{  

for( j = 0 ; j < 8 ; j++ )  

    {  

if( buf & mask ) DrawPixel(x+j,y+i);  

        mask = mask >> 1;  

    }  

}  


从零开始构建计算机系统——二维图形库(字符串输出、键盘输入)_第2张图片

五、键盘输入

主要有两种方式,一种是轮询法,一种是中断法。轮询法中,系统需要周期性的查询键盘的输入情况,如果有输入,就需要将输入数据送到消息队列中。中断法中,当键盘有输入时,打断系统的正常执行,系统立即中止当前的工作,获取键盘的输入并送到消息队列中。

如下图所示,是一个4×4矩阵键盘,4行4列共16个按钮,行线P10~P13为输出线,列线P14~P17为输入线。

从零开始构建计算机系统——二维图形库(字符串输出、键盘输入)_第3张图片

判断哪个键按下的具体方法是:首先将单片机将行线(P10~P13)全部输出低电平,此时读入列线数据,若列线全为高电平则没有键按下,当列线有出现低电平时调用延时程序以此来去除按键抖动。延时完成后再判断是否有低电平,如果此时读入列线数据还是有低电平,则说明确实有键按下。

最后一步确定键值。现在我们以第二行的S5键为例,若按下S5后我们应该怎么得到这个键值呢?当判断确实有键按下之后,行线轮流输出低电平,根据读入列线的数据可以确定键值。首先,单片机将P10输出为低电平,其它P11~P13输出高电平,此时读取列线的数据全为高电平,说明没有在第一行有键按下;其次,单片机将P11输出低电平,其它P10、P12、P13仍为高电平,此时再来读取列线数据,发现列线读到的数据有低电平,数值为1011(0x0B),如果我们的键盘布局已经确定,那么0x0B就代表S5的值了。

按键消抖:按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

从零开始构建计算机系统——二维图形库(字符串输出、键盘输入)_第4张图片

抖动时间:其长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

按键判断完毕后,需要对按键消息进行打包,然后送入消息队列中。在分时操作系统中,一般需要等到专门处理消息队列的任务获取CPU控制权,还有一种就是消息进入队列后直接触发等待此消息的任务。如果一个任务需要等待键盘的输入,它有两种处理方式:一种是同步式的,一种是异步式或阻塞式。通常我们会采取阻塞式的方式,但是对于一些特殊的场景,比如对实时性要求特别高的任务,或者必须等待键盘的某个输入之后才能继续往下执行的任务。阻塞式在编程中主要通过回调的方式实现,系统需要提供标准的API。

你可能感兴趣的:(从零开始构建计算机系统——二维图形库(字符串输出、键盘输入))