两个定时器同时工作为何会没作用?

[复制链接]
4110|39
 楼主| LKC134 发表于 2019-7-23 15:09 | 显示全部楼层 |阅读模式
这两天做了一款产品,在编程时使用两个定时器同时工作就没起作用了,芯片手册也看了,也调试了N次还是这样,请各位大神指点下
程序如下:
  1. #include "STC15W.H"
  2. #include"intrins.h"
  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. #define ADC_POWER   0x80            //ADC电源控制位
  6. #define ADC_FLAG    0x10            //ADC完成标志
  7. #define ADC_START   0x08            //ADC起始控制位
  8. #define ADC_SPEEDLL 0x00            //540个时钟
  9. #define ADC_SPEEDL  0x20            //360个时钟
  10. #define ADC_SPEEDH  0x40            //180个时钟
  11. #define ADC_SPEEDHH 0x60            //90个时钟
  12. #define LED_Time1 500
  13. #define LED_Time2 3000
  14. void LED_TSK1(void);
  15. void LED_TSK2(void);            
  16. void keyScan();
  17. void key_tak();
  18. void time0_Init(void);
  19. void t2int();
  20. void timer0();
  21. void time2_Init(void);   
  22. void LED_san();

  23. void AD_ris();

  24. uint temper,tt=0;
  25. uint set_sum=0;          //设定温度
  26. uchar num=0,time=0,n,c,g;
  27. uchar ZKB=100;                //占空比调节参数
  28. volatile uchar key_sec=0;
  29. uchar kp,ki,kd;
  30. int e1,e2,e3,duk,uk;  
  31. uint data1=0,data2=0,data3=0,temp=0,volatge=0,NTC_bat=0;
  32. uchar ADC_chunal_rnt=0;                                       
  33. volatile uint s1=0,s2=0,j=0,m=0,d=0;        //定时时间
  34. //bit flag1=0,flag2=0;
  35. sbit LED=P3^3;
  36. sbit Pout=P1^4; //开机/关机
  37. sbit PINT=P1^5;//检测

  38. sbit key=P1^3;
  39. sbit PWM_out=P3^6;
  40. /**********延时子程序**********/
  41. void Delay(uint z)
  42. {
  43. uint y,x;
  44. for(y=0;y<z;y++)
  45.    for(x=0;x<120;x++);
  46.    }
  47.        
  48. /*********定时器初始化*********/
  49. void time0_Init(void)
  50. {
  51. //        AURX=0x7f;               //定时器时钟12T模式
  52.         TMOD&=0xf0;
  53.         TMOD|=0x01;                //设置定时器模式
  54.         TL0=0x9C;                    //设置定时初值100uS
  55.         TH0=0xFF;                   //设置定时初值
  56.        
  57.         TF0=0;           //清除TF0标志
  58.         ET0=1;
  59.         EA=1;                       
  60.         TR0=1;
  61.         }
  62. void time2_Init(void)
  63. {
  64.         AUXR&=~0x04;           //12T模式
  65.         T2L=0x18;                //设置定时初值         1ms
  66.         T2H=0xfc;                //设置定时初值
  67.         AUXR|=0x10;                    //定时器0开始计时     
  68.         IE2|=0x04;
  69.         EA=1;
  70.         }
  71. /************IO初始化*************/
  72. void IO_Init(void)
  73. {       
  74.         P1M0=0X10;
  75.     P1M1=0X2E;
  76.     P3M0=0X48;
  77.     P3M1=0X00;
  78.     P5M0=0X00;
  79.     P5M1=0X00;
  80.         }
  81. /***************AD初始化*****************/
  82. void ADC_Init()
  83. {
  84.    P1ASF=0x07;           //设置P1.2和P1.1,P1.0为模拟输入
  85.     ADC_RES=0;               
  86.    ADC_RESL=0;
  87.    ADC_CONTR=0x80;
  88.    Delay(1);
  89.    if(ADC_chunal_rnt%3==0)        //外部基准电压
  90.    {
  91.     ADC_CONTR=0xf4;//设P1.2口转换,90个时钟周期转换一次。
  92.         _nop_();
  93.         _nop_();         
  94.           _nop_();
  95.         _nop_();
  96.     ADC_CONTR=0xe8;//(1110 1000)清零
  97.          }

  98.   if(ADC_chunal_rnt&3==1)
  99.   {
  100.            ADC_CONTR=0xe2;//设P1.1口转换,90个时钟周期转换一次。
  101.         _nop_();
  102.         _nop_();         
  103.           _nop_();
  104.         _nop_();
  105.     ADC_CONTR=0xe8;//(1110 1000)清零
  106.      }
  107.    if(ADC_chunal_rnt%3==2)
  108.    {
  109.     ADC_CONTR=0xe1;//设P1.0口转换,90个时钟周期转换一次。
  110.         _nop_();
  111.         _nop_();         
  112.           _nop_();
  113.         _nop_();
  114.     ADC_CONTR=0xe8;//(1110 1000)清零
  115.         }
  116. }        
  117. /***************ADC处理********************/
  118. void AD_ris() interrupt  5
  119. {   
  120.    ADC_CONTR &= !ADC_FLAG;         //清除ADC中断标志
  121.   if(ADC_chunal_rnt%3==0)        //外部基准电压 (PTC采样处理)
  122.    {
  123.     data1=ADC_RES*4+ADC_RESL;//高八位+低两位结果
  124.          for(n=0;n<10;n++)                   //采样10次滤波
  125.           {
  126.                    temp+=data1;
  127.                 }
  128.             temp=temp/10;
  129.          }
  130.           if(ADC_chunal_rnt%3==1)                 //外部电压设置值处理
  131.          {
  132.            data2=ADC_RES*4+ADC_RESL;
  133.            for(c=0;c<10;c++)
  134.             {
  135.                   volatge+=data2;
  136.                   }
  137.                   volatge=volatge/10;
  138.                   }
  139.           if(ADC_chunal_rnt%3==2)           //外部电池温度检测采样处理
  140.            {
  141.              data3=ADC_RES*4+ADC_RESL;
  142.                  data3=(uint)(data3*5)/1024;
  143.                  for(g=0;g<10;g++)
  144.                   {
  145.                     NTC_bat+=data3;
  146.                         }
  147.                         NTC_bat=NTC_bat/10;
  148.                         }
  149.                 }
  150. /*****************PID初始化****************/
  151. void PID_Init()
  152. {
  153.   ZKB=0;   //输出占空比
  154.   e1=0;           //本次的温度差
  155.   e2=0;           //前一次温度差
  156.   e3=0;           //前两次温度差
  157.   kp=10;   //比例值
  158.   ki=0;           //积分值
  159.   kd=0;           //微分值
  160.   }       


  161. /******************温度比较处理及PID运算*********************/
  162. void PID_compare_temp()
  163. {
  164.    
  165.   if(set_sum>temper)   //如果设定温度大于实际温度
  166.   {
  167.    if(set_sum-temper>20)  //如果相差20度
  168.    {
  169.      ZKB=100;                          //全速加热
  170.          
  171.          }

  172.         else                                  //否则进行PID运算平滑加热
  173.           {
  174.             e1=set_sum-temper;
  175.                 duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10;
  176.                 uk=uk+duk;
  177.                    if(uk>100)
  178.                 uk=100;
  179.          else
  180.             if(uk<-100)
  181.                 uk=-100;
  182.                 if(uk<0)
  183.                 {
  184.                  ZKB=-uk;
  185.            }
  186.         else
  187.            {
  188.              ZKB=uk;
  189.           }
  190.           e3=e2;
  191.           e2=e1;
  192.          }
  193.         }
  194.          if(temper>=set_sum)         //如果实际温度大于设定温度
  195.          {
  196.           if(temper-set_sum>0)   //如果实际温度与设定温度不相等
  197.           {
  198.                    ZKB=0;                                //停止加热
  199.                
  200.                 }
  201.          else
  202.          {
  203.            e1=temper-set_sum;
  204.            duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3));
  205.            uk=uk+duk;
  206.            if(uk>100)
  207.                    uk=100;
  208.           else
  209.             if(uk<-100)
  210.                 uk=-100;
  211.                 e3=e2;
  212.                 e2=e1;                 
  213.            }
  214.         }
  215. }       
  216.    
  217. /********定时器0***********/
  218. void timer0() interrupt 1
  219. {
  220.   
  221. TL0=0x9C;                //设置定时初值        0.1ms
  222. TH0=0xFF;                //设置定时初值
  223. time++;
  224. num++;
  225.   if(num>=100)
  226.    num=0;
  227.   if(num<ZKB)
  228.   PWM_out=1;
  229.   else
  230.   PWM_out=0;
  231.    }
  232.   
  233. /*********定时器2**********/
  234. void t2int() interrupt 12          //5ms定时
  235. {
  236.   keyScan();
  237.         m++;
  238.     j++;
  239.         if(m>=5)
  240.         {
  241.           m=0;
  242.         ADC_Init();         //ADC每5MS转换一次通道
  243.         }          
  244.    if(j==500) //0.5秒
  245.     {
  246.             j=0;
  247.     s1++;   
  248.   if(s1==2000)//10分钟后停止输出
  249.   {
  250.     s1=0;
  251.         TR0=0;
  252.     s2++;
  253.        }
  254.         }
  255.        
  256. //  IE2&=~0x04;  //清中断标志
  257. //  IE2|=0x04;   //再开中断
  258. }
  259. /**********LED闪**********/
  260. void LED_TSK1(void)
  261. {
  262.   if(time>=5000)//0.5秒
  263.     time=0;
  264.         LED=!LED;

  265. /* Delay(1000);                  //约0.5秒闪
  266. LED=0;
  267. Delay(1000);
  268. LED=1;*/
  269.   }
  270. void LED_TSK2(void)          //约3秒闪
  271. {

  272.    Delay(20000);
  273.    LED=0;
  274.    Delay(20000);
  275.    LED=1;
  276.   }



  277. /***********按键扫描及处理*************/
  278. void keyScan()
  279. {
  280. //  static uchar tt=0;
  281.   static bit key1_lock=0;
  282.   static uchar count1=0;
  283.              
  284.         if(0==key)
  285.         {

  286.    if((count1++>=25)&&(key1_lock==0)&&(PINT==1))//延时滤波25ms
  287.           {
  288.             key1_lock=1;
  289.             TR0=~TR0;
  290.                 LED_TSK2();                 
  291.         }
  292.        
  293.           }
  294.   else
  295.     {
  296.          key1_lock=0;//按键自锁标志清0
  297.      count1=0; //消抖计数清0
  298.           }
  299.    if(PINT==0)
  300.     {
  301.           Pout=0;
  302.         
  303.            }  
  304.         }           
  305. /*void key_tak()
  306. {
  307. if(key_sec==0)
  308.   {
  309.     return;
  310.         }
  311. switch(key_sec)
  312. {
  313.   case 1:
  314.          TR0=~TR0;
  315.                  LED=0;
  316.           key_sec=0;
  317.           break;
  318.           }
  319.         }  */
  320. /************判断LED闪烁处理***********/
  321. void LED_san()
  322. {
  323. if(temper<300)
  324. {
  325.             LED_TSK1();
  326.         }
  327. else
  328.    if(temper>=300)
  329.    {
  330.      LED=1;
  331.          }
  332.   
  333. if((PWM_out==0)&&(tt++>=10000))
  334.    {
  335.   
  336.     tt=0;
  337.         LED_TSK2();
  338.         }
  339.   }
  340. /*void NTC_asc()
  341. {
  342. if(NTC_bat<=400)
  343. {
  344.    Pout=0;
  345.    PWM_out=0;
  346.    }
  347. } */
  348.    
  349. /**********主程序**********/   
  350. void main()
  351. {

  352. Delay(100);
  353. time0_Init();
  354. time2_Init();
  355. IO_Init();

  356. PID_Init();
  357. while(1)
  358. {       
  359.   set_sum=volatge;//装载设定值
  360. temper=temp;//给PID装载实际值
  361.   PID_compare_temp();
  362. // LED_san();
  363.    LED_TSK1();       
  364.    if(s2==2)//20分钟后关机
  365.    {
  366.      s2=0;
  367.          Pout=0;  
  368.           }
  369.          }
  370.         }          


 楼主| LKC134 发表于 2019-7-23 15:13 | 显示全部楼层
