×
单片机 > 单片机程序设计 > 详情

自制51单片机超大数码管时钟

发布时间:2020-06-23 发布时间:
|

市面上出售的数码管一般都很小,本人用led发光管自己制作了一种个头很非常大的数码管,挂在家里显示效果非常牛逼下面是实物图:
   
 

        


 

下面是c51程序源代码:

#include
#include
#define uchar unsigned char
#define uint unsigned int
#define pos P0 //设置数码显示的位选
#define segs P1 //设置数码显示的段选

code unsigned char d[]=
    {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,

0x7c,0x39,0x5e,0x79,0x71,0x40,0};
// 0    1    2 3    4    5    6   7   8     9   a     b   c    d     e   f    -    熄灭
    //P0段选,共阴数码管 0-9 a-f - 表

unsigned char code w[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
    //P1位选,直接使用P1的8个端口进行8位选择(此演示中未用到)

//ds1302连线设置
sbit SCL2=P2^0;   //SCL2定义为P2口的第2位脚,连接DS1302SCL
sbit SDA2=P2^1;   //SDA2定义为P2口的第1位脚,连接DS1302SCL
sbit RST = P2^2;   // DS1302片选脚

unsigned char now[8]= {0,   19, 9, 17, 1, 7 ,   10, 0};
                      // 秒 分 时   日 月   星期 年 写入禁止(0允许写入,1禁止写入)
unsigned char nowtoshow[8];//进行数据位的拆分处理用   
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //保存写入寄存器位置
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //保存读取寄存器位置

unsigned char flash=0; //闪秒
void display(unsigned char *lp);//数字的显示函数;lp为指向数组的地址,lc为显示的个数
          
void Write_Ds1302_byte(unsigned char temp); //字节写入函数
void Write_Ds1302( unsigned char address,unsigned char dat );    //调用字节定入函数在特定的地址写入特定的数据
unsigned char Read_Ds1302 ( unsigned char address );    //调用指定的地址的数据

void Read_RTC(void);//read RTC     //读取时间日期值到nowtoshow
void Set_RTC(void);//set RTC    //设定时间日期值,这里用于赋初值
void keydelay(unsigned char t);////键盘消抖延时
delay();


void main()
{
unsigned int k=0;    //使k在0到4000之间循环,不同的时间段显示不同的内容,以较多的时间显示时间,以很少的时间显示日期和星期

//Set_RTC();    //设初值,第一次使用,以后就可以注释掉,以免再次调校时间,当然必须给1302接上2~5.5V的备用电源或电池

Read_RTC();
      nowtoshow[0]=now[2]/16;    //数据的转换,因我们采用数码管0~9的显示,将数据分开
      nowtoshow[1]=now[2]&0x0f;
   nowtoshow[2]=now[1]/16;
   nowtoshow[3]=now[1]&0x0f;
display(nowtoshow);

while(1)
{
if (k<2000)   //显示时间
{
   if (k%100==0)    //循环1000次后进行一次数据更新
   {
    Read_RTC();
     if (flash==0)      //象征性的闪秒,并不准确,也没有必要准确
     { flash=1;}
        else
     {flash=0;}
      nowtoshow[0]=now[2]/16;    //数据的转换,因我们采用数码管0~9的显示,将数据分开
     if (nowtoshow[0]==0)nowtoshow[0]=17; //如果是0则不显示
      nowtoshow[1]=now[2]&0x0f;
   nowtoshow[2]=now[1]/16;
   nowtoshow[3]=now[1]&0x0f;
   }
   }
   if (k>2000&&k<2500)   //显示日期
   {
   flash=17;
      nowtoshow[0]=now[4]/16;    //数据的转换,因我们采用数码管0~9的显示,将数据分开
        if (nowtoshow[0]==0)nowtoshow[0]=17; //如果是0则不显示
      nowtoshow[1]=now[4]&0x0f;
   nowtoshow[2]=now[3]/16;
        if (nowtoshow[2]==0)nowtoshow[2]=17; //如果是0则不显示

   nowtoshow[3]=now[3]&0x0f;

  
   }
   if (k>2500)      //显示星期
   {
     flash=17;
      nowtoshow[0]=17;    //数据的转换,因我们采用数码管0~9的显示,将数据分开
      nowtoshow[1]=17;
      nowtoshow[2]=17;
      nowtoshow[3]=now[5];
   }
k++;
if (k==3000)k=0;
display(nowtoshow);
   }
}[page]

delay()
{
int j;
for (j=0;j<100;j++);
}

void display(unsigned char *lp)//显示
{
uint k;
for (k=0;k<4;k++)
{
pos=w[k];
segs=d[lp[k]];
delay();
segs=d[17];
}

pos=w[4];
segs=d[flash];   //秒闪烁灯
delay();
segs=d[17];

}

void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)     //循环8次 写入数据
{
   SCL2=0;
     SDA2=temp&0x01;     //每次传输低字节
     temp>>=1;    //右移一位
     SCL2=1;
   }
}

/***********************************************************

*****************/
void Write_Ds1302( unsigned char address,unsigned char dat )    
{
   RST=0;
_nop_();
   SCL2=0;
_nop_();
   RST=1;
   _nop_();   //启动
   Write_Ds1302_Byte(address); //发送地址
   Write_Ds1302_Byte(dat);   //发送数据
   RST=0;    //恢复
}
/*********************************************************

*******************/
unsigned char Read_Ds1302 ( unsigned char address )
{
   unsigned char i,temp=0x00;
   RST=0;
_nop_();
   SCL2=0;
_nop_();
   RST=1;
_nop_();
   Write_Ds1302_Byte(address);
   for (i=0;i<8;i++)    //循环8次 读取数据
   {
    if(SDA2)
    temp|=0x80;    //每次传输低字节
   SCL2=0;
   temp>>=1;    //右移一位
    SCL2=1;
}
   RST=0;
_nop_();   //以下为DS1302复位的稳定时间
   RST=0;
SCL2=0;
_nop_();
SCL2=1;
_nop_();
SDA2=0;
_nop_();
SDA2=1;
_nop_();
return (temp);    //返回
}
/**************************************************************

**************/
void Read_RTC(void)   //读取 日历
{
unsigned char i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++)   //分7次读取 年月日时分秒星期
{
now[i]=Read_Ds1302(*p);
p++;
}
}
/***********************************************************

************/
void Set_RTC(void)   //设定 日历
{
unsigned char i,*p,tmp;
for(i=0;i<7;i++){
   tmp=now[i]/10;
   now[i]=now[i]%10;
   now[i]=now[i]+tmp*16;
}
   Write_Ds1302(0x8E,0X00);

   p=write_rtc_address; //传地址
   for(i=0;i<7;i++)   //7次写入 年月日时分秒星期
   {
    Write_Ds1302(*p,now[i]);
    p++;
}
Write_Ds1302(0x8E,0x80);
}

void keydelay(unsigned char t)
{
unsigned char i,j;
for(i=0;ifor(j=0;j<120;j++);
}

关键字:51单片机  超大数码管时钟 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向