我是改的别人的程序,版权属于这位同学。
/****************************************
程序设计部分
主函数中调用:draw_rect(19,5,160,87);
下面是LM4229驱动程序(0811更新)
****************************************/
//========================================
// 使用LCD 280124 液晶屏制作时钟
// 显示“北京欢迎您”
// 改进: 2008/08/08增加显示5个32*32汉字程序
// 2008/08/10增加显示a*b大小照片(a为8的倍数)
// 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; //数据(L)/命令(H)选择
sbit READ=P2^5; //读,低电平有效
sbit WRIT=P2^6; //写,低电平有效
sbit CE=P2^7; //使能,低电平有效
//===========================================
// 函数声明
//-------------------------------------------
//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();
//--------------------------------------------
// 延时函数
//--------------------------------------------
void delay_lcd(uchar t)
{
for(;t!=0; t--);
}
//--------------------------------------------
// 写数据函数
//--------------------------------------------
void write_data(uchar dat)
{
CD=0; //数据
CE=0; //LCD使能
WRIT=0; //写
DATA_PORT=dat; //把数据送到P口
delay_lcd(1); //当晶振较高时加延时
WRIT=1; //关写
CE=1; //关使能
}
//--------------------------------------------
// 写命令函数
//--------------------------------------------
void write_com(uchar com)
{
CD=1; //命令
CE=0; //LCD使能
WRIT=0; //写命令
DATA_PORT=com; //把命令送到P口
delay_lcd(1); //当晶振较高时加延时
WRIT=1; //关写命令
CE=1; //关使能
}
//--------------------------------------------
// 指定位置、长度清屏
//--------------------------------------------
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); //关闭自动写
}
//--------------------------------------------
// ------- 【显示16*16字符】 -------
//--------------------------------------------
// 指定位置向LCD写入指定字符
// 参数说明: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); //设置数据自动写
if(flag)
{
write_data (ASC_MSK[(c1-0x20)*16+k ]);
}
/*---例如:0的ASCII码为0x30,在ASC_MSK中的位置为0x10*16 ---16字节字码依次写入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 //否则,不换行,继续写下一个字符
{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])) //------如果汉字在子码表内
{
for(k=0;k<16;k++) //字符设置为16*8
{
write_data(place&0xff); //写入地址高位
write_data(place/256); //写入地址低位
write_com(0x24); //地址设置
write_com(0xb0); //设置数据自动写
if(flag)
{
write_data(GB_16[j]/Msk[k*2]);
write_data(GB_16[j]/Msk[k*2+1]); //16*16,每行2字节
}
else
{
write_data(~GB_16[j]/Msk[k*2]);
write_data(~GB_16[j]/Msk[k*2+1]); //16*16,每行2字节
}
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); //设置数据自动写
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初始化函数
//--------------------------------------------
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); //图形区域设置
write_com(0x80); //设置为OR模式
write_com(0x98); //关闭文本显示,开图形显示
}
//========【显示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); //设置数据自动写
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的倍数)
//--------------------------------------------
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行数据
{
write_data(place&0xff); //写地址低8位
write_data(place/256); //写地址高8位
write_com(0x24); //设置地址
write_com(0xb0); //设置数据自动写
for(j=0;j<a/8;j++) //a/8列数据
{write_data(tab_image[(a/8)*i+j]);}
write_com(0xb2); //自动复位
place=place+30; //换行
}
}
//============【画线和矩形部分】==============
//--------------------------------------------
// LM4229在指定位置画横线a
// 参数说明:x、y 坐标 a 长度
// (a为8的倍数)
//--------------------------------------------
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); //设置数据自动写
for(j=0;j<=a/8;j++) //a/8列数据
{write_data(0xff);}
write_com(0xb2); //自动复位
}
//--------------------------------------------
// LM4229在指定位置画竖线b
// 参数说明: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列数据
{
write_data(place&0xff); //写地址低8位
write_data(place/256); //写地址高8位
write_com(0x24); //设置地址
write_com(0xb0); //设置数据自动写
write_data(0x01);
write_com(0xb2); //自动复位
place=place+30;
}
}
//--------------------------------------------
// LM4229在指定位置画竖线b
// 参数说明: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列数据
{
write_data(place&0xff); //写地址低8位
write_data(place/256); //写地址高8位
write_com(0x24); //设置地址
write_com(0xb0); //设置数据自动写
write_data(0x80);
write_com(0xb2); //自动复位
place=place+30;
}
}
//--------------------------------------------
// LM4229在指定位置画矩形a*b
// 参数说明:x、y 坐标 a、b 长度
// 调用到上面几个函数
//--------------------------------------------
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下边长才和上边长一样,不知道为啥??
}
/*----- 测试数据------*/
/*********************************
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;
//--------------------------
//------- 函数声明 --------
void trans();
void key_scan();
void week();
void delay(uint);
//void write_lcd(uchar);
//============================================
// 主函数
//============================================
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();
}
}
//----------------------------------
// 按键函数
//----------------------------------
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--);
}
//------------------------------------------
// 数据转换
//------------------------------------------
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};
//--------------------------
//----- 函数声明 ------
//--------------------------
//void ds13021(); //获取DS1302时间
void writeds_byte(uchar); //向DS1302写一字节
uchar readds_byte(); //从DS1302读一字节
void ds1302_init(); //DS1302初始化
void writeds_add(uchar,uchar); //指定地址向1302写一数据
uchar readds_add(uchar); //指定地址从1302读一数据
//=========================================
//------ 函数 ------
//=========================================
//-------------------------------
//---- 向DS1302写一字节 (上升沿有效) -------
//---- 数据输入从低位到高位 ------------
//-------------------------------
void writeds_byte(uchar dat)
{
uchar i,
dat_w;
dat_w=dat; //数据送给变量
dat_w;
for(i=0;i<8;i++)
{
io=0; //数据线先拉低
if(dat_w&0x01) //如果是1
{io=1;}
else //如果是0
{io=0;}
dat_w=dat_w>>1; //右移一位
sclk=0; //先拉低时钟信号
sclk=1; //拉高时钟信号
}
sclk=0; //写一字节完毕,拉低时钟信号
}
//-------------------------------
//---- 从DS1302读一字节 (下降沿有效) --------
//---- 读出数据时从低位0位到高位7 -----------
//-------------------------------
uchar readds_byte()
{
uchar i,k;k=0;
for(i=0;i<8;i++)
{
k=k>>1; //k右移一位,确保先读来的数据在低位
if(io)
{k=k|0x80;} //读取的值先送K最高位
sclk=1; //先拉低时钟信号
sclk=0; }
sclk=0;
return (k);
}
//-------------------------------
//---- 指定地址写一数据 --------
//-------------------------------
void writeds_add(uchar add,uchar dat) //dat为十进制数
{
rst=0;
sclk=0;
rst=1; //拉高RST
writeds_byte(add); // 写地址
writeds_byte((dat/10<<4)|(dat%10)); // DS1302中的时间数据是BCD码形式
sclk=0;
rst=0;
}
//-------------------------------
//---- 指定地址读出一数据 ------
//-------------------------------
uchar readds_add(uchar add)
{
uchar temp,dat1,dat2;
rst=0; sclk=0;
rst=1;
writeds_byte(add);
temp=readds_byte(); //读取的数据为16进制
sclk=0; //读取完毕,拉低SCLK
rst=0; //拉低SCLK
dat1=temp/16; //16进制转成BCD
dat2=temp%16;
temp=dat1*10+dat2; //转换成10进制数字
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时间 --------
//---- 在主函数中调用 --------
//-------------------------------
void ds13021()
{
uchar i,add;
add=0x81; //
writeds_add(0x8e,0x00); //允许向DS1302写入数据
for(i=0;i<7;i++)
{
tab_1302[i]=readds_add(add); //获得的数据已转换为十进制
add+=2;
}
writeds_add(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠性
}
此程序虽然通过编译但不一定能用,故直接贴出来了,请版主见谅。
|