10 LCM 設計模式

LCM 是 LCD MODULE 的簡稱,俗稱液晶顯示器模組。
這裡採用的方式是使用 80 位元組的視訊記憶體。
以 2 毫秒的速度更新 LCM,完成一次更新需要 168 毫秒。
這樣的方式很浪費記憶體,好處是只要對記憶體填寫要顯示的資料,不需其他的動作。


10 LCM 標頭檔

1.定義符號 LCM_H,避免標頭檔的重複引入。
2.宣告結構原型 LCM_CONTROL,這是LCM控制結構的原型。
3.引出 LCM 控制結構 LcmCtrl。
4.引出 LCM 顯示記憶體 LcmChar[80]。
5.引出 LCM 函式庫,之後所有引入標頭檔的程式檔都可以連結並呼叫偵錯器函式庫。

01 #ifndef LCM_H
01 #define LCM_H
01 typedef struct {
01   INT8U State; 
01   INT8U Position;  
01   INT8U Timer;      
01 }LCM_CONTROL;
01 extern LCM_CONTROL LcmCtrl;
01 extern INT8U LcmChar[80];
01 
01 extern void LcmInit(void);
01 extern void LcmSvc(void);
01 extern void LcmCommandWrite(INT8U);
01 extern void LcmDataWrite(INT8U);
01 #endif


10 LCM 結構與變數

宣告一個 80 位元組的陣列,將所要顯示的字元寫入陣列。

01 INT8U LcmChar[80]={ 
01 '8','O','5','1',' ','C','O','N','T','R','O','L',' ','S','Y','S','T','E','M',' ',
01 'M','O','T','O','R',':',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
01 'U','A','R','T',':',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
01 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
01 };
01 

定義 LCM 資料埠信號 LcmData 為 P0,P0 會連接到 LCM 模組的資料腳位。
定義 LCM 致能信號 LcmEnableSignal 為 P2.5,P0 會連接到 LCM 模組的資料腳位。
定義 LCM 讀寫信號為 P2.6,P0 會連接到 LCM 模組的資料腳位。
定義 LCM 暫存器選擇信號 LcmRegSelect 為 P2.7,P0 會連接到 LCM 模組的資料腳位。
宣告 LCM 控制結構 LcmCtrl。

01 #define LcmData P0       
01 sbit LcmEnableSignal=P2^5;  
01 sbit LcmRw= P2^6;   
01 sbit LcmRegSelect=   P2^7;  
01 struct LCM_CONTROL LcmCtrl;  


10 LCM 函式庫

LED 函式庫。

函式名稱說明
LcmInitLCM 初始化函式。
LcmSvcLCM 服務函式。
LcmCommandWriteLCM 命令寫入函式。
LcmDataWriteLCM 資料寫入函式。


10 LCM 初始化函式

初始化變數,。
初始化硬體接腳準位,。

01 void LcmInit(void){   
01   LcmCtrl.Position=0; 
01   LcmCtrl.Timer=20;
01   LcmCtrl.State=LcmInitial0State;  
01 
01   LcmRw=1;    
01   LcmRegSelect=1;  
01   LcmEnableSignal=1;
01   LcmData=0xff; 
01 }


10 LCM 服務函式

LCM 服務函式掃描 LCM,更新 LCM 內容。
每兩毫秒會對 LCM 寫入一筆命令或資料,完成 80 個字的更新約 168 毫秒。
初始化程序會執行 0x38、0x08、0x01、0x06、0x0c、0x80,之後轉移到第一行的資料寫入狀態 LcmShowLine0State。
程式會從第一行開始,寫入顯示資料,到了第四行後再回到第一行,一直循環。

