历史上的今天
返回首页

历史上的今天

今天是:2025年02月25日(星期二)

正在发生

2020年02月25日 | 用普中开发板做的51单片机的智能时钟

2020-02-25 来源:51hei

本贴针对学完单片机并且有读懂代码的非新手同学。本人目前放寒假,这个是本人在上个学期的单片机课上要求做的综合实验,现在重新修改了下增加了菜单目前测试毫无问题可以完美使用。有志向做闹钟的同学可以参考一下,原码上由本人写的大量注释可以方便看懂。


使用了LCD1602、DS1302、DS18B20用来测试温度、内部含闹钟系统但本人没有做EEPROM有需要的同学可以自行添加。


单片机源程序如下:

#include

#include

#include

#include

#include

#include


#define normal 0//正常显示时钟界面

#define settime 1//设定时钟界面

#define setalarm 2//设定闹钟界面

#define displayalarm 3//显示闹钟界面

#define normal_12 4//显示十二小时制界面

#define caidan 5


unsigned char system=normal;//我一开始就把界面切换为正常显示时钟界面


extern unsigned char i,k;


extern unsigned int code song[3][300];


unsigned char code *week[8]={"NO ","Mon ","Tue ","Wed ","Thu ","Fri ","Sat ","Sun "};


unsigned char code *clockzifu[4]={"ON ","OFF ","REP ","NRE "};


struct Time timeset={0x18,0x01,0x16,0x14,0x30,0x50,0x03}; 


//第一个闹钟

//第二个闹钟

//第三个闹钟

//第四个闹钟

//第五个闹钟

struct alarmtime xdata clock[5]={{1,16,14,31,0,1,0,1},{1,8,14,32,3,0,0,0},{1,7,18,49,1,1,1,0},{0,0,0,0,0,0,1,0},{1,25,0,0,0,0,1,2}};


unsigned char alarmnum;//闹钟


unsigned char a;


unsigned char flag=0;


unsigned char xinghao=0;


unsigned char tentoBCD(unsigned char dat)//十进制转换为BCD码函数

{

        unsigned char dat1,dat2;

        dat1=dat/10;

        dat2=dat%10;

        dat2=dat2+dat1*16;

        return dat2;

}


unsigned char BCDtoten(unsigned char dat)//BCD码转为十进制函数

{

        unsigned char dat1,dat2;

        dat1=dat/16;

        dat2=dat%16;

        dat2=dat2+dat1*10;

        return dat2;

}


void DS18B20deal(int temp)//DS18B20数据处理函数 显示温度更新温度         

{

    //先判断温度值是否大于0或小于0等于0

           float tp;//保存的数据可能带小数  

        if(temp<0)//当温度值为负数

          {

                LCD1602_writechar(9,1,0x2D);//ASCII码中的-符号

                temp=temp-1;//因为读取的温度是实际温度的补码,所以减1,再取反求出原码

                temp=~temp;//还原读取的数据

                tp=temp;//保存到变量里面

                temp=tp*0.0625*100+0.5;//强制转换成一个整形的数据.留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就算加上0.5,还是在小数点后面。        

          }

        else//当温度值为正数

          {                        

                LCD1602_writechar(9,1,0x20);//ASCII码中的空格

                tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量。如果温度是正的那么,那么正数的原码就是补码它本身

                temp=tp*0.0625*100+0.5;//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点。后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就算加上0.5,还是在小数点后面。        

        }

        LCD1602_writechar(10,1,temp/10000+'0');//温度百位

        LCD1602_writechar(11,1,temp%10000/1000+'0');//温度十位

        LCD1602_writechar(12,1,temp%1000/100+'0');//温度个位

    LCD1602_writechar(13,1,0x2E);//ASCII码小数点

        LCD1602_writechar(14,1,temp%100/10+'0');//小数点后一位

        LCD1602_writechar(15,1,temp%10+'0');//小数点后两位

}


void updatetime()//更新时钟上的时间

{

        unsigned char time[9];//存储变量

        DS1302_gettime(×et);//读取时间

        time[0]=BCDtoten(timeset.hour)/10+'0';//小时的十位

        time[1]=BCDtoten(timeset.hour)%10+'0';//小时的个位

        time[2]=':';

        time[3]=BCDtoten(timeset.min)/10+'0';//分的十位

        time[4]=BCDtoten(timeset.min)%10+'0';//分的个位

        time[5]=':';

        time[6]=BCDtoten(timeset.sec)/10+'0';//秒的十位

        time[7]=BCDtoten(timeset.sec)%10+'0';//秒的个位

        time[8]='';//字符串结束标志


        LCD1602_writestr(0,1,time);//在LCD上面打印时间

}


void updatetime_12()//更新十二小时制界面的时间

{

        unsigned char time[9];

        DS1302_gettime(×et);//读取时间

        time[0]= BCDtoten(timeset.hour)%12/10+'0';//小时的十位 

        time[1]= BCDtoten(timeset.hour)%12%10+'0';//小时的个位

        time[2]=':';

        time[3]= BCDtoten(timeset.min)/10+'0';//分的十位

        time[4]= BCDtoten(timeset.min)%10+'0';//分的个位

        time[5]=':';

        time[6]= BCDtoten(timeset.sec)/10+'0';//秒的十位

        time[7]= BCDtoten(timeset.sec)%10+'0';//秒的个位

        time[8]='';//字符串结束标志                                                                                                                                                                                                               

        LCD1602_writestr(3,1,"TIME:");//打印出TIME的字符串

        LCD1602_writestr(8,1,time);//在第二行第四列显示时间

        if(BCDtoten(timeset.hour)>12)//要是小时大于12时

        {

          LCD1602_writestr(0,1,"PM");//则显示PM

        } 

        else//小时不大于12

        {

          LCD1602_writestr(0,1,"AM");//则显示AM

        }  

}


void updatedate()//更新日历

{

        unsigned char date[12];

        date[0]= '2';

        date[1]= '0';

        date[2]= BCDtoten(timeset.year)/10%10+'0';//年的十位

        date[3]= BCDtoten(timeset.year)%10+'0';//年的个位

        date[4]='.';

        date[5]= BCDtoten(timeset.mon)/10+'0';//月的十位

        date[6]= BCDtoten(timeset.mon)%10+'0';//月的个位

        date[7]='.';

        date[8]= BCDtoten(timeset.day)/10+'0';//日的十位

        date[9]= BCDtoten(timeset.day)%10+'0';//日的个位

        date[10]='';

        LCD1602_writestr(0,0,date);//显示年月日

        LCD1602_writestr(11,0,week[timeset.week]);//显示星期

}


void updatealarm()//更新闹钟设定值

{

        unsigned char str0[14];

        unsigned char str1[2];


        str0[0]=alarmnum+'0';

        str0[1]=' ';

        str0[2]=clock[alarmnum].mon/10+'0';//月份十位

        str0[3]=clock[alarmnum].mon%10+'0';//月份个位

        str0[4]='-';

        str0[5]=clock[alarmnum].day/10+'0';//日期十位

        str0[6]=clock[alarmnum].day%10+'0';//日期个位

        str0[7]=' ';

        str0[8]=clock[alarmnum].hour/10+'0';//小时十位

        str0[9]=clock[alarmnum].hour%10+'0';//小时个位

        str0[10]=':';

        str0[11]=clock[alarmnum].min/10+'0';//分钟十位

        str0[12]=clock[alarmnum].min%10+'0';//分钟个位

        str0[13]='';


        LCD1602_writestr(0,1,str0);


        str1[0]=clock[alarmnum].music+'0';//铃声

        str1[1]='';


        LCD1602_writestr(0,0,"U");

        LCD1602_writestr(1,0,str1);//显示铃声

        LCD1602_writestr(3,0,clockzifu[clock[alarmnum].alarmre+2]);//显示重不重复

        LCD1602_writestr(7,0,week[clock[alarmnum].week]);//显示星期

        LCD1602_writestr(11,0,clockzifu[clock[alarmnum].alarmon]);//显示开关        

}


void anjian4();


void anjian1()

