基于51单片机的万年历(包含闹钟,秒表)实现

发布者:qinghong最新更新时间:2020-06-23 来源: eefocus关键字:51单片机  万年历  闹钟  秒表 手机看文章 扫描二维码
随时随地手机看文章

开头唠一唠:


趁着寒假的时间,也趁着课程设计正好是做一个万年历。就打算好好从头到尾来一遍。涨涨知识。首先说的是本人也是小白一颗,大神们能帮忙指正错误的话,不胜感激。写博客只是为了总结经验,要是帮到一部分人就更好了。我想是从硬件到软件都介绍的详细一点,还想说一说自己遇到的一些问题,可能要写的长一点。代码的话我会在后面上传。好,闲话不多说。进入正题。


概述:


首先说一下我用到的东西,硬件方面(电路都是自己拿万能板焊的):一片51单片机,一块12864液晶,一片ds1302时钟芯片,四个按键。还有些电容、电阻、晶振什么的,下面讲到的时候再说吧。主要的就这么多吧。再简单说一下按键的功能吧,假设按键分别是k1,k2,k3,k4。首先lcd主界面是显示的当前的日期时间和四路闹钟的时间。附图。k1,k2,k3,k4最开始被按下时分别对应的功能是k1:进入时间设定模式;k2:进入日期设定模式;k3:进入闹钟设定模式;k4:进入秒表计数模式。进入不同的模式后,四个按键有都有了新的功能,首先k4一直是退出,就是退出到最开始的选四种模式。k1,k2,k3对于日期和时间设定模式是一样的功能k1:数值加1,k2:数值减1,k3:更换调的是小时还是分钟抑或年份还是月份。对于闹钟模式,k1:数值加1,k2:更换调的是小时还是分钟,k3:更换调的是第几个闹钟。对于秒表模式,k1:第一次按是开始计数,然后再按就是记录一下当前是多少秒,最多可以记录9次。k2:暂停/开始,k3:重新计数。有点绕得慌,简单的的说就是有两重循环。要是还没理解,可以看后面的代码。


一:硬件电路


这部分怎么说,说简单也挺简单的。但其中有个梗我现在还没过去。就是最开始我打算自己焊个下载电路在上面的,结果总是下不进去程序。这部分算是题外话了,但还是想简单说一说。最开始打算用CH340芯片直接usb转uart的,结果芯片买回来发现好像没有直插的。自己腐板子什么的又嫌太麻烦。最后打算先用usb转九针串口转成rs232电平,再用max232转成uart电平的。照着电路图一顿焊,结果果然不出我所料,不可能一下就成功下进去程序。就找问题啊,找啊找,找啊找。好像是找到了一个,就是51下程序不是有一个断电在上电的过程吗?我是这样做的,但其中好像有问题,断的这个电应该只是单片机的电,而不包括max232的电。于是又改电路,改完还是不行。算了,这个我以后搞明白了再来说说吧。


其余的应该就不算什么难的了,找一个51最小系统原理图照着焊呗,没什么太大的问题的。


对了,还有几个小的点,提一提吧。51的P0口是相当于集电极开路的门电路的,记得接上拉电阻。LCD屏导完程序时,最开始如果什么也不显示的话,记得调一下3脚接的电位器调一下背光。


二.软件设计


1.按键检测


这一部分在我最开始看来是没有什么大文章的,也没有什么可以值得写的,有点基础的人几分钟就可以把程序写出了。可是当自己正真写的时候,才知道自己不懂得太多,要学的也太多。单片机的IO口最普通的两种功能,输入和输出嘛。记得自己学stm32时,IO口的输入输出是要在最开始初始化的是定义的。也就是IO口在同一时刻只能有一种功能吧,总不能又输入有输出吧。可是51呢?让我懵逼,在任何地方,包括启动文件里都没有定义IO口是输入还是输出。这让我很郁闷,总不会我让一个IO口输出一个高电平后,还可以从IO口读输入吧,那样不一直应该读到的就是我输出的高电平吗。直到我好好研究了一波51IO口的内部电路,才明白其中的玄机。

这里是最简单的P1口的内部结构图。有点数电基础的人大概可以看明白。具体我就不讲了。你可以参考这里https://www.eeworld.com.cn/mcu/article_2017120236473_2.html


由上图可见,要正确地从引脚上读入外部信息,必须先使场效应管关断,以便由外部输入的信息确定引脚的状态。为此,在作引脚读入前,必须先对该端口写入l。具有这种操作特点的输入/输出端口,称为准双向I/O口。8051单片机的P1、P2、P3都是准双向口。P0端口由于输出有三态功能,输入前,端口线已处于高阻态,无需先写入l后再作读操作。弄懂IO口的内部结构之后。我就直接上程序了,慢慢研究吧。注释的和没有用到的部分大家就不要纠结了。


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

程序说明:按键的检测程序(基于51单片机),现在只有独立按键检测函数

Author: xingcheng

IO说明:按键接的

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

 

#include"key.h"

sbit KeyPort2=P1^5;

sbit KeyPort0=P1^7;

sbit KeyPort1=P1^6;

sbit KeyPort3=P1^4; //自己焊的按键接的单片机引脚

//sbit KeyPort2=P1^2;

//sbit KeyPort0=P1^0;

//sbit KeyPort1=P1^1;

//sbit KeyPort3=P1^3;

 

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

函数名称:key_scan()

函数功能:4个独立按键检测

输入参数:无