原理图如下:

 楼主| LKC134 发表于 2019-7-23 15:14 | 显示全部楼层
如下:
 楼主| LKC134 发表于 2019-7-23 15:15 | 显示全部楼层
怎么图片放不上去呢?
 楼主| LKC134 发表于 2019-7-23 15:30 | 显示全部楼层
这功能是采用3路ADC采样输入,一,每5MS转换一次通道,没有显示功能单纯控温。
                                              二,使用PTC热敏电阻作返馈信号。
                                              三,外部电位器调节电压来设定温度值。
                                              四,外接电池温度检测。
 楼主| LKC134 发表于 2019-7-23 15:34 | 显示全部楼层
有没有那位大神看出问题没?
 楼主| LKC134 发表于 2019-7-23 16:06 | 显示全部楼层
顶下。
 楼主| LKC134 发表于 2019-7-23 16:29 | 显示全部楼层
只有定时器2工作,定时器0没输出。
叶春勇 发表于 2019-7-23 16:47 | 显示全部楼层
本帖最后由 叶春勇 于 2019-7-23 16:55 编辑
    1. <div>
    2. </div>
    一个定时器可以产生多个时基

  1. void timer0() interrupt 1
  2. {
  3.   
  4. TL0=0x9C;                //设置定时初值        0.1ms
  5. TH0=0xFF;                //设置定时初值
  6. if(ticks<60000) ticks++;
  7. else ticks=0;
  8. t_1ms_flag=((ticks%10)==0);//采用此法产生一个一个定时器生成多个时基准。
  9. t_5ms_flag=((ticks%50)==0);
  10. }


