一个利用中断来实现计时停止与启动的问题
时间:10-02
整理:3721RD
点击:
请各位高手看下红色部分的代码。
我主要问题是,在键盘扫描时,如果按了“停止”(TR0=0)或“启动(TR0=1)“,在中断时,又会被”TR0=0“或”TR0=1“覆盖。实现不了停止与启动。
我感觉在中断里面放置key_scan()的“启动与暂停”有些问题,貌似不可以这么设置,但我想不到如何设置。
所以想请教各位大神用什么方法可以解决此问题。 初学单片机,请各位多多指教,非常感谢。
//头文件:
#include "reg51.h"
//变量定义:
code unsigned char Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//表:共阳数码管 0-9
unsigned char GeWei;
unsigned char ShiWei;
unsigned char BaiWei;
unsigned char QianWei;
unsigned char tt;//中断次数
//引脚定义:
//P3作为键盘控制时间显示
sbit S2=P3^2; //P32设置为 启动计时
sbit S3=P3^3; //P33设置为 停止计时
sbit S4=P3^4; //P34设置为 个位加1
sbit S5=P3^5; //P35设置为 十位加1
sbit S6=P3^6; //P36设置为 百位加1
sbit S7=P3^7; //P37设置为 千位加1
//P1作为数码管位选信号
sbit SMG_q = P1^0; //定义数码管阳级控制脚(千位)
sbit SMG_b = P1^1; //定义数码管阳级控制脚(百位)
sbit SMG_s = P1^2; //定义数码管阳级控制脚(十位)
sbit SMG_g = P1^3; //定义数码管阳级控制脚(个位)
sbit Sound = P1^5; //定义蜂鸣器控制脚
//函数声明:
void delay(unsigned int timer); //数码管扫描延时
void DisplayGeWei(unsigned char G);//个位显示函数
void DisplayShiWei(unsigned char S); //十位显示函数
void DisplayBaiWei(unsigned char B); //百位显示函数
void DisplayQianWei(unsigned char Q);//千位显示函数
void delay60ms(void);//键盘消抖延时
void key_scan(void);//键盘扫描
void main()
{
TMOD=0x01; //设置定时器1为模式一,即16位计算模式
TH0=(65536-50000)/256; //给计数寄存器赋值,50毫秒时间
TL0=(65536-50000)%256;
EA=1; //开启总中断
ET0=1; //开启定时器0中断
TR0=1; //启定定时器0
GeWei=0; //初始化
ShiWei=0;
BaiWei=0;
QianWei=0;
tt=0;
while(1)
{
if(tt==20)
{ //20*50ms定时时间为1秒
tt=0;
GeWei++; //计数变量加1
if(GeWei>9)
{
GeWei=0;
ShiWei++;}
if(ShiWei>9)
{
ShiWei=0;
BaiWei++;}
if(BaiWei>9)
{
BaiWei=0;
QianWei++;}
if(QianWei>9)
{
GeWei=0;
ShiWei=0;
BaiWei=0;
QianWei=0;}
if(QianWei==9&BaiWei==9&ShiWei==9&GeWei==9){
Sound=0;}
else
Sound=1;
}
DisplayGeWei(GeWei);
DisplayShiWei(ShiWei);
DisplayBaiWei(BaiWei);
DisplayQianWei(QianWei);
}
}
//中断函数
void timer() interrupt 1
{
TR0=0;
tt++;
key_scan(); //执行键盘扫描
TH0=(65536-46083)/256; //定时器T0高四位赋值
TL0=(65536-46083)%256; //定时器T0低四位赋值
TR0=1;
}
//键盘扫描函数
void key_scan(void)
{
P3=0xff; //将P3置高电平
if((P3&0xff)!=0xff) //p3与自身与,如果不为原来的,则说明有键按下
{
delay60ms(); //延时60ms再检测
if((P3&0xff)!=0xff) //确实有键按下
{
/*if(S2==0) //如果是S2按下
TR0=1; //启动计时
if(S3==0) //如果是S3按下
TR0=0; //停止计时*/
if(S4==0) //如果是S4键按下
GeWei++; //个位加1
if(S5==0) //如果是S5键按下
ShiWei++; //十位加1
if(S6==0) //如果是S6键按下
BaiWei++; //百位加1
if(S7==0) //如果是S7键按下
QianWei++; //千位加1
}
}
}
//显示个位
void DisplayGeWei(unsigned char G)
{
SMG_g=0; //P1.3引脚输出低电平,个位点亮
P0=Tab[G%10];
delay(500);
SMG_g=1; //熄灭个位
}
//显示十位
void DisplayShiWei(unsigned char S)
{
SMG_s=0; //P1.2引脚输出低电平,十位点亮
P0=Tab[S%10];
delay(500);
SMG_s=1; //熄灭十位
}
//显示百位
void DisplayBaiWei(unsigned char B)
{
SMG_b=0; //P1.1引脚输出低电平,百位点亮
P0=Tab[B%10];
delay(500);
SMG_b=1; //熄灭百位
}
//显示千位
void DisplayQianWei(unsigned char Q)
{
SMG_q=0; //P1.0引脚输出低电平,千位点亮
P0=Tab[Q%10];
delay(500);
SMG_q=1; //熄灭千位
}
//键盘扫描延时消抖
void delay60ms(void)
{
unsigned char i,j;
for(i=0;i<200;i++)
for(j=0;j<100;j++)
;
}
//动态扫描延时
void delay(unsigned int timer)
{
while(timer--)
;
}
我也很关注这个问题,各位大师帮忙。谢谢
你中断函数里面key_scan();这个语句后面有TR0=1;因此你设置他暂停是没有用的。设置退出key_scan()后TR0的值又被置1了不起作用。
路过看看啊
是的,这个问题我一直很纠结。但如何设置停止与启动,我很困惑。请指点迷津
为什么不用两个定时器?
或者把启动停止做成外部中断
高见!我尝试看看,非常感谢!
看看先,有空就解决
主函数设置一个标志位变量bit flag。当启动按键按下时flag=1,停止按键按下时flag=0.
中断上面将tt++;改为if(flag)t++;
这样就能现实按键控制时间启动或停止,但是中断是一直运行的,一直扫描按键。
哈哈,按照您的指点,我实现了题目要求! 太感谢您啦!
通过此例,我知道了汇编与C语言在单片机里面的区别。
以下是我的理解,希望能帮助后来人。
假如我用汇编的话,那个flag标志应该相当于在汇编里面开辟一个字节单元存储标志位,在C里面由于是高级语言,自动完成了。在这里,不能对TR0直接操作,会互相覆盖的。
真的非常感谢您的帮助!
学汇编能更好的理解单片机里面的内部结构,程序是怎样运行的。而C是高级语言,使用更方便。好多人一上来就学C,个人觉得学过汇编更有利于以后发展。不需要太深入,但至少得懂一点。
嗯,受教了。