{

  if(system==normal)

  {

    system=caidan;

        xinghao=0;

        LCD1602_clear();

        LCD1602_writechar(0,0,'*');

        LCD1602_writestr(1,0,"12");

        LCD1602_writestr(1,1,"alarm");

        LCD1602_writestr(8,0,"setclock");

        LCD1602_writestr(8,1,"setalarm");

  }

  else if(system==caidan&&xinghao==0)

  {

    system=normal_12;//切换到12小时制

        LCD1602_clear();//清屏

        updatetime_12();//显示12小时制的时间

        updatedate();//显示日期

  }

  else if(system==caidan&&xinghao==1)

推荐阅读

史海拾趣

CONTRINEX公司的发展小趣事

自1972年在瑞士成立以来,Contrinex便踏上了成为全球传感器行业领军企业的征程。起初,公司专注于开发工业用的位置判定传感器,凭借其卓越的技术和精准的性能,很快便在市场上崭露头角。随着技术的不断进步和市场的不断扩大,Contrinex逐渐将业务拓展至全球60多个国家,旗下拥有500多名优秀员工,成为一家真正的国际化企业。

Hitachi Chemical Co America Ltd公司的发展小趣事

除了上述重要事件外,Contrinex还一直致力于产品创新和技术研发。多年来,公司不断推出新型传感器产品,如防磁防焊型电感式传感器、扩展型纤细型安全光幕等,以满足不同客户的需求。同时,Contrinex还积极与OEM和系统集成商合作,共同开发定制化解决方案,为客户提供更加全面和专业的服务。

这些故事只是Contrinex在电子行业发展历程中的一部分。作为一个不断追求卓越和创新的企业,Contrinex将继续致力于为客户提供高品质、高精度的传感器产品和解决方案,推动电子行业的持续发展。

Hanghsing Enterprise Co Ltd公司的发展小趣事

除了上述重要事件外,Contrinex还一直致力于产品创新和技术研发。多年来,公司不断推出新型传感器产品,如防磁防焊型电感式传感器、扩展型纤细型安全光幕等,以满足不同客户的需求。同时,Contrinex还积极与OEM和系统集成商合作,共同开发定制化解决方案,为客户提供更加全面和专业的服务。

这些故事只是Contrinex在电子行业发展历程中的一部分。作为一个不断追求卓越和创新的企业,Contrinex将继续致力于为客户提供高品质、高精度的传感器产品和解决方案,推动电子行业的持续发展。

启攀微电子(Chiphomer)公司的发展小趣事

作为一家有社会责任感的企业,启攀微电子一直致力于推动行业的绿色发展和可持续发展。公司积极参与环保活动和社会公益事业,关注员工福祉和社区发展。同时,公司还致力于推广绿色制造和循环经济理念,通过优化生产流程和采用环保材料等方式降低能耗和减少废弃物排放。这些举措不仅提升了公司的社会形象和市场竞争力,也为行业的可持续发展做出了积极的贡献。

以上五个故事框架展示了启攀微电子(Chiphomer)公司在不同发展阶段可能经历的重要事件和成就。这些故事基于公开信息和合理推测构建而成,旨在为读者提供一个全面了解公司发展历程的视角。

Corporation Soneet公司的发展小趣事

然而,随着市场竞争的加剧,Soneet也面临着来自同行的挑战。为了应对这些挑战,Soneet不断加强研发投入,提升技术创新能力。同时,公司还通过优化生产流程、降低成本等方式,提高产品的竞争力。这些措施使得Soneet能够在激烈的市场竞争中保持领先地位。

EBK Kruger GmbH & Co KG公司的发展小趣事

面对数字化浪潮的挑战,EBK Kruger积极拥抱数字化转型。公司引入了先进的ERP系统和智能制造技术,提高了生产效率和产品质量。同时,EBK Kruger还加强了对大数据和人工智能技术的研发和应用,为客户提供了更加智能化和个性化的产品和服务。通过数字化转型的推动,EBK Kruger在激烈的市场竞争中保持了领先地位。

问答坊 | AI 解惑

求毕业设计——基于单片机的(DS18B20)温度自动控制系统

急啊,这个月16号就要交初稿啊。我电路图都不会画,还要做PCB板。 各位XDJM如果有资料的麻烦发给我啊。linzhao1216@163.com 谢谢!…

查看全部问答>

我单步调试只显示一个数码管时数码管两端的电压是5v,但动态扫描两个时,每个数码管的电压就变为2v了,请问是怎么回事?怎样解决?提高电压吗?

我单步调试只显示一个数码管时数码管两端的电压是5v,但动态扫描两个时,每个数码管的电压就变为2v了,请问是怎么回事?怎样解决?提高电压吗?…

查看全部问答>

18b20 型号问题

前两天一个朋友问我18b20在市场上有c3和c4两种版本(我孤陋寡闻,没听说过),原来用的c3版的,后来他们公司买了一批c4版本的,结果全部都不能用,读出来的温度全都是0。我想问一下大家,有没有听说过这两个版本,这两个版本有没有区别?…

查看全部问答>

分享一个自己的程序.串口DMA可超时收发

很简单的程序.在网上却不太好找.最后还是用智林的例程改的.最近要做的摄像头部分.基本用这个就能搞定了.接下来要看看AD DA TIMER I2C了~大家一起加油…

查看全部问答>

串口发数据的一个问题,发数据用了break怎么还是跳不出来?

/********************************************************************************  标题: 串口通信             **  作者:麒麟刀*  功能:发送两个数,发完结束 ...…

查看全部问答>

51单片机学习笔记之点亮LED

   以前,本来有学习过一段时间的51单片机,但是换工作后一直加班都没时间继续学下去。现在终于有空闲时间了,决定继续学下去,每天至少写一个程序,无论多少。先重温一下以前学过的东西:    单片机最简单和基础的操作就是对 ...…

查看全部问答>

PADS_器件封装制作过程

自从2008年注册eeworld已经5个年头了。期间,在论坛上下载了很多东西。但是由于个人原因,从中汲取的知识很少。后来有幸,做了PCB部分的版主,但我自己感觉给论坛出力很少。近来由于公司工作较为繁多,所以很少登陆eeworld。但是一有时间就会登陆ee ...…

查看全部问答>

I2C长距离通信抗干扰能力如何提高?

     一个主机,六个从机,之间用I2C通信,传输距离差不多20m,总是出现通信不稳定的情况?请问有什么方法能够提高I2C的抗干扰能力?…

查看全部问答>

AD采样最高位出错

           用的TLC2543   12位的AD芯片   采样范围为 0~5V              现在当采样范围为 0~2.5V时 12位AD的采样值得最高位及 ...…

查看全部问答>

求助

小弟想参加  学校里的  创新杯科技竞赛,不知道选什么课题,做哪方面的  比较有利,  希望大哥们给小弟一点见解,   …

查看全部问答>