依據國標碼的規則,每一個漢字都有了確認的二進制代碼,可是這個代碼在核算機內部處理時會與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_16codeGB_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位低功耗mcu單片機
超低功耗mcu單片機能夠界說位變量,可是不能夠界說位數組。用c言語寫只是看著簡略,實際生成的代碼量是最多的,用于操控的單片機幾乎不必浮點數運算,不僅慢還麻煩還占當地,假如是DSP芯片,本身有合適的硬件結構,會好許多。
答復3:一般是主動分配的,能夠c言語和匯編言語混合編程,也能夠用Keil C在線匯編,芯片與外部的數據交換都是經過端口進行的。