我是改的別人的程序,版權(quán)屬于這位同學。
/****************************************
程序設計部分
主函數(shù)中調(diào)用:draw_rect(19,5,160,87);
下面是LM4229驅(qū)動程序(0811更新)
****************************************/
//========================================
// 使用LCD 280124 液晶屏制作時鐘
// 顯示“北京歡迎您”
// 改進: 2008/08/08增加顯示5個32*32漢字程序
// 2008/08/10增加顯示a*b大小照片(a為8的倍數(shù))
// 2008/08/11增加反白顯示、畫直線和矩形
//=========================================
#include<reg52.h>
#include<math.h>
#include<absacc.h>
//#include<ds1302.h>
//#include<lm4229.h>
//#include<en_code.h>
//#include<cn_code.h>
//#include<picture.h>
#define uchar unsigned char
#define uint unsigned int
#define DATA_PORT P0
//#define ASC_MSK[]
//------------------------------------------
// 管腳定義
//------------------------------------------
sbit HALT=P2^0; //暫不清楚
sbit FS1=P2^1; //字體模式選擇
sbit MD2=P2^2; //方式選擇
sbit RST=P2^3; //復位
sbit CD=P2^4; //數(shù)據(jù)(L)/命令(H)選擇
sbit READ=P2^5; //讀,低電平有效
sbit WRIT=P2^6; //寫,低電平有效
sbit CE=P2^7; //使能,低電平有效
//===========================================
// 函數(shù)聲明
//-------------------------------------------
//void delay_lcd(uchar);
//void write_data(uchar);
//void write_com(uchar);
//void clr_lcd(uchar,uchar,uint);
unsigned char ASC_MSK[];
unsigned char GB_16[];
unsigned char tab_pic[];
unsigned char Index[];
unsigned char Msk[];
unsigned char tab_1302[];
unsigned char ds1302();
//--------------------------------------------
// 延時函數(shù)
//--------------------------------------------
void delay_lcd(uchar t)
{
for(;t!=0; t--);
}
//--------------------------------------------
// 寫數(shù)據(jù)函數(shù)
//--------------------------------------------
void write_data(uchar dat)
{
CD=0; //數(shù)據(jù)
CE=0; //LCD使能
WRIT=0; //寫
DATA_PORT=dat; //把數(shù)據(jù)送到P口
delay_lcd(1); //當晶振較高時加延時
WRIT=1; //關(guān)寫
CE=1; //關(guān)使能
}
//--------------------------------------------
// 寫命令函數(shù)
//--------------------------------------------
void write_com(uchar com)
{
CD=1; //命令
CE=0; //LCD使能
WRIT=0; //寫命令
DATA_PORT=com; //把命令送到P口
delay_lcd(1); //當晶振較高時加延時
WRIT=1; //關(guān)寫命令
CE=1; //關(guān)使能
}
//--------------------------------------------
// 指定位置、長度清屏
//--------------------------------------------
void clr_lcd(uchar x,uchar y,uint length)
{
uint i,place;
place=x*30+y;
write_data(place&0xff);
write_data(place/256);
write_com(0x24); //設置
for(i=0;i<length;i++)
write_data(0xff); //寫入空格,清屏
write_com(0xb2); //關(guān)閉自動寫
}
//--------------------------------------------
// ------- 【顯示16*16字符】 -------
//--------------------------------------------
// 指定位置向LCD寫入指定字符
// 參數(shù)說明:x、y 坐標 cha字符串 flag 反白顯示標志 1正常,0反白
//
//--------------------------------------------
void write_lcd(uchar x,uchar y,char *cha,bit flag)
{
uint place,i=0;
uchar length,c1,c2,j,k;
for(length=0;cha[length]!=0;length++);
do
{
c1=cha[i]; //取字符串的ASCII碼
c2=cha[i+1];
place=x*30+y;
if(c1<=128) //#####小于128為字符,大于128為漢字
{
for(k=0;k<16;++k) //字符設置為16*8
{
write_data(place&0xff); //寫入地址高位
write_data(place/256); //寫入地址低位
write_com(0x24); //地址設置
write_com(0xb0); //設置數(shù)據(jù)自動寫
if(flag)
{
write_data (ASC_MSK[(c1-0x20)*16+k ]);
}
/*---例如:0的ASCII碼為0x30,在ASC_MSK中的位置為0x10*16 ---16字節(jié)字碼依次寫入LCD---*/
else
{write_data(~ASC_MSK[(c1-0x20)*16+k]);}
write_com(0xb2); //自動復位
place=place+30;
}
if(y>28) //y>28時候需要換行
{x=x+16;y=0;}
else //否則,不換行,繼續(xù)寫下一個字符
{y++;}
i++;
}
else //#####c1大于128為漢字
{
for(j=0;j<sizeof(GB_16)/sizeof(GB_16[0]);j++) //找到漢字
{
if(c1==GB_16[j],Index[0]&&c2==GB_16[j],Index[1])
break; //漢字找到則跳出
}
if(j<sizeof(GB_16)/sizeof(GB_16[0])) //------如果漢字在子碼表內(nèi)
{
for(k=0;k<16;k++) //字符設置為16*8
{
write_data(place&0xff); //寫入地址高位
write_data(place/256); //寫入地址低位
write_com(0x24); //地址設置
write_com(0xb0); //設置數(shù)據(jù)自動寫
if(flag)
{
write_data(GB_16[j]/Msk[k*2]);
write_data(GB_16[j]/Msk[k*2+1]); //16*16,每行2字節(jié)
}
else
{
write_data(~GB_16[j]/Msk[k*2]);
write_data(~GB_16[j]/Msk[k*2+1]); //16*16,每行2字節(jié)
}
write_com(0xb2); //自動復位
place=place+30; //下一行
}
}
else //-----沒找到對應漢字則涂黑
{
for(k=0;k<16;k++) //字符設置為16*8
{
write_data(place&0xff); //寫入地址高位
write_data(place/256); //寫入地址低位
write_com(0x24); //地址設置
write_com(0xb0); //設置數(shù)據(jù)自動寫
write_data(0xff);
write_data(0xff);
write_com(0xb2); //自動復位
place=place+30; //下一行
}
}
if(y>27) //-------換行
{x+=16;y=0;}
else //--------不用換行,則下一個字
{y+=2;}
i+=2;
}
}
while(i<length);
}
//--------------------------------------------
// LM4229初始化函數(shù)
//--------------------------------------------
void lcd_init()
{
FS1 = 0; //fs1管腳高電平時表示字體為8*6;
//低電平時為8*8
MD2 = 0;
HALT = 0;
write_data(0);
write_data(0); //圖形首地址
write_com(0x42); //圖形首地址設置
write_data(30);
write_data(0);
write_com(0x43); //圖形區(qū)域設置
write_com(0x80); //設置為OR模式
write_com(0x98); //關(guān)閉文本顯示,開圖形顯示
}
//========【顯示5個大漢字】===================
//--------------------------------------------
// LM4229在指定位置顯示32*32漢字
//--------------------------------------------
void write_pic(uchar x,uchar y)
{
uint place;
uchar i,n;
place=x*30+y;
for(n=0;n<5;n++) //5個漢字
{
for(i=0;i<32;i++) //32*32
{
write_data(place&0xff);
write_data(place/256);
write_com(0x24); //設置地址
write_com(0xb0); //設置數(shù)據(jù)自動寫
write_data(tab_pic[4*i+0+128*n]);
write_data(tab_pic[4*i+1+128*n]);
write_data(tab_pic[4*i+2+128*n]);
write_data(tab_pic[4*i+3+128*n]);
write_com(0xb2); //自動復位
place=place+30;
}
place=x*30+y+4*(n+1);
}
}
//=========【顯示圖片部分】====================
//--------------------------------------------
// LM4229在指定位置顯示a*b圖片
// a為圖片長,b為圖片寬(a為8的倍數(shù))
//--------------------------------------------
void write_image(uchar x,uchar y,uchar a,uchar b,uchar *tab_image)
{
uint place;
uchar i,j;
place=x*30+y;
for(i=0;i<b;i++) //b行數(shù)據(jù)
{
write_data(place&0xff); //寫地址低8位
write_data(place/256); //寫地址高8位
write_com(0x24); //設置地址
write_com(0xb0); //設置數(shù)據(jù)自動寫
for(j=0;j<a/8;j++) //a/8列數(shù)據(jù)
{write_data(tab_image[(a/8)*i+j]);}
write_com(0xb2); //自動復位
place=place+30; //換行
}
}
//============【畫線和矩形部分】==============
//--------------------------------------------
// LM4229在指定位置畫橫線a
// 參數(shù)說明:x、y 坐標 a 長度
// (a為8的倍數(shù))
//--------------------------------------------
void draw_h(uchar x,uchar y,uchar a)
{
uint place;
uchar j;
//---- 畫橫線長 a -----
place=x*30+y;
write_data(place&0xff); //寫地址低8位
write_data(place/256); //寫地址高8位
write_com(0x24); //設置地址
write_com(0xb0); //設置數(shù)據(jù)自動寫
for(j=0;j<=a/8;j++) //a/8列數(shù)據(jù)
{write_data(0xff);}
write_com(0xb2); //自動復位
}
//--------------------------------------------
// LM4229在指定位置畫豎線b
// 參數(shù)說明:x、y 坐標 b 長度 0000 0001
//--------------------------------------------
void draw_lr(uchar x,uchar y,uchar b)
{
uint place;
uchar j;
place=x*30+y;
for(j=0;j<b;j++) //a/8列數(shù)據(jù)
{
write_data(place&0xff); //寫地址低8位
write_data(place/256); //寫地址高8位
write_com(0x24); //設置地址
write_com(0xb0); //設置數(shù)據(jù)自動寫
write_data(0x01);
write_com(0xb2); //自動復位
place=place+30;
}
}
//--------------------------------------------
// LM4229在指定位置畫豎線b
// 參數(shù)說明:x、y 坐標 b 長度 1000 0000
//--------------------------------------------
void draw_ll(uchar x,uchar y,uchar b)
{
uint place;
uchar j;
place=x*30+y;
for(j=0;j<b;j++) //a/8列數(shù)據(jù)
{
write_data(place&0xff); //寫地址低8位
write_data(place/256); //寫地址高8位
write_com(0x24); //設置地址
write_com(0xb0); //設置數(shù)據(jù)自動寫
write_data(0x80);
write_com(0xb2); //自動復位
place=place+30;
}
}
//--------------------------------------------
// LM4229在指定位置畫矩形a*b
// 參數(shù)說明:x、y 坐標 a、b 長度
// 調(diào)用到上面幾個函數(shù)
//--------------------------------------------
void draw_rect(uchar x,uchar y,uchar a,uchar b)
{
draw_h(x,y,a); //畫上邊
draw_lr(x,y-1,b); //畫左寬
draw_ll(x,y+a/8,b); //畫右寬
draw_h(x+b,y,a-8); //畫下邊 ;a-8下邊長才和上邊長一樣,不知道為啥??
}
/*----- 測試數(shù)據(jù)------*/
/*********************************
draw_h(33,4,160); //畫上邊
draw_lr(33,3,51); //畫左寬
draw_ll(33,3+21,51); //畫右寬
draw_h(83,4,152); //
*********************************/
//=====================================
/***主程序部分 lm4229_ds1302.c ***/
//=====================================
// 祝福北京,祝福奧運
// 北京歡迎你
// 時鐘暫未加設置時間功能
//=====================================
//#include<reg52.h>
//#include<math.h>
//#include<absacc.h>
//#include<ds1302.h>
//#include<lm4229.h>
/* 0123 67 1011 1516 1819 2122*/
unsigned char tab_time[]="2008年08月08日 00:00:00 星期";
/* 年 月 日 時 分 秒 星期 */
sbit k1=P3^3;
sbit k2=P3^4;
//--------------------------
//------- 函數(shù)聲明 --------
void trans();
void key_scan();
void week();
void delay(uint);
//void write_lcd(uchar);
//============================================
// 主函數(shù)
//============================================
void main()
{
lcd_init();
write_lcd(10,0,"------------------------------");
write_lcd(102,0,"------------------------------"); //
write_lcd(0,0,"2008年08月08日 00:00:00 星期五");
write_lcd(22,1,"同");
write_lcd(38,1,"一");
write_lcd(54,1,"個");
write_lcd(72,1,"世");
write_lcd(90,1,"界");
write_lcd(22,27,"同");
write_lcd(38,27,"一");
write_lcd(54,27,"個");
write_lcd(72,27,"夢");
write_lcd(90,27,"想");
write_lcd(112,0," 偉大中國 厲害了我的國 我愛你");
write_pic(30,5); //北京歡迎你 大字
write_lcd(70,8,"2008 北京奧運");
while(1)
{
ds1302();
trans();
write_lcd(0,0,tab_time);
week();
}
}
//----------------------------------
// 按鍵函數(shù)
//----------------------------------
void key_scan()
{
if(k1==0)
{
delay(5);
if(k1==0)
{
tab_time[2]++;
}
}
}
void delay(uint k)
{
uint i,j;
for(i=k;i>0;i--)
for(j=110;j>0;j--);
}
//------------------------------------------
// 數(shù)據(jù)轉(zhuǎn)換
//------------------------------------------
void trans()
{
tab_time[2]=tab_1302[6]/10+'0'; //年十位
tab_time[3]=tab_1302[6]%10+'0'; //年個位
tab_time[6]=tab_1302[4]/10+'0'; //月十位
tab_time[7]=tab_1302[4]%10+'0'; //月個位
tab_time[10]=tab_1302[3]/10+'0'; //日十位
tab_time[11]=tab_1302[3]%10+'0'; //日個位
tab_time[15]=tab_1302[2]/10+'0'; //小時十位
tab_time[16]=tab_1302[2]%10+'0'; //小時個位
tab_time[18]=tab_1302[1]/10+'0'; //分十位
tab_time[19]=tab_1302[1]%10+'0'; //分個位
tab_time[21]=tab_1302[0]/10+'0'; //秒十位
tab_time[22]=tab_1302[0]%10+'0'; //秒個位
}
//------------------------------------------
// 星期顯示
//------------------------------------------
void week()
{
uchar i;
i=tab_1302[5]-1;
/*實時時鐘里的值是6,但是2008/08/08是星期五,所以減1, Proteus的問題?? */
switch(i)
{
case 1: write_lcd(0,28,"一"); break;
case 2: write_lcd(0,28,"二"); break;
case 3: write_lcd(0,28,"三"); break;
case 4: write_lcd(0,28,"四"); break;
case 5: write_lcd(0,28,"五"); break;
case 6: write_lcd(0,28,"六"); break;
case 7: write_lcd(0,28,"日"); break;
default: break; //其它情況
}
}
//======================================================
//----- 星期一 monday 星期二 tuesday 星期三 wednesday
//----- 星期四 thursday 星期五 friday 星期六 saturday
//----- 星期日 sunday //----- //-----
//======================================================
//--------------------------
//#define uchar unsigned char
//#define uint unsigned int
//--------------------------
//------ 定義端口 ---------
sbit rst=P3^0;
sbit sclk=P3^1;
sbit io=P3^2;
//---------------------------
uchar tab_1302[7]={0,10,19,30,7,3,8}; //初始化時時間日期設置
//秒 分 時 日 月 星期 年
uchar tab1_1302[7]={0,10,19,30,7,3,8};
//--------------------------
//----- 函數(shù)聲明 ------
//--------------------------
//void ds13021(); //獲取DS1302時間
void writeds_byte(uchar); //向DS1302寫一字節(jié)
uchar readds_byte(); //從DS1302讀一字節(jié)
void ds1302_init(); //DS1302初始化
void writeds_add(uchar,uchar); //指定地址向1302寫一數(shù)據(jù)
uchar readds_add(uchar); //指定地址從1302讀一數(shù)據(jù)
//=========================================
//------ 函數(shù) ------
//=========================================
//-------------------------------
//---- 向DS1302寫一字節(jié) (上升沿有效) -------
//---- 數(shù)據(jù)輸入從低位到高位 ------------
//-------------------------------
void writeds_byte(uchar dat)
{
uchar i,
dat_w;
dat_w=dat; //數(shù)據(jù)送給變量
dat_w;
for(i=0;i<8;i++)
{
io=0; //數(shù)據(jù)線先拉低
if(dat_w&0x01) //如果是1
{io=1;}
else //如果是0
{io=0;}
dat_w=dat_w>>1; //右移一位
sclk=0; //先拉低時鐘信號
sclk=1; //拉高時鐘信號
}
sclk=0; //寫一字節(jié)完畢,拉低時鐘信號
}
//-------------------------------
//---- 從DS1302讀一字節(jié) (下降沿有效) --------
//---- 讀出數(shù)據(jù)時從低位0位到高位7 -----------
//-------------------------------
uchar readds_byte()
{
uchar i,k;k=0;
for(i=0;i<8;i++)
{
k=k>>1; //k右移一位,確保先讀來的數(shù)據(jù)在低位
if(io)
{k=k|0x80;} //讀取的值先送K最高位
sclk=1; //先拉低時鐘信號
sclk=0; }
sclk=0;
return (k);
}
//-------------------------------
//---- 指定地址寫一數(shù)據(jù) --------
//-------------------------------
void writeds_add(uchar add,uchar dat) //dat為十進制數(shù)
{
rst=0;
sclk=0;
rst=1; //拉高RST
writeds_byte(add); // 寫地址
writeds_byte((dat/10<<4)|(dat%10)); // DS1302中的時間數(shù)據(jù)是BCD碼形式
sclk=0;
rst=0;
}
//-------------------------------
//---- 指定地址讀出一數(shù)據(jù) ------
//-------------------------------
uchar readds_add(uchar add)
{
uchar temp,dat1,dat2;
rst=0; sclk=0;
rst=1;
writeds_byte(add);
temp=readds_byte(); //讀取的數(shù)據(jù)為16進制
sclk=0; //讀取完畢,拉低SCLK
rst=0; //拉低SCLK
dat1=temp/16; //16進制轉(zhuǎn)成BCD
dat2=temp%16;
temp=dat1*10+dat2; //轉(zhuǎn)換成10進制數(shù)字
return (temp);
}
//-------------------------------
//---- DS1302初始化 --------
//---- 設置初始時間 --------
//-------------------------------
void ds1302_init()
{
uchar i,add;
add=0x80;
writeds_add(0x8e,0x00); //允許寫入
for(i=0;i<7;i++)
{
writeds_add(add,tab1_1302[i]);
add+=2;
}
writeds_add(0x90,0xa6); //寫充電控制寄存器.
writeds_add(0x8e,0x80); //禁止寫入
}
//-------------------------------
//---- 獲取DS1302時間 --------
//---- 在主函數(shù)中調(diào)用 --------
//-------------------------------
void ds13021()
{
uchar i,add;
add=0x81; //
writeds_add(0x8e,0x00); //允許向DS1302寫入數(shù)據(jù)
for(i=0;i<7;i++)
{
tab_1302[i]=readds_add(add); //獲得的數(shù)據(jù)已轉(zhuǎn)換為十進制
add+=2;
}
writeds_add(0x8e,0x80); //獲取完一次時間,禁止向DS1302寫入數(shù)據(jù),提高可靠性
}
此程序雖然通過編譯但不一定能用,故直接貼出來了,請版主見諒。
|