找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 6947|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

lcd12864繪圖功能實(shí)現(xiàn)驅(qū)動(dòng)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:242836 發(fā)表于 2017-12-15 17:47 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
一下是用12864 繪制出的圖


本文作者:林子木
本人學(xué)歷有限,如有紕漏請(qǐng)見諒!

的補(bǔ)充,是基于430單片機(jī)的實(shí)現(xiàn),很簡(jiǎn)單的可以移植到51單片機(jī)上去

如果想具體的實(shí)現(xiàn),請(qǐng)先看上面網(wǎng)址的文章

以下是"Lcd_12664.h"聲明代碼,注意一定需要,或者也可以寫在.c的前面或者,后者函數(shù)不能調(diào)用前者的函數(shù)
voidDelay_1ms(void);
voidDelay(unsignedintn);
voidWrite_Cmd(unsignedcharcod);
voidWrite_Data(unsignedchardat);
voidIni_Lcd(void);
voidDisp_HZ(unsignedcharaddr,constunsignedchar*pt,unsignedcharnum);
voidDisp_ND(unsignedcharaddr,unsignedint thickness);
voidDraw_TX(unsignedcharYaddr,unsignedcharXaddr,constunsignedchar*dp);
voidDraw_PM(constunsignedchar*ptr);
voidDraw_PM_CLR(void);
voidDraw_Point(unsignedcharx,unsignedchary);
unsignedchar Read_Data(void);
unsignedintRead_Add(unsignedcharx,unsignedchary);

Lcd_12664.c

以下標(biāo)注為紅色的,是我們需要注意的地方

#include<msp430x14x.h>
#include"subfuncs.h"
typedefunsignedcharuchar;
typedefunsignedint uint;

externconstunsignedcharshuzi_table[];

#defineLCD_DataIn P4DIR=0x00 //數(shù)據(jù)口方向設(shè)置為輸入
#defineLCD_DataOut  P4DIR=0xff //數(shù)據(jù)口方向設(shè)置為輸出
#defineLCD2MCU_Data P4IN
#defineMCU2LCD_Data P4OUT
#defineLCD_CMDOut P3DIR|=0x07 //P3口的低三位設(shè)置為輸出
#defineLCD_RS_H P3OUT|=BIT0 //P3.0
#defineLCD_RS_L P3OUT&=~BIT0 //P3.0
#defineLCD_RW_H P3OUT|=BIT1 //P3.1
#defineLCD_RW_L P3OUT&=~BIT1 //P3.1
#defineLCD_EN_H P3OUT|=BIT2 //P3.2
#defineLCD_EN_L P3OUT&=~BIT2 //P3.2

/*******************************************
函數(shù)名稱:Delay_1ms
功 能:延時(shí)約1ms的時(shí)間
參 數(shù):無
返回值 :無
********************************************/
voidDelay_1ms(void)
{
uchari;

for(i=150;i>0;i--) _NOP();
}
/*******************************************
函數(shù)名稱:Delay_Nms
功 能:延時(shí)N個(gè)1ms的時(shí)間
參 數(shù):n--延時(shí)長(zhǎng)度
返回值 :無
********************************************/
voidDelay_Nms(uintn)
{
uinti;

for(i=n;i>0;i--) Delay_1ms();
}
/*******************************************
函數(shù)名稱:Write_Cmd
功 能:向液晶中寫控制命令
參 數(shù):cmd--控制命令
返回值 :無
********************************************/
voidWrite_Cmd(ucharcmd)
{
ucharlcdtemp=0;

LCD_RS_L;
LCD_RW_H;
LCD_DataIn;
do //判忙
{
LCD_EN_H;
_NOP();
lcdtemp=LCD2MCU_Data;
LCD_EN_L;

}
while(lcdtemp&0x80);

LCD_DataOut;
LCD_RW_L;
MCU2LCD_Data=cmd;
LCD_EN_H;
_NOP();
LCD_EN_L;
}
/*******************************************
函數(shù)名稱:Write_Data
功 能:向液晶中寫顯示數(shù)據(jù)
參 數(shù):dat--顯示數(shù)據(jù)
返回值 :無
********************************************/
void Write_Data(uchardat)
{
ucharlcdtemp=0;

LCD_RS_L;
LCD_RW_H;
LCD_DataIn;
do //判忙
{
LCD_EN_H;
_NOP();
lcdtemp=LCD2MCU_Data;
LCD_EN_L;
}
while(lcdtemp&0x80);

LCD_DataOut;
LCD_RS_H;
LCD_RW_L;

MCU2LCD_Data=dat;
LCD_EN_H;
_NOP();
LCD_EN_L;
}

