欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
lcd12864液晶驅動源碼,獨創中英文混合輸出 控制器7920
[打印本頁]
作者:
51黑電子迷
時間:
2017-1-14 17:55
標題:
lcd12864液晶驅動源碼,獨創中英文混合輸出 控制器7920
控制器7920
代碼沒啥好說,我盡量多寫了注釋,播放動畫也很流暢的
亮點就是支持中英文混合輸出,其他沒啥
昨天發現座的公交車上用的也是這種12864 ,顯示溫度和時間...
完整源碼下載:
lcd12864源碼.rar
(7.58 KB, 下載次數: 32)
2017-2-9 22:24 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
c語言程序:
#ifndef _LCD12864_H
#define _LCD12864_H
#include "my51.h"
#define LCD_dataBus P0 //總線
sbit LCD_EN = P3^4; //使能控制
sbit LCD_RS = P3^5; //數據_命令選擇端
sbit LCD_RW = P3^6; //讀寫控制
sbit LCD_PSB= P3^7; //串并選擇,H并行,L串行
extern bool bShowPicFlag; //繪圖時圖像顯示控制(僅控制GDRAM)
/*************************基本功能函數*********************************************/
extern void LCD12864_init(); //初始化,必須置頂調用
extern void LCD12864_setPos(u8 row, u8 cols); //設置光標位置
extern void LCD12864_writeByte(u8 dat); //寫一個字節
extern void LCD12864_writeCmd(u8 cmd); //寫指令
extern u8 LCD12864_readByte(); //讀一個字節ram
extern u8 LCD12864_readIR(); //讀暫存器
extern bool LCD12864_isBusy(); //判忙
/*************************調用基本字庫顯示文字**************************************/
//獨創支持全角半角字符及中英混合的字符串,或字符串的子串,起始行號row(0-3)和列坐標cols(0-15),寫滿屏幕為止
//行號4-7行是滾動區
extern void LCD12864_writeData(u8 row, u8 cols,u8* pBuf,u8 dataSize);//寫一堆數據
extern void LCD12864_earseSomeDDRam(u8 row,u8 cols,u8 dataSize); //擦除N字節DDRam
/*************************用戶自定義圖標字體****************************************/
extern void LCD12864_writeCGRAM(u8 userRamNum,u8* pCGRAM_userCode); //寫自定義圖標字體
extern void LCD12864_showCGRAM(u8 row,u8 cols,u8 num) ; //顯示自定義圖標字體,row(0-3),cols(0-15)
extern void LCD12864_clearCGRAM(u8 CGRAM_groupNum) ; //CGRAM清零(初始化也可清0)
/*************************圖像顯示功能函數**********************************************/
extern void LCD12864_showGDRAM(bool bShowImage); //GDRAM繪圖顯示開關
extern void LCD12864_clearGDRAM(); //液晶整個可視區的GDRAM快速清0
//前4參數:起始點x(0-7)位址,y(0-63)坐標,要顯示的寬度(1-128)和高度(1-64)[可顯示從圖像左上角開始的部分區域]
//后4參數:圖像代碼地址,圖像本身的寬度(1-128)和高度(1-64), 反白(true反白,false不反白)
//畫圖填充GDRAM ,注:顯示的區域或者圖像本身寬度必須是8的倍數
extern u8 LCD12864_drawGDRAM(u8 x,u8 y,u8 width,u8 height,u8 *pImageCode,u8 imageWidth,u8 imageHight,bool bReverse);
extern void LCD12864_drawDot(u8 x,u8 y,u8 flag); //打點,x(0-127),y(0-63),flag(0正常,1反白,2清0)
extern bool LCD12864_drawXYLine(u8 x1, u8 y1,u8 x2, u8 y2,u8 flag); //畫水平或垂直直線
extern void LCD12864_drawAnyLine(u8 x1, u8 y1,u8 x2, u8 y2,u8 flag) ; //畫任意直線
extern void LCD12864_drawRectangle(u8 x,u8 y ,u8 width,u8 height,u8 flag);//畫矩形
extern void LCD12864_drawFillRect(u8 x,u8 y, u8 width,u8 hight,u8 flag); //填充矩形,可對矩形區反白或清0
extern void LCD12864_drawVerticalSquare(u8 x,u8 y,u8 r,u8 flag) ; //畫站立的正方形
extern void LCD12864_drawCircle(u8 x0,u8 y0,u8 r,u8 flag); //畫圓
//打點法全屏畫圖有點慢了,打點法反白矩形區還可以,建議矩形范圍小一些,不然比較慢
//打點法效果最好,因為文字的矩形區比較小,速度很快
//不過繪圖法反白文字效率高,flash空間充裕的建議用繪圖法
/***************************全屏滾動*******************************************/
//需要滾動時,用LCD12864_writeScrollData()函數,參數和LCD12864_writeData()一樣
extern void LCD12864_writeScrollData(u8 row,u8 cols,u8* pBuf,u8 dataSize);//寫數據 (滾動模式)
extern void LCD12864_setScrollPos(u8 row, u8 cols); //設置滾動模式的坐標
extern void LCD12864_showScrollCGRAM(u8 row,u8 cols,u8 CGRAM_groupNum);//用于CGRAM滾動顯示前執行
extern void LCD12864_startScroll(u8 scrollNum,u16 delay_ms); //滾動開始
#endif
復制代碼
#include "lcd12864.h"
//圖像與文字,圖像與用戶圖標,像素重合時是異或關系
//文字與用戶圖標是覆蓋關系
bool bShowPicFlag=false; //繪圖時圖像顯示控制
/*
u8 LCD12864_table[]={"123456789"};
*/
void LCD12864_drawFillRect(u8 x,u8 y, u8 width,u8 hight,u8 flag)//填充任意位置的整個矩形
{//矩形起始坐標x(0-127),y(0-63),寬(1-128)高(1-64),flag有3種值,0正常填充,1反色,2清0
u8 i=0;
u8 j=0;
if(0==width||0==hight) //矩形寬度或高度為0時返回
{
return ;
}
if( (x+width>128 ||(y+hight)>64) )
{
led2=0;
return;
}
for(j=0;j<hight;j++)
{
for(i=0;i<width;i++)
{
LCD12864_drawDot(x+i, y+j,flag);
}
}
}
void LCD12864_drawRectangle(u8 x,u8 y, u8 width,u8 hight,u8 flag)//畫矩形
{ //矩形起始坐標x(0-127),y(0-63),寬度(1-128)和高度(1-64) flag有3種值,0正常寫1,1反色,2清0
if(0==width||0==hight) //矩形寬度或高度為0時返回
{
return ;
}
width--;hight--;
LCD12864_drawXYLine(x, y,x+width, y, flag);
LCD12864_drawXYLine(x+width, y,x+width, y+hight, flag);
LCD12864_drawXYLine(x, y,x, y+hight, flag);
LCD12864_drawXYLine(x, y+hight,x+width, y+hight, flag);
}
bool LCD12864_drawXYLine(u8 x1,u8 y1, u8 x2, u8 y2, u8 flag)//畫水平或垂直直線
{ //起始點坐標和終點坐標,x(0-127),y(0-63), flag有3種值,0正常寫1,1反色,2清0
u8 n=0;
if(flag>2|| x1>127||x2>127||y1>63||y2>63)
{
return false;
}
if(x1==x2)
{
for(n=0;n<abs(y2-y1)+1;n++)
{
LCD12864_drawDot( x1,y1+(y2>=y1?n:-n) ,flag);
}
}
if(y1==y2)
{
for(n=0;n<abs(x2-x1)+1;n++)
{
LCD12864_drawDot(x1+(x2>=x1?n:-n),y1,flag) ;
}
}
return true;
}
void LCD12864_drawCircle(u8 x0,u8 y0,u8 r,u8 flag)
{
s8 a,b;
s8 di;
if(r>31 ||r==0) return; //參數過濾,次液晶顯示的最大圓半徑為31
a=0;
b=r;
di=3-2*r; //判斷下個點位置的標志
while(a<=b)
{
LCD12864_drawDot(x0-b,y0-a,flag); //3
LCD12864_drawDot(x0+b,y0-a,flag); //0
LCD12864_drawDot(x0-a,y0+b,flag); //1
LCD12864_drawDot(x0-b,y0-a,flag); //7
LCD12864_drawDot(x0-a,y0-b,flag); //2
LCD12864_drawDot(x0+b,y0+a,flag); //4
LCD12864_drawDot(x0+a,y0-b,flag); //5
LCD12864_drawDot(x0+a,y0+b,flag); //6
LCD12864_drawDot(x0-b,y0+a,flag);
a++;
//使用Bresenham算法畫圓
if(di<0)
di +=4*a+6;
else
{
di +=10+4*(a-b);
b--;
}
LCD12864_drawDot(x0+a,y0+b,flag);
}
}
void LCD12864_drawVerticalSquare(u8 x,u8 y,u8 r,u8 flag) //畫站立的正方形
{
u8 a,b;
float c=0;
a = 0;
b = r;
c = 3 - 2*r;
while(a < b)
{
LCD12864_drawDot(x+a,y+b,flag);
LCD12864_drawDot(x-a,y+b,flag);
LCD12864_drawDot(x+a,y-b,flag);
LCD12864_drawDot(x-a,y-b,flag);
LCD12864_drawDot(x+b,y+a,flag);
LCD12864_drawDot(x-b,y+a,flag);
LCD12864_drawDot(x+b,y-a,flag);
LCD12864_drawDot(x-b,y-a,flag);
if(c < 0)
{
c = c+4*a + 6;
}
else
{
c= c + 4*(a - b) + 10;
b-=1;
}
a = a + 1; //控制打點間隔
}
if(a == b)
{
LCD12864_drawDot(x+a,y+b,flag);
LCD12864_drawDot(x-a,y+b,flag);
LCD12864_drawDot(x+a,y-b,flag);
LCD12864_drawDot(x-a,y+b,flag);
LCD12864_drawDot(x+b,y+a,flag);
LCD12864_drawDot(x-b,y+a,flag);
LCD12864_drawDot(x+b,y-a,flag);
LCD12864_drawDot(x-b,y-a,flag);
}
}
void LCD12864_drawAnyLine(u8 StartX, u8 StartY,u8 EndX, u8 EndY, u8 flag) //畫任意直線
{
u8 t, distance ; /*根據屏幕大小改變變量類型(如改為int型)*/
s16 x = 0 , y = 0 ;
s8 incx, incy, dx, dy ;
if((StartX==EndX) ||(StartY==EndY))
{
LCD12864_drawXYLine(StartX,StartY,EndX,EndY,flag);
return;
}
dx = EndX - StartX ;
dy = EndY - StartY ;
incx = dx > 0 ?1:-1;
incy = dy > 0 ?1:-1;
dx = abs( dx );
dy = abs( dy );
if( dx > dy )
{
distance = dx ;
}
else
{
distance = dy ;
}
LCD12864_drawDot( StartX, StartY, flag ) ; //反白補點
for( t = 0 ; t <= distance+1 ; t++ )
{
LCD12864_drawDot( StartX, StartY, flag ) ;
x += dx ;
y += dy ;
if( x > distance )
{
x -= distance ;
StartX += incx ;
}
if( y > distance )
{
y -= distance ;
StartY += incy ;
}
}
}
void LCD12864_drawDot(u8 x, u8 y,u8 flag) //畫點,0打點,1反色,2清0
{ //x(0-127),y(0-63),flag有3種值,0正常寫1,1反色,2清0
u8 x_word=0; //水平(0-127)個像素中的哪個字,一字16位
u8 x_mode=0; //取余
u8 y_part=0;
u8 y_bit=0;
u8 tempH=0;
u8 tempL=0;
x_word=x>>4; //在哪一個字(0-7) ,x_word=x/16
x_mode=x&0x0f; //在該字的哪一位 ,x_mode= x%16
y_part=y>>5; //在哪個屏0或1 ,y_part=y/32
y_bit= y&0x1f; //垂直方向,y_bit范圍(0-31),y_bit=y%32
bShowPicFlag?LCD12864_writeCmd(0x36):LCD12864_writeCmd(0x34);
LCD12864_writeCmd(0x80+y_bit); //垂直坐標
LCD12864_writeCmd(0x80+8*y_part+x_word); //水平位址
LCD12864_readByte();
tempH=LCD12864_readByte(); //先將該字16位數據保存
tempL= LCD12864_readByte();
LCD12864_writeCmd(0x80+y_bit); //重設地址,因為AC計數器變了
LCD12864_writeCmd(0x80+8*y_part+x_word); //水平位址
if(0==flag) //不反白,打1,
{
if(x_mode<8) //如果x_mode小于8,說明點應位于該字的左邊高8位中
{
LCD12864_writeByte( tempH | bit(7- x_mode) );
//LCD12864_writeByte(tempL);
}
else
{
//LCD12864_writeByte(tempH);
LCD12864_readByte(); //讓AC走半步
LCD12864_writeByte(tempL|bit(15-x_mode));
}
}
else if(1==flag) //反白,該點與原來的狀態相反
{
if(x_mode<8) //如果x_mode小于8,說明點應位于該字的左邊高8位中
{
if(tempH & bit(7- x_mode)) //原來是1
{
LCD12864_writeByte( tempH&~bit(7- x_mode) ); //寫0
}
else //原來是0
{
LCD12864_writeByte( tempH | bit(7- x_mode) ); //寫1
}
}
else
{
LCD12864_readByte(); //讓AC走半字
if(tempL& bit(15-x_mode)) //原來是1的寫0
{
LCD12864_writeByte(tempL&~bit(15-x_mode)); //寫0
}
else
{
LCD12864_writeByte(tempL|bit(15-x_mode)); //寫0
}
}
}
else if(2==flag) //清0
{
if(x_mode<8) //如果x_mode小于8,說明點應位于該字的左邊高8位中
{
LCD12864_writeByte( tempH&~bit(7- x_mode) );
}
else
{
LCD12864_readByte(); //讓AC走半字
LCD12864_writeByte(tempL&~bit(15-x_mode));
}
}
}
void LCD12864_showGDRAM(bool bShowImage) //GDRAM圖像顯示開關
{
if(bShowImage) //開啟顯示
{
LCD12864_writeCmd(0x36);
LCD12864_writeCmd(0x30);
}
else //關閉顯示
{
LCD12864_writeCmd(0x34);
LCD12864_writeCmd(0x30);
}
}
//填充GDRAM
u8 LCD12864_drawGDRAM(u8 x,u8 y,u8 width,u8 height,u8* pImageCode,u8 imageWidth,u8 imageHight,bool bReverse)
{//前4參數:起始點x(0-7)位址,y(0-63)坐標,要顯示的寬度(1-128)和高度(1-64)[可顯示從圖像左上角開始的部分區域]
//后4參數:圖像代碼地址,圖像本身的寬度(1-128)和高度(1-64), 反白(true反白,false不反白)
u8 i=0;
u8 j=0;
if( height > imageHight ) //檢測顯示高度,寬度不檢測不會亂碼
{ //顯示的高度不能超過圖片本身高度
return 0x01; //也就是說可顯示圖像的部分區域(從圖像左上角開始的部分區域)
}
width>>=3; //像素寬度轉化為字節個數,所以width必須是8的整數倍
imageWidth>>=3; //像素寬度轉化為字節個數,所以width必須是8的整數倍
if(bShowPicFlag)
{
LCD12864_writeCmd(0x36); //改寫GDRAM時,開啟繪圖顯示,可防止動畫顯示時閃動
}
else
{
LCD12864_writeCmd(0x34); //改寫GDRAM時,關閉繪圖顯示
}
for(j=0;j<height;j++) //寫GDRAM
{
if(y+j>31) //地址變換
{
LCD12864_writeCmd(0x80+y+j-32); //垂直坐標
LCD12864_writeCmd(0x88+x); //水平位址
}
else
{
LCD12864_writeCmd(0x80+y+j);
LCD12864_writeCmd(0x80+x);
}
for(i=0;i<width;i++) //水平方向寫數據,帶反白控制
{
LCD12864_writeByte(bReverse?~pImageCode[imageWidth*j+i]:pImageCode[imageWidth*j+i]);
}
}
LCD12864_writeCmd(0x30);
return 0x02;
}
void LCD12864_clearGDRAM() //液晶可視區的繪圖GDRAM清0
{
u8 j=0;
u8 i=0;
LCD12864_writeCmd(0x34); //擴展指令
for(j=0;j<64;j++) //垂直方向地址手動增加,當j=64時清整個GDram
{ //我們只要清可視區的GDRAM就可以了
LCD12864_writeCmd(0x80+j); //y軸坐標
LCD12864_writeCmd(0x80); //x軸坐標
for(i=0;i<32;i++) //水平方向位址自動增加
{
LCD12864_writeByte(0x00);
}
}
LCD12864_writeCmd(0x30); //回到基本指令
}
/*--------------------------------CGRAM start----------------------------------------------*/
void LCD12864_clearCGRAM(u8 CGRAM_groupNum)//將用戶自定義編碼區CGRAM清0
{ //參數一是CGRAM的4組用戶空間組號碼(0~3) ,參數二是用戶自定義圖表或漢字的編碼
u8 i,addr=0;
bShowPicFlag?LCD12864_writeCmd(0x36):LCD12864_writeCmd(0x34);//擴展指令,繪圖開關保持
LCD12864_writeCmd(0x02); //SR等于0,允許設置卷動地址
LCD12864_writeCmd(0x30); //恢復為8位并行,基本指令集
addr=(CGRAM_groupNum<<4)|0x40; //將CGRAM空間號轉換為相應存儲地址
LCD12864_writeCmd(addr); //定位到該位址(用戶空間位址范圍0x40-0x7F共128字節)
for(i=0;i<16;i++) //將用戶自定義編碼寫入該16*16位元組空間
{
LCD12864_writeByte(0); //連續寫2個字節共16位
LCD12864_writeByte(0);
}
}
void LCD12864_writeScrollCGRAM(u8 CGRAM_groupNum, u8* pUserCode)//將用戶自定義編碼寫入CGRAM
{ //參數一是CGRAM的4組用戶空間組號碼(0~3) ,參數二是用戶自定義圖表或漢字的編碼
u8 i,addr=0;
if(bShowPicFlag)
{
LCD12864_writeCmd(0x36); //開啟繪圖顯示,可流暢播放動畫
}
else
{
LCD12864_writeCmd(0x34); //默認關閉繪圖顯示
}
LCD12864_writeCmd(0x02); //SR等于0,允許設置卷動地址
LCD12864_writeCmd(0x30); //恢復為8位并行,基本指令集
addr=(CGRAM_groupNum<<4)|0x40; //將CGRAM空間號轉換為相應存儲地址
LCD12864_writeCmd(addr); //定位到該位址(用戶空間位址范圍0x40-0x7F共128字節)
for(i=0;i<16;i++) //將用戶自定義編碼寫入該16*16位元組空間
{
LCD12864_writeByte(pUserCode[i*2]); //連續寫2個字節共16位
LCD12864_writeByte(pUserCode[i*2+1]);
}
}
void LCD12864_writeCGRAM(u8 CGRAM_groupNum, u8* pUserCode)//將用戶自定義編碼寫入CGRAM
{ //參數一是CGRAM的4組用戶空間組號碼(0~3) ,參數二是用戶自定義圖表或漢字的編碼
u8 i,addr=0;
if(bShowPicFlag)
{
LCD12864_writeCmd(0x36); //開啟繪圖顯示,可流暢播放動畫
}
else
{
LCD12864_writeCmd(0x34); //默認關閉繪圖顯示
}
LCD12864_writeCmd(0x02); //SR等于0,允許設置卷動地址
LCD12864_writeCmd(0x30); //恢復為8位并行,基本指令集
addr=(CGRAM_groupNum<<4)|0x40; //將CGRAM空間號轉換為相應存儲地址
LCD12864_writeCmd(addr); //定位到該位址(用戶空間位址范圍0x40-0x7F共128字節)
for(i=0;i<16;i++) //將用戶自定義編碼寫入該16*16位元組空間
{
LCD12864_writeByte(pUserCode[i*2]); //連續寫2個字節共16位
LCD12864_writeByte(pUserCode[i*2+1]);
}
}
void LCD12864_showScrollCGRAM(u8 row,u8 cols,u8 CGRAM_groupNum)//滾動CGRAM
{ //row(0-3), cols(0-15)
//第三個參數是用戶空間號碼(0~3共4組空間號碼),該號碼乘2就是它所對應的[調用用戶空間編碼]
LCD12864_setScrollPos(row,cols);
LCD12864_writeByte(0x00);//4組用戶空間的編碼的高字節都固定為0,我猜這是為和E文ASCII碼區分開
LCD12864_writeByte(CGRAM_groupNum*2); //對應編碼00h,02h,04h,06h
LCD12864_showCGRAM(row,cols,CGRAM_groupNum);
}
void LCD12864_showCGRAM(u8 row,u8 cols,u8 CGRAM_groupNum)//定位液晶光標,并顯示自定義內容
{ //row(0-3), cols(0-15)
//第三個參數是用戶空間號碼(0~3共4組空間號碼),該號碼乘2就是它所對應的[調用用戶空間編碼]
LCD12864_setPos(row,cols);
LCD12864_writeByte(0x00);//4組用戶空間的編碼的高字節都固定為0,我猜這是為和E文ASCII碼區分開
LCD12864_writeByte(CGRAM_groupNum*2); //對應編碼00h,02h,04h,06h
}
/*--------------------------------CGRAM end----------------------------------------------*/
/*--------------------------------DDRAM start----------------------------------------------*/
void LCD12864_earseSomeDDRam(u8 row,u8 cols,u8 dataSize) //擦除N個字節DDRam
{ //row(0-3),cols(0-15),如果起始地址是漢字的低字節,則會一同擦除漢字的高字節
LCD12864_setPos(row, cols); //定位
if(cols%2!=0) //如果從奇數列開始
{
LCD12864_readByte(); //空讀一次,讓位址指針移動半字
if(LCD12864_readByte()>127) //檢測高位是否是漢字碼
{
LCD12864_setPos(row, cols); //是漢字碼的話要擦除,不然要亂碼
LCD12864_writeByte(' '); //其實是寫空格,看不到了就等于擦除了
} //連續寫2個0的話是亂碼
}
while(dataSize--) //擦除
{
if(cols) //cols>0
{
if(0==cols%16) //如果一行滿了
{
row++; //準備將光標移到下一行
cols=0; //列坐標置于行首
LCD12864_setPos(row, cols); //設置新光標
}
}
LCD12864_writeByte(' '); //其實是寫空格,但為啥不寫0呢
cols++; //因為0與是CGRAM重碼了,寫2個0會亂碼的
}
}
/*****************************************************************************************
pBuf如果用來修飾字符串,dataSize=strlen(pBuf);
pBuf如果是一個字符數組,dataSize=sizeof(pBuf);
strlen()雖然也可以用來計算字符數組長度,但遇到'\0'時就會返回,不會再計算后面的其他字符
在VC中strlen()只能計算字符串長度,不能計算字符數組,否則編譯出錯
sizeof("你好5"),sizeof("你好56"),最終液晶光標位置是一樣的,故不要用sizeof計算字符串
*****************************************************************************************/
void LCD12864_writeData(u8 row,u8 cols,u8* pBuf,u8 dataSize)//寫數據
{ //支持全角半角字符及中英混合的字符串,也可寫入字符串的子串,(行坐標0~3,列坐標0~15)
u8 flag=0; //液晶低字節ram數據檢測標志,0不檢測
LCD12864_setPos(row, cols); //設置光標
if(cols%2!=0) //列號不為偶數(漢字在液晶上要偶對齊)
{ //要讓位址空移一個字節,執行下面這句讀操作后,效果是達到了
LCD12864_readByte();//但AC值沒變,我懷疑除了這個AC字型指針,另有一個標志位沒公開)
flag=1; //此時需要檢測液晶低位字節ram
} //因為高位字節現在可能是漢字碼
while(dataSize--) //循環處理目標字節流
{
if(0==cols%2) //偶對齊時,對于ram高字節
{
if(*pBuf>127) //如果寫入ram的高字節是漢字碼
{
flag=0; //下一次不要檢測低字節,因為肯定是漢字了
}
else //如果高字節是半角字符
{
flag=1; //若在低字節ram寫入漢字就亂碼了,故檢測
}
}
if(cols%2!=0) //對于液晶低字節
{
if(flag) //如果要檢測低字節
{
if(*pBuf>127) //如果低字節是漢字碼
{
LCD12864_writeByte(0x20); //插入一個空格
cols++; //字節計數器++
flag=0; //清檢測標志
}
}
}
if(cols) //行尾檢測
{
if(0==cols%16) //如果一行滿了
{
row++; //準備將光標移到下一行
cols=0; //列坐標置于行首
LCD12864_setPos(row, cols); //設置新位址
}
}
LCD12864_writeByte(*pBuf++); //終于可以寫數據了
cols++; //列號累加
}
}
//滾屏模式的寫數據函數
void LCD12864_writeScrollData(u8 row,u8 cols,u8* pBuf,u8 dataSize)//寫數據,卷動模式
{ //支持全角半角字符及中英混合的字符串,也可寫入字符串的子串,(行坐標0~3,列坐標0~15)
u8 flag=0; //液晶低字節ram數據檢測標志,0不檢測
LCD12864_writeData(row,cols,pBuf,dataSize);
LCD12864_setScrollPos(row, cols); //設置光標
if(cols%2!=0) //列號不為偶數(漢字在液晶上要偶對齊)
{ //要讓位址空移一個字節,執行下面這句讀操作后,效果是達到了
LCD12864_readByte();//但AC值沒變,我懷疑除了這個AC字型指針,另有一個標志位沒公開)
flag=1; //此時需要檢測液晶低位字節ram
} //因為高位字節現在可能是漢字碼
while(dataSize--) //循環處理目標字節流
{
if(0==cols%2) //偶對齊時,對于ram高字節
{
if(*pBuf>127) //如果寫入ram的高字節是漢字碼
{
flag=0; //下一次不要檢測低字節,因為肯定是漢字了
}
else //如果高字節是半角字符
{
flag=1; //若在低字節ram寫入漢字就亂碼了,故檢測
}
}
if(cols%2!=0) //對于液晶低字節
{
if(flag) //如果要檢測低字節
{
if(*pBuf>127) //如果低字節是漢字碼
{
LCD12864_writeByte(0x20); //插入一個空格
cols++; //字節計數器++
flag=0; //清檢測標志
}
}
}
if(cols) //行尾檢測
{
if(0==cols%16) //如果一行滿了
{
row++; //準備將光標移到下一行
cols=0; //列坐標置于行首
LCD12864_setScrollPos(row, cols); //設置新位址
}
}
LCD12864_writeByte(*pBuf++); //終于可以寫數據了
cols++; //列號累加
}
}
void LCD12864_startScroll(u8 scrollNum,u16 delay_ms) //滾動
{ //scrollNum建議值為64
u8 i;
LCD12864_writeCmd(0x34);
LCD12864_writeCmd(0x03);
for(i=0x40;i<0x40+scrollNum;i++)
{
LCD12864_writeCmd(i); //設置卷動地址
delayms(delay_ms); //實際使用時建議用定時器處理
}
LCD12864_writeCmd(0x40); //補滾一行
LCD12864_writeCmd(0x30);
}
void LCD12864_setScrollPos(u8 row, u8 cols) //設置光標位置 ,卷動模式
{ //row行坐標0~3
u8 newPos=0; //cols列坐標0~15
switch(row)
{
case 0:
{
row=0xa8;
}
break;
case 1:
{
row=0xb8;
}
break;
case 2:
{
row=0xa0;
}
break;
case 3:
{
row=0xb0;
}
break;
default: //如果需要檢測行坐標范圍,可在這里加代碼
break;
}
newPos=row+cols/2; //液晶寫指令坐標只能8級,我的函數中列坐標是16級的,支持半角全角混合
LCD12864_writeCmd(newPos);
}
void LCD12864_setPos(u8 row, u8 cols) //設置光標位置
{ //row行坐標0~3
u8 newPos=0; //cols列坐標0~15
switch(row)
{
case 0:
{
row=0x80;
}
break;
case 1:
{
row=0x90;
}
break;
case 2:
{
row=0x88;
}
break;
case 3:
{
row=0x98;
}
break;
case 4:
{
row=0xa0;
}
break;
case 5:
{
row=0xb0;
}
break;
case 6:
{
row=0xa8;
}
break;
case 7:
{
row=0xb8;
}
break;
default: //如果需要檢測行坐標范圍,可在這里加代碼
break;
}
newPos=row+cols/2; //液晶寫指令坐標只能8級,我的函數中列坐標是16級的,支持半角全角混合
LCD12864_writeCmd(newPos);
}
/*
void LCD12864_setPos(u8 row, u8 cols) //設置光標位置
{ //row行坐標0~3
u8 newPos=0; //cols列坐標0~15
switch(row)
{
case 0:
{
row=0x80;
}
break;
case 1:
{
row=0x90;
}
break;
case 2:
{
row=0x88;
}
break;
case 3:
{
row=0x98;
}
break;
default: //如果需要檢測行坐標范圍,可在這里加代碼
break;
}
newPos=row+cols/2; //液晶寫指令坐標只能8級,我的函數中列坐標是16級的,支持半角全角混合
LCD12864_writeCmd(newPos);
}
*/
void LCD12864_init() //初始化
{
delayms(40); //rst由低到高后保持40ms以上,我們的rst接VCC
LCD_PSB= 1; //選擇并口方式
LCD12864_writeCmd( B(110000) ); //0x30,啟用基本指令集
delayXus(15); //要求延時100us以上,(8+6x)*1.085=106us
LCD12864_writeCmd( B(110000) ); //0x30,要求寫2次該指令
delayXus(5); //要求延時37us以上,(8+6x)*1.085=41us
LCD12864_writeCmd( B(1100) ); //0x0f,整體顯示,游標,游標反白
delayXus(15); //要求延時100us以上
LCD12864_writeCmd( B(0001) ); //0x01,清屏指令,整屏幕寫滿空格
delayms(10); //要求延時10ms以上
LCD12864_writeCmd( B(110) ); //0x06,進入模式設置,游標自動指向下一位置,
delayms(5); //手冊上沒說這里要延時,額,還是加上吧
}
void LCD12864_writeCmd(u8 cmd) //寫指令
{
while(LCD12864_isBusy());
LCD_EN=0; //使能 拉低
LCD_RW=0; //寫
LCD_RS=0;_nop_(); //命令
LCD_EN=1; //使能
LCD_dataBus=cmd; //送指令
_nop_();_nop_(); //穩定
LCD_EN=0;_nop_(); //取走
}
void LCD12864_writeByte(u8 dat) //寫一個字節
{
while(LCD12864_isBusy());
LCD_EN=0; //使能先拉低
LCD_RW=0; //寫
LCD_RS=1;_nop_(); //數據
LCD_EN=1;
LCD_dataBus=dat;
_nop_();_nop_(); //延時大于1.5us
LCD_EN=0;_nop_(); //下降沿取走數據
}
u8 LCD12864_readByte() //讀數據暫存器Data Register
{ //用的時候要空操作一次
u8 temp=0;
while(LCD12864_isBusy());//忙檢測
LCD_dataBus=0xff; //用總線讀數據時必須先置為輸入模式
LCD_EN=0; //使能線拉低
LCD_RW=1; //讀
LCD_RS=1;_nop_(); //數據
LCD_EN=1;_nop_(); //使能
temp=LCD_dataBus; //取走數據
_nop_();
LCD_EN=0; //使能恢復
return temp;
}
bool LCD12864_isBusy() //檢測液晶是否忙
{
if(LCD12864_readIR() & 0x80) //檢測BF位
{
return TRUE; //忙
}
return FALSE; //不忙
}
u8 LCD12864_readIR() //讀指令暫存器Instruction Register
{
u8 temp=0;
LCD_EN=0; //使能準備
LCD_RW=1; //讀
LCD_RS=0;_nop_(); //命令字
LCD_dataBus=0xff; //準備輸入
LCD_EN=1;_nop_(); //使能
temp=LCD_dataBus; //提取數據
_nop_();
LCD_EN=0; //使能拉低
return temp;
}
復制代碼
作者:
zmc419
時間:
2022-8-30 12:49
太好了,生成了頭文件,使用很方便,感謝
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1