返回列表 发新帖我要提问本帖赏金: 10.00元(功能说明)

[C语言] 开启TR0如何能使之循环工作!!!

[复制链接]
1769|12
 楼主| fang355 发表于 2017-8-2 16:53 | 显示全部楼层 |阅读模式

#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按一次仅报警一次,  后面就是杂音连续  而不是连续的报警。
错误哪里?,  请路过的高手 指定迷津     新手在此谢谢了!


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
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延时。
更专业的代码要充分利用这个公用定时器。比如按键扫描、数码管显示,长延时等。

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

  8. void DelayUs2x(unsigned char t);
  9. void DelayMs(unsigned char t);


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

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

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

  17. bit b_frg_;
  18. unsigned char _frg_;

  19. void bj_on(void)
  20. {
  21.         b_frg_=0;
  22.         _frg_=0;
  23. //        TR0=1;
  24.         Init_Timer0();
  25. }
  26. void bj_off(void)
  27. {
  28.         TR0=0;
  29. }

  30. void Init_Timer1(void)
  31. {
  32.         TMOD &= 0x0f;
  33.         TMOD |= 0x10;
  34.         TH1 = T_RELOAD_HI;
  35.         ET1 = 1;
  36.         TR1 = 1;
  37. //        EA = 1;
  38. }

  39. void Timer1_isr(void)interrupt 3   //T1中断 约10mS执行一次
  40. {
  41.         TH1 = T_RELOAD_HI;
  42.        
  43.         if(TR0)
  44.         {
  45.                 frg=_frg_;

  46.                 if(b_frg_) _frg_--;
  47.                 else _frg_++;
  48.                 if((_frg_>=245)&&(_frg_==0)) b_frg_=!b_frg_;
  49.         }
  50. }







  51. void Init_Timer0(void)         //初始函数
  52. {
  53.         TMOD=0x01;
  54.         TH0=0xfe;
  55.         TL0=frg;
  56.         EA=1;
  57.         ET0=1;
  58.         TR0=1;
  59. }

  60. //void bj() // 报警子函数
  61. //{
  62. //        Init_Timer0();//  必须的
  63. //    for(i=0;i<245;i++)
  64. //        {
  65. //                DelayMs(10);
  66. //                frg=i;
  67. //        }
  68. //        for(i=245;i>0;i--)
  69. //        {
  70. //                DelayMs(10);
  71. //                frg=i;
  72. //        }
  73. //        SPK=~SPK;
  74. //}

  75. main()          //主函数
  76. {
  77.         TMOD=0x01;
  78.         EA=1;
  79.         ET0=1;
  80.         //Init_Timer0();
  81.         Init_Timer1();//yuan
  82.         for(; ;)        //相当于while(1)
  83.         {
  84.                 if(k3==0)        //ok ! 实现了 开关的触发一次开 再触发一次停的功能 .
  85.                 {
  86.                         DelayMs(10);
  87.                         while(!k3);//松手按键弹起后 计数
  88.                         {
  89.                                 keystep++;
  90.                                 if(keystep==2) keystep=0;
  91.                         }
  92.                         switch(keystep)
  93.                         {
  94.                                 case 0: bj_on();  break; //
  95.                                 case 1: bj_off(); break; //                 
  96.                         }
  97.                 }
  98.         }
  99. }

  100. void DelayUs2x(unsigned char t)         //延时函数
  101. {
  102.         while(--t);
  103. }

  104. void DelayMs(unsigned char t)
  105. {
  106.         while(t--)
  107.         {
  108.                 DelayUs2x(245);
  109.                 DelayUs2x(245);
  110.         }
  111. }

  112. void Timer0_isr(void)interrupt 1   //TR0 中断发音函数
  113. {
  114.         TMOD=0x01;
  115.         TH0=0xfe;
  116.         TL0=frg;
  117.         SPK=~SPK;
  118. }







评分

参与人数 1威望 +3 收起 理由
fang355 + 3 很给力!

查看全部评分

hanlie2345678 发表于 2017-8-3 15:54 | 显示全部楼层
大师你分享的这个很不错,建议你用MDT的单片机来写会方便很多!
datouyuan 发表于 2017-8-4 09:03 | 显示全部楼层
我4楼地板的代码中的“if((_frg_>=245)&&(_frg_==0)) b_frg_=!b_frg_;”
应改为

  1. if((_frg_>=245)||(_frg_==0)) b_frg_=!b_frg_;
 楼主| 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
 楼主| fang355 发表于 2017-8-4 14:04 | 显示全部楼层
hanlie2345678 发表于 2017-8-3 15:54
大师你分享的这个很不错,建议你用MDT的单片机来写会方便很多!

你好! MDT单片机 可以使用C语言吗?
hanlie2345678 发表于 2017-8-4 14:07 | 显示全部楼层
可以,我们工程师开发程序都是用C语言。
 楼主| fang355 发表于 2017-8-4 14:54 | 显示全部楼层
datouyuan 发表于 2017-8-3 15:40
多用个定时器做10mS延时。
更专业的代码要充分利用这个公用定时器。比如按键扫描、数码管显示,长延时等 ...

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

查看全部评分

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 很给力!

查看全部评分

 楼主| fang355 发表于 2017-8-6 13:26 | 显示全部楼层
datouyuan 发表于 2017-8-4 15:43
在中断函数中使用其它函数时要小心些。注意,我没有在中断中调用函数。
没听说在中断中控制别的中断,获 ...

非常感谢! 大师的指点 受益匪浅!    谢过了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

48

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部