一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 1922|回复: 5

[其他综合] 单片机写的钟求解决

[复制链接]
发表于 2012-10-24 23:40 | 显示全部楼层 |阅读模式
编了一个ds1302  +74hc573 +89c52 的钟  带整点报时,  现在的问题是一旦整点了一报时  这个报时的1秒里  显示不正常,  我现在的意思是想  在报时(蜂鸣器响1秒)的1,秒里  他能正常显示   上程序:
#include"89.h"
#include"INTRINS.h"
#define uchar unsigned char
#define uint unsigned int
sbit T_CLK=P2^5;
sbit T_IO=P2^6;
sbit T_RST=P2^7;
//数码管显示 定义
sbit k1=P1^5;   //实现复位(就是ds1302初始化)
sbit wei1=P2^0;  //四位数码管
sbit wei2=P2^1;
sbit wei3=P2^2;
sbit wei4=P2^3;
sbit k2=P1^2;  //实现设置键
sbit jia=P1^3;   //实现加
sbit jian=P1^4;//实现减
sbit duan=P2^4;//74hc573  高允许,低不允许。
sbit led=P1^1;//  实现两个LED灯 每秒闪一下
sbit fmq=P1^0;//蜂鸣器
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar a,b,c,d,n,x,s,zs,za;
char z,m;
void ys1s(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}
void baoshi()             //报时,为了美观 我这里把位  全开了
{
fmq=0;
wei1=0;
wei2=0;
wei3=0;
wei4=0;
ys1s();
fmq=1;
}
/******************蜂鸣器延时*********************/
void fmq50ms(void)   //误差 0us
{
unsigned char a,b;
for (b=173;b>0;b--)
  for (a=143;a>0;a--);
}
/******************按键延时*********************/
void aj10ms(void)   //误差 0us
{
unsigned char a,b,c;
for (c=1;c>0;c--)
  for (b=38;b>0;b--)
   for (a=130;a>0;a--);
}
/******************DS1302:写入操作(上升沿)*********************/
void write_byte(unsigned char da)
{
unsigned char i;
ACC=da;
for (i=8;i>0;i--)
{
  T_IO=ACC0;
  T_CLK=0;
  T_CLK=1;
  ACC=ACC>>1;
}
}
/******************DS1302:读取操作(下降沿)*****************/
unsigned char read_byte(void)
{
unsigned char i;
for (i=0;i<8;i++)
{
  ACC=ACC>>1;
  T_CLK = 1;
  T_CLK = 0;
  //delay(1);
  ACC7 = T_IO;
}
return(ACC);
}
/******************DS1302:写入数据(先送地址,再写数据)***************************/
void write_1302(unsigned char addr,unsigned char da)
{
T_RST=0;             //停止工作
T_CLK=0;
T_RST=1;            //重新工作
write_byte(addr);          //写入地址
write_byte(da);
T_RST=0;
T_CLK=1;
}
/******************DS1302:读取数据(先送地址,再读数据)**************************/
unsigned char read_1302(unsigned char addr)
{
unsigned char temp;
T_RST=0;                                    //停止工作
T_CLK=0;
T_RST=1;                            //重新工作
write_byte(addr);          //写入地址
temp=read_byte();
T_RST=0;
T_CLK=1;             //停止工作
return(temp);
}
/******************数码管显示延时程序1ms*********************************************/
void xs1ms(void)
{
unsigned char a,b,c;
for (c=1;c>0;c--)
  for (b=142;b>0;b--)
   for (a=2;a>0;a--);
}
/******************数码管显示程序*********************************************/
void xs()
{
duan=0;
wei4=1;
//第一位
duan=1;
P0=table[d];
duan=0;
wei1=0;
xs1ms();
//第二位
wei1=1;
duan=1;
P0=table[c];
duan=0;
wei2=0;
xs1ms();
//第三位
wei2=1;
duan=1;
P0=table[b];
duan=0;
wei3=0;
xs1ms();
//第四位
wei3=1;
duan=1;
P0=table[a];
duan=0;
wei4=0;
xs1ms();
}
/******************复位(初始化)程序*********************************************/
void init()
{
write_1302(0x8e,0x00);                 //WP=0 写操作
write_1302(0x80,0x00);                 //写秒
write_1302(0x82,0x00);                 //写分
write_1302(0x84,0x00);                 //写时
write_1302(0x90,0xaa);                 //设置电池参数!
write_1302(0x8e,0x80);                 //WP=1 写保护
}
/******************数据读取后处理分配*********************************************/
void chuli()
{
s=(read_1302(0x81))%16;     //读秒个
//c=(read_1302(0x81))/16;     //读秒个
d=(read_1302(0x83))%16;     //读分个
c=(read_1302(0x83))/16;     //读分个
b=(read_1302(0x85))%16;     //读时个
a=(read_1302(0x85))/16;     //读时个
za=read_1302(0x81);

zs=read_1302(0x83);
}
/******************设置显示分*********************************************/
void xsfen()
{
duan=0;
wei2=1;
wei4=1;
//第一位
duan=1;
P0=table[(m%10)];
duan=0;
wei1=0;
xs1ms();
//第二位
wei1=1;
duan=1;
P0=table[(m/10)];
duan=0;
wei2=0;
xs1ms();
}
/******************设置显示时*********************************************/
void xsshi()
{
duan=0;
wei4=1;
//第三位
wei2=1;
duan=1;
P0=table[(z%10)];
duan=0;
wei3=0;
xs1ms();
//第四位
wei3=1;
duan=1;
P0=table[(z/10)];
duan=0;
wei4=0;
xs1ms();
}
/******************主函数*********************************************/
void main()
{
uchar mu;
mu=0;
m=0;
n=0;
while (1)
{
  if (k1==0)   //按键复位
  {
   aj10ms();
   if (k1==0)
   {
    fmq=1;
    fmq=0;
    fmq50ms();
    fmq=1;
    while (!k1);
    init();
   }
  }
  if (k2==0)
  {
   aj10ms();
   if (k2==0)
   {
    while (!k2);
    mu++;
   }
   if (mu==3)
   {
    mu=0;
   }
  }
  if (mu>0&&mu<3)
  {
   switch (mu)
   {
   case 1:
    if (jia==0)
    {
     aj10ms();
     if (jia==0)
     {
      fmq=0;
      fmq50ms();
      fmq=1;
      while (!jia);
      m++;
      if (m==60)
      {
       m=0;
      }
     }
    }
    if (jian==0)
    {
     aj10ms();
     if (jian==0)
     {
      fmq=0;
      fmq50ms();
      fmq=1;
      while (!jian);
      m--;
      if (m<0)
      {
       m=59;
      }
     }
    }
    xsfen();
    n=m%10+m/10*16;
    write_1302(0x8e,0x00);                 //WP=0 写操作
    write_1302(0x82,n);
    write_1302(0x8e,0x80);                 //WP=1 写保护
    break;
   case 2:
    if (jia==0)
    {
     aj10ms();
     if (jia==0)
     {
      fmq=0;
      fmq50ms();
      fmq=1;
      while (!jia);
      z++;
      if (z==24)
      {
       z=0;
      }
     }
    }
    if (jian==0)
    {
     aj10ms();
     if (jian==0)
     {
      fmq=0;
      fmq50ms();
      fmq=1;
      while (!jian);
      z--;
      if (z<0)
      {
       z=23;
      }
     }
    }
    xsshi();
    x=z%10+z/10*16;
    write_1302(0x8e,0x00);                 //WP=0 写操作
    write_1302(0x84,x);
    write_1302(0x8e,0x80);                 //WP=1 写保护
    break;
   }
  }
  else
  {
   chuli();
   xs();
   if (s%2==0)
    led=0;
   else
    led=1;
   if ((zs==0)&&(za==0))
   {
    baoshi();
    fmq50ms();
   }
  }
}
}
发表于 2012-10-24 23:55 | 显示全部楼层
肯定是出在延时1秒函数上,把这个函数换成若干个显示就行了。
回复