叶春勇 发表于 2019-7-23 16:55 | 显示全部楼层
一个定时器可以产生多个时间基准
  1. void timer0() interrupt 1
  2. {
  3.   
  4. TL0=0x9C;                //设置定时初值        0.1ms
  5. TH0=0xFF;                //设置定时初值
  6. if(ticks<60000) ticks++;
  7. else ticks=0;
  8. t_1ms_flag=((ticks%10)==0);//采用此法产生一个一个定时器生成多个时基准。1ms
  9. t_5ms_flag=((ticks%50)==0);//5ms
  10. }



 楼主| LKC134 发表于 2019-7-23 17:33 | 显示全部楼层
叶春勇 发表于 2019-7-23 16:55
一个定时器可以产生多个时间基准

我知道可以产生多个定时器,问题是我的功能会实现不了,因为有个按键是暂停输出和恢复输出功能,定时10分钟后暂停输出,按一下按键就恢复输出,要用到TR0=~TR0作开关。
 楼主| LKC134 发表于 2019-7-23 17:35 | 显示全部楼层
LKC134 发表于 2019-7-23 17:33
我知道可以产生多个定时器,问题是我的功能会实现不了,因为有个按键是暂停输出和恢复输出功能,定时10分 ...

开机LED以0.5秒闪,到达目标温度后LED长亮,暂停输出LED以3秒闪一次。20分钟后断电关机。
 楼主| LKC134 发表于 2019-7-23 17:44 | 显示全部楼层