/*******************************************
函數(shù)名稱:Ini_Lcd
功 能:初始化液晶模塊
參 數(shù):無
返回值 :無
********************************************/
voidIni_Lcd(void)
{
LCD_CMDOut; //液晶控制端口設(shè)置為輸出

Delay_Nms(500);
Write_Cmd(0x30);  //基本指令集
Delay_1ms();
Write_Cmd(0x02);  // 地址歸位
Delay_1ms();
Write_Cmd(0x0c);  //整體顯示打開,游標(biāo)關(guān)閉
Delay_1ms();
Write_Cmd(0x01);  //清除顯示
Delay_1ms();
Write_Cmd(0x06);  //游標(biāo)右移
Delay_1ms();
Write_Cmd(0x80);  //設(shè)定顯示的起始地址
}
/*******************************************
函數(shù)名稱:Disp_HZ
功 能:控制液晶顯示漢字
參 數(shù):addr--顯示位置的首地址
pt--指向顯示數(shù)據(jù)的指針
num--顯示字符個(gè)數(shù)
返回值 :無
********************************************/
voidDisp_HZ(ucharaddr,constuchar*pt,ucharnum)
{
uchari;

Write_Cmd(addr);
for(i=0;i<(num*2);i++)
Write_Data(*(pt++));
}
/*******************************************
函數(shù)名稱:Clear_GDRAM
功 能:清除液晶GDRAM中的隨機(jī)數(shù)據(jù)
參 數(shù):無
返回值 :無
********************************************/
voidClear_GDRAM(void)
{
uchari,j,k;

Write_Cmd(0x34); //打開擴(kuò)展指令集
i=0x80;
for(j=0;j<32;j++)
{
Write_Cmd(i++);
Write_Cmd(0x80);
for(k=0;k<16;k++)
{
Write_Data(0x00);
}
}
i=0x80;
for(j=0;j<32;j++)
{
Write_Cmd(i++);
Write_Cmd(0x88);
for(k=0;k<16;k++)
{
Write_Data(0x00);
}
}
Write_Cmd(0x30); //回到基本指令集
}
/*******************************************
函數(shù)名稱:Draw_PM
功 能:在整個(gè)液晶屏幕上畫圖
參 數(shù):無
返回值 :無
********************************************/
voidDraw_PM(constuchar*ptr)
{

uchari,j,k;

Write_Cmd(0x34); //打開擴(kuò)展指令集
i=0x80;
for(j=0;j<32;j++)//32Y(Y是以位位單位,所以是32)32*2
{ //X是以word為單位的 所以為16
Write_Cmd(i++);
//寫入Y的地址0x80 代表0//RWRSDB7DB6DB5DB4DB3DB2DB1DB0
//L  L H AC6AC5AC4AC3AC2AC1AC0
Write_Cmd(0x80); // 寫入X的地址
for(k=0;k<16;k++)//16*8=128
{
Write_Data(*ptr++);//寫入數(shù)據(jù)(8位)
}

}
i=0x80;
for(j=0;j<32;j++)
{
Write_Cmd(i++);
Write_Cmd(0x88);
for(k=0;k<16;k++)
{
Write_Data(*ptr++);
}

}
Write_Cmd(0x36); //打開繪圖顯示
Write_Cmd(0x30); //回到基本指令集
}
/*******************************************
函數(shù)名稱:Draw_TX
功 能:顯示一個(gè)16*16大小的圖形
參 數(shù):Yaddr--Y地址
Xaddr--X地址
dp--指向圖形數(shù)據(jù)存放地址的指針
返回值 :無
********************************************/
voidDraw_TX(ucharYaddr,ucharXaddr,constuchar*dp)
{
ucharj;
uchark=0;

Write_Cmd(0x01); //清屏,只能清除DDRAM
Write_Cmd(0x34); //使用擴(kuò)展指令集,關(guān)閉繪圖顯示
for(j=0;j<16;j++)
{
Write_Cmd(Yaddr++); //Y地址
Write_Cmd(Xaddr); //X地址
Write_Data(dp[k++]);
Write_Data(dp[k++]);
}
Write_Cmd(0x36); //打開繪圖顯示
Write_Cmd(0x30); //回到基本指令集模式
}

