微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 一个利用中断来实现计时停止与启动的问题

一个利用中断来实现计时停止与启动的问题

时间: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,个人觉得学过汇编更有利于以后发展。不需要太深入,但至少得懂一点。

嗯,受教了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top