单片机课程设计(数字时钟) 麻烦大家不要发链接 直接帮我把程序写过来。

单片机课程设计(数字时钟) 麻烦大家不要发链接 直接帮我把程序写过来。,第1张

哈哈 有个1602显示的 不过程序太长 贴不上 给你个数码管的吧 不行再联系

1302.c

#include<DS1302.h>

#include<key.h>

uchar bit_ser[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}

uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}

/***********************时间显示*****************/

void timer0_init(void)  //T0初始化函数,用于时间的动态显示

{

TMOD = 0x21

TL0 = (65536-5000) % 256

TH0 = (65536-5000) / 256

EA = 1

ET0 = 1

TR0 = 1

}

void timer0_isr(void) interrupt 1  //T0中断处理函数

{

char flag   //flag用于表示调整时闪烁的亮或灭

TR0 = 0

TL0 = (65536-5000) % 256

TH0 = (65536-5000) / 256

TR0 = 1

flag = x / 100 * 0xff //设置闪烁标志,如果x大于100则flag为0xff,小于100则为0x00

x++

if(x > 200)

x = 0

switch(i)

{

case 0:

P2 = bit_ser[0]

if(setflag == 3)  //根据setflag的值判断当前位是否需要闪烁

P0 = flag | seven_seg[dis_buffer[0]]

else

P0 = seven_seg[dis_buffer[0]]

break

case 1:

P2 = bit_ser[1]

if(setflag == 3)

P0 =flag | seven_seg[dis_buffer[1]]

else

P0 =seven_seg[dis_buffer[1]]

break

case 2:

P2 = bit_ser[2]

if(setflag == 2)

P0 =flag | seven_seg[dis_buffer[2]]

else

P0 =seven_seg[dis_buffer[2]]

break

case 3:

P2 = bit_ser[3]

if(setflag == 2)

P0 =flag | seven_seg[dis_buffer[3]]

else

P0 =seven_seg[dis_buffer[3]]

break

case 4:

P2 = bit_ser[4]

if(setflag == 1)

P0 =flag | seven_seg[dis_buffer[4]]

else

P0 =seven_seg[dis_buffer[4]]

break

case 5:

P2 = bit_ser[5]

if(setflag == 1)

P0 =flag | seven_seg[dis_buffer[5]]

else

P0 =seven_seg[dis_buffer[5]]

break

}

i++

if(i >= 6)

{

i = 0

if(j == 10)

{

j = 0

if(setflag == 0)

DS1302_GetTime(&Time) //如果setflag是0,就从1302中读出时间,因为setflag不是0时,说明处于调整状态,不需要读时间

dis_buffer[5] = Time.Second % 10 //把当前时间放入显示缓冲区

dis_buffer[4] = Time.Second / 10

dis_buffer[3] = Time.Minute % 10

dis_buffer[2] = Time.Minute / 10

dis_buffer[1] = Time.Hour % 10

dis_buffer[0] = Time.Hour / 10

}

j++

}

}

void main()

{

Initial_DS1302(Time)

timer0_init()

while(1)

{

set_down()

timer_down()

up_down()

down_down()

beepflag_down()

if(setflag == 0 && Time.Hour == romhour && Time.Minute == romminute && Beepflag == 1) //判断蜂鸣器是否要响

Beep = !Beep

}

}

//key.c

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

uchar i = 0,j = 0,x = 0,setflag,flag_set,flag_timer   //setflag用来表示调整的位置,flag_set和flag_timer分别表示当前处于调整状态还是定时状态

SYSTEMTIME Time={0,20,15,3,30,6,10}    //系统时间的初始值2010年6月30日星期三,15时20分0秒

char dis_buffer[6]    //存放显示数据的缓冲区

sbit Beep_flag = P3^2    //蜂鸣器的接口

sbit key_timer = P3^4    //定时按钮

sbit key_set = P3^5    //调整按钮

sbit key_up = P3^6    //增加按钮

sbit key_down = P3^7    //减小按钮

char romhour,romminute,romsec    //分别存放定时的时,分,秒

bit Beepflag    //标记闹钟是否开启

//延时函数

void delays(uchar x)

{

while(x) x--

}

//设置键的处理函数

void set()

{

setflag ++

flag_set = 1

if(setflag >= 4)

{

setflag = 0

flag_set = 0

Initial_DS1302(Time)

}

}

//定时间的处理函数

void timer()

{

setflag ++

flag_timer = 1

if(setflag == 1)

{

Time.Hour = romhour

Time.Minute = romminute

Time.Second = romsec

}

else if(setflag >= 4)

{

setflag = 0

flag_timer = 0

romhour = Time.Hour

romminute = Time.Minute

romsec = Time.Second

}

}

//增加键的处理函数

void up()

{

switch(setflag)

{

case 0:

break

case 1:

Time.Second ++

if(Time.Second >= 60)

Time.Second = 0

break

case 2:

Time.Minute ++

if(Time.Minute >= 60)

Time.Minute = 0

break

case 3:

Time.Hour ++

if(Time.Hour >= 24)

Time.Hour = 0

break

}

}

//减小键的处理函数

void down()

{

switch(setflag)

{

case 0:

break

case 1:

Time.Second --

if(Time.Second < 0)

Time.Second = 59

break

case 2:

Time.Minute --

if(Time.Minute < 0)

Time.Minute = 59

break

case 3:

Time.Hour --

if(Time.Hour < 0)

Time.Hour = 23

break

}

}

//设置键的扫描函数

void set_down()

{

if(key_set == 0 && flag_timer == 0)

{

delays(100)

if(key_set == 0)

{

set()

}

while(!key_set)

}

}

//定时键的扫描函数

void timer_down()

{

if(key_timer == 0 && flag_set == 0)

{

delays(100)

if(key_timer == 0)

{

timer()

}

while(!key_timer)

}

}

//增加键的扫描函数

void up_down()

{

if(key_up == 0 && setflag != 0)

{

delays(100)

if(key_up == 0)

{

up()

while(!key_up)

}

}

}

//减少键的处理函数

void down_down()

{

if(key_down == 0 && setflag != 0)

{

delays(100)

if(key_down == 0)

{

down()

while(!key_down)

}

}

}

//定时开关的扫描处理函数

void beepflag_down()

{

if(Beep_flag == 0)

{

delays(100)

{

Beepflag = !Beepflag

while(!Beep_flag)

}

}

}

//ds1302.h

#ifndef _REAL_TIMER_DS1302

#define _REAL_TIMER_DS1302

#include <REG51.h>

sbit  DS1302_CLK = P1^1              //实时时钟时钟线引脚

sbit  DS1302_IO  = P1^2              //实时时钟数据线引脚

sbit  DS1302_RST = P1^3              //实时时钟复位线引脚

sbit  ACC0 = ACC^0

sbit  ACC7 = ACC^7

sbit  Beep = P2^7

typedef struct __SYSTEMTIME__

{   char Second

char Minute

char Hour

char Week

char Day

char Month

char Year

}SYSTEMTIME //定义的时间类型

#define AM(X) X

#define PM(X) (X+12)               // 转成24小时制

#define DS1302_SECOND 0x80          //秒寄存器

#define DS1302_MINUTE 0x82          //分寄存器

#define DS1302_HOUR 0x84

#define DS1302_WEEK 0x8A

#define DS1302_DAY 0x86

#define DS1302_MONTH 0x88

#define DS1302_YEAR 0x8C

#define DS1302_RAM(X) (0xC0+(X)*2)    //用于计算 DS1302_RAM 地址的宏

void DS1302InputByte(unsigned char d)  //实时时钟写入一字节(内部函数)

