标题: 求助:写了个数码管闹钟程序,有几个地方调不出来。 [打印本页]
作者: 18380429586 时间: 2016-5-16 20:33
标题: 求助:写了个数码管闹钟程序,有几个地方调不出来。
8位LED数码管可调闹钟。
8个LED数码管88-88-88这样。
采用 2个锁存器输出 段选,位选。
采用3个独立按键:
1、SET(按一下调整秒钟,在按一下调整分钟,按三下调整小时,按4下完成调整。)
2、加减按键,按一下,就加减一个数字。先由SET选择调试 小时 还是分钟, 然后按加减键 调节数字。
问题:
1、SET键那里我采用的是记录键值思路。
按一下SET , keynumber=1, TR0=0 暂停计时,
按下加按键, 如果键值=1、2或者3, 秒、分钟或者小时的计数变量加一。
但是问题就来了, 按下SET 键后 有的时候是 调节小时,有的时候是调节分钟,有的时候没变化。
下面是原理图 和 程序。
-
人生日历截图20160516203142.png
(38.58 KB, 下载次数: 114)
电路原理图
作者: 18380429586 时间: 2016-5-16 20:49
#include<reg51.h>
#define uchar unsigned char
uchar code led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x040,0x80};
sbit duEN=P3^6;
sbit weiEN=P3^7;
sbit k0=P2^0;
sbit k1=P2^1;
sbit k2=P2^2;
char countsec,countmin,counthou;
uchar flag;
char key;
延时程序略过。
键盘扫描。
void keyboard()
{
if(k0==0)
{
键盘消抖。
ys(50);
if(k0==0)
{
松手检测。
while(!k0)
{
key++;
TR0=0;
if(key==4)
{
key=0;
TR0=1;
}
}
}
}
if(k1==0)
{
ys(50);
if(k1==0)
{
while(!k1);
if(key==1)
{
countsec++;
if(countsec==60)
countsec=0;
}
if(key==2)
{
countmin++;
if(countmin==60)
countmin=0;
}
if(key==3)
{
counthou++;
if(counthou==24)
counthou=0;
}
}
}
if(k2==0)
{
ys(50);
if(k2==0)
{
while(!k2);
if(key==1)
{
countsec--;
if(countsec==-1)
countsec=59;
}
if(key==2)
{
countmin--;
if(countmin==-1)
countmin=59;
}
if(key==3)
{
counthou--;
if(counthou==-1)
counthou=23;
}
}
}
}
一共8位,有点长,就发一段吧,其他都是一样的。
void ledxs()
{
P0=led[counthou/10];
duEN=1;
duEN=0;
P0=wei[0];
weiEN=1;
weiEN=0;
ys(5);
以下为消隐,求教 为什么这样可以消隐。按我理解 先给P0赋值,然后开锁存器使能,瞬间值就付给锁存,然后关使能。应该不会出现鬼影的。事 实是不加下面几句,仿真中时钟乱显示。
P0=0xff;
duEN=1;
duEN=0;
}
主程序: T0初始化,最后不断扫描键盘和显示,等待中断发生,从而刷新显示。
void main()
{
TMOD=0X01;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{
keyboard();
ledxs();
}
}
中断子程序:秒计数。
void timer0() interrupt 1 using 0
{
flag++;
if(flag==20)
{
flag=0;
countsec++;}
if(countsec==60)
{
countsec=0;
countmin++; }
if(countmin==60)
{
countmin=0;
counthou++; }
if(counthou==24)
{
counthou=0;
}
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
}
作者: 18380429586 时间: 2016-5-16 20:55
oh, fvck。 整理排版的时候发现,我SET键(K0) 的松手检测写错了。 写成下面这个:
while(!k0)
{
key++;
TR0=0;
if(key==4)
{
key=0;
TR0=1;
}
} MD 怪不得 按了这个键是调整小时还是分钟,是无规律的,等待松手的时候不知道KEY加了多少次。
修改之后 。仿真没有问题了。
while(!k0);
key++;
TR0=0;
if(key==4)
{
key=0;
TR0=1;
}
作者: 18380429586 时间: 2016-5-16 21:14
还有几个问题。
我采用的是共阳极数码管, 使用锁存器作为驱动。1、位选 是不是 为1的时候 允许该位显示?
如果采用9012 PNP三极管作为驱动,是不是 某个位控制I0口输出为0的时候允许该位点亮。
看网上程序的时候 没注意每个人的驱动方法不一样,只发现同样共阳怎么位选不一样, 把我搞晕了,所以请教一下大家,给我个准确答复。
2、数码管 消隐,共阳极数码管段选 是低电平有效。消隐就是关闭所有发光管,就是P0=0xff?
关于消隐程序 我最开始用的 郭天祥的, 如下:
duEN=1;
P0=led[counthou/10];
duEN=0;
P0=0Xff;
weiEN=1;
P0=wei[0];
weiEN=0;
ys(5);
居然 没法显示, 然后 从网上学了 这种:
P0=led[counthou/10];
duEN=1;
duEN=0;
P0=wei[0];
weiEN=1;
weiEN=0;
ys(5);
P0=0xff;
duEN=1;
duEN=0;
消隐这个 我知道就是关掉P0,以免动态显示要输出下一位时,把上一位的段选给输过去. 我感觉我理解的很糙,还请大家帮我梳理一下。
然后还有一个单片机 跑程序的流程就是 逐行扫描运行,好像还默认的从头到尾不断循环。这个理解是不是对的?这个也请大家帮我梳理一下。
还有一个问题。
我想做成 按下SET键后,调整秒钟/分钟/时钟的时候, 秒/分/时的那2位会闪烁,这个怎么做?我完全没有思路。
作者: ahshmj 时间: 2016-5-16 22:33
本帖最后由 ahshmj 于 2016-5-16 22:35 编辑
不是“键值”,是按键次数。设一个计数器,每按一次加1 。根据这个计数值,确定调整的项目。当然循环完后转回0或1,
当需要调的项目需要闪烁时,可以用另一个定时器中断方法,一般取0.3~0.5秒中断一次,每次中断变换一次,在输出正常的段码和全灭之间变换即可。
我做的是设一个标志,中断一次标志转换一次,调显示程序时,根据标志输出亮、灭。
作者: zl2168 时间: 2016-5-17 07:45
本帖最后由 zl2168 于 2016-5-17 08:58 编辑
模拟电子钟(由80C51定时器产生秒时基)已在本坛“51单片机”专栏2016.5.11上传,可参阅。
K0、K1和K2具有时钟校正功能,其控制过程为:
按下K0(带锁),进入时钟修正;首先,时数据(包括时十位、时个位)快速闪烁(亮暗各131ms);
按一次K1(不带锁),被修正数据(快速闪烁)按时、分、秒(同时包括十位、个位)次序右移(循环往复);
按一次K2(不带锁),被修正数据整体加1(最大值不超过时钟规定值,超过复0);时钟修正期间,计时继续运行;
释放K0,退出时钟修正。
作者: 18380429586 时间: 2016-5-17 19:55
谢谢,我去看看。
作者: 18380429586 时间: 2016-5-17 20:51
好的,我去看看,谢谢了。
作者: 18380429586 时间: 2016-5-17 21:01
我试了一下,不知道是不是我没弄好。 结果是8位全部都在闪烁,就是动态扫描 显示延时 设太长的那种现象。我没用 2个定时器,因为我还不知道怎么设中断优先。待会学习下。然后在试一下。
作者: zl2168 时间: 2016-5-19 18:38
本帖最后由 zl2168 于 2016-5-19 18:42 编辑
模拟电子钟(由80C51定时器产生秒时基)已在本坛“51单片机”专栏2016.5.11上传,可参阅。
开机显示0时0分0秒,随后开始计时运行,2组发光二极管秒闪烁(亮暗各500ms)。同时要求K0、K1和K2具有时钟校正功能,其控制过程为:按下K0(带锁),进入时钟修正;首先,时数据(包括时十位、时个位)快速闪烁(亮暗各131ms);按一次K1(不带锁),被修正数据(快速闪烁)按时、分、秒(同时包括十位、个位)次序右移(循环往复);按一次K2(不带锁),被修正数据整体加1(最大值不超过时钟规定值,超过复0);时钟修正期间,计时继续运行;释放K0,退出时钟修正。
作者: zl2168 时间: 2016-5-19 21:13
试试上述模拟电子钟Proteus仿真演示,包你满意。
作者: 18380429586 时间: 2016-5-21 10:24
恩! 我看了下,确实给力。谢谢了,让我知道有 74595这种 驱动。
作者: zl2168 时间: 2016-5-21 10:25
本帖最后由 zl2168 于 2016-5-21 10:26 编辑
模拟电子钟程序如下:
-
t0t1.jpg
(108.49 KB, 下载次数: 89)
作者: zl2168 时间: 2016-5-21 10:29
上述电路和程序引自张志良编著《单片机实验实训100例》 ISBN 978-7-5124-1603-1,北航社出版、《80C51单片机实用教程》ISBN 978-7-04-044532-9,高教社出版。欢迎咨询,zzlls@126.com
作者: 18380429586 时间: 2016-5-21 10:31
前辈,请教一下,uchar 是无符号的吧。 可是在时钟里 按键调时间的时候,用到一句 : 如果减计数按键被按下,秒计数减一,如果秒计数=-1,秒计数=59。
我的秒计数变量是 uchar型的, uchar不是无符号吗?为什么程序 可以编译成功,仿真也可以用呢?
if(k1==0)
{
countsec--;
if(countsec==-1)
countsec=59;
}
作者: zl2168 时间: 2016-5-21 10:39
为什么要秒计数减一?时钟都是加一的。你看我的程序,加到60,复0.
作者: zl2168 时间: 2016-5-21 10:42
啊哦!你可能是到计时秒表。介绍你一本书,张志良编著《单片机实验实训100例》 ISBN 978-7-5124-1603-1,北航社出版,里面有99.9秒表和能预设初值的倒计时秒表实例。
作者: zl2168 时间: 2016-5-21 10:55
啊哦!我知道你问的问题了。-1是补码,255,仍属于uchar。
作者: zl2168 时间: 2016-5-21 10:57
0-1=255
作者: 慌张 时间: 2016-5-21 14:41
还是用lcd1602写比较实用点
作者: zl2168 时间: 2016-5-21 15:27
这是一个题目。有LED显示,也有LCD显示。本题是LED显示。
作者: zl2168 时间: 2016-5-21 15:30
还有秒基准取自于外时钟芯片,还是取自于内振荡时钟。本题是内振荡时钟,分频后产生秒基准。
作者: zl2168 时间: 2016-5-21 15:32
介绍你一本书,张志良编著《单片机实验实训100例》 ISBN 978-7-5124-1603-1,北航社出版,里面有4种1302的电路、程序和仿真案例
作者: zl2168 时间: 2016-5-21 15:37
上述4种1302的电路、程序和仿真案例已上传至本坛“51单片机”专栏
作者: zl2168 时间: 2016-5-21 15:38
2016-5-3 本人上传的“开机显示PC机时间的时钟1302”(1602显示)
作者: zl2168 时间: 2016-5-21 15:38
2016-5-4 本人上传的“具有校正功能的时钟1302”(1602显示)
作者: zl2168 时间: 2016-5-21 15:38
2016-5-5 本人上传的“开机显示PC机时分秒的时钟1302”(LED数码管显示)
作者: zl2168 时间: 2016-5-21 15:39
2016-5-6 本人上传的“具有校正功能的时钟1302(LED数码管显示)”
作者: zl2168 时间: 2016-5-21 19:49
Proteus仿真试了没有?试后满意再谢。
作者: 18380429586 时间: 2016-5-23 11:19
试过了!效果很好,谢谢了。
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |