Опубликовано 2010-04-10 16:21:01 автором SWO

Таймери лічильники мікроконтролерів AVR (годинник реального часу)


Коли я ще починав вивчати мікроконтролери , мені захотілося зробити часовий таймер , щоб керувати навантаженням змінного струму . Чесно зізнаюся , я хотів спробувати вмикати телевізор тільки з 7 до 8 годин , а весь інший час він повинен був бути відключений . Пристрій я зробив , але так його і не застосував ...

У всіх мікроконтролерах AVR є кілька вбудованих таймерів . Їх ще можна розділити на таймери загального призначення і сторожовий таймер , який призначений для перезавантаження МК при зависанні .

Таймери загального призначення вміють :

  • Тактіровать від зовнішнього годинного кварцу на 32768 герц
  • Рахувати різні часові інтервали
  • Рахувати зовнішні імпульси в режимі лічильника
  • Генерувати ШІМ- сигнал на певних виводах МК
  • Генерувати переривання по якійсь події , наприклад , при переповненні

Таймери лічильники можуть тактувати від внутрішнього генератора тактової частоти і від рахункового входу. Давайте розглянемо функціонал таймера- лічильника 1 в мікроконтролері atmega8 . Запускаємо CodeVision AVR , створюємо новий проект і погоджуємося на пропозицію запустити Code WizardAVR

Code WizardAVR

переходимо у вкладку Timers , далі натискаємо на timer2 .

Code WizardAVR

Тут :

  • Clock Source - джерело тактового сигналу , тут в випадаючому списку можна вибрати
  • Clock Source в Code WizardAVR

    • System Clock - таймер тактується частотою, на якій працює мікроконтролер
    • TOSC1 pin - таймер буде працювати від зовнішнього кварцу на ніжках TOSC1 , TOSC2
  • Clock Value - обираємо переддільник тактової частоти , наприклад якщо ми виберемо переддільник 8, то кожні 8 тактів генератора будуть вважатися як один

    Clock Value в Code WizardAVR

  • Mode - визначає режим функціонування таймера лічильника. Залежить від типу мк , може бути :

    • Normal top - лічильник рахує від 0 до 255 , після переповнення скидається в 0 і рахунок повторюється
    • Fast PWM - лічильник рахує від 0 до 255 , після переповнення скидається в 0 і рахунок повторюється. Коли значення в рахунковому регістрі досягає значення в регістрі порівняння ( задається в рядку Compare ), таймер виставляє певний логічний рівень ( в випадаючому списку Output) на ніжці OCxx
    • CTC - скидання при збігу: коли значення в рахунковому регістрі досягає значення в регістрі порівняння, рахунковий регістр скидається в нуль і рахунок починається спочатку.
    • Phase Correct PWM - таймер спочатку рахує від 0 до 255 , потім від 255 до 0 . Вивід OCxx при першому збігу скидається , при другому встановлюється.
    • Overflow interrupt - генерується переривання при переповненні
    • Compare Match interrupt - генерується переривання при збігу
    • Timer Value - початкове значення рахункового регістра
    • Compare - значення регістра порівняння

    Давайте на прикладі timer2 реалізуємо годинник реального часу з виведенням на lcd дисплей. Для цього виставляємо таймер як показано на скріншоті

    часи реального часу на avr

    тут виставляється зовнішнє джерело тактування таймера , в якості зовнішнього джерела ми будемо використовувати часовий кварц на 32 768 герц. Далі встановимо переддільник на 128, тобто таймер буде працювати на частоті 32768 / 128 = 256 , а рахунковий регістр то в нас 8-бітний (максимальне число 255 ), виходить, що він буде переповняться раз в секунду. Далі ми виставляємо галочку біля Overflow interrupt та натискаємо на file - > Generate , save and exit .

    Code Wizard Cгенерировано ось такий код

    
     # include <mega8.h>  
      
    // Timer2 overflow interrupt service routine   
    interrupt [ TIM2_OVF ] void timer2_ovf_isr ( void )   
    {   
    }   
      
    void main ( void )   
    {   
    // Input / Output Ports initialization   
    // Port B initialization   
    PORTB = 0x00;   
    DDRB = 0x00;   
      
    // Port C initialization   
    PORTC = 0x00;   
    DDRC = 0x00;   
      
    // Port D initialization   
    PORTD = 0x00;   
    DDRD = 0x00;   
      
    // Timer / Counter 0 initialization   
    // Clock source : System Clock   
    // Clock value : Timer 0 Stopped   
    TCCR0 = 0x00;   
    TCNT0 = 0x00;   
      
    // Timer / Counter 1 initialization   
    // Clock source : System Clock   
    // Clock value : 125,000 kHz   
    // Mode: Fast PWM top = 00FFh   
    // OC1A output : Discon .   
    // OC1B output : Discon .   
    // Noise Canceler : Off   
    // Input Capture on Falling Edge   
    // Timer1 Overflow Interrupt : Off   
    // Input Capture Interrupt : Off   
    // Compare A Match Interrupt : Off   
    // Compare B Match Interrupt : Off   
    TCCR1A = 0x01;   
    TCCR1B = 0x0A ;   
    TCNT1H = 0x00;   
    TCNT1L = 0x00;   
    ICR1H = 0x00;   
    ICR1L = 0x00;   
    OCR1AH = 0x00;   
    OCR1AL = 0x00;   
    OCR1BH = 0x00;   
    OCR1BL = 0x00;   
      
    // Timer / Counter 2 initialization   
    // Clock source : TOSC1 pin   
    // Clock value : PCK2/128   
    // Mode: Normal top = FFh   
    // OC2 output : Disconnected   
    ASSR = 0x08 ;   
    TCCR2 = 0x05 ;   
    TCNT2 = 0x00;   
    OCR2 = 0x00;   
      
    // External Interrupt ( s ) initialization   
    // INT0 : Off   
    // INT1 : Off   
    MCUCR = 0x00;   
      
    // Timer ( s ) / Counter ( s ) Interrupt ( s ) initialization   
    TIMSK = 0x40 ;   
      
    // Analog Comparator initialization   
    // Analog Comparator : Off   
    // Analog Comparator Input Capture by Timer / Counter 1 : Off   
    ACSR = 0x80 ;   
    SFIOR = 0x00;   
      
    // Global enable interrupts   
    # asm ( " sei " )   
      
    while ( 1 )   
          {   
          } ;   
    }
     

    Далі в переривання таймера дописуємо підрахунок часу і викидаємо ініціалізацію невикористовуваних пристроїв

    
     # include <mega8.h>   
     # include <stdio.h.h>   
    // Alphanumeric LCD Module functions   
    # asm   
       . equ __ lcd_port = 0x12 ; PORTD   
    # endasm   
    # include <lcd.h.h>      
         unsigned char second = 0 ; // змінна для зберігання секунд   
         unsigned char minute = 0 ; // змінна для зберігання хвилин   
         unsigned char hour = 0 ; // змінна для зберігання годин   
         char lcd_buffer [ 32 ] ; // змінна буфер для виведення на дисплей   
    // Timer2 overflow interrupt service routine   
    interrupt [ TIM2_OVF ] void timer2_ovf_isr ( void )   
    {   
     if ( + + second == 59 ) // збільшуєммо кількість секунд на 1 і перевіряємо рівність 59   
     { second = 0 ;   
         if ( + + minute == 59 )   
         { minute = 0 ;   
           if ( + + hour == 59 )   
           {   
            hour = 0 ;   
           }   
         }   
     }   
     lcd_clear (); // чистимо дисплей перед виведенням   
     lcd_gotoxy (0,0) ; // Переводимо курсор в точку x = 0 y = 0   
     sprintf ( lcd_buffer , " % i : % i : % i " , hour , minute , second ) ; // Формуємо рядок для виведення   
     lcd_puts ( lcd_buffer ) ; // Виводимо рядок на дисплей   
    }   
      
    void main ( void )   
    {   
    // Timer / Counter 2 initialization   
    // Clock source : TOSC1 pin   
    // Clock value : PCK2/128   
    // Mode: Normal top = FFh      
    // OC2 output : Disconnected         
    ASSR = 0x08 ;   
    TCCR2 = 0x05 ;   
    TCNT2 = 0x00;      
    OCR2 = 0x00;   
      
    // Timer ( s ) / Counter ( s ) Interrupt ( s ) initialization   
    TIMSK = 0x40 ;   
      
    // LCD module initialization   
    lcd_init ( 16 ) ;   
      
    // Global enable interrupts   
    # asm ( " sei " )   
      
    while ( 1 )   
          {   
          } ;   
    }   
    

    Програма готова , тепер складемо схему в Proteus схема годин реального времені Тепер можна запускати симуляцію. Програма і схема в Proteus знаходяться в архіві time.zip . У наступній статті я розкажу, як за допомогою таймера можна генерувати ШІМ сигнал

    Комментарии - (0)

    Добавить комментарий

    Для отправки комментария вы должны авторизоваться.