使用道具 举报

发表于 2012-10-25 00:02 | 显示全部楼层
其实用定时器最简单。
回复

使用道具 举报

 楼主| 发表于 2012-10-25 00:24 | 显示全部楼层
请看官结合楼主的程序看看这样怎么样:
else
                {
                        chuli();
                        xs();
                        if (s%2==0)
                                led=0;
                        else
                                led=1;
                        if ((zs==0)&&(za==0))
                        {
                                fmq=0;
                        }
                        if(s==1)
                        {
                                fmq=1;
                        }
                }
回复

使用道具 举报

发表于 2012-10-25 07:10 | 显示全部楼层
2楼正解,延时里面改成若干个显示函数就可以了,具体数字根据实际情况调整
回复

使用道具 举报

发表于 2012-10-25 08:35 | 显示全部楼层
本帖最后由 gw168sh 于 2012-10-25 08:37 编辑

main()

    while(1)
     {
     x++;
     if(x<=100) bz=1;
     if(x==200)
    {bz=0; x=0;}
     这样子程序会一直跑,不会停下来等待,要响的时候执行一下这个就行 了

   }

闹钟时间到的时候,把闹响标志打开
主程序循环的时候,判断到闹响标志打开,进去后x++;把蜂鸣器打开bz=1;,不等待,接着去处理别的事情
下一次进入到这里,x++;判断是不是到200了,不是bz=1; 退出拉接着处理别的事情
知道x==200  才会进去把蜂鸣器关掉,x=0; 闹钟标志关闭。
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-11-3 17:27 , Processed in 0.033519 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表