精華區beta sttmountain 關於我們 聯絡資訊
這是我一篇用來教學的範例,使用的是11.058MHZ CRYSTAL的AT89S52 用C寫得,您就參考一下流程吧(尤其是其中的LCD初始化部份): #define pmCOM 0 #define pmLCM 1 #define pmAUX 2 extern unsigned char data _wlsPutcMode; extern char putchar(char c); #define print2lcd() _wlsPutcMode=pmLCM #define print2com() _wlsPutcMode=pmCOM #define print2aux() _wlsPutcMode=pmAUX // LCD Define ----------------------------------------------------------------- sbit LCD_RS =P1^0;//定義接腳 sbit LCD_RW =P1^1; sbit LCD_E =P1^2; sbit LCD_PW =P3^2; #define LCD_Data P2 #define Busy 0x80 //用於檢測LCD狀態字中的Busy標識 #define _LCM_CDLY 10 #define lcmWidth 20 #define lcmSoftOff() WriteCommandLCD(0x08,1) #define lcmOff() WriteCommandLCD(0x08,1);LCD_PW=0 #define lcmOn() WriteCommandLCD(0x0c,1);LCD_PW=1 #define lcmShftON() WriteCommandLCD(0x07,1) #define lcmShftOff() WriteCommandLCD(0x06,1) #define lcmCurOn() WriteCommandLCD(0x0e,1) #define lcmFlash() WriteCommandLCD(0x0d,1) #define lcmCurOff() WriteCommandLCD(0x0c,1) #define lcmPutChar(a) WriteDataLCD(a) #define lcmPutBCDByte(a) lcmPutBCDChar(a>>4);lcmPutBCDChar(a) #define lcmClear() \ WriteCommandLCD(0x01,1);Delay2Ms();WriteCommandLCD(0x03,1);Delay2Ms() #define lcmOffset(x,y) y&=1;x%=lcmWidth;if(y)x|=0x40 //LCD------------------------------------------------------------------------- //---------------------------------------------------------------------------- /**lcd***********************************************************************/ void _lcmCmdDelay(void){unsigned char i=_LCM_CDLY;while(i--){_nop_();}} void WriteDataLCD(unsigned char WDLCD){ ReadStatusLCD(); //檢測忙 LCD_Data = WDLCD; LCD_RS = 1; LCD_RW = 0; LCD_E = 0; //若振盪速度太高可以在這後加小的延時 LCD_E = 0; //延時 LCD_E = 1; } //寫指令 void WriteCommandLCD(unsigned char WCLCD,unsigned char BuysC){ //BuysC為0時忽 略忙檢測 if (BuysC) ReadStatusLCD(); //根據需要檢測忙 LCD_Data = WCLCD; LCD_RS = 0; LCD_RW = 0; LCD_E = 0; LCD_E = 0; LCD_E = 1; } //讀資料 unsigned char ReadDataLCD(void){ LCD_RS = 1; LCD_RW = 1; LCD_E = 0; LCD_E = 0; LCD_E = 1; return(LCD_Data); } //讀狀態 unsigned char ReadStatusLCD(void){ LCD_Data = 0xFF; LCD_RS = 0; LCD_RW = 1; LCD_E = 0; LCD_E = 0; LCD_E = 1; while (LCD_Data & Busy); //檢測忙信號 return(LCD_Data); } void LCDInit(void){ //LCM初始化 LCD_Data = 0; WriteCommandLCD(0x38,0); //三次顯示模式設置,不檢測忙信號 Delay5Ms(); WriteCommandLCD(0x38,0); Delay5Ms(); WriteCommandLCD(0x38,0); Delay5Ms(); Delay1Ms(); WriteCommandLCD(0x38,1); //顯示模式設置,開始要求每次檢測忙信號 WriteCommandLCD(0x08,1); //關閉顯示 WriteCommandLCD(0x01,1); //顯示清除 WriteCommandLCD(0x06,1); // 顯示游標移動設置 // WriteCommandLCD(0x07,1); // 顯示游標移動設置 WriteCommandLCD(0x0C,1); // 顯示開及游標設置 _lcmCmdDelay(); } //按指定位置顯示一個字 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){ lcmOffset(X,Y); //限制X不能大於width,Y不能大於1,當要顯示第二行時位址碼+0x40; X |= 0x80; // 算出指令碼 WriteCommandLCD(X, 0); //這裡不檢測忙信號,發送位址碼 WriteDataLCD(DData); } /* //按指定位置顯示一個BCD字 void DisplayBCDChar(unsigned char X, unsigned char Y, unsigned char DData){ lcmOffset(X,Y); X |= 0x80; DData&=0xf; if(DData>9){DData=DData+55;}else{DData=DData+48;} //Adjust to ASCII WriteCommandLCD(X, 0); //這裡不檢測忙信號,發送位址碼 WriteDataLCD(DData); } */ void lcmPutBCDChar(unsigned char DData){ DData&=0xf; if(DData>9){DData=DData+55;}else{DData=DData+48;}; lcmPutChar(DData); } //按指定位置顯示一串字串 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){ unsigned char ListLength; ListLength = 0; Y &= 0x1; X=X%20; //限制X不能大於20,Y不能大於1 while (DData[ListLength]>=0x20) //若到達字串尾則退出 { if (X <= 20) //X坐標應小於0xF { DisplayOneChar(X, Y, DData[ListLength]); //顯示單個字 ListLength++; X++; } } } void lcmGoTo(unsigned char x,unsigned char y){ y&=1;x%=lcmWidth;if(y)x|=0x40;x|=0x80;WriteCommandLCD(x,1); } //void dlyT0Rst(void){TCON=0x40;TL0=0;TH0=0;TMOD=0x1|(TMOD&0xf);TCON=0x50;} void dlyT0Rst(void){TCON=0x40;TL0=0;TH0=0;TCON=0x50;} #define dylStopT0() TCON=0x40; #define _dyyLoopByT0(a,b,c) do{if(TH0>a){if((TL0>c)||(TH0>b)) break;}_nop_();_nop_();}while(1);TCON=0x40 void Delay1Ms(void){//using T0 // TL0=0;TH0=0;TMOD=0x1|(TMOD&0xf);TCON=0x50; dlyT0Rst(); _dyyLoopByT0(2,3,150); // 256*3 + 150. max to 256 *4 } void Delay2Ms(void){//using T0 dlyT0Rst(); _dyyLoopByT0(6,7,48); // 256*7 + 48. max to 256 *8 } //5ms延時 void Delay5Ms(void){ dlyT0Rst(); _dyyLoopByT0(17,18,0); // 256*18 + 232. max to 256 *4 } //400ms延時 void Delay400Ms(void){ unsigned char b; for(b=0;b<80;b++){dlyT0Rst();_dyyLoopByT0(17,18,0);} } void DelayXms(int delay){ unsigned int a; for(a=0;a<delay;a++){ dlyT0Rst();_dyyLoopByT0(2,3,120); // 256*3 + 200. max to 256 *4 } } /------------------------- #ifndef _wdtclear #define _wdtclear() _nop_(); #endif #define waitSerialTx() while (!TI){_wdtclear();} unsigned char data _wlsPutcMode=0; /* char putchar(char c){ if(_wlsPutcMode==0){ //Direct To Serial _putchardefault: waitSerialTx();TI=0;return (SBUF = c); }else{ if(_wlsPutcMode==1){ //To LCM // // return(1); }else{ if(_wlsPutcMode==2){ //To Serial CR LF if (c == '\n'){waitSerialTx();TI = 0;SBUF = 0x0d;} waitSerialTx();TI=0;return (SBUF = c); }else{goto _putchardefault;}// Default Direct To Serial } } } */ char putchar(char c){ switch(_wlsPutcMode){ case 1://To LCM lcmPutChar(c); break; case 2: //CR-LF To Serial if (c=='\n'){waitSerialTx();TI=0;SBUF=0x0d;} case 0: //Direct To Serial default : waitSerialTx();TI=0;return (SBUF = c); break; } return(1); } -- ~~~ 一切的正義在曼尼大神的正義之前均無足輕重 在海賊的砲口下唯有曼尼大神的正義可以私下研究 ~~~ -= WolfLord =- BM4GMR - A23203 - -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.46.201.106
gjz780628:想請問一下 我使用UV3先編譯您的程式碼 09/17 02:00
gjz780628:但是有錯誤 小弟不才= = 再請大大指教 09/17 02:01
gjz780628:可以順便請教大大有沒有組合語言的LCD練習程式 09/17 02:01
gjz780628:十分不好意思麻煩您 09/17 02:02
WolfLord:編譯會有錯是這只是一個叫做LCD.C而以,前麵的DEFINE是 09/17 02:51
WolfLord:PORJEXT.H上貼過來的。您需要完整得MAIN與其他定義 09/17 02:52
WolfLord:你要ASM的話,我有一個別人的範例可以計給你,請站內信 09/17 02:54
WolfLord:給我你的EMAIL(別人的程式我不可以公開張貼) 09/17 02:54
easypro:這..隨便一本教單晶片的都會有吧 就算指令不同控制大都是 09/17 08:57
easypro:類似方式 09/17 08:57
WolfLord:不能同一樓上更多 ^^;; 我覺得發問同學只是想精簡流程 09/17 13:39
WolfLord:卻沒弄清楚LCM的啟用流程精簡過頭了,因此建議稍微花點 09/17 13:39
WolfLord:時間看範例的流程,不要只是忙著CON看看 09/17 13:40