独立按键控制ds1302

今天才明白CSDN中复制代码时不能复制keil中的空白行,但如果加上空格就没事了。
(本文是参考各种资料,自己将其进行总结,最终总结如下)
编写读和写函数用到的时序图:根据这个图来编写ds1302的写和读函数
在这里插入图片描述

寄存器的地址(读和写的地址),根据这个表格可以对时间的格式进行设置,设置的方法是:发送两个字节,第一个字节是地址,第二个字节是自己想要设置的格式。
在这里插入图片描述

以下为main.c文件

#include "reg52.h"    
#include"ds1302.h" 
typedef unsigned int u16;   //对数据类型进行声明定义
typedef unsigned char u8;


sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit k1 = P3^1;
sbit k2 = P3^0;
sbit k3 = P3^2;
sbit k4 = P3^3;


char num=0;
u8 DisplayData[8];//数码缓冲区
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//分别是0~9

void delay(u16 i)
{
 while(i--); //延迟函数
}

/*时间处理转换函数*/
void datapros()   
{
 Ds1302ReadTime();
 DisplayData[0] = smgduan[TIME[2]/16];//时,最高位数码管
 DisplayData[1] = smgduan[TIME[2]&0x0f];//时,次高位数码管
 DisplayData[2] = 0x40;
 DisplayData[3] = smgduan[TIME[1]/16]; //分  
 DisplayData[4] = smgduan[TIME[1]&0x0f]; 
 DisplayData[5] = 0x40;
 DisplayData[6] = smgduan[TIME[0]/16];  //秒  
 DisplayData[7] = smgduan[TIME[0]&0x0f];
}

void DigDisplay()
{
 u8 i;
 for(i=0;i<8;i++)
 {
  switch(i) 
  {
   case(0):
    LSA=0;LSB=0;LSC=0; break;
   case(1):
    LSA=1;LSB=0;LSC=0; break;
   case(2):
    LSA=0;LSB=1;LSC=0; break;
   case(3):
    LSA=1;LSB=1;LSC=0; break;
   case(4):
    LSA=0;LSB=0;LSC=1; break;//数码管显示
   case(5):
    LSA=1;LSB=0;LSC=1; break;
   case(6):
    LSA=0;LSB=1;LSC=1; break;
   case(7):
    LSA=1;LSB=1;LSC=1; break;
  }
  P0=DisplayData[7-i];
  delay(100); 
  P0=0x00;
 }  
/*定义按键的功能,k1进入设置,按一次k2调节秒,按两次是分,三次是小时,在按一次k1退出,按键k3为加,按键k4为减*/
int keypros() 
{
 u8 count_k1=0;
 u8 count_k2=0;
 u8 count_k3_k4=0;
 if(k1==0)    
 { 
  delay(1000);   //按键消抖
  if(k1==0) 
  {
   count_k1++; 
   while(!k1);  
   while(k1&&k3&&k4)  
   {
      if(k2==0)
    {
     delay(1000);
     if(k2==0)
      {
      count_k2++;
      if(count_k2==4)
       count_k2=1;
      while(!k2); 
     }
    }
   }
   while(k1)
   {
    if(k3==0) 
     {
     delay(1000);
     if(k3==0)
      count_k3_k4++;
     while(!k3);  
    }
    if(k4==0)
    {
     delay(1000);
     if(k4==0)
      count_k3_k4--;
     while(!k4);  
    }
    if(count_k2==1)
    {
     TIME[2]=TIME[2]+count_k3_k4;
    }
    if(count_k2==2)
     {
     TIME[1]=TIME[1]+count_k3_k4;
    }
    if(count_k2==3)
    {
     TIME[0]=TIME[0]+count_k3_k4;
    }
    count_k3_k4=0;
    }
   while(!k1);
  }
 }
 return count_k1;  
} 


void main()
{ 
 Ds1302Init();//初始化ds1302函数
 while(1)
 {
  datapros(); //时间处理转换函数
  DigDisplay();//数码管显示
 if(keypros())//按键
   Ds1302Init();  
 }  
}

以下为ds1302.h文件

#ifndef __DS1302_H_//固定格式
#define __DS1302_H_

#include<reg52.h>
#include<intrins.h>

#ifndef uchar
#define uchar unsigned char//定义uchar,其大致意思是如果没有定义uchar,则定义uchar为usigned char类型
#endif

#ifndef uint 
#define uint unsigned int
#endif

sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;//时钟信号

void Ds1302Write(uchar addr, uchar dat);//写字节函数
uchar Ds1302Read(uchar addr);//读取字节的函数
void Ds1302Init();
void Ds1302ReadTime();

extern uchar TIME[7]; 
#endifqi

以下为ds1302.c文件

#include"ds1302.h"
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//分别代表秒、分、时、星期、日、月、年

uchar TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};//采用的是十六进制,后面需要转化为十进制。


void Ds1302Write(uchar addr, uchar dat)//传入两个字节,第一个是地址,第二个是需要写入的数据
{
 uchar n;
 RST = 0;
 _nop_();
 SCLK = 0;
 _nop_();
 RST = 1;
 _nop_();
 for (n=0; n<8; n++)
 {
  DSIO = addr & 0x01;
  addr >>= 1;
  SCLK = 1;
  _nop_();
  SCLK = 0;
  _nop_();
 }
 for (n=0; n<8; n++)
 {
  DSIO = dat & 0x01;
  dat >>= 1;
  SCLK = 1;
  _nop_();
  SCLK = 0;
  _nop_(); 
 }   
 RST = 0;
 _nop_();
}


uchar Ds1302Read(uchar addr)//因为是读取函数,所以设置其为拥有返回值的模式
{
 uchar n,dat,dat1;
 RST = 0;
 _nop_();
 SCLK = 0;
 _nop_();
 RST = 1;
 _nop_();
 for(n=0; n<8; n++)
 {
  DSIO = addr & 0x01;
  addr >>= 1;
  SCLK = 1;
  _nop_();
  SCLK = 0;
  _nop_();
 }
 _nop_();
 for(n=0; n<8; n++)
 {
  dat1 = DSIO;
  dat = (dat>>1) | (dat1<<7);
  SCLK = 1;
  _nop_();
  SCLK = 0;
  _nop_();
 }
 RST = 0;
 _nop_();
 SCLK = 1;
 _nop_();
 DSIO = 0;
 _nop_();
 DSIO = 1;
 _nop_();
 return dat; 
}

void Ds1302Init()//初始化ds1302
{
 uchar n;
 Ds1302Write(0x8E,0X00);  
 for (n=0; n<7; n++)
 {
  Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); 
 }
 Ds1302Write(0x8E,0x80);  
}


void Ds1302ReadTime()
{
 uchar n;
 for (n=0; n<7; n++)
 {
  TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
 }  
}

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是C语言实现80c51独立按键控制数码管依次显示储存的一串数字的代码: #include<reg52.h> //头文件 #define uchar unsigned char //宏定义 #define uint unsigned int sbit key = P1^0; //按键复位 sbit dula = P2^6; //段锁锁存器1 sbit wela = P2^7; //位锁锁存器2 uchar ds1, ds2; //两个数码管的值 uint ms; //定时器的延时时间 void delayms(uint xms) //延时函数 { uint i,j; for(i=xms;i>0;i--) for(j=112;j>0;j--); } void display(uint num) //显示函数 { uchar ge,shi,bai,qian; //定义个十百千位的值 ge = num % 10; //取个位的值 shi = num / 10 % 10; //取十位的值 bai = num / 100 % 10; //取百位的值 qian = num / 1000 % 10; //取千位的值 if(ds1 == shi) //第一个数码管显示十位 { wela = 0xfe; //位锁锁存器2置低 P0 = 0x3f; //段锁锁存器1置0,使数码管不显示 dula = 0; //开启锁存器1 dula = 1; //锁定锁存器1 wela = 0xff; //开启锁存器2 ds1 = ge; //存储个位的值 } else //第一个数码管显示百位 { wela = 0xfd; //位锁锁存器2置低 P0 = 0x3f; //段锁锁存器1置0,使数码管不显示 dula = 0; //开启锁存器1 dula = 1; //锁定锁存器1 wela = 0xff; //开启锁存器2 ds1 = shi; //存储十位的值 } //第二个数码管显示千位 wela = 0xfb; //位锁锁存器2置低 P0 = 0x3f; //段锁锁存器1置0,使数码管不显示 dula = 0; //开启锁存器1 dula = 1; //锁定锁存器1 wela = 0xff; //开启锁存器2 ds2 = bai; //存储百位的值 } void main() { TMOD = 0x01; //定时器T0的模式设置,用时钟计时 TH0 = 0xfc; //定时器高位初始化 TL0 = 0x67; //定时器低位初始化 ET0 = 1; //打开定时器0中断 EA = 1; //打开总中断 TR0 = 1; //启动定时器T0 wela = 0xff; //位锁锁存器2置1,初始化位 ds1 = ds2 = 0; //初始化数码管的值 while(1) { if(key == 0) //按键按下 { delayms(5); //延时消抖 if(key == 0) //再次确认按键按下 { ms++; //定时器的延时时间加1 if(ms == 10000) //如果达到了设定的延时时间 { ms = 0; //重置定时器的延时时间 display(1234); //显示储存的一串数字 } } while(!key); //等待按键松开 } } } void timer0() interrupt 1 //定时器0中断函数 { TH0 = 0xfc; //重新加载高位 TL0 = 0x67; //重新加载低位 ms++; //定时器的延时时间加1 if(ms == 1000) //如果达到了设定的延时时间 { ms = 0; //重置定时器的延时时间 display(1234); //显示储存的一串数字 } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值