/*******************************************
函數(shù)名稱:Draw_Point
功 能:在整個(gè)液晶屏幕上畫圖
參 數(shù):無
返回值 :無
********************************************/
voidDraw_Point(unsignedcharx,unsignedchary)
{
uintdat=0; //讀取需要寫入的兩個(gè)字節(jié)的值
dat=Read_Add(x,y); //注意,因?yàn)閞ead 或者 write之后 地址指針AC會(huì)自動(dòng)加
+ 想對(duì)莫一塊進(jìn)行讀和寫的工作,就需要重新寫入地址
if(x>127)x=127;
if(y>63) y=63;
uchary_Byte,y_bit,x_Byte,x_bit;
y_Byte=y/32; //0:上半屏幕 1:下半屏幕
y_bit=y%32; //y的行號(hào)
x_Byte=x/16; //x的列號(hào)
x_bit=x%16; //x的位
Write_Cmd(0x34); //打開擴(kuò)展指令集
Write_Cmd(0x80+31-y_bit); //因?yàn)橐壕是從上往下的,這里簡(jiǎn)單的轉(zhuǎn)換成從下
往上
Write_Cmd(0x80+x_Byte+(1-y_Byte)*8);//(1-y_Byte)*8 代表上下半頁
if(x_bit>7) //因?yàn)槭堑刂肥莾蓚(gè)字節(jié),但是寫入還是一個(gè)一個(gè)字節(jié)
的,所以需要判斷
{
Write_Data(0x00|((dat>>8)&0xff));
Write_Data((0x80>>x_bit%8)|(dat&0xff));//因?yàn)橐壕э@示,高位在前
} //如如果想把第八位點(diǎn)亮 直接寫
0x80 那么會(huì) 成100000000
else //而不是我們要的從左到右的 第八
位 00000001 所以需要轉(zhuǎn)換下
{
Write_Data((0x80>>x_bit%8)|((dat>>8)&0xff));
Write_Data(0x00|(dat&0xff));
}
Write_Cmd(0x36); //打開繪圖顯示
Write_Cmd(0x30); //回到基本指令集
}
/*******************************************
函數(shù)名稱:Read_Data
功 能:讀取液晶屏幕的值
參 數(shù):無
返回值 :無
********************************************/

uchar Read_Data(void)
{
ucharlcdtemp=0;
uchardat=0;

LCD_RS_L;
LCD_RW_H;
LCD_DataIn; //設(shè)置為輸入方式
do //判忙
{
LCD_EN_H;
_NOP();
lcdtemp=LCD2MCU_Data;
LCD_EN_L;
}
while(lcdtemp&0x80);

LCD_RS_H; //置高
LCD_RW_H; //置高
_NOP();

LCD_EN_H; //使能
_NOP();
dat=LCD2MCU_Data;//讀數(shù)據(jù)
_NOP();
LCD_EN_L;
return(dat);
}

/*******************************************
函數(shù)名稱:Read_Add
功 能:讀取液晶屏幕莫一點(diǎn)的值
參 數(shù):無
返回值 :無
********************************************/

unsignedintRead_Add(unsignedcharx,unsignedchary)
{
unsignedintdat;
uchardat_H=0,dat_L=0;
if(x>127)x=127;
if(y>63) y=63;
uchary_Byte,y_bit,x_Byte,x_bit;
y_Byte=y/32; //0:上半屏幕 1:下半屏幕
y_bit=y%32; //y的行號(hào)
x_Byte=x/16; //x的列號(hào)
x_bit=x%16; //x的位
Write_Cmd(0x34); //打開擴(kuò)展指令集
Write_Cmd(0x36); //打開繪圖顯示
Write_Cmd(0x80+31-y_bit);
Write_Cmd(0x80+x_Byte+(1-y_Byte)*8);

Read_Data(); //
Read_Data(); //
RReeaadd__DDaattaa(());; ////注意:讀操作要先執(zhí)行有一個(gè)空讀命令

dat_H=Read_Data();
dat_L=Read_Data();
Write_Cmd(0x30); //回到基本指令集
dat=dat_H*0x0100+dat_L;
returndat;
}

完整的pdf格式文檔51黑下載地址:
lcd12864-繪圖功能實(shí)現(xiàn)驅(qū)動(dòng).pdf (2.46 MB, 下載次數(shù): 93)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:137543 發(fā)表于 2018-6-19 23:45 | 只看該作者
謝謝,哈哈
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表