单片机控制程序 问 设置时钟程序 因代码太多 以至于数码管用延时函数无法稳定显示,前辈们有什么方法?
用的是51单片机,因为动态显示代码存在于外部中断0函数中,目的是为了调节时钟并动态显示调节的结果,所以定时器中断不起作用,不能用于动态显示,目前只完成了能够实现秒分时其中...
用的是51单片机,因为动态显示代码存在于外部中断0 函数中,目的是为了调节时钟并动态显示调节的结果,所以定时器中断不起作用,不能用于动态显示,目前只完成了能够实现 秒 分 时其中之一的调节, 想过利用 创建调用函数 用 指针参数来节约代码,但可能因为消震用得太多,嵌入的太深,以至于一在外部中断中调用函数就使得KEIL4 宝镜告..求前辈们热心解答!!!
void int0() interrupt 0
{
uint key=0,temp;
uint i=12000;
while(i--);
if(key1==0)
{
time_s=time_m=time_h=0;
jishu[0]=jishu[1]=jishu[3]=jishu[4]=jishu[6]=jishu[7]=0;
while(1)
{
if(key1==0)
{
i=12000;
while(i--);
if(key1==0)
{break;}
}
P0=number[jishu[weishu-1]];
P2=control[weishu-1];
for(i=0;i<300;i++);
weishu++;
if(weishu==9)
weishu=1;
if(key2==0)
{
i=12000;
while(i--);
if(key2==0)
{
time_s+=1;
if(time_s==60)
time_s=0;
temp=time_s;
jishu[0]=time_s%10;
jishu[1]=time_s/10%10;
}
}
}
}
这个外部中断函数勉强合适, 除了在调的时候会有一点点不稳定之外,别无大碍
但功能上只能实现秒的转换 如果再加上2套分和时的调整代码,基本上晃得眼睛花而且不容易由while语句识别按键...实现对应功能. 展开
void int0() interrupt 0
{
uint key=0,temp;
uint i=12000;
while(i--);
if(key1==0)
{
time_s=time_m=time_h=0;
jishu[0]=jishu[1]=jishu[3]=jishu[4]=jishu[6]=jishu[7]=0;
while(1)
{
if(key1==0)
{
i=12000;
while(i--);
if(key1==0)
{break;}
}
P0=number[jishu[weishu-1]];
P2=control[weishu-1];
for(i=0;i<300;i++);
weishu++;
if(weishu==9)
weishu=1;
if(key2==0)
{
i=12000;
while(i--);
if(key2==0)
{
time_s+=1;
if(time_s==60)
time_s=0;
temp=time_s;
jishu[0]=time_s%10;
jishu[1]=time_s/10%10;
}
}
}
}
这个外部中断函数勉强合适, 除了在调的时候会有一点点不稳定之外,别无大碍
但功能上只能实现秒的转换 如果再加上2套分和时的调整代码,基本上晃得眼睛花而且不容易由while语句识别按键...实现对应功能. 展开
4个回答
展开全部
前面几个的回答都很好,找到了问题的原因和解决办法。
写程序之前一定要先从系统的级别构建一下程序的结构。
你的程序中,有数码管扫描显示、按键扫描、RTC三部分。
在构建程序结构的时候,考虑到几个部分的特点,一般情况如下:
1、如果时间显示到秒,应在100ms左右读一次RTC。
2、为了保证显示不删,应在20ms以内完成一次显示刷新,假设你用了20个数码管显示日期和时间。
3、按键是随机的,需要检测,一般按键按下的时间不小于50ms,可以考虑在10ms检测一次按键。
程序可以定义一个1ms的定时器,设置几个变量对定时器进行计数。
每个1ms定时到时,自加对定时器的计数,并更新数码管显示,20ms更新完20个数码管。
每到10ms检测一次按键,记录状态,与上次状态进行比较,如果连续两次或三次检测到按键按下,设置按键动作的标记,并确定如何更改显示,改变显存。
如果不在设置状态,每100ms读一次RTC的值,将值更新到显存。
如果数码管需要调整亮度,可以将1ms定时器改为100us,分给每个数码管的1ms内,改变其点亮的时间,就可以调出十种亮度。
用这种架构做这个程序,处理器负担很轻,对所有的外设的响应一样迅速。你会感到51单片机还是能干很多活的。
写程序之前一定要先从系统的级别构建一下程序的结构。
你的程序中,有数码管扫描显示、按键扫描、RTC三部分。
在构建程序结构的时候,考虑到几个部分的特点,一般情况如下:
1、如果时间显示到秒,应在100ms左右读一次RTC。
2、为了保证显示不删,应在20ms以内完成一次显示刷新,假设你用了20个数码管显示日期和时间。
3、按键是随机的,需要检测,一般按键按下的时间不小于50ms,可以考虑在10ms检测一次按键。
程序可以定义一个1ms的定时器,设置几个变量对定时器进行计数。
每个1ms定时到时,自加对定时器的计数,并更新数码管显示,20ms更新完20个数码管。
每到10ms检测一次按键,记录状态,与上次状态进行比较,如果连续两次或三次检测到按键按下,设置按键动作的标记,并确定如何更改显示,改变显存。
如果不在设置状态,每100ms读一次RTC的值,将值更新到显存。
如果数码管需要调整亮度,可以将1ms定时器改为100us,分给每个数码管的1ms内,改变其点亮的时间,就可以调出十种亮度。
用这种架构做这个程序,处理器负担很轻,对所有的外设的响应一样迅速。你会感到51单片机还是能干很多活的。
追问
呵呵 谢谢你们的思路 都说得很好 给我上了一课 以前我都是看着题目就写程序 对架构,算法,没有考虑,谢谢你们的提醒,真心感谢,一会去实践实践。
追答
呵呵,刚上手都这样,以后慢慢更好了。
展开全部
void int0() interrupt 0
{
uint key=0,temp;
uint i=12000;
while(i--);--这是延时多少时间哪??!!!!
……
在中断函数里面,延时干什么?
呵呵,编程的思路,有问题。
{
uint key=0,temp;
uint i=12000;
while(i--);--这是延时多少时间哪??!!!!
……
在中断函数里面,延时干什么?
呵呵,编程的思路,有问题。
更多追问追答
追问
怎么思路有问题?说了哈 在中断调时的时候需要动态显示数码管所以需要一个延时函数 ,你刚刚说的uint key=0,temp;
uint i=12000;
while(i--);--
这个 是为了消震啊 ,确保按一下键位就是一个指令 而不是按一个键发出了好几次的指令,不知道么?
追答
按键,是有抖动的,需要延时消抖,延时后,确认按下了再进行处理。
呵呵,这样不紧不慢的东西,就不应该放在《外部中断》上。
在外部中断,应该连接那些需要《立即执行处理》的外设。
编程思路,确实需要端正一下了。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
....
uint ex0flag;
void int0() interrupt 0
{
ex0flag=1;//仅仅作为有键按下的标记
}
main()
{
....
uint key=0,temp,i;
ex0flag=0;
while(1)
{
if(ex0flag==1)如果有键按下则做如下按键处理
{
ex0flag=0;
i=12000;
while(i--);
if(key1==0)
{
time_s=time_m=time_h=0;
jishu[0]=jishu[1]=jishu[3]=jishu[4]=jishu[6]=jishu[7]=0;
while(1)
{
if(key1==0)
{
i=12000;
while(i--);
if(key1==0)
{break;}
}
P0=number[jishu[weishu-1]];
P2=control[weishu-1];
for(i=0;i<300;i++);
weishu++;
if(weishu==9)
weishu=1;
if(key2==0)
{
i=12000;
while(i--);
if(key2==0)
{
time_s+=1;
if(time_s==60)
time_s=0;
temp=time_s;
jishu[0]=time_s%10;
jishu[1]=time_s/10%10;
}
}
}
}
}
}
uint ex0flag;
void int0() interrupt 0
{
ex0flag=1;//仅仅作为有键按下的标记
}
main()
{
....
uint key=0,temp,i;
ex0flag=0;
while(1)
{
if(ex0flag==1)如果有键按下则做如下按键处理
{
ex0flag=0;
i=12000;
while(i--);
if(key1==0)
{
time_s=time_m=time_h=0;
jishu[0]=jishu[1]=jishu[3]=jishu[4]=jishu[6]=jishu[7]=0;
while(1)
{
if(key1==0)
{
i=12000;
while(i--);
if(key1==0)
{break;}
}
P0=number[jishu[weishu-1]];
P2=control[weishu-1];
for(i=0;i<300;i++);
weishu++;
if(weishu==9)
weishu=1;
if(key2==0)
{
i=12000;
while(i--);
if(key2==0)
{
time_s+=1;
if(time_s==60)
time_s=0;
temp=time_s;
jishu[0]=time_s%10;
jishu[1]=time_s/10%10;
}
}
}
}
}
}
更多追问追答
追问
这个不错 可以 但是貌似遗漏了一点 要暂停计时器。不然就算没按键计时器一样运行让秒增加
追答
可以稍微修改一下,不按键就停止定时器TR0=0不就可以了吗,中断是处理特殊事件和紧急事件的,里面程序不能太多,特别忌讳的是延时。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
中断当中使用标志位,不要运行太多程序,在大循环里去找标志位执行相应的程序
更多追问追答
追问
在大循环中执行了数遍 最多是跳的频率快了一点,没有任何稳定迹象
而且他确实需要这么多条语句才能达到效果
追答
楼上几位答得比我详尽,但是我已经说出了要点,能不能悟道,看你造化啦
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询