刚开始不设置LED,两个定时器是有作用的,定时器0是PWM输出,定时器2是按键控制PWM和定时时间,但一增加LED设置或其它功能程序时就只有定时器2有作用。
叶春勇 发表于 2019-7-23 18:13 | 显示全部楼层
本帖最后由 叶春勇 于 2019-7-23 18:18 编辑
  1. <div>if(T_1ms_flag)
  2. {
  3. T_1ms_flag=0;
  4. //防抖
  5. if(key)
  6. {
  7.   if(++key_high_acc>100) vkey=1;
  8.   key_low_acc=0;
  9. }
  10. else
  11. {
  12.   if(++key_low_acc>100) vkey=0;
  13.   key_high_acc=0;
  14. }</div><div> switch(pause_state)
  15. {
  16.   case INIT:
  17.    auto_run_acc=0;
  18.    output_enable=0;
  19.    pause_state=WAIT_RUN;
  20.    break;
  21.   case WAIT_PAUSE:
  22.    if(vkey) state=PAUSE;break;
  23.   case PAUSE:
  24.    output_enable=0; //输出控制位
  25.    if(vkey=0) state=WAIT_RUN;//暂停时按下按键进入运行
  26.    if(++auto_run_acc>xxxx) state=WAIT_RUN;//暂停持续一定时间进入运行
  27.    break;
  28.   case WAIT_RUN:
  29.    auto_run_acc=0;
  30.    if(vkey) state=RUN;break;
  31.   case RUN:
  32.    output_enable=1;
  33.    if(vkey==0) state=WAIT_PAUSE;//运行时按下按键进入暂停
  34.    break;
  35. }
  36. }
  37. </div>
叶春勇 发表于 2019-7-23 18:19 | 显示全部楼层
  1. if(T_1ms_flag)
  2. {
  3.         T_1ms_flag=0;
  4.         //防抖
  5.         if(key)
  6.         {
  7.                 if(++key_high_acc>100) vkey=1;
  8.                 key_low_acc=0;
  9.         }
  10.         else
  11.         {
  12.                 if(++key_low_acc>100) vkey=0;
  13.                 key_high_acc=0;
  14.         }

  15.         switch(pause_state)
  16.         {
  17.                 case INIT:
  18.                         auto_run_acc=0;
  19.                         output_enable=0;
  20.                         pause_state=WAIT_RUN;
  21.                         break;
  22.                 case WAIT_PAUSE:
  23.                         if(vkey) state=PAUSE;break;
  24.                 case PAUSE:
  25.                         output_enable=0; //输出控制位
  26.                         if(vkey=0) state=WAIT_RUN;//暂停时按下按键进入运行
  27.                         if(++auto_run_acc>xxxx) state=WAIT_RUN;//暂停持续一定时间进入运行
  28.                         break;
  29.                 case WAIT_RUN:
  30.                         auto_run_acc=0;
  31.                         if(vkey) state=RUN;break;
  32.                 case RUN:
  33.                         output_enable=1;
  34.                         if(vkey==0) state=WAIT_PAUSE;//运行时按下按键进入暂停
  35.                         break;
  36.         }
  37. }

叶春勇 发表于 2019-7-23 18:34 | 显示全部楼层
LED灯闪烁处理

if(T_1ms_flag)
{
        T_1ms_flag=0;
        if(flash_acc<60000) flash_acc++;
        else flash_acc=0;
       
        flash_500ms=(flash_acc%1000)>500; //0.5s灭,0.5s亮
        flash_3s=(flash_acc%6000)>3000;//3秒灭,3秒亮
}


void LED_display_with_drive(uint8_t flash)
{
        if(flash) LED=1;
        else LED=0;
}

LED_display_with_drive(1); //常亮
LED_display_with_drive(0); //常灭
LED_display_with_drive(flash_500ms); //0.5秒闪
LED_display_with_drive(flash_3s); //3s闪

你这个程序闪烁,卡循环。不要用delay,也用定时器。
 楼主| LKC134 发表于 2019-7-23 19:55 | 显示全部楼层

本帖子中包含更多资源

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

×
 楼主| LKC134 发表于 2019-7-23 19:56 | 显示全部楼层
这是原理图,在公司电脑老是传不上,现在家里就传上了.
 楼主| LKC134 发表于 2019-7-23 19:59 | 显示全部楼层
叶春勇 发表于 2019-7-23 18:34
LED灯闪烁处理

if(T_1ms_flag)

多谢!其实我一开始就用定时器做LED的,用1个定时器开始没问题,后来再加多个定时器就不行了.
 楼主| LKC134 发表于 2019-7-23 20:01 | 显示全部楼层
明天我再调试下.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

348

帖子

6

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