MCU最强科普总结【建议收藏】(三)

2021-05-11 14:07:12 62
12、汉字概览:

为了将汉字在显示器或打印机上输出,把汉字按图形符号设计成点阵图,就得到了相应的点阵代码(字形码)。

为在计算机内表示汉字而统一的编码方式形成汉字编码叫内码(如国标码),内码是惟一的(相当于该字的身份证号)。为方便汉字输入而形成的汉字编码为输入码,属于汉字的外码,输入码因编码方式不同而不同,是多种多样的。为显示和打印输出汉字而形成的汉字编码为字形码,计算机通过汉字内码在字模库中找出汉字的字形码,实现其转换。

机内码

根据国标码的规定,每一个汉字都有了确定的二进制代码,但是这个代码在计算机内部处理时会与ASCII码发生冲突,为解决这个问题,把国标码的每一个字节的首位上加1。由于ASCII码只用7位,所以,这个首位上的“1”就可以作为识别汉字代码的标志,计算机在处理到首位是“1”的代码时把它理解为是汉字的信息,在处理到首位是“0”的代码时把它理解为是ASCII码。经过这样处理后的国标码(内码)就是机内码。

如果我们把这个“口”字图形的“.”处用“0”代替,就可以很形象地得到“口”的字形码:0000H 0004H 3FFAH 2004H 2004H 2004H 2004H 2004H 2004H 2004H 2004H2004H 3FFAH 2004H 0000H 0000H。计算机要输出“口”时,先找到显示字库的首址,根据“口”的机内码经过计算,再去找到“口”的字形码,然后根据字形码(要用二进制)通过字符发生器的控制在屏幕上进行依次扫描,其中二进制代码中是“0”的地方空扫,是“1”的地方扫出亮点,于是就可以得到“口”的字符图形。

汉字字模按国标码的顺序排列,以二进制文件形式存放在存储器中,构成汉字字模字库,亦称为汉字字形库,称汉字库

两种编码方法,见头文件
GB1616.h//------------------ 汉字字模的数据结构定义 ------------------------//struct typFNT_GB16 //汉字字模数据结构{ unsignedchar  Index[3]; //汉字内码索引  unsignedchar   Msk[32]; //点阵码数据 }; /////////////////////////////////////////////////////////////////////////// 汉字字模表                                                        //// 汉字库: 宋体16.dot,横向取模左高位,数据排列:从左到右从上到下        ///////////////////////////////////////////////////////////////////////////conststruct  typFNT_GB16 codeGB_16[]= //数据表{/*------------------------------------------------------------------------------;  源文件 /文字 :徐;  宽×高(像素):16×16------------------------------------------------------------------------------*/ "徐",0x10,0x80,0x10,0x80,0x21,0x40,0x42,0x20,0x94,0x10,0x1B,0xEC,0x20,0x80,0x60,0x80,0xAF,0xF8,0x20,0x80,0x22,0xA0,0x24,0x90,0x2A,0x88,0x21,0x00,0x00,0x00,0x00,0x00,

这个结构,很简单的:一个是内码,一个点阵序列,以前的点阵库是按内码顺序放的,不需要内码索引的,如果只放部分汉字,就需要内码索引了。(前面的汉字“徐”是为了要输出“徐”的时候找到该字的点阵序列,这个点阵序列是自己写的,当用1602显示时,因为该芯片内存在英文的点阵序列,所以就不用写了)一般内码两个字节就行了,多用1个字节是加了个尾0而已,这样,汉字内码处直接放汉字字符串就可;


codeGB_16[k].Index[0]
codeGB_16[k]说明有一个结构体typFNT_GB16的数组叫做codeGB_16
codeGB_16[k]是数组中第k+1个成员
index是结构体typFNT_GB16的成员,所以可以用codeGB_16[k].Index来进行引用
同时index又是个数组,所以可以index[0]
 
if((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1]))
&&是 逻辑与运算符
意思是 &&符号的两边的值都为真 &&的值才为真,也就是 true && true =true
这句的意思是
codeGB_16[k].Index[0]==c[0]  和 codeGB_16[k].Index[1]==c[1] 同时成立
if下面的语句才执行
codeGB_16[]是个结构体数组,codeGB_16[k].Index[0]是说结构体数组的第K个结构体的index成员的第0个元素值。
 

13、12864液晶:

每个显示点对应一位二进制数,1 表示亮,0 表示灭。存储这些点阵信息的RAM称为显示数据存储器。要显示某个图形或汉字就是将相应的点阵信息写入到相应的存储单元中。


