51单片机初学3 您所在的位置:网站首页 52单片机电子时钟程序 51单片机初学3

51单片机初学3

2024-07-16 07:48| 来源: 网络整理| 查看: 265

今天我们用STC89C52制作一款简单的单片机作品:电子时钟。除了基本的走时功能,还能手动调节时间,设置闹钟,待机唤醒。

本文包括硬件与软件设计。

我认为电子时钟需要考虑的两点:一是计时准确,误差小;二是省电,使其能在移动电源供电下超长待机。

硬件设计:

首先我们需要构思好系统框架:

基本的时钟电路与复位电路不用多说,我们用八位数码管来作为时间显示方式(显示样式为:12-00-00),其中P0口控制其段,P2口控制其位;以八个点动按钮作为键盘输入;蜂鸣器、LED分别作为提示音和指示灯。

接下来就可以设计原理图:

可以看到数码管的接线较复杂,其原理暂不多说(可参考文章51单片机初学2-数码管动态扫描_#liufenges#的博客-CSDN博客_数码管动态扫描),可以看到两个数码管的1、2、3、4、5、7、10、11是分别连起来的,然后引出来连接到P0口;两个数码管的6、8、9、12共8个脚与P2口连接。

需要注意,数码管位控制与P2口之间加入了一个锁存器74HC373,其作用是在待机时方便关闭数码管。其11脚是地址锁存端口,将其接高电平时,锁存器为透明模式,输入与输出完全相同,这里我直接接入VCC;1脚为输出锁存,高电平时无输出,低电平才有输出,这里我们用P3.6来控制其输出。下图是74HC373引脚图及其功能。

为了简化电路,蜂鸣器与LED共用一个I/O口;

单片机的数据串口引出来接到排针上,方便程序烧录。

需要注意,为了防止数码管烧坏,在P0口应串联470欧姆的限流电阻(原理图中未画出)。

所以得到所需材料:

STC89C52芯片(1块),40P底座(1只),面包板(2片),3461BS数码管(2只),点动按钮(9只),LED灯(1只),74HC373锁存芯片(1片),10K 9P排阻(4只),470欧电阻(15只),12M晶振(1只),30pF瓷片电容(两个),排针(15针),led灯,有源蜂鸣器一只(关于有源与无源蜂鸣器的区别可在网上查阅),PNP型三极管一只。

最后我们按照原理图焊接元件。以下为成品图片可供参考

为了使作品看起来简洁,我们采用双主板设计,上层为数码管、键盘,下层为单片机最小系统,两层主板使用小螺栓固定。

由于定做PCB时间较长,所以我使用洞洞板来制作电路板(若是不擅长电子焊接,最好是制作PCB),可以看到飞线很多,两块主板之间有较多的连接线(为了防止焊点受力而脱落,可以将线绕在洞洞之间)。注意焊接单片机底座时,不要把单片机装在底座上,以免焊接时烧坏单片机芯片;同样,焊接晶振时,要尽可能快,避免长时间给晶振加热而损坏晶振;安插单片机芯片时要注意对齐引脚,以免折断或者接触不良,插好后可以用万用表测量一遍所有引脚是否与底座导通;排阻公共端判断方法:在排阻最左边或者最右边会有个白色小点,有白点的一端为公共端;点动按钮有四个引脚(一组常开触点,一组常闭触点),可按照原理图所示将两个引脚接入。

单片机程序开发常用 keil软件(这里我们以Keil uVision3为例):

首先新建工程(点击project→new→选择一个文件地址后保存),然后选择CPU型号。

STC89C52是完全兼容AT89C52的(因为STC是国产芯片,keil中没有STC芯片,只能用其他芯片代替),所以我们选择AT89C52即可(首先点Atmel,下拉之后,可以找到AT89C52)。

之后会弹出询问窗口:Copy standard 8051 Startup code to Project Folder and Add File to project?(是否复制8051启动编码到工程文件夹?),点击确认即可。若点击取消,在创建文件时也会自动添加。

可以看到创建了一个Target1的工程文件,下拉时候还有一个Source Group1的文件夹。这个文件夹里有个STARTUP.A51的文件,这就是刚才复制的8051启动编码,里面包含51单片机的寄存器、I/O口等地址的分配,这些都是软件自动生成的,一般不需要去更改。

之后添加C程序文件:File→new。然后会创建一个text1的空白文件。然后我们点击保存(或者Ctrl+S),选择保存地址(保存在一个容易找到的地方,后面需要用到),输入文件名,注意文件名要加后缀.c保存为C文件。如果是用汇编语言写程序,则加后缀.ASM。

接着右击Source Group1,在菜单中找到Add Files To Group ‘Source Group1’点击(这个选项在菜单中有加粗显示)。然后将刚才的c程序文件添加至工程,关闭对话框。可以看到Source Group1下多了之前的C文件。

然后就可以写程序了。

程序编写:

定义单片机C程序的头文件#include

为了方便后面写程序时,搞混I/O口,我们可以先定义一些功能引脚。例如蜂鸣器,我们查看原理图可以看到,蜂鸣器是由P3.1控制的,所以我们定义P3.1为蜂鸣器:sbit fm=P3^1;(‘sbit’是单片机用于定义引脚的关键字,在C语言中是没有这个关键字的;P3.1之间的点在程序中要用‘^’表示),这样,在之后的程序中,如果我们要用到蜂鸣器,只要让fm等于0或者等于1,就可以控制蜂鸣器的工作了,而不再需要使用P3^1了。

然后我们还要对数码管进行编码,数码管需要显示的字符较多,我们可以使用一个数组来定义:

char codeduan[]={0xc0,0xcf,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f,0xbf,0xff,0x89};

(char数据类型:在单片机中,char数据类型所占空间最少,只有1个字节(八位二进制),但他的范围为 -128~127 (signed有符号型),unsigned为0~255。所以如果该变量数据范围不大,一般用char类型,这样做可以节省单片机空间) 。

接着定义全局变量 sec,min,hour.之所以定义为全局变量,是为了让这三个量所有函数中都是能使用的。

在本作品中,延时函数必不可少,比如数码管扫描,走时都需要延时函数(常用的方法还有定时器中断)。关于延时函数的计算问题可自行百度,为了方便,我们可以直接使用STC-IPS软件自动生成,只要输入需要延时的时间,软件可以自动生成一个延时函数,直接复制粘贴就可以(最小时间为1us)。   由于我们需要多种时间的延时,所以我们可以先把需要的延时函数先写在前面,方便之后的调用。

定义好需要的变量,我们就可以开始写主函数了。这里我们把数码管扫描与计时作为主程序,数码管扫描与计时同时进行。

接着编写调时子函数,闹钟子函数。在主程序插入判定条件,以此调用子函数。

为了添加更多花样,还添加了一个开机‘动画’  motos();(详情看后面的程序)

需要注意的是,子函数应置于主函数前面,否则编译时会提示 未定义子函数 。

再说说键盘的处理。键盘排列与键位设置如下。

K1、K2控制光标的左右移动,K3、K4控制数字加减,K5为确定键,K6为调时(长按4秒进入),K7设置闹钟,K8待机模式。

其他细节暂不多说,看程序即可。

完整程序如下:

/*电子时钟程序:基本电子时钟功能,能调节时间,能设置闹钟(已删减),有待机模式(已删减)*/ /*LED数码管显示器设定; P0.0---P0.7段控线,接LED的显示段a,b,c,d,e,f,g,dp. P2.0---P2.7位控线,从左至右 ************键位设置******************* W3(+) W1(光标左移) W5(确认) W2(光标右移) W6(调时) W7(闹铃) W8 (唤醒) W4(-) **************************************/ #include #include //定义单片机的头文件 sbit fm=P3^1; //定义单片机蜂鸣器 sbit plays=P3^6; //定义73HC373输出控制位 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 // char codeduan[]={0xc0,0xcf,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f,0xbf,0xff,0x89}; //数码管段编码 // 0 1 2 3 4 5 6 7 8 9 dp - 空 H // char codebite[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00}; //数码管位编码 char sec=0,min=0,hour=0; void Delay1ms() //@12.000MHz,1ms延时函数,用于数码管动态输出 { unsigned char i, j; i = 2;j = 239; do { while (--j); } while (--i); } void Delay50ms() //@12.000MHz,用于蜂鸣器提示音,30ms { unsigned char i, j, k; i = 2;j = 95;k = 43; do { do { while (--k); } while (--j); } while (--i); } void adjust() //时间调整模式子程序 { int H=0,cursor=3; char ks,twi,temps[8],K[8]; temps[2]=11; temps[5]=11; fm=0;Delay50ms();fm=1; //蜂鸣器响一声提示进入时间调整模式 while(P1!=0xef) //如果没有按下K8,则执行循环 { if(H180) {twi=1;} if(H==360) {H=0;} for(ks=0;ks59) {sec=0; } /*对时,分,秒范围进行限制 */ if(sec59) {min=0; } if(min23){hour=0; } if(hour


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有