问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

51单片机控制DS1302,时间显示在数码管上。21

发布网友 发布时间:2023-09-18 11:04

我来回答

1个回答

热心网友 时间:2023-10-17 22:34

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_SECOND0x80          //秒寄存器      

#define DS1302_MINUTE0x82          //分寄存器

#define DS1302_HOUR0x84 

#define DS1302_WEEK0x8A      

#define DS1302_DAY0x86

#define DS1302_MONTH0x88

#define DS1302_YEAR0x8C

#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

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
长期胃胀怎么调理 魔渊之刃弓箭手攻略 弓箭手法盘装备发育攻略 妻妾迎新送死,倏恩倏爱,倏痛倏悲,缠绵不了是什么意思? 请学过美术或者动漫游戏设计的人回答我的问题。 画一个穿着和头型都相 ... ...和“我有一个可爱并且很淘气的女儿”用英文怎么说 “如果你叫我回答这个问题就是浪费时间,希望老师能找下一个学生”有英 ... 加勒比海盗拍了几部 《加勒比海盗5》第四部女主或回归 与开花同框 购买佳能相机开出的正式发票是佳能公司统一的发票还是各销售公司自己... ...我想早点上美国陪他,请问现在可以办旅游探亲证吗? 如何只用单片机让小灯“渐亮渐灭” 杨洋真名叫什么2179 杨洋个人资料爱好,特长264 关于杨洋的网名有哪些不想太直接3835 为什么越来越多的人选择了在职研究生? 杨洋应援口号是什么801 为什么小灯泡灯丝由暗变亮的过程及小灯泡温度逐渐升高的过程? 孩子的学习兴趣培养有哪些好的方法? 如何申请第二个? 英雄联盟烬的技能有哪些? 猎聘网上给猎头发了简历为啥都不被查看呢12 看到你以前有过打了狂犬疫苗为阴的经历,我想问下后来你是怎么做... 疾控中心没有检测狂犬病毒抗体,请问上海哪个医院有检测血清抗狂...7 请问我是不是得了狂犬病啊?1 打完狂犬疫苗要不要检查抗体24 如何理解万达企业文化4 小规模没有成本发票怎么处理3 只有开出去的票,没有成本发票怎么办?13 公司没成本票怎么解决? 华为P10 Plus拆机详解 谁知道&lt;道北人&gt;这部电视剧啊12 胡亚捷主演的电视剧详细的?1 糖尿病患者可以学跳爵士舞吗? 猎聘网上怎样和猎头联系(有免费的方法吗)16 滴滴手续办下来以后能值钱吗 怎么让快递员把货送到自己家楼下的架空层 水肿怎么把水排出来?怎样预防水肿? 这个黄笑话看不懂啊~ 小红帽去找奶奶,然后奶奶就被大灰狼吃掉了。_百度... 体温35.5度,36度,属于正常体温吗 楚霸王项羽VS李元霸 只说单条啊 哪个比较强 亚洲水稻种植业区位因素?87 最正宗酱香排骨的做法 怎么做酱香排骨好吃2 单冲模,落料模,复合模分别都由几块板组成各起什么作用?我想学...9 怎样做好吃的酱香排骨1 我最近在完成一个冲压模具的设计,是冲孔落料复合模。下模具上有...2 圆环垫片的生产流程图,用的是冲孔落料复合模,生产的流程是什么...1 哪个版本的《雪山飞狐》最好看,大家推荐一下,说说理由! hpv凝胶医保可以报销吗 全国最大的万达广场在哪个城市?137 单片机 怎么把俩个程序整合到一起 一个是基于单片机的电子钟程...