01 void LcmSvc(void){
01   if(LcmCtrl.Timer!=0) return;
01   LcmCtrl.Timer=2;
01   switch(LcmCtrl.State){
01     case LcmIdleState:
01       break;
01     case LcmInitial0State:
01       LcmCommandWrite(0x38);
01       LcmCtrl.State=LcmInitial1State;
01       break;
01     case LcmInitial1State:
01       LcmCommandWrite(0x08);
01       LcmCtrl.State=LcmInitial2State;
01       break;
01     case LcmInitial2State:
01       LcmCommandWrite(0x01);
01       LcmCtrl.State=LcmInitial3State;
01       break;
01     case LcmInitial3State:
01       LcmCommandWrite(0x06);
01       LcmCtrl.State=LcmInitial4State;
01       break;
01     case LcmInitial4State:
01       LcmCommandWrite(0x0c);
01       LcmCtrl.State=LcmInitial5State;
01       break;
01     case LcmInitial5State:
01       LcmCommandWrite(0x80);
01       LcmCtrl.State=LcmShowLine0State;
01       break;
01     case LcmShowLine0State:
01       LcmDataWrite(LcmChar[LcmCtrl.Position]);
01       LcmCtrl.Position++;
01       if(LcmCtrl.Position==20){
01         LcmCtrl.Position=0;
01         LcmCtrl.State=LcmChangeLine1State;
01       }
01       break;
01     case LcmShowLine1State:
01       LcmDataWrite(LcmChar[LcmCtrl.Position+20]);
01       LcmCtrl.Position++;
01       if(LcmCtrl.Position==20){
01         LcmCtrl.Position=0;
01         LcmCtrl.State=LcmChangeLine2State;
01       }
01       break;
01     case LcmShowLine2State:
01       LcmDataWrite(LcmChar[LcmCtrl.Position+40]);
01       LcmCtrl.Position++;
01       if(LcmCtrl.Position==20){
01         LcmCtrl.Position=0;
01         LcmCtrl.State=LcmChangeLine3State;
01       }
01       break;
01     case LcmShowLine3State:
01       LcmDataWrite(LcmChar[LcmCtrl.Position+60]);
01       LcmCtrl.Position++;
01       if(LcmCtrl.Position==20){
01         LcmCtrl.Position=0;
01         LcmCtrl.State=LcmChangeLine0State;
01       }
01       break;
01     case LcmChangeLine0State:  
01         LcmCommandWrite(0x80);
01       LcmCtrl.State=LcmShowLine0State;
01       break;
01     case LcmChangeLine1State:
01       LcmCommandWrite(0xC0);
01       LcmCtrl.State=LcmShowLine1State;
01       break;
01     case LcmChangeLine2State:
01       LcmCommandWrite(0x94);
01       LcmCtrl.State=LcmShowLine2State;
01       break;
01     case LcmChangeLine3State:
01       LcmCommandWrite(0xD4);
01       LcmCtrl.State=LcmShowLine3State;
01       break;      
01     default:
01       LcmCtrl.State=LcmIdleState; 
01       break; 
01   }
01 }


10 LCM 命令寫入函式

1.清除讀寫訊號為 0,表示要執行寫入動作。
2.清除暫存器選擇訊號為 0,表示要寫入命令。
3.將命令值放到 LCM 資料線。
4.傳送致能信號脈波,表示要寫入資料。
5.清除讀寫訊號為 1,表示不執行寫入動作。

01 void LcmCommandWrite(INT8U Command){
01   LcmRw=0;       
01   _nop_();
01   _nop_();
01   LcmRegSelect=0;   
01   _nop_();
01   _nop_();
01   LcmData=Command;   
01   _nop_();
01   _nop_();
01   LcmEnableSignal=1;
01   _nop_();
01   _nop_();
01   LcmEnableSignal=0;
01   _nop_();
01   _nop_();
01   LcmEnableSignal=1;
01 }


10 LCM 資料寫入函式

1.清除讀寫訊號為 0,表示要執行寫入動作。
2.清除暫存器選擇訊號為 1,表示要寫入資料。
3.將資料值放到 LCM 資料線。
4.傳送致能信號脈波,表示要寫入資料。
5.清除讀寫訊號為 1,表示不執行寫入動作。

01 void LcmDataWrite(INT8U Data){  
01   LcmRw=0;       
01   _nop_();
01   _nop_();
01   LcmRegSelect=1;   
01   _nop_();
01   _nop_();
01   LcmData=Data;
01   _nop_();
01   _nop_();
01   LcmEnableSignal=1;
01   _nop_();
01   _nop_();
01   LcmEnableSignal=0; 
01   _nop_();
01   _nop_();
01   LcmEnableSignal=1;
01 }