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

[复制链接]
2907|39
手机看帖
扫描二维码
随时随地手机跟帖
LKC134|  楼主 | 2019-7-23 15:09 | 显示全部楼层 |阅读模式
这两天做了一款产品,在编程时使用两个定时器同时工作就没起作用了,芯片手册也看了,也调试了N次还是这样,请各位大神指点下
程序如下:
#include "STC15W.H"
#include"intrins.h"
#define uchar unsigned char
#define uint  unsigned int
#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_FLAG    0x10            //ADC完成标志
#define ADC_START   0x08            //ADC起始控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_SPEEDL  0x20            //360个时钟
#define ADC_SPEEDH  0x40            //180个时钟
#define ADC_SPEEDHH 0x60            //90个时钟
#define LED_Time1 500
#define LED_Time2 3000
void LED_TSK1(void);
void LED_TSK2(void);            
void keyScan();
void key_tak();
void time0_Init(void);
void t2int();
void timer0();
void time2_Init(void);   
void LED_san();

void AD_ris();

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

sbit key=P1^3;
sbit PWM_out=P3^6;
/**********延时子程序**********/
void Delay(uint z)
{
uint y,x;
for(y=0;y<z;y++)
   for(x=0;x<120;x++);
   }
       
/*********定时器初始化*********/
void time0_Init(void)
{
//        AURX=0x7f;               //定时器时钟12T模式
        TMOD&=0xf0;
        TMOD|=0x01;                //设置定时器模式
        TL0=0x9C;                    //设置定时初值100uS
        TH0=0xFF;                   //设置定时初值
       
        TF0=0;           //清除TF0标志
        ET0=1;
        EA=1;                       
        TR0=1;
        }
void time2_Init(void)
{
        AUXR&=~0x04;           //12T模式
        T2L=0x18;                //设置定时初值         1ms
        T2H=0xfc;                //设置定时初值
        AUXR|=0x10;                    //定时器0开始计时     
        IE2|=0x04;
        EA=1;
        }
/************IO初始化*************/
void IO_Init(void)
{       
        P1M0=0X10;
    P1M1=0X2E;
    P3M0=0X48;
    P3M1=0X00;
    P5M0=0X00;
    P5M1=0X00;
        }
/***************AD初始化*****************/
void ADC_Init()
{
   P1ASF=0x07;           //设置P1.2和P1.1,P1.0为模拟输入
    ADC_RES=0;               
   ADC_RESL=0;
   ADC_CONTR=0x80;
   Delay(1);
   if(ADC_chunal_rnt%3==0)        //外部基准电压
   {
    ADC_CONTR=0xf4;//设P1.2口转换,90个时钟周期转换一次。
        _nop_();
        _nop_();         
          _nop_();
        _nop_();
    ADC_CONTR=0xe8;//(1110 1000)清零
         }

  if(ADC_chunal_rnt&3==1)
  {
           ADC_CONTR=0xe2;//设P1.1口转换,90个时钟周期转换一次。
        _nop_();
        _nop_();         
          _nop_();
        _nop_();
    ADC_CONTR=0xe8;//(1110 1000)清零
     }
   if(ADC_chunal_rnt%3==2)
   {
    ADC_CONTR=0xe1;//设P1.0口转换,90个时钟周期转换一次。
        _nop_();
        _nop_();         
          _nop_();
        _nop_();
    ADC_CONTR=0xe8;//(1110 1000)清零
        }
}        
/***************ADC处理********************/
void AD_ris() interrupt  5
{   
   ADC_CONTR &= !ADC_FLAG;         //清除ADC中断标志
  if(ADC_chunal_rnt%3==0)        //外部基准电压 (PTC采样处理)
   {
    data1=ADC_RES*4+ADC_RESL;//高八位+低两位结果
         for(n=0;n<10;n++)                   //采样10次滤波
          {
                   temp+=data1;
                }
            temp=temp/10;
         }
          if(ADC_chunal_rnt%3==1)                 //外部电压设置值处理
         {
           data2=ADC_RES*4+ADC_RESL;
           for(c=0;c<10;c++)
            {
                  volatge+=data2;
                  }
                  volatge=volatge/10;
                  }
          if(ADC_chunal_rnt%3==2)           //外部电池温度检测采样处理
           {
             data3=ADC_RES*4+ADC_RESL;
                 data3=(uint)(data3*5)/1024;
                 for(g=0;g<10;g++)
                  {
                    NTC_bat+=data3;
                        }
                        NTC_bat=NTC_bat/10;
                        }
                }
/*****************PID初始化****************/
void PID_Init()
{
  ZKB=0;   //输出占空比
  e1=0;           //本次的温度差
  e2=0;           //前一次温度差
  e3=0;           //前两次温度差
  kp=10;   //比例值
  ki=0;           //积分值
  kd=0;           //微分值
  }       


/******************温度比较处理及PID运算*********************/
void PID_compare_temp()
{
   
  if(set_sum>temper)   //如果设定温度大于实际温度
  {
   if(set_sum-temper>20)  //如果相差20度
   {
     ZKB=100;                          //全速加热
         
         }

        else                                  //否则进行PID运算平滑加热
          {
            e1=set_sum-temper;
                duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10;
                uk=uk+duk;
                   if(uk>100)
                uk=100;
         else
            if(uk<-100)
                uk=-100;
                if(uk<0)
                {
                 ZKB=-uk;
           }
        else
           {
             ZKB=uk;
          }
          e3=e2;
          e2=e1;
         }
        }
         if(temper>=set_sum)         //如果实际温度大于设定温度
         {
          if(temper-set_sum>0)   //如果实际温度与设定温度不相等
          {
                   ZKB=0;                                //停止加热
               
                }
         else
         {
           e1=temper-set_sum;
           duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3));
           uk=uk+duk;
           if(uk>100)
                   uk=100;
          else
            if(uk<-100)
                uk=-100;
                e3=e2;
                e2=e1;                 
           }
        }
}       
   
/********定时器0***********/
void timer0() interrupt 1
{
  
TL0=0x9C;                //设置定时初值        0.1ms
TH0=0xFF;                //设置定时初值
time++;
num++;
  if(num>=100)
   num=0;
  if(num<ZKB)
  PWM_out=1;
  else
  PWM_out=0;
   }
  
/*********定时器2**********/
void t2int() interrupt 12          //5ms定时
{
  keyScan();
        m++;
    j++;
        if(m>=5)
        {
          m=0;
        ADC_Init();         //ADC每5MS转换一次通道
        }          
   if(j==500) //0.5秒
    {
            j=0;
    s1++;   
  if(s1==2000)//10分钟后停止输出
  {
    s1=0;
        TR0=0;
    s2++;
       }
        }
       
//  IE2&=~0x04;  //清中断标志
//  IE2|=0x04;   //再开中断
}
/**********LED闪**********/
void LED_TSK1(void)
{
  if(time>=5000)//0.5秒
    time=0;
        LED=!LED;

/* Delay(1000);                  //约0.5秒闪
LED=0;
Delay(1000);
LED=1;*/
  }
void LED_TSK2(void)          //约3秒闪
{

   Delay(20000);
   LED=0;
   Delay(20000);
   LED=1;
  }



/***********按键扫描及处理*************/
void keyScan()
{
//  static uchar tt=0;
  static bit key1_lock=0;
  static uchar count1=0;
             
        if(0==key)
        {

   if((count1++>=25)&&(key1_lock==0)&&(PINT==1))//延时滤波25ms
          {
            key1_lock=1;
            TR0=~TR0;
                LED_TSK2();                 
        }
       
          }
  else
    {
         key1_lock=0;//按键自锁标志清0
     count1=0; //消抖计数清0
          }
   if(PINT==0)
    {
          Pout=0;
        
           }  
        }           
/*void key_tak()
{
if(key_sec==0)
  {
    return;
        }
switch(key_sec)
{
  case 1:
         TR0=~TR0;
                 LED=0;
          key_sec=0;
          break;
          }
        }  */
/************判断LED闪烁处理***********/
void LED_san()
{
if(temper<300)
{
            LED_TSK1();
        }
else
   if(temper>=300)
   {
     LED=1;
         }
  
if((PWM_out==0)&&(tt++>=10000))
   {
  
    tt=0;
        LED_TSK2();
        }
  }
/*void NTC_asc()
{
if(NTC_bat<=400)
{
   Pout=0;
   PWM_out=0;
   }
} */
   
/**********主程序**********/   
void main()
{

Delay(100);
time0_Init();
time2_Init();
IO_Init();

PID_Init();
while(1)
{       
  set_sum=volatge;//装载设定值
temper=temp;//给PID装载实际值
  PID_compare_temp();
// LED_san();
   LED_TSK1();       
   if(s2==2)//20分钟后关机
   {
     s2=0;
         Pout=0;  
          }
         }
        }          


使用特权

评论回复

相关帖子

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 编辑
  • <div>
    </div>
    一个定时器可以产生多个时基

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


使用特权

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



使用特权

评论回复
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 编辑
<div>if(T_1ms_flag)
{
T_1ms_flag=0;
//防抖
if(key)
{
  if(++key_high_acc>100) vkey=1;
  key_low_acc=0;
}
else
{
  if(++key_low_acc>100) vkey=0;
  key_high_acc=0;
}</div><div> switch(pause_state)
{
  case INIT:
   auto_run_acc=0;
   output_enable=0;
   pause_state=WAIT_RUN;
   break;
  case WAIT_PAUSE:
   if(vkey) state=PAUSE;break;
  case PAUSE:
   output_enable=0; //输出控制位
   if(vkey=0) state=WAIT_RUN;//暂停时按下按键进入运行
   if(++auto_run_acc>xxxx) state=WAIT_RUN;//暂停持续一定时间进入运行
   break;
  case WAIT_RUN:
   auto_run_acc=0;
   if(vkey) state=RUN;break;
  case RUN:
   output_enable=1;
   if(vkey==0) state=WAIT_PAUSE;//运行时按下按键进入暂停
   break;
}
}
</div>

使用特权

评论回复
叶春勇| | 2019-7-23 18:19 | 显示全部楼层
if(T_1ms_flag)
{
        T_1ms_flag=0;
        //防抖
        if(key)
        {
                if(++key_high_acc>100) vkey=1;
                key_low_acc=0;
        }
        else
        {
                if(++key_low_acc>100) vkey=0;
                key_high_acc=0;
        }

        switch(pause_state)
        {
                case INIT:
                        auto_run_acc=0;
                        output_enable=0;
                        pause_state=WAIT_RUN;
                        break;
                case WAIT_PAUSE:
                        if(vkey) state=PAUSE;break;
                case PAUSE:
                        output_enable=0; //输出控制位
                        if(vkey=0) state=WAIT_RUN;//暂停时按下按键进入运行
                        if(++auto_run_acc>xxxx) state=WAIT_RUN;//暂停持续一定时间进入运行
                        break;
                case WAIT_RUN:
                        auto_run_acc=0;
                        if(vkey) state=RUN;break;
                case RUN:
                        output_enable=1;
                        if(vkey==0) state=WAIT_PAUSE;//运行时按下按键进入暂停
                        break;
        }
}

使用特权

评论回复
叶春勇| | 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 | 显示全部楼层
pp.pdf (158.26 KB)

使用特权

评论回复
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 | 显示全部楼层
明天我再调试下.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

339

帖子

6

粉丝