Опубликовано 2010-04-10 16:21:01 автором SWO Таймери лічильники мікроконтролерів AVR (годинник реального часу)
Коли я ще починав вивчати мікроконтролери , мені захотілося зробити часовий таймер , щоб керувати навантаженням змінного струму . Чесно зізнаюся , я хотів спробувати вмикати телевізор тільки з 7 до 8 годин , а весь інший час він повинен був бути відключений . Пристрій я зробив , але так його і не застосував ...
У всіх мікроконтролерах AVR є кілька вбудованих таймерів . Їх ще можна розділити на таймери загального призначення і сторожовий таймер , який призначений для перезавантаження МК при зависанні .
Таймери загального призначення вміють :
- Тактіровать від зовнішнього годинного кварцу на 32768 герц
- Рахувати різні часові інтервали
- Рахувати зовнішні імпульси в режимі лічильника
- Генерувати ШІМ- сигнал на певних виводах МК
- Генерувати переривання по якійсь події , наприклад , при переповненні
Таймери лічильники можуть тактувати від внутрішнього генератора тактової частоти і від рахункового входу. Давайте розглянемо функціонал таймера- лічильника 1 в мікроконтролері atmega8 . Запускаємо CodeVision AVR , створюємо новий проект і погоджуємося на пропозицію запустити Code WizardAVR
переходимо у вкладку Timers , далі натискаємо на timer2 .
Тут :
- Clock Source - джерело тактового сигналу , тут в випадаючому списку можна вибрати
- System Clock - таймер тактується частотою, на якій працює мікроконтролер
- TOSC1 pin - таймер буде працювати від зовнішнього кварцу на ніжках TOSC1 , TOSC2
- Clock Value - обираємо переддільник тактової частоти , наприклад якщо ми виберемо переддільник 8, то кожні 8 тактів генератора будуть вважатися як один
Mode - визначає режим функціонування таймера лічильника. Залежить від типу мк , може бути :
- Normal top - лічильник рахує від 0 до 255 , після переповнення скидається в 0 і рахунок повторюється
- Fast PWM - лічильник рахує від 0 до 255 , після переповнення скидається в 0 і рахунок повторюється. Коли значення в рахунковому регістрі досягає значення в регістрі порівняння ( задається в рядку Compare ), таймер виставляє певний логічний рівень ( в випадаючому списку Output) на ніжці OCxx
- CTC - скидання при збігу: коли значення в рахунковому регістрі досягає значення в регістрі порівняння, рахунковий регістр скидається в нуль і рахунок починається спочатку.
- Phase Correct PWM - таймер спочатку рахує від 0 до 255 , потім від 255 до 0 . Вивід OCxx при першому збігу скидається , при другому встановлюється.
ul >
- Overflow interrupt - генерується переривання при переповненні
- Compare Match interrupt - генерується переривання при збігу
- Timer Value - початкове значення рахункового регістра
- Compare - значення регістра порівняння
Давайте на прикладі timer2 реалізуємо годинник реального часу з виведенням на lcd дисплей. Для цього виставляємо таймер як показано на скріншоті
тут виставляється зовнішнє джерело тактування таймера , в якості зовнішнього джерела ми будемо використовувати часовий кварц на 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) Добавить комментарийДля отправки комментария вы должны авторизоваться.
|