返回值:KeyV 通过返回值的不同来确定哪个按键被按下

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

uchar key_scan()

{

uchar KeyV;

KEYPORT=0xff; //从51IO口读数据,一般要先给锁存器写1,

//具体请参考51IO口内部结构

if(KeyPort0==0||KeyPort1==0||KeyPort2==0||KeyPort3==0) //判断是否有按键按下

//这里改成if((P3&0xf0)!=0xf0)总是错,原因可能是P3读数据不是从引脚读的

//而是从锁存器读的,一直是0xff

{

delay_ms(10); //防止抖动(拿板子实验时,发现这里延不延时并无影响)

if(KeyPort0==0) //判断哪个按键被按下//

{

KeyV=K1;

}

else if(KeyPort1==0)

{

KeyV= K2;

}

else if(KeyPort2==0)

{

KeyV=K3;

}

else if(KeyPort3==0)

{

KeyV=K4;

}

else 

{

KeyV= 0;

}   //判断哪个按键被按下//

if(KeyV != 0) //有按键按下时,进行松手检测

              while(KeyPort0==0||KeyPort1==0||KeyPort2==0||KeyPort3==0);

delay_ms(10); //延时消抖(拿板子实验,这里延时非常必要)

   }

 

    return KeyV; //返回KeyV来标识哪一个按键被按下

}

 

/*****************************有时间再完善连按,长按等功能************************/

 

/* while((KEYPORT&0Xf0)!=NO_KEY)

{

delay_ms(15);

PressCnt--;

if(PressCnt==0)

{

PressCnt=SHORTCNT;

return KeyV;

}

}

}

delay_ms(15);

if((KEYPORT&0Xf0)==NO_KEY)

{

ReleaseCon=0;

return KeyV;

}

  */

#ifndef __KEY_H#define _KEY_H

 

#include#include"delay.h"

 

#ifndef uchar #define uchar  unsigned char#endif

 

#define KEYPORT P3  //   四个按键接在了P3口的四个引脚#define NO_KEY   0xf0#define K1    0X01#define K2    0X02#define K3    0X03#define K4   0X04#define KEYSUB    0X02#define KEYADD    0X01#define KEYSET    0X04#define KEYNEXT   0X03 //K1,2,3,4,和这些是一样的,只是写.c文件时#define LONGCNT  150#define SHORTCNT 12

 

 

 

      uchar key_scan();

 

#endif



 

  2.lcd12864


     这个就是真的没什么好说的了。就是记得调电位器调背光。对了,还有一个 好坑的地方,不知道各位有没有解决方法,就是那个光标(一闪一闪的那个)每次移动都是两个字两个字的移。上程序。


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

程序功能:12864液晶驱动程序

其他:   只包括基本的字符串显示功能

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

 

 

#include

#define uchar unsigned char

#define uint  unsigned int

#define LCD_data  P0             //数据口

 

 

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

函数名称:delay(int ms)

函数功能:延时

输入参数:ms  要延时的ms数                                                                                                                                                                      

返回值:  无

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

 void delay(int ms)

 {

     while(ms--)

 {

       uchar i;

  for(i=0;i<250;i++)  

   {

    ; ; ; ;

   }

 }

 } 

 

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

函数名称:lcd_busy()

函数功能:检测LCD忙状态。

输入参数:无

返回值:  result result为1时,忙等待;result为0时,闲,可写指令数据

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

bit lcd_busy()

  {                          

     bit result;

     LCD_RS = 0;

     LCD_RW = 1;

     LCD_EN = 1;

      delay_ms(1);

     result = (bit)(LCD_data&0x80);

     LCD_EN = 0;

     return(result); 

  }

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

 /*写指令数据到LCD                                                  */

 /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             */                                                                

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

 void lcd_wcmd(uchar cmd)

 {                          

    while(lcd_busy());

     LCD_RS = 0;

     LCD_RW = 0;

     LCD_EN = 0;

     delay_ms(1);

     LCD_data = cmd;

    delay_ms(1);

     LCD_EN = 1;

    delay_ms(1);

     LCD_EN = 0;  

 }

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

 /*写显示数据到LCD                                                  */

 /*RS=H,RW=L,E=高脉冲,D0-D7=数据。                               */

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

 void lcd_wdat(uchar dat)

 {                          

    while(lcd_busy());

     LCD_RS = 1;

     LCD_RW = 0;

     LCD_EN = 0;

     LCD_data = dat;

    delay_ms(1);

     LCD_EN = 1;

   delay_ms(1);

     LCD_EN = 0; 

 }

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

 /*  LCD初始化设定                                                  */

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

 void lcd_init()

 { 

 

 

    LCD_PSB = 1;         //并口方式

     

     lcd_wcmd(0x34);      //扩充指令操作

     delay_ms(5);

     lcd_wcmd(0x30);      //基本指令操作

     delay_ms(5);

     lcd_wcmd(0x0C);      //显示开,关光标

     delay(5);

     lcd_wcmd(0x01);      //清除LCD的显示内容

     delay(5);

 }

 

 

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

 /* 设定显示位置       X:行数                Y:列数                                   */

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

 void lcd_pos(uchar X,uchar Y)

 {                          

    uchar  pos;

[1] [2] [3] [4]
关键字:51单片机  万年历  闹钟  秒表 引用地址:基于51单片机的万年历(包含闹钟,秒表)实现

上一篇:51单片机(九).51单片机简单项目—万年历和温度采集
下一篇:51单片机万年历

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved