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

Таймеры счетчики микроконтроллеров AVR (часы реального времени). Урок AVR 7


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

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

Таймеры общего назначения умеют:

  • Тактировать от внешнего часового кварца на 32768 герц
  • Считать разные временные интервалы
  • Считать внешние импульсы в режиме счетчика
  • Генерировать ШИМ-сигнал на определённых выводах МК
  • Генерировать прерывания по какому-то событию, например, при переполнению

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

Code WizardAVR

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

Code WizardAVR

Здесь:

  • Clock Source - источник тактового сигнала, здесь в выпадающем списке можно выбрать

    Clock Source в Code WizardAVR

    • System Clock - таймер тактируeтся частотой, на которой работает микроконтроллер
    • 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

здесь выставляется внешний источник тактирования таймера, в качестве внешнего источника мы будем использовать часовой кварц на 32768 герц, далее установим предделитель на 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>  
// Alphanumeric LCD Module functions  
#asm  
   .equ __lcd_port=0x12 ;PORTD  
#endasm  
#include <lcd.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)

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

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