{   unsigned char i

ACC = d

for(i=8 i>0 i--)

{ DS1302_IO  = ACC0            //相当于汇编中的 RRC

DS1302_CLK = 1

DS1302_CLK = 0                 //发一个高跳变到低的脉冲

ACC = ACC >> 1

}

}

unsigned char DS1302OutputByte(void)  //实时时钟读取一字节(内部函数)

{  unsigned char i

for(i=8 i>0 i--)

{ ACC = ACC >>1          //相当于汇编中的 RRC

ACC7 = DS1302_IO

DS1302_CLK = 1

DS1302_CLK = 0                 //发一个高跳变到低的脉冲

}

return(ACC)

}

void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据

{ DS1302_RST = 0

DS1302_CLK = 0

DS1302_RST = 1

DS1302InputByte(ucAddr)        // 地址,命令

DS1302InputByte(ucDa)        // 写1Byte数据

DS1302_CLK = 1

DS1302_RST = 0                  //RST 0->1->0,CLK 0->1

}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据

{ unsigned char ucData

DS1302_RST = 0

DS1302_CLK = 0

DS1302_RST = 1                      //enable

DS1302InputByte(ucAddr|0x01)        // 地址,命令

ucData = DS1302OutputByte()         // 读1Byte数据

DS1302_CLK = 1                      //RST 0->1->0,CLK 0->1

DS1302_RST = 0

return(ucData)

}

void DS1302_SetProtect(bit flag)        //是否写保护

{ if(flag)

Write1302(0x8E,0x80) //WP=1,不能写入

else

Write1302(0x8E,0x00)//WP=0,可以写入

}

void DS1302_SetTime(unsigned char Address, unsigned char Value)        // 设置时间函数

{ DS1302_SetProtect(0)

Write1302(Address, ((Value/10)<<4 | (Value%10))) //高4位为十位,低4位为个位

DS1302_SetProtect(1)

}

//获取时间函数,从DS1302内读取时间然后存入Time内

void DS1302_GetTime(SYSTEMTIME *Time)

{ unsigned char ReadValue

ReadValue = Read1302(DS1302_SECOND)

Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)//转换成10进制的秒

ReadValue = Read1302(DS1302_MINUTE)

Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

ReadValue = Read1302(DS1302_HOUR)

Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

ReadValue = Read1302(DS1302_DAY)

Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

ReadValue = Read1302(DS1302_WEEK)

Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

ReadValue = Read1302(DS1302_MONTH)

Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

ReadValue = Read1302(DS1302_YEAR)

Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F)

}

//利用STime初始化DS1302

void Initial_DS1302(SYSTEMTIME STime)

{ unsigned char Second=Read1302(DS1302_SECOND)

if(Second&0x80)   DS1302_SetTime(DS1302_SECOND,0)  //如果第七为1(表明没有启动), 则启动时钟

DS1302_SetTime(DS1302_SECOND,STime.Second)  //设定起始时间

DS1302_SetTime(DS1302_MINUTE,STime.Minute)

DS1302_SetTime(DS1302_HOUR,STime.Hour)

DS1302_SetTime(DS1302_DAY,STime.Day)

DS1302_SetTime(DS1302_MONTH,STime.Month)

DS1302_SetTime(DS1302_YEAR,STime.Year)

DS1302_SetTime(DS1302_WEEK,STime.Week)

}

#endif

像做电子钟一般你要先确定你的各个模块用什么实现,比如显示是用LCD还是数码管,计时用定时器还是时钟芯片。对于你这个我推荐你用专门的日历时钟芯片,如DS1302。虽然看起来加个模块更复杂了,其实不然,对于你这个功能比较多的项目,不用时钟芯片,程序会变得很复杂。本人大学是做过这个,完全软件实现。后来又做过DS1302的,其实这个不难,你只需要通过SPI接口对它进行简单的读写,至于如何计时不用在程序中专门去写。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/yw/11212473.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存