作者WolfLord (呆呆小狼)
看板ASM
標題Re: [問題] 請教有關於LCD控制問題
時間Fri Sep 17 01:40:44 2010
這是我一篇用來教學的範例,使用的是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