标题:
基于51单片机的16*64点阵仿真加源程序 生日字模
[打印本页]
作者:
BOOKS
时间:
2019-3-8 23:09
标题:
基于51单片机的16*64点阵仿真加源程序 生日字模
16*64点阵仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
QQ截图20190308230723.png
(43.66 KB, 下载次数: 58)
下载附件
2019-3-8 23:08 上传
16*64点阵单片机源程序如下:
#include<reg51.H>
#define uchar unsigned char
#define uint unsigned int
#define light 3 //定义亮度
uchar code hanzi[]; //汉字字模
uchar code shengri[]; //生日字模
uchar code timer[13][16]; //0~9数字
uchar code sw[]; //138驱动数据
void Show_word(); //待机显示按三秒间隔分别显示年、月日、星期、时分秒。
void Show_pass(); //不显示一个字
void Send_data(unsigned char *d); /*串口发送一行*/
/******************************************/
sbit resget=P0^2; //时钟复位
sbit key_moda=P0^3; //模式转换
sbit key_up=P0^4; //时钟加
sbit key_Down=P0^5; //时钟减
sbit T_CLK=P2^1; //DS1302引脚连接
sbit T_IO =P2^2;
sbit T_RST=P2^3;
sbit ACC0=ACC^0; //1bit数据存储位
sbit ACC7=ACC^7;
sbit STR=P1^7; //锁存
sbit CLK=P3^1; //时钟
sbit Data= P3^0; //数据
sbit Data1= P1^6;
sbit E=P1^4;
sbit UU=P1^7;
sbit DQ= P2 ^ 0;//ds1820data(单总线)
uchar starts_time[7]={0x00,0x10,0x22,0x21,0x10,0x03,0x09}; //初始化后设置
uchar Move,Speed,Flicker,line,Sec,Cent,Hour,Year,Month,Day,Week; //时间温度变量
uchar a,b,f,h,msec,id,x; //标志计数器 a为自动转换显示时间,b为手动与自动标志
uint zimuo,tvalue; //字模计数器
uchar BUFF[10]; //缓存
void RTInputByte(uchar); //* 输入 1Byte */
uchar RTOutputByte(void); //* 输出 1Byte */
void W1302(uchar, uchar); // 向DS1302写入一个字节
uchar R1302(uchar); // 从DS1302读出一个字节
void Set1302(uchar *); // 写DS1302时间
void du1302(); // 读时间
void DelayMs(void); // 延时
void Set(uchar,uchar ); // 变量调整
void in_data(); // 调整移动数据
void rxd_data(); // 串口发送移动数据
read_temp(); //*读取温度值并转换*/
/*主函数*/
void main()
{
Data1=1;
Move=0;
zimuo=0;
TMOD=0x01; //16位定时
TH0=0xC5; //15ms晶振为12M
TL0=0x68;
EA=1;
TR0=1;
ET0=1;
SCON=0; //初始化串口为工作方式0(同步通信方式,TxD输出同步脉冲)
while(zimuo<512)
{
while(Move<16) //数据移位。
{
for(Speed=0;Speed<4;Speed++) //移动速度
{
for(line=0;line<16;line++)
{
in_data(); //调整移动数据
rxd_data();
P1=sw[line];
STR=1;//锁存
STR=0;
UU=1;
DelayMs(); //延时,等待一段时间,让这列显示的内容在人眼内产生“视觉暂留”现象。*/
}
}
Move++; //移动一步
}
Move=0;
zimuo=zimuo+32;
}
zimuo=0;
while(1) //重复(无限)循环显示
{
if(resget==0)
{ DelayMs();
if(resget==0)
Set1302(starts_time); //初始化
W1302(0x8e,0x00); //控制命令,WP=0,写操作
W1302(0x90,0xa5); //打开充电二级管 一个二级管串联一个2K电阻
}
du1302(); //读取 秒 分 时 日 月 星期 年
read_temp();//读取温度
zimuo=0;
if (key_moda==0) //设置和选择项目键
{ DelayMs();
if(key_moda==0)
{
if(id++==10) {id=0;}
h=0;msec=0; //清闪烁标志
while(key_moda==0){ Show_word();}
}
}
if(id!=0)
{
if (key_up==0) //增加
{
DelayMs();
if(key_up==0)
{
while(key_up==0)
{Show_word();} //调用显示
h=0;msec=0; //清闪烁标志
Set(id,0); //调用时间调调整
}
}
if (key_Down==0) //减少
{
DelayMs();
if(key_Down==0)
{
while(key_Down==0)
{Show_word();} //调用显示
h=0;msec=0; //清闪烁标志
Set(id,1); //调用时间调调整
}
}
}
else
{
if (key_up==0) //增加
{
DelayMs();
if(key_up==0)
{
while(key_up==0)
{Show_word();} //调用显示
h=0;msec=0; //清闪烁标志
if(b!=0) //手动调整显示的内容
{
if(f++==5) //f为显示转换标志
f=0;
}
}
}
}
Show_word(); //待机显示按三秒间隔分别显示年、月日、星期、时分秒。
}
}
/************************************************/
void Show_word() //串行输出显示
{ uchar h;
for(h=0;h<16;h++)
{
if((id==0)&(f==0)|(id==1)) //f为三秒转换显示
{
Send_data(&timer[0][0]); //不显示
if((Flicker==1)&(id==1)) //闪烁标志为1时不亮,为零时亮
{ Show_pass(); //不显示一个字
Show_pass();
}
else
{
Send_data(&timer[2][h]); //20年
Send_data(&timer[0][h]);
Send_data(&timer[Year/16][h]); //年值
Send_data(&timer[Year%16][h]);
}
Send_data(&hanzi[h*2+641]); //年字符
Send_data(&hanzi[h*2+640]);
Send_data(&timer[0]); //不显示
}
if((id==0)&(f==1)|(id==2)|(id==3))
{
if((Flicker==1)&(id==2)) //闪烁标志为1时不亮,为零时亮
{ Show_pass(); //不显示一个字
}
else
{
if(Month/16<1)
Send_data(&timer[0]); //月十位为零时不显示
else
Send_data(&timer[Month/16][h]); //月值
Send_data(&timer[Month%16][h]);
}
Send_data(&hanzi[h*2+673]); //月字符
Send_data(&hanzi[h*2+672]);
if((Flicker==1)&(id==3)) //闪烁标志为1时不亮,为零时亮
{ Show_pass(); //不显示一个字
}
else
{
Send_data(&timer[Day/16][h]); //日值
Send_data(&timer[Day%16][h]);
}
Send_data(&hanzi[h*2+961]); //日字符
Send_data(&hanzi[h*2+960]);
}
if((id==0)&(f==2)|(id==4)) //f为三秒转换显示
{
Send_data(&timer[0]); //不显示
Send_data(&hanzi[h*2+705]); //星字符
Send_data(&hanzi[h*2+704]);
Send_data(&hanzi[h*2+737]); //期字符
Send_data(&hanzi[h*2+736]);
if((Flicker==1)&(id==4)) //闪烁标志为1时不亮,为零时亮
{ Show_pass(); //不显示一个字
}
else
{
Send_data(&hanzi[Week%16*32+h*2+737]); //星期值
Send_data(&hanzi[Week%16*32+h*2+736]);
}
Send_data(&timer[0][0]); //不显示
}
if((id==0)&(f==3)|(id>4)) //f为三秒转换显示
{
if((Flicker==1)&(id==5)) //闪烁标志为1时不亮,为零时亮
{
Show_pass(); //不显示一个字
}
else
{
if(Hour/16<1)
Send_data(&timer[0][0]); //时十位小于1时不显示
else
Send_data(&timer[Hour/16][h]); //时值
Send_data(&timer[Hour%16][h]);
}
Send_data(&timer[10][h]); //两个点
if((Flicker==1)&(id==6)) //闪烁标志为1时不亮,为零时亮
{
Show_pass(); //不显示一个字
}
else
{
Send_data(&timer[Cent/16][h]);
Send_data(&timer[Cent%16][h]); //分值
}
Send_data(&timer[10][h]); //两个点
if((Flicker==1)&(id==7)) //闪烁标志为1时不亮,为零时亮
{
Show_pass(); //不显示一个字
}
else
{
Send_data(&timer[Sec/16][h]); //秒
Send_data(&timer[Sec%16][h]);
}
}
if((id==0)&(f==4)) //f为三秒转换显示
{
Send_data(&hanzi[h*2+1185]); //温字符
Send_data(&hanzi[h*2+1184]);
Send_data(&hanzi[h*2+1217]); //度字符
Send_data(&hanzi[h*2+1216]);
Send_data(&timer[10][h]); //两个点
if (tvalue/10==0x00)
Send_data(&timer[0][0]);
else
Send_data(&timer[tvalue/10][h]); //温度值的十位值
Send_data(&timer[tvalue%10][h]); //温度值的个位
Send_data(&timer[11][h]); //温度值的符号
}
if((id==0)&(f==5))
{
if(Month == 0x04 && Day == 0x19)
{
while(zimuo<64)
{
while(Move<16) //数据移位。
{
for(Speed=0;Speed<4;Speed++) //移动速度
{
for(line=0;line<16;line++)
{
char s;
for(s=4;s>=0;s--) //i为向后先择字节计数器,zimuoo为向后先字计数器
{
BUFF[2*s+1]=shengri[zimuo+32*s+2*line]; //把第一个字模的第一个字节放入BUFF0中,第二个字模和第一个字节放入BUFF2中
BUFF[2*s]=shengri[zimuo+1+32*s+2*line];} //把第一个字模的第二个字节放入BUFF1中,第二个字模的第二个字节放入BUFF3中 //调整移动数据
rxd_data();
P1=sw[line];
STR=1;//锁存
STR=0;
UU=1;
DelayMs(); //延时,等待一段时间,让这列显示的内容在人眼内产生“视觉暂留”现象。*/
}
}
Move++; //移动一步
}
Move=0;
zimuo=zimuo+32;
}
}
else if(Month == 0x10 && Day == 0x26)
{
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1249]); //重阳节字符
Send_data(&hanzi[h*2+1248]);
Send_data(&hanzi[h*2+1281]);
Send_data(&hanzi[h*2+1280]);
Send_data(&hanzi[h*2+1313]);
Send_data(&hanzi[h*2+1312]);
Send_data(&timer[0][0]);
}
else if(Month == 0x11 && Day == 0x26)
{
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1345]); //感恩节字符
Send_data(&hanzi[h*2+1344]);
Send_data(&hanzi[h*2+1377]);
Send_data(&hanzi[h*2+1376]);
Send_data(&hanzi[h*2+1313]);
Send_data(&hanzi[h*2+1312]);
Send_data(&timer[0][0]);
}
else if(Month == 0x12 && Day == 0x22)
{
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1409]); //冬至节字符
Send_data(&hanzi[h*2+1408]);
Send_data(&hanzi[h*2+1441]);
Send_data(&hanzi[h*2+1440]);
Send_data(&hanzi[h*2+1313]);
Send_data(&hanzi[h*2+1312]);
Send_data(&timer[0][0]);
}
else if(Month == 0x12 && Day == 0x25)
{
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1473]); //圣诞节字符
Send_data(&hanzi[h*2+1472]);
Send_data(&hanzi[h*2+1505]);
Send_data(&hanzi[h*2+1504]);
Send_data(&hanzi[h*2+1313]);
Send_data(&hanzi[h*2+1312]);
Send_data(&timer[0][0]);
}
else if (Hour>= 0x06 &&Hour< 0x18 )
{
Send_data(&timer[0][0]);
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1537]); //白天字符
Send_data(&hanzi[h*2+1536]);
Send_data(&hanzi[h*2+1569]);
Send_data(&hanzi[h*2+1568]);
Send_data(&timer[0][0]);
Send_data(&timer[0][0]);
}
else
{
Send_data(&timer[0][0]);
Send_data(&timer[0][0]);
Send_data(&hanzi[h*2+1601]); //晚上字符
Send_data(&hanzi[h*2+1600]);
Send_data(&hanzi[h*2+1633]);
Send_data(&hanzi[h*2+1632]);
Send_data(&timer[0][0]);
Send_data(&timer[0][0]);
}
}
if(id>7) //id大于7时为对显示转换模式设置
{ if((Flicker==1)&(id==8))
{ Show_pass();
Show_pass();
Show_pass();
Show_pass();
}
else if(b==0)
{
Send_data(&hanzi[h*2+993]); //显示汉字 “自”
Send_data(&hanzi[h*2+992]);
Send_data(&hanzi[h*2+1057]); //显示汉字“动”
Send_data(&hanzi[h*2+1056]);
Send_data(&hanzi[h*2+1089]); //显示汉字“模”
Send_data(&hanzi[h*2+1088]);
Send_data(&hanzi[h*2+1121]); //显示汉字“式”
Send_data(&hanzi[h*2+1120]);
}
else
{
Send_data(&hanzi[h*2+1025]); //显示汉字“手”
Send_data(&hanzi[h*2+1024]);
Send_data(&hanzi[h*2+1057]); //显示汉字“动”
Send_data(&hanzi[h*2+1056]);
Send_data(&hanzi[h*2+1089]); //显示汉字“模”
Send_data(&hanzi[h*2+1088]);
Send_data(&hanzi[h*2+1121]); //显示汉字“式”
Send_data(&hanzi[h*2+1120]);
}
if(id==9)
{
if(b==1) //手动模式
{
id=0;f=0;
}
else
{
Send_data(&hanzi[h*2+993]); //显示汉字“自”
Send_data(&hanzi[h*2+992]);
Send_data(&hanzi[h*2+1057]); //显示汉字“动”
Send_data(&hanzi[h*2+1056]);
if(Flicker==1)
{
Show_pass();
}
else
{
Send_data(&timer[a/16][h]); //转换时间
Send_data(&timer[a%16][h]);
}
Send_data(&hanzi[h*2+1153]); //显示汉字“秒”
Send_data(&hanzi[h*2+1152]);
}
}
}
P1=sw[h]; //输出行信号
STR=1;STR=0;
UU=1; //锁存为高,595锁存信号
DelayMs(); //延时,等待一段时间,让这列显示的内容在人眼内产生“视觉暂留”现象。*/
}
}
/************************************************/
//temp=255-temp;
//return temp;
void timer_1(void) interrupt 1 //中断入口,闪烁
{
TH0=0xC5; //15ms定时 晶振12M
TL0=0x68;
if(msec++==40) //1000ms
{ msec=0;
x++;
if(x>=a)
{ x=0;
if(b==0) //自动模式
{
if(f++==5)
f=0; //f显示转换计数器 ,d为用户设置的自动转换时间的值。
}
}
if(h++==4) //5秒后进入正常走时。
{id=0;h=0;}
}
if(msec<20)
Flicker=0; //闪烁标志反转
else
Flicker=1;
}
/***********************输出一个字的不显示数据。*****************/
void Show_pass()
{
Send_data(&timer[0][0]); //不显示
Send_data(&timer[0][0]); //不显示
}
/**********************************************************/
void in_data(void) //调整数据
{
char s;
for(s=4;s>=0;s--) //i为向后先择字节计数器,zimuoo为向后先字计数器
{
BUFF[2*s+1]=hanzi[zimuo+32*s+2*line]; //把第一个字模的第一个字节放入BUFF0中,第二个字模和第一个字节放入BUFF2中
BUFF[2*s]=hanzi[zimuo+1+32*s+2*line]; //把第一个字模的第二个字节放入BUFF1中,第二个字模的第二个字节放入BUFF3中
}
}
/***********************发送移动的数据****************************/
void rxd_data(void) //串行发送数据
{
uchar s;
uchar inc,tempyid,temp;
if(Move<8)
inc=0;
else
inc=1;
for(s=0+inc;s<8+inc;s++) //发送8字节数据
{
if(Move<8)
tempyid=Move;
else
tempyid=Move-8;
temp=(BUFF[s]>>tempyid)|(BUFF[s+1]<<(8-tempyid)); //h1左移tempyid位后和h2右移8-tempyid相或,取出移位后的数据。
temp=255-temp;
SBUF=temp; //把BUFF中的字节从大到小移位相或后发送输出。
while(TI==0); //等待发送完毕
TI=0;
}
}
/*******************************************************/
void Send_data(unsigned char *d) /*从串口发送数据*/
{
SBUF=*d;
while(TI==0); //等待发送完毕
TI=0;
}
//根据选择调整相应项目
void Set(uchar sel,uchar sel_1)
{
uchar address,time;
uchar max,min;
if(sel==9) {address=0xc2; max=20;min=1;} //自动转换时间时最大为20秒。
if(sel==8) {address=0xc0; max=1;min=0; } //显示自动转换或手动转换。为零自动,为1手动。
if(sel==7) {address=0x80; max=59;min=0;} //秒
if(sel==6) {address=0x82; max=59;min=0;} //分钟
if(sel==5) {address=0x84; max=23;min=0;} //小时
if(sel==4) {address=0x8a; max=7; min=1;} //星期
if(sel==3) {address=0x86; max=31;min=1;} //日
if(sel==2) {address=0x88; max=12;min=1;} //月
if(sel==1) {address=0x8c; max=99;min=0;} //年
time=R1302(address+1)/16*10+R1302(address+1)%16;
if (sel_1==0) time++; else time--;
if(time>max) time=min;
if(time<min) time=max;
W1302(0x8e,0x00);
W1302(address,time/10*16+time%10);
W1302(0x8e,0x80);
}
/**************************延时***********************/
void DelayMs(void)
{
uchar TempCyc;
for(TempCyc=110;TempCyc>1;TempCyc--)
{;}
}
//********DS1302读写程序***************//
/********************************************************************
函 数 名:RTInputByte()
功 能:实时时钟写入一字节
说 明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据
返 回 值:无
***********************************************************************/
void RTInputByte(uchar d)
{
uchar h;
ACC = d;
for(h=8; h>0; h--)
{
T_IO = ACC0; /*相当于汇编中的 RRC */
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/********************************************************************
函 数 名:RTOutputByte()
功 能:实时时钟读取一字节
说 明:从DS1302读取1Byte数据 (内部函数)
入口参数:无
返 回 值:ACC
设 计:zhaojunjie 日 期:2002-03-19
修 改: 日 期:
***********************************************************************/
uchar RTOutputByte(void)
{
uchar h;
for(h=8; h>0; h--)
{
ACC = ACC >>1; /*相当于汇编中的 RRC */
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
/********************************************************************
函 数 名:W1302()
功 能:往DS1302写入数据
说 明:先写地址,后写命令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
***********************************************************************/
void W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,命令 */
RTInputByte(ucDa); /* 写1Byte数据*/
T_CLK = 1;
T_RST = 0;
}
/********************************************************************
函 数 名:R1302()
功 能:读取DS1302某地址的数据
说 明:先写地址,后读命令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址
返 回 值:ucData :读取的数据
***********************************************************************/
uchar R1302(uchar ucAddr)
{
uchar ucData;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,命令 */
ucData = RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST = 0;
return(ucData);
}
/********************************************************************
函 数 名:Set1302()
功 能:设置初始时间
说 明:先写地址,后读命令/数据(寄存器多字节方式)
调 用:W1302()
入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B
返 回 值:无
***********************************************************************/
void Set1302(uchar *pClock)
{
uchar h;
uchar ucAddr = 0x80;
W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
for(h =7; h>0; h--)
{
W1302(ucAddr,*pClock); /* 秒 分 时 日 月 星期 年 */
pClock++;
ucAddr +=2;
}
W1302(0xc0,0x01);
W1302(0XC2,0X03); //初始自动转换显示时间为3秒。
W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/
}
/******************读取DS1302中的时间****************/
void du1302()
{
Sec=R1302(0x81); //对取 秒 分 时 日 月 星期 年
Cent=R1302(0x83);
Hour=R1302(0x85);
Day=R1302(0x87);
Month=R1302(0x89);
Week=R1302(0x8b);
Year=R1302(0x8d);
b=R1302(0xc1);
a=R1302(0xc3);
a=a/16*10+a%16;
}
/******************************ds1820程序***************************************/
void delay_18B20(unsigned int i)//延时1微秒
{
while(i--);
}
void ds1820rst()/*ds1820复位*/
{ unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd()/*读数据*/
{ unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{ DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{unsigned char i=0;
for (i=8; i>0; i--)
{ DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
read_temp()/*读取温度值并转换*/
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b*16+a/16;
//tvalue=b;
//tvalue<<=8;
//tvalue=tvalue|a;
//if(tvalue<0x0fff)
//tflag=0;
// else
//{tvalue=~tvalue+1;
//tflag=1;
//}
return(tvalue);
}
/*******************************************************************/
uchar code sw[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};/*16行段码*/
const uchar code timer[13][16]={ /*0~9字符*/
/*-- 文字: 0 --*/
/*-- Book Antiqua12; 此字体下对应的点阵为:宽x高=8x20 --*/
0xFF,0xFF,0xE3,0xDD,0xBE,0xBE,0xBE,0xBE,0xBE,0xBE,0xBE,0xBE,0xDD,0xE3,0xFF,0xFF,
/*-- 文字: 1 --*/
/*-- Book Antiqua12; 此字体下对应的点阵为:宽x高=8x20 --*/
0xFF,0xFF,0xEF,0xE7,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0x83,0xFF,0xFF,
/*-- 文字: 2 --*/
/*-- Book Antiqua12; 此字体下对应的点阵为:宽x高=8x20 --*/
0xFF,0xFF,0xC7,0xBB,0x7D,0x7F,0x7F,0xBF,0xCF,0xF7,0xFB,0xFD,0xFD,0x01,0xFF,0xFF,
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
16x64点阵(2).rar
(115.76 KB, 下载次数: 90)
2019-3-8 23:06 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1