绘图RAM的地址计数器(AC)只会对水平地址(X  轴)自动加一, 当水平地址=0FH  时会重新设为00H  但并不会对垂直地址做进位自动加一,故当连续写入多笔资料时,程序需自行判断垂直地址是否需重新设定


14、绘图RAM(GDRAM)

绘图显示RAM提供128×8 个字节的记忆空间,在更改绘图RAM时,先连续写入水平与垂直的坐标值,再写入两个字节的数据到绘图RAM,而地址计数器(AC)会对水平地址(X 地址)自动加一,当水平地址为0XFH 时会重新设为00H ;不会对垂直地址做进位自动加 1. 。在写入绘图 RAM的期间,绘图显示必须关闭。

[cpp] view plain copy// 显示汉字 voiddispString (uchar X, Y,uchar *msg) //X为哪一行,Y 为哪一列。msg 为汉字 {  if(X==0)       X = 0x80; // 第一行,汉字显示坐标  else if(X==1) X = 0x90; // 第二行  else if(X==2) X = 0x88; // 第三行  else X = 0x98; //第四行  Y = X + Y; //Y 为1 往右移一位  write_com(Y); // 写入坐标  while (*msg)  {  write_data(*msg++); //显示汉字 } } //////////////////////////////// //////////////// /////////////// // 显示图象 voiddisppicture(uchar code *adder) {  uint i,j; //*******显示上半屏内容设置  for(i=0;i<32;i++) // 上半屏32个列地址  {  write_com(0x80 + i); //SET  垂直地址 VERTICALADD  write_com(0x80); //SET   水平地址 HORIZONTAL ADD  for(j=0;j<16;j++)  {  write_data(*adder);  adder++;  }  } //*******显示下半屏内容设置  for(i=0;i<32;i++) //  {  write_com(0x80 + i); //SET 垂直地址 VERTICALADD  write_com(0x88); //SET  水平地址 HORIZONTAL ADD  for(j=0;j<16;j++)  {  write_data(*adder);  adder++;  }  } }

对于C语言,定义的变量,自动为其分配空间,其地址为该变量的名称。通过该名称,可以在内存中招到该数据,经过运算得到新数据,而汇编中需要编程者自己定义存储空间及把数据送到累加器等进行运算,每一步都需要编程者操作。而C语言这些过程由编译器去完成。


15、一些有用的答疑解惑

①、单片机C语言,其变量的内存开辟是如何进行的?难道是编译器,在编译过程中智能地加入分配与回收的代码?关键之处在于我所做的程序,如何保证其没有内存溢出错误?如果我进行的是递归运算,这样的话,内存需求是很难自己计算的。

②、单片机C语言在变量定义上是否会受到约束?比如浮点型数据的乘除运算,通过汇编还写,代码相当复杂,如果直接C语言来写,岂不过份简单?

③、单片机C语言生成的hex文件中,指令及数据的ROM的地址分布是否编译器自动分配?可否用户进行分配?

回答1:c语言写的单片机程序,先由1个程序(好像是c51.exe)编译,编译完成后,变量的存储空间大小已经安排好,只是还没分配具体地址(地址浮动),接下来有另一个程序(好像是a51.exe)进行连接,连接以后,具体地址确定。

如果变量过多,编译会提示数据段too large,要保证其没有内存溢出错误,主要考虑堆栈是否溢出,要靠经验

单片机c语言一般禁止递归,一般都避免用递归运算,单片机毕竟不是PC,会影响速度的,要递归的话,用DSP芯片更合适,总之,要会挑合适的芯片

回答2:变量的大小(位数)一般和芯片累加器的位数一样,比如51常用8位的,因为它是8位单片机

单片机可以定义位变量,但是不可以定义位数组。用c语言写只是看着简单,实际生成的代码量是最多的,用于控制的单片机几乎不用浮点数运算,不仅慢还麻烦还占地方,如果是DSP芯片,本身有适合的硬件结构,会好很多。

回答3:一般是自动分配的,可以c语言和汇编语言混合编程,也可以用Keil C在线汇编,芯片与外部的数据交换都是通过端口进行的。


免责声明:本文转载自“国际电子商情”,本文仅代表作者个人观点,不代表萨科微及行业观点,只为转载与分享,支持保护知识产权,转载请注明原出处及作者,如有侵权请联系我们删除。