发新帖本帖赏金 10.00元(功能说明)我要提问
返回列表
打印
[C语言]

开启TR0如何能使之循环工作!!!

[复制链接]
1259|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

#include<reg52.h>
#include<intrins.h>
sbit SPK=P3^7;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
unsigned char keystep=1,keydelay,frg,i;
void bj();
void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);
void Init_Timer0(void)         //初始函数
{
TMOD=0x01;
TH0=0xfe;
TL0=frg;
EA=1;
ET0=1;
TR0=1;
}
void bj() // 报警子函数
{  Init_Timer0();//  必须的
    for(i=0;i<245;i++)
        {
          DelayMs(10);
      frg=i;
        }
        for(i=245;i>0;i--)
        {
          DelayMs(10);
      frg=i;
         }
        SPK=~SPK;
}
main()          //主函数
{
TMOD=0x01;
EA=1;
ET0=1;
//Init_Timer0();
for(; ;)        //相当于while(1)
  {
    if(k3==0)        //ok ! 实现了 开关的触发一次开 再触发一次停的功能 .
        { DelayMs(10);
          while(!k3);//松手按键弹起后 计数
          {keystep++;
           if(keystep==2) keystep=0;}
          switch(keystep)
     { case 0:   bj(); break; //只发出一次报警声??遗憾!!!
       case 1:  TR0=0;  break; // 停止报警发音。                   
                
            }
        }

   }
}
void DelayUs2x(unsigned char t)         //延时函数
{
  while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
  {
    DelayUs2x(245);
        DelayUs2x(245);
  }
}

void Timer0_isr(void)interrupt 1   //TR0 中断发音函数
{

TMOD=0x01;
TH0=0xfe;
TL0=frg;
SPK=~SPK;

}
其上的程序是:“ K3按键 控制报警声输出;  K3按一次 就能报警循环继续, 再按键一次 停止报警”。 但是 此段程序实现是K3按一次仅报警一次,  后面就是杂音连续  而不是连续的报警。
错误哪里?,  请路过的高手 指定迷津     新手在此谢谢了!


11111111.jpg (325.84 KB )

11111111.jpg

相关帖子

沙发
datouyuan| | 2017-8-2 17:44 | 只看该作者
你的函数bj() 就是只发一声。

for(; ;) {bj();}//连续想

bj()这个函数是阻塞型的,mcu运行上面的语句就没法做其它事情,比如你的按键检测没法做了。

你这种程序结构是业余的,玩玩可以,实际做项目不行。

使用特权

评论回复

打赏榜单

fang355 打赏了 5.00 元 2017-08-03
理由:期待进一步的解析! 谢谢

评分
参与人数 1威望 +3 收起 理由
fang355 + 3 很给力!
板凳
fang355|  楼主 | 2017-8-3 11:10 | 只看该作者
分析的很透彻!  大师, 我这个问题出现这里, 可否帮解决或更改?

使用特权

评论回复

打赏榜单

datouyuan 打赏了 5.00 元 2017-08-03
理由:只要自己愿意多加思考,论坛上会有大把人愿意帮助你。

地板
datouyuan| | 2017-8-3 15:40 | 只看该作者
fang355 发表于 2017-8-3 11:10
分析的很透彻!  大师, 我这个问题出现这里, 可否帮解决或更改?

多用个定时器做10mS延时。
更专业的代码要充分利用这个公用定时器。比如按键扫描、数码管显示,长延时等。

#include<reg52.h>
#include<intrins.h>
sbit SPK=P3^7;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
unsigned char keystep=1,keydelay,frg,i;

void DelayUs2x(unsigned char t);
void DelayMs(unsigned char t);


#define FOSC                12.0//11.0592        //晶振频率
#define MACHINE_NUM 12                //SH88F2051 STC_MCU 定时器1T/12T可选
#define M_NUM       12                //SH88F2051 STC_MCU 为1T,老51为12T

#define TICKS_PER_SEC 100.0        //每秒100次,10mS一次

#define TICK_COUNT ( (unsigned int)(FOSC*1000000L/MACHINE_NUM/TICKS_PER_SEC) )
        #define T_RELOAD_LO        ( (unsigned char) ((0x10000-TICK_COUNT) & 0x00ff) )
        #define T_RELOAD_HI        ( (unsigned char) ((0x10000-TICK_COUNT) >> 8) )

bit b_frg_;
unsigned char _frg_;

void bj_on(void)
{
        b_frg_=0;
        _frg_=0;
//        TR0=1;
        Init_Timer0();
}
void bj_off(void)
{
        TR0=0;
}

void Init_Timer1(void)
{
        TMOD &= 0x0f;
        TMOD |= 0x10;
        TH1 = T_RELOAD_HI;
        ET1 = 1;
        TR1 = 1;
//        EA = 1;
}

void Timer1_isr(void)interrupt 3   //T1中断 约10mS执行一次
{
        TH1 = T_RELOAD_HI;
       
        if(TR0)
        {
                frg=_frg_;

                if(b_frg_) _frg_--;
                else _frg_++;
                if((_frg_>=245)&&(_frg_==0)) b_frg_=!b_frg_;
        }
}







void Init_Timer0(void)         //初始函数
{
        TMOD=0x01;
        TH0=0xfe;
        TL0=frg;
        EA=1;
        ET0=1;
        TR0=1;
}

//void bj() // 报警子函数
//{
//        Init_Timer0();//  必须的
//    for(i=0;i<245;i++)
//        {
//                DelayMs(10);
//                frg=i;
//        }
//        for(i=245;i>0;i--)
//        {
//                DelayMs(10);
//                frg=i;
//        }
//        SPK=~SPK;
//}

main()          //主函数
{
        TMOD=0x01;
        EA=1;
        ET0=1;
        //Init_Timer0();
        Init_Timer1();//yuan
        for(; ;)        //相当于while(1)
        {
                if(k3==0)        //ok ! 实现了 开关的触发一次开 再触发一次停的功能 .
                {
                        DelayMs(10);
                        while(!k3);//松手按键弹起后 计数
                        {
                                keystep++;
                                if(keystep==2) keystep=0;
                        }
                        switch(keystep)
                        {
                                case 0: bj_on();  break; //
                                case 1: bj_off(); break; //                 
                        }
                }
        }
}

void DelayUs2x(unsigned char t)         //延时函数
{
        while(--t);
}

void DelayMs(unsigned char t)
{
        while(t--)
        {
                DelayUs2x(245);
                DelayUs2x(245);
        }
}

void Timer0_isr(void)interrupt 1   //TR0 中断发音函数
{
        TMOD=0x01;
        TH0=0xfe;
        TL0=frg;
        SPK=~SPK;
}







使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
fang355 + 3 很给力!
5
hanlie2345678| | 2017-8-3 15:54 | 只看该作者
大师你分享的这个很不错,建议你用MDT的单片机来写会方便很多!

使用特权

评论回复
6
datouyuan| | 2017-8-4 09:03 | 只看该作者
我4楼地板的代码中的“if((_frg_>=245)&&(_frg_==0)) b_frg_=!b_frg_;”
应改为

if((_frg_>=245)||(_frg_==0)) b_frg_=!b_frg_;

使用特权

评论回复
7
fang355|  楼主 | 2017-8-4 13:46 | 只看该作者
datouyuan 发表于 2017-8-4 09:03
我4楼地板的代码中的“if((_frg_>=245)&&(_frg_==0)) b_frg_=!b_frg_;”
应改为

很好的 程序!非常感激你 细心的列出源程序! 触发开关很好地实现了我的要求, 能连续报警了  
只是还有一个小问题的 发出的 报警声音, 不太完全像火警声音  可能延时上 还需要调整一下吧

原先如下这个一段报警声 很准的
void bj() // 报警子函数
{
       Init_Timer0();//  必须的
    for(i=0;i<245;i++)
        {
               DelayMs(10);
                frg=i;
        }
       for(i=245;i>0;i--)
      {
               DelayMs(10);
               frg=i;
        }
        SPK=~SPK

使用特权

评论回复
8
fang355|  楼主 | 2017-8-4 14:04 | 只看该作者
hanlie2345678 发表于 2017-8-3 15:54
大师你分享的这个很不错,建议你用MDT的单片机来写会方便很多!

你好! MDT单片机 可以使用C语言吗?

使用特权

评论回复
9
hanlie2345678| | 2017-8-4 14:07 | 只看该作者
可以,我们工程师开发程序都是用C语言。

使用特权

评论回复
10
fang355|  楼主 | 2017-8-4 14:54 | 只看该作者
datouyuan 发表于 2017-8-3 15:40
多用个定时器做10mS延时。
更专业的代码要充分利用这个公用定时器。比如按键扫描、数码管显示,长延时等 ...

高人!  怎么在T1中断内 好像使用到T0的中断, 难道是T1调用T0 好像也不对吧!? T0优先T1吗?  我还在琢磨你的思路。有时间 可以详细注释一下吗?

使用特权

评论回复
11
datouyuan| | 2017-8-4 15:26 | 只看该作者
fang355 发表于 2017-8-4 13:46
很好的 程序!非常感激你 细心的列出源程序! 触发开关很好地实现了我的要求, 能连续报警了   ...

你void bj()函数的作用:
每隔10mS让frg产生变化,变化规律是0、1、2、3~~243、244、245、244、243~~3、2、1
只有1次。

我在T1中断中的代码作用是:
每隔10mS让frg产生变化,变化规律是
0、1、2、3~~243、244、245、244、243~~3、2、1、
0、1、2、3~~243、244、245、244、243~~3、2、1、
0、1、2、3~~243、244、245、244、243~~3、2、1、
0、1、2、3~~243、244、245、244、243~~3、2、1、
0、1、2、3~~243、244、245、244、243~~3、2、1、
0、1、2、3~~243、244、245、244、243~~3、2、1、
一直循环。按理说和你的代码是没有区别的。

是不是你软件延时的时间实际不是10mS?你用示波器看看。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
fang355 + 3 很给力!
12
datouyuan| | 2017-8-4 15:43 | 只看该作者
fang355 发表于 2017-8-4 14:54
高人!  怎么在T1中断内 好像使用到T0的中断, 难道是T1调用T0 好像也不对吧!? T0优先 ...

在中断函数中使用其它函数时要小心些。注意,我没有在中断中调用函数。
没听说在中断中控制别的中断,获取别的中断的状态信息会有问题。

在51中,没有特别设置,T1和T0的服务函数是平级的。假如进入了其中一个中断服务函数,一定会执行完,才会响应另一个中断。不过T1和T0同时请求响应时,T0的优先级更高,会先响应T0的中断服务函数。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
fang355 + 3 很给力!
13
fang355|  楼主 | 2017-8-6 13:26 | 只看该作者
datouyuan 发表于 2017-8-4 15:43
在中断函数中使用其它函数时要小心些。注意,我没有在中断中调用函数。
没听说在中断中控制别的中断,获 ...

非常感谢! 大师的指点 受益匪浅!    谢过了

使用特权

评论回复
发新帖 本帖赏金 10.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

48

帖子

0

粉丝