Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Проблем с таймер
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=14023
Страница 1 от 3

Автор:  bobi13 [ Вто Сеп 08, 2015 3:18 pm ]
Заглавие:  Проблем с таймер

Здравейте, ползвам микроконтролер 8051f021 и имам следния проблем. Използвам 2 таймера, за да генерирам честата и импулс. Таймерът на импулса е през 1мс и е с приоритет. Проблемът е че на изхода не получавам увеличаване през 1мс както е зададено, а получавам сигнал с разлика от 200-800us от искания. Например аз искам 8мс, а на изхода имам 7,8us. А към края на при искани 30мс получавам 29мс.

void timer1_ISR(void) interrupt 3 //Timer to generate output signal
{
TH1 = 0xFA; //1ms
TL1 = 0xCB;

FRQ1 = FRQ1 - 1;
if(FRQ1 == 0)
{
Valve_on = 1; // valve OFF
FRQ1=FRQ;
CNTIMP1=CNTIMP;
CNTIMP1++;
LED = 0;
}

CNTIMP1 = CNTIMP1 - 1;
if(CNTIMP1 == 0)
{

CNTIMP1=CNTIMP;

Valve_on = 0; // valve ON
LED = 1;
}

}

Автор:  Dimitar [ Вто Сеп 08, 2015 3:42 pm ]
Заглавие:  Re: Проблем с таймер

Много добре си ги получаваш - дължи се на софтуерния ти PWM. Можеш малко да го оптимизираш, но никога няма да е точно колкото искаш. Ако искаш точна честота ползвай хардуерен PWM.

Автор:  bobi13 [ Вто Сеп 08, 2015 4:20 pm ]
Заглавие:  Re: Проблем с таймер

Нямам възможност да го ползвам. Има ли друг начин?

Автор:  stefan63 [ Вто Сеп 08, 2015 4:52 pm ]
Заглавие:  Re: Проблем с таймер

Тези 200-300 микросекунди ...
-или има друго прекъсване с по-голям приоритет, което твърде често съвпада с прекъсването по таймера
-или някъде забраняваш прекъсванията и нещо чакаш.
На каква честота работи процесора?

Автор:  stefan63 [ Вто Сеп 08, 2015 4:58 pm ]
Заглавие:  Re: Проблем с таймер

Всъщност, покажи цялата програма.

Автор:  bobi13 [ Вто Сеп 08, 2015 4:58 pm ]
Заглавие:  Re: Проблем с таймер

Имам два таймера, този таймер е на 1мс и е с най- висок приоритет. Другият таймер е на 5мс - той ми следи за бутони и други функции. Процесорът е на 16MHz/12

Автор:  bobi13 [ Вто Сеп 08, 2015 4:59 pm ]
Заглавие:  Re: Проблем с таймер

Код:
#include "c8051F020.h"
#include <intrins.h>
//#include "delay.h"

unsigned char bdata BUT1FL = 0x100;
sbit BUT1FL_0 = BUT1FL^0;
sbit BUT1FL_1 = BUT1FL^1;
sbit BUT1FL_2 = BUT1FL^2;
sbit BUT1FL_3 = BUT1FL^3;
sbit BUT1FL_4 = BUT1FL^4;
sbit BUT1FL_5 = BUT1FL^5;
sbit BUT1FL_6 = BUT1FL^6;
sbit BUT1FL_7 = BUT1FL^7;

unsigned char bdata BUT2FL = 0x101;
sbit BUT2FL_0 = BUT2FL^0;
sbit BUT2FL_1 = BUT2FL^1;
sbit BUT2FL_2 = BUT2FL^2;
sbit BUT2FL_3 = BUT2FL^3;
sbit BUT2FL_4 = BUT2FL^4;
sbit BUT2FL_5 = BUT2FL^5;
sbit BUT2FL_6 = BUT2FL^6;
sbit BUT2FL_7 = BUT2FL^7;

unsigned char bdata FFP = 0x102;
sbit FFP_0 = FFP^0;
sbit FFP_1 = FFP^1;
sbit FFP_2 = FFP^2;
sbit FFP_3 = FFP^3;
sbit FFP_4 = FFP^4;
sbit FFP_5 = FFP^5;
sbit FFP_6 = FFP^6;
sbit FFP_7 = FFP^7;


unsigned char bdata FSS = 0x103;
sbit FSS_0 = FSS^0;
sbit FSS_1 = FSS^1;
sbit FSS_2 = FSS^2;
sbit FSS_3 = FSS^3;
sbit FSS_4 = FSS^4;
sbit FSS_5 = FSS^5;
sbit FSS_6 = FSS^6;
sbit FSS_7 = FSS^7;
unsigned char bdata  CNTFSSB4 = 0x104;
unsigned char bdata  CNTB2 = 0x105;
unsigned char bdata  CNTB1 = 0x106;
unsigned char bdata  CNTFFPB3 = 0x107;
void but_plus(); // Button up
void butplus ();
void but_minus(); // Button down
void butminus ();
void but_FP();      // Button frquency/pulse selector
void but_Start_Stop();
void Start_Stop();
void Master_button();

sbit FP =  P1^5; // Frequency/Pulse width selector
sbit Start =  P1^6; // Start/stop button for signal
sbit Plus =  P2^3; // Plus
sbit Minus =  P2^4; // Minus
sbit Valve_on = P0^5;//output for valve

sbit LED = P1^7; // Pulse indicator


unsigned char c;
unsigned int   CNTIMP;
unsigned int   CNTIMP1;
unsigned int   CNTFRQ;

unsigned int FRQ1;
unsigned int FRQ;

#define  LCD_DATA P3
sbit LCD_RS   =   P0^2;
sbit LCD_EN   =   P0^4;

unsigned char  data_ind[3];
char init_value;
#define lcd_delay 400

void delay(unsigned int j)
{
                unsigned int i=0;
                for(i=0;i<j;i++);
}
/*=======================================

            LCD INITIALIZAIOTN

=======================================*/


void LCD_STROBE (void);

void lcd_write(unsigned char c)
{
delay(lcd_delay);
   LCD_DATA = ( ( c >> 4 ) & 0x0F );
   LCD_STROBE();
   LCD_DATA = ( c & 0x0F );
   LCD_STROBE();
}

/*
*    Clear and home the LCD
*/

void lcd_clear(void)
{
   LCD_RS = 0;
   lcd_write(0x1);
delay(lcd_delay);
}

/* write a string of chars to the LCD */

void lcd_puts(const char * s)
{
   LCD_RS = 1;   // write characters
   while(*s)
      lcd_write(*s++);
}

/* write one character to the LCD */
/*
void lcd_putch(char c)
{
   LCD_RS = 1;   // write characters
   lcd_write( c );
}
*/

/*
* Go to the specified position
*/

void lcd_goto(unsigned char pos)
{
   LCD_RS = 0;
   lcd_write(0x80+pos);
}
   
/* initialise the LCD - put into 4 bit mode */

void lcd_init()
{
   

   init_value = 0x3;

   LCD_RS = 0;
   LCD_EN = 0;
   

delay(lcd_delay);

//Delay after starting the LCD
   LCD_DATA    = 0x30;
   LCD_STROBE();

delay(lcd_delay);

   LCD_DATA    = 0x30;//3
   LCD_STROBE();
delay(lcd_delay);
   
   LCD_DATA    = 0x30;//3
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA    = 0x20;//3
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA    = 0x02;//2
   LCD_STROBE();
delay(lcd_delay);
   
   LCD_DATA    = 0x08;//2
   LCD_STROBE();
   LCD_DATA    = 0x08;//8
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA    = 0x00;//0
   LCD_STROBE();
   LCD_DATA    = 0x08;//8
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA    = 0x00;//0
   LCD_STROBE();
   LCD_DATA    = 0x0f;//0x0f
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA   =0x00;
   LCD_STROBE();
   LCD_DATA   =0x06;
   LCD_STROBE();
delay(lcd_delay);

   LCD_DATA   =0x00;
   LCD_STROBE();
   LCD_DATA   =0x0c;//0c
   LCD_STROBE();
delay(lcd_delay);



   
LCD_RS = 1;
}


void LCD_STROBE(void)
{
   LCD_EN = 1;
delay(lcd_delay);
   LCD_EN= 0;
}


/*=======================================

         END LCD INITIALIZAIOTN

========================================*/
void itoa(int number)
{
data_ind[2] = '\0';
data_ind[1] = (number%10);
data_ind[0] = ((number%100) - data_ind[1])/10;

data_ind[1] = data_ind[1] + '0';
data_ind[0] = data_ind[0] + '0';

}

void LCD_show()
{
   itoa(CNTFRQ); // Write in array value of FRQ or IMP and displey it to the LCD
   lcd_goto(0x00);
   lcd_puts("FRQ");

   lcd_goto(0x05);
   lcd_puts(data_ind);

   lcd_goto(0x09);
   lcd_puts("Hz");

   itoa(CNTIMP);
   lcd_goto(0x40);
   lcd_puts("PWM");

   lcd_goto(0x45);
   lcd_puts(data_ind);
   
   lcd_goto(0x49);
   lcd_puts("ms");
}


void Start_Stop(void)
{
   if (Start==0)
      {
      TR1=1; //Enable
         }
         else
            {
         
               TR1=0; // Disable
                        
            }

}

void FP_Selector(void)
{

   if (FP==0)
      {
   
                  // Start only Timer0
         lcd_goto(0x4d);
         lcd_puts(" ");
         lcd_goto(0x4e);
         lcd_puts(" ");
         lcd_goto(0x0d);
         lcd_puts("<<");


      }
      
         else
         {
         lcd_goto(0x0d);
         lcd_puts(" ");
         lcd_goto(0x0e);
         lcd_puts(" ");
         lcd_goto(0x4d);
         lcd_puts("<<");

            }

}




void Timer_Init()
{
    TMOD      = 0x11; // Timer0/Timer1 16 bit 11
   IP        = 0x08; // Timer 1 priority high
   OSCICN    = 0x07;
    WDTCN     = 0xDE;
    WDTCN     = 0xAD;
   IE        = 0x8A; // timer0/1 interrupt

}

void Port_init()
{

   P0MDOUT   = 0x3C;
    P1MDOUT   = 0x06;
    P2MDOUT   = 0x18;
    P3MDOUT   = 0x0F;
    XBR2      = 0x40;

}


void main(void)
{
   TR0=0;
//   TR1=0;
//TL1  = 0x65;   //Lower Byte
//TH1  = 0xFD;   //Upper Byte
//   TH1 = 0xFA;       //1ms
//   TL1 = 0xCB;
//   TH0 = 0xE5;//5ms
//   TL0 = 0xF5;
   Port_init();
   Timer_Init();
   lcd_init();
   TR0=1;
   Valve_on = 1;
   CNTFRQ = 1; // Starting value to frequency
   CNTIMP   =1; //Starting value tO  impuls

   while(1);

}


void timer1_ISR(void) interrupt 3 //Timer to generate output signal
{

   TH1 = 0xFA;       //1ms
   TL1 = 0xCB;


   FRQ1 = FRQ1 - 1;
   if(FRQ1 == 0)
   {
         Valve_on = 1; // valve OFF
       FRQ1=FRQ;
       CNTIMP1=CNTIMP;
       CNTIMP1++;
   
   }
      
   CNTIMP1 = CNTIMP1 - 1;
   if(CNTIMP1 == 0)
   {
   
       CNTIMP1=CNTIMP;
       
       Valve_on = 0; // valve ON

   }
   
}
void timer0_ISR (void) interrupt 1
{
TH0 = 0xE5;//5ms
TL0 = 0xF5;

      
   Master_button();
   LCD_show();//
  //Start_Stop();//
   FP_Selector();//
   but_plus();//
   but_minus();//
   but_Start_Stop();//


}
void Master_button()
{

   if(Plus==0)
      {
      BUT1FL_7=1;
      }
      else
      {   
      BUT1FL=0;
      }
     
      if(Minus==0)
      {
      BUT2FL_7=1;
      }
      else
      {   
      BUT2FL=0;
      }

   if(Start==0)
      {
      FSS_7=1;
      }
      else
      {   
      FSS=0;
      }



}


void broiach_FRQ()
{
   FRQ =  1000/CNTFRQ;// counter for frequency depending on timer1
   FRQ1 = FRQ; // working


}

void butplus () // count up
{   

   if (FP==0)
   {   
   if(CNTFRQ==30)
   {;}
      else
      {
         CNTFRQ = CNTFRQ+1;
          broiach_FRQ();


      }
      }
               else //PWM
            {
                  if(CNTIMP==30)
                  {;}
                  else
                  {
                  CNTIMP = CNTIMP+1;
                  
                  }      
            }
}         


void butminus () // count down
{
    
     if (FP==0)
   {
      if(CNTFRQ==1)
      {;}
      else
      {
         CNTFRQ = CNTFRQ-1;
         broiach_FRQ();

      }
      }
               else //PWM
            {      
                     if(CNTIMP==1)
                  {;}
                  else
                  {
                     CNTIMP = CNTIMP-1;

                  }
                  
                  

            }

}     

/*====================================

            BUTTON FLAG
            
======================================*/

void but_Start_Stop () // BUTTON FREQ OR PWM
{
if(FSS_7==1)
{
    if(FSS_5==0)      //if result is 1 - the button is ready
    {
       if(FSS_0==0)   //starting 30ms delay
       {
        FSS_0=1;
        CNTFSSB4=2;
       }
      else
      {
         if (FSS_2==1)
         {
            FSS_5=1;   
      //   Start = ~Start;
            Start_Stop();
         }
            else
            {
            CNTFSSB4--; 
               if(CNTFSSB4==0)
               {
               FSS_2=1;
               }
             }
            }
      }
      }
    else
    {
       Start_Stop();
    }
}

void but_plus ()
{
if(BUT1FL_7==1)
{
    if(BUT1FL_5==0)      //if result is 1 - the button is ready
    {
       if(BUT1FL_0==0)   //starting 30ms delay
       {
        BUT1FL_0=1;
        CNTB1=1;
      }
      else
      {
         if (BUT1FL_2==1)
         {
            BUT1FL_5=1;   
            butplus();
         }
            else
            {
            CNTB1--; 
               if(CNTB1==0)
               {
               BUT1FL_2=1;
               }
}}}}}

void but_minus ()
{
if(BUT2FL_7==1)
{
    if(BUT2FL_5==0)      //if result is 1 - the button is ready
    {
       if(BUT2FL_0==0)   //starting 30ms delay
       {
        BUT2FL_0=1;
        CNTB2=1;
       }

       else
      {
            if (BUT2FL_2==1)
         {
            BUT2FL_5=1;   
            butminus();
         }
            else
            {
            CNTB2--; 
               if(CNTB2==0)
               {
               BUT2FL_2=1;
               }
}}}}}

Автор:  stefan63 [ Вто Сеп 08, 2015 5:38 pm ]
Заглавие:  Re: Проблем с таймер

В ISR таймер 0 имаш твърде много неща.
Виж си таймер 1 ISR, няма никакви извиквания на други функции.
Където и да ти е проблемът - първо и задължително - първо се опразва таймер 0 ISR.
Не може главната програма нищо да не прави
while(1);

Кой знае как ти се омазват регистри и памет.

Т0 се презарежда от ISR, там се вдига някакъв флаг "Ехо, минаха 5 милискунди" и излиза, нищо друго.
Главната програма следи този флаг.
Като го види вдигнат - нулира флага и изпълнява всичко това което си вкарал в Т0.

Отделно обработката ти на бутоните е лоша. Потърси из темите "debounce", оттам може да ти набъбне Т0 ISR, но малко.

Според даташийта:
Цитат:
Therefore, the fastest possible response time is 5 system clock cycles:
1 clock cycle to detect the interrupt and 4 clock cycles to complete the LCALL to the ISR. If an interrupt is pending
when a RETI is executed, a single instruction is executed before an LCALL is made to service the pending interrupt.
Therefore, the maximum response time for an interrupt (when no other interrupt is currently being serviced or the
new interrupt is of greater priority) occurs when the CPU is performing an RETI instruction followed by a DIV as the
next instruction. In this case, the response time is 18 system clock cycles:


Това означава, че смяната на порт в T1ISR ще сработва с "житер" между 5 и 18 такта,
което на 16МХц не би трябвало да е важно.
Периодът на импулсите обаче може да се регулира доста добре , трябва малко да се
пипне презареждането на Т1 в прекъсването. Но това е твърде далечно .

Автор:  ToHu [ Вто Сеп 08, 2015 6:03 pm ]
Заглавие:  Re: Проблем с таймер

Освен всичко написано от колегите, какво означава че мне можеш да изпозлваш хардуерния PWM, точно тоя не го знам колко има, но повето от тия имат поне 4 PWM-а, не може и 4-те да са ти заети.
Също така не знам с какво компилираш, но в кейла имаше пак някаква особенност при обслужване на прекъсванията, трябва да погледна но имам спомен че за някои проекти съм изпозлвал мой код за обслужване на прекъсването. Но като цяло с тоя процесор не би следвлао да имаш никакви грижи дори и за софтуерно реализиран PWM.

Автор:  Dimitar [ Вто Сеп 08, 2015 6:16 pm ]
Заглавие:  Re: Проблем с таймер

bobi13 написа:
Нямам възможност да го ползвам. Има ли друг начин?

Има - като си оптимизираш кода в прекъсванията и приоритетите им. Генерално правило е всичко, което може да е извън прекъсване. Не може да наблъскаш всичко вътре. И въпреки всичко няма да е идеално - винаги ще има малко грешка.

Автор:  bobi13 [ Вто Сеп 08, 2015 6:23 pm ]
Заглавие:  Re: Проблем с таймер

Тъй като ползвам само вътрешния осцилатор, немога да го накарам да работи на толкова ниска честота
променям честотата от 1-30Хц
импулса - 1мс-30мс

Автор:  stefan63 [ Вто Сеп 08, 2015 6:24 pm ]
Заглавие:  Re: Проблем с таймер

Bobi13,
Обработката ти на бутоните е твърде разхвърляна и сложна, трудно е да се ориентирам.
Но предполагам ,че имаш проблеми и с бутоните.
Бих те посъветвал да оставиш Т1 за момента ,
направи си бутоните и дисплея, Т0 - минималистично.
Т1 както си го замислил- може би е добре, може и да не е - не съм наясно какво точно правиш. Остави го за края, наистина не е нещо особено - проблемите ти не идват оттам.

Автор:  bobi13 [ Вто Сеп 08, 2015 6:31 pm ]
Заглавие:  Re: Проблем с таймер

Целта на Т0 е да следя бутоните през 5мс и ако има натиснат да направи проверка чрез флагове, дали наистина е натиснат и ако е да го обработи след 15мс (това е за бутони плюс и минус). Другия бутон е за старт/стоп на сигнала който изпращам към изхода.
Функцията мастер бутон, следи дали са вдигнати флаговете за натиснат бутон

Автор:  stefan63 [ Вто Сеп 08, 2015 6:41 pm ]
Заглавие:  Re: Проблем с таймер

Да, но съм си сипал ракийка, и това усложнява още нещата.
И да не бях с ракийка, пак не бих се зачел - някои неща не си струват времето, без да се обиждаш.
Ако LCDto се управлява коректно, изнеси му функциите - да не си гумбим времето с тях и
почвай другите неща. Пишеш - постваш. Все някой ще коментира. След 2 дена можеш да пробваш.

Автор:  stefan63 [ Вто Сеп 08, 2015 6:42 pm ]
Заглавие:  Re: Проблем с таймер

На всяка функция напиши коментар на български - какво трябва да прави.

Страница 1 от 3 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/