Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование TIMER2 (можно сделать программные часы)


Исследование TIMER2 (можно сделать программные часы)

Сообщений 1 страница 8 из 8

1

Исследование TIMER2 (можно сделать программные часы)

0

2

Софтовые часы на TIMER2

Исходник

'===============================================================================
'*
'*  Автор: Sasha_1973
'*  Дата:  14.01.2014 г.
'*
'*  МК:  ATmega8А
'*  Тактовая частота МК:  1 MГц
'*
'*  Скорость передачи USART: 9600 бод
'*
'*  Компилятор: BASCOM-AVR 2.0.7.1
'*  Используемый шрифт в Bascom: Consolas; размер = 14
'*
'*  Программа симулятор: Proteus 7.10 SR0
'*
'*  Описание:
'*           Реализация программных часов на TIMER2, кварц 32768 кГц на выводах XTAL1(PB6) и XTAL2(PB7)
'*
'===============================================================================

'-------------------  Настройка контроллера  -----------------------------------

  $map              ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m8def.dat"       ' Используемый контроллер
  $crystal = 1000000       ' 2000000  ' 4000000  ' 8000000
  $framesize = 32
  $hwstack = 40
  $swstack = 16

'--------------------------  Настройка USART  ----------------------------------

  $baud = 4800      '1200     '2400     '4800     '9600     '19200     '38400     '57600     '115000
  Ucsra.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'---  Настройка прерывания TIMER2, для работы часов (раскомментировать нужное)

'  Config Timer2 = Timer , Async = On , Prescale = 64       ' Делитель 32768 / 64 / 256 = 0,5 сек (прерывание TIMER2 = 2 раза в секунду)
'  Const Количество_срабатываний_timer2 = 2

'---------------------------------------------------------------

  Config Timer2 = Timer , Async = On , Prescale = 128       ' Делитель 32768 / 128 / 256 = 1 сек (прерывание TIMER2 = 1 раз в секунду)
  Const Количество_срабатываний_timer2 = 1       ' Значение константы используется в подпрограмме "Обработка_прерывания_timer2"
' Ссылка на подпрограмму обработчика прерывания TIMER2, для работы часов
  On Timer2 Обработка_прерывания_timer2 Nosave       ' Ссылка на подпрограмму обработчика прерывания TIMER2

'---------------  Настройка пониженного энергопотребления МК  ------------------

  Assr.3 = 1 : Waitms 100       ' Включить НЧ-генератор AS2 и подождать стабилизации амплитуды генератора
'  При включении  бита AS2 (3) в регистре ASSR (ASSR.3), становится возможным применение режима
' "Powersave" - разновидность спящего режима. Пробуждение МК от TIMER2
'  Mcucr = &B10000000                              ' Разрешаем режим пониженного энергопотребления  Power Idle
  Mcucr = &B10110000       ' Разрешаем режим пониженного энергопотребления  Power Save

'-----------------------  Используемые переменные  -----------------------------

  Dim Часы As Byte
  Dim Минуты As Byte
  Dim Секунды As Byte

  Dim Время_работы_часы As Byte
  Dim Время_работы_минуты As Byte
  Dim Время_работы_секунды As Byte

  Dim Флаг_работа_окончена As Byte
  Dim Осталось_работать_часы As Byte
  Dim Осталось_работать_минуты As Byte
  Dim Осталось_работать_секунды As Byte

  Dim Счетчик_прерываний_timer2 As Byte
  Dim Флаг_обновить_данные_времени As Byte
  Dim Флаг_данные_для_передачи_usart As Byte

'------------------------  Предварительные настройки  --------------------------

  Часы = 20
  Минуты = 50
  Секунды = 0

  Осталось_работать_часы = 1
  Осталось_работать_минуты = 0
  Осталось_работать_секунды = 0

'-------------------  Передайм настройки времени в USART  ----------------------
  Print "Настройки времени"
  Print Часы ; ":" ; Минуты ; ":" ; Секунды : Print
  Wait 1
'--------------  Разрешаем работу необходимых прерываний  ----------------------

  Enable Timer2

'------------  Разрешаем работу всех включенных прерываний  --------------------

  Enable Interrupts

'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л

'===============================================================================
  Главный_цикл:

      If Флаг_обновить_данные_времени = 1 Then
          Gosub Расчет_времени_работы
          Gosub Обновить_данные_времени
          Gosub Расчет_осталось_работать
          Флаг_обновить_данные_времени = 0
          Флаг_данные_для_передачи_usart = 1
          Goto Главный_цикл
      End If

      If Флаг_данные_для_передачи_usart = 1 Then
          Gosub Передача_uart
          Флаг_данные_для_передачи_usart = 0
          Goto Главный_цикл
      End If

'-----------------------
   Спящий_режим:
    sleep           ' или так Power Powersave
  Goto Главный_цикл
End
'===============================================================================

'               И С П О Л Ь З У Е М Ы Е    П О Д П Р О Г Р А М М Ы

'===============================================================================

'===============================================================================
' Подпрограмма обработки прерывания TIMER2, происходит 1 или 2 раза в секунду, в зависимости от настроек TIMER2
'===============================================================================
  Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------

'----  Сохраняем регистры, которые используем в обработке прерывания

      !Push R31     ' Сохраняем регистры, которые используем в обработке прерывания
      !In R31 , Sreg
      !Push R31

'------------------  Считаем количество прерываний TIMER2  ---------------------

      !Lds R31 , {счетчик_прерываний_timer2}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
      !Inc R31      ' Увеличиваем значение переменной в регистре "R31"
      !sts {счетчик_прерываний_timer2} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"

'------------------

      !Andi R31 , количество_срабатываний_timer2       ' Сравниваем полученное значение с значением "Const количество_срабатываний_timer2"

'------------------

      !Breq Выход_прерывание_timer2       ' Если полученное значение меньше значениея "Const количество_срабатываний_timer2", уходим на метку "Выход_прерывание_timer2" -- иначе
      !clr R31                                     ' Если полученное значение равно значениию "Const количество_срабатываний_timer2", пишем "0" в регистр "R31
      !sts {счетчик_прерываний_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и переходим к подпрограмме расчета времени

'--------  Подпрограммы обрабатываемые по 2 срабатыванию TIMER2  ---------------

      !ldi R31 , 1
      !sts {Флаг_обновить_данные_времени} , R31       ' Поднимаем флажок, что надо обновить время

'---------------  Восстанавливаем ранее сохраненные регистры  ------------------

     Выход_прерывание_timer2:
      !Pop R31
      !Out Sreg , R31       ' Восстанавливаем регистры
      !Pop R31

'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
'-----------  Подпрограмма расчета времени: часов, минут и секунд  ---------
'===============================================================================
  Обновить_данные_времени:
'-------------------------------------------------------------------------------
    Incr Секунды    ' Плюс секунда

    If Секунды > 59 Then       ' При необходимости
        Секунды = 0 : Goto Обновить_минуты       ' корректируем счетчик секунд и обновляем счетчик минут
    End If

    Goto Выход_обновить_данные_времени
'----------------------------------------------------
   Обновить_минуты:
'----------------------------------------------------
    Incr Минуты     ' Плюс минута

    If Минуты > 59 Then       ' При необходимости
        Минуты = 0 : Goto Обновить_часы       ' корректируем счетчик минут и обновляем счетчик часов
    End If

      Goto Выход_обновить_данные_времени
'----------------------------------------------------
    Обновить_часы:
'----------------------------------------------------
      Incr Часы     ' Плюс час

      If Часы > 23 Then       ' При необходимости
          Часы = 0  ' корректируем счетчик часов
      End If
'-------------------------------------------------------------------------------
   Выход_обновить_данные_времени:
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Расчет_времени_работы:
'-------------------------------------------------------------------------------
nop
    Incr Время_работы_секунды       ' Плюс секунда

    If Время_работы_секунды > 59 Then       ' При необходимости
        Время_работы_секунды = 0 : Goto Обновить_время_работы_минуты       ' корректируем счетчик секунд и обновляем счетчик минут
    End If

    Goto Выход_расчет_времени_работы
'----------------------------------------------------
   Обновить_время_работы_минуты:
'----------------------------------------------------
    Incr Время_работы_минуты       ' Плюс минута

    If Время_работы_минуты > 59 Then       ' При необходимости
        Время_работы_минуты = 0 : Goto Обновить_время_работы_часы       ' корректируем счетчик минут и обновляем счетчик часов
    End If

      Goto Выход_расчет_времени_работы
'----------------------------------------------------
    Обновить_время_работы_часы:
'----------------------------------------------------
      Incr Время_работы_часы       ' Плюс час

      If Время_работы_часы > 23 Then       ' При необходимости
          Время_работы_часы = 0       ' корректируем счетчик часов
      End If

   Выход_расчет_времени_работы:
nop
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Расчет_осталось_работать:
'-------------------------------------------------------------------------------
nop
    If Осталось_работать_секунды = 0 Then       ' При необходимости
        Осталось_работать_секунды = 59 : Goto Обновить_осталось_работать_мин       ' корректируем счетчик секунд и обновляем счетчик минут
    End If

    Decr Осталось_работать_секунды       ' Минус секунда

    Goto Выход_расчет_осталось_работать
'----------------------------------------------------
   Обновить_осталось_работать_мин:
'----------------------------------------------------
    If Осталось_работать_минуты = 0 Then       ' При необходимости
        Осталось_работать_минуты = 59 : Goto Обновить_осталось_работать_часы       ' корректируем счетчик минут и обновляем счетчик часов
    End If

    Decr Осталось_работать_минуты       ' Минус минута

    Goto Расчет_осталось_работать
'----------------------------------------------------
   Обновить_осталось_работать_часы:
'----------------------------------------------------
    If Осталось_работать_часы = 0 And Осталось_работать_минуты = 0 And Осталось_работать_секунды = 0 Then       ' При необходимости
        Флаг_работа_окончена = 1
    '    Осталось_работать_часы = 0       ' корректируем счетчик часов
    End If

    Decr Осталось_работать_часы       ' Минус час

   Выход_расчет_осталось_работать:
nop
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
'---  Подпрограмма обработки вывода на компьютер (аппаратный USART)
'===============================================================================
  Передача_uart:
'-------------------------------------------------------------------------------

    Print

    Print "Время работы - " ;
    Print Время_работы_часы ; ":" ;
    If Время_работы_минуты < 10 Then Print "0" ;
    Print Время_работы_минуты ; ":";
    If Время_работы_секунды < 10 Then Print "0" ;
    Print Время_работы_секунды

    Print "Текущее время - " ;
    Print Часы ; ":" ;
    If Минуты < 10 Then Print "0" ;
    Print Минуты ; ":";
    If Секунды < 10 Then Print "0" ;
    Print Секунды

    Print "Осталось работать - " ; Осталось_работать_часы ; ":" ; Осталось_работать_минуты ; ":" ; Осталось_работать_секунды

    Print

'-------------------------------------------------------------------------------
  Return
'===============================================================================

http://s7.uploads.ru/t/SDuZW.jpg

Симуляция в Протеус 7.10 + исходники (Bascom 2.0.7.1)  -  скачать

+2

3

Секундные прерывания TIMER2 с выводом секундных импульсов на OC2A

Bascom, время выполнения 120 тактов, когда "Счетчик_прерываний_timer2 => Const_количество_прерыв_timer2", тогда 135 тактов

'=================================================
' Подпрограмма обработки прерывания TIMER2, происходит 1 или 2 раза в секунду, в зависимости от настроек TIMER2
'=================================================
  Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------------------
    Incr Счетчик_прерываний_timer2
    If Счетчик_прерываний_timer2 < Const_количество_прерыв_timer2 Then Goto Выход_прерывание_timer2

    Incr Счетчик_секунд
    Счетчик_прерываний_timer2 = 0
    Флаг_было_прерывание_timer2 = 1
    Флаг_данные_для_передачи_usart = 1
'-----------------------------------
  Выход_прерывание_timer2:
'-------------------------------------------------------------------------------------------
  Return
'=================================================

Прерывание реализовано на ASM AVR, время выполнения 18 тактов, когда "Счетчик_прерываний_timer2 => Const_количество_прерыв_timer2", тогда 30 тактов

'=================================================
' Подпрограмма обработки прерывания TIMER2, происходит 1 или 2 раза в секунду, в зависимости от настроек TIMER2
'=================================================
  Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------------------
    $asm
'---  Сохраняем регистры, которые используем в обработке прерывания  ---
        Push R31       ' Сохраняем регистры, которые используем в обработке прерывания
        In R31 , Sreg
        Push R31
'------------------  Считаем количество прерываний TIMER2  --------------------
        Lds R31 , {счетчик_прерываний_timer2}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        sts {счетчик_прерываний_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
        Andi R31 , Const_количество_прерыв_timer2       ' Сравниваем полученное значение с значением "Const_количество_прерыв_timer2"
'----------------  Делаем, что надо, по результату сравнения  ------------------
        Breq Выход_прерывание_timer2       ' Перейти если меньше чем "Количество_переменных + 1 "                         если переход на метку тогда 2 такта иначе 1 такт
        clr R31                                     ' Если полученное значение равно значениию "Const_количество_прерыв_timer2", пишем "0" в регистр "R31
        sts {счетчик_прерываний_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
'-------------------------------------------------------------------------------------------
' Подпрограммы и флаги обрабатываемые по значению константы "Const_количество_прерыв_timer2"
'---------------------------  Считаем секунды  ----------------------------------------
        lds R31 , {Счетчик_секунд}       ' Считываем значение переменной "Счетчик_секунд" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        sts {Счетчик_секунд} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_секунд" и идем дальше
'-----------------  Пишем числовое значение поднятых флагов  -----------------
        Ldi R31 , 1       ' Пишем числовое значение (любое байтовое значение (1-255)) в регистр "R31", для последующих операций с флагами
'----------------------  Подымаем нужные флажки  ---------------------------------
'        sts {Флаг_обновить_данные_времени} , R31       ' Пишем значение из регистра "R31" в переменную "Флаг_обновить_данные_времени"
'        sts {Флаг_обновить_индикатор} , R31       ' (STS) Прямое сохранение    ,     Пишем значение из регистра "R31" в переменную "Флаг_обновить_индикатор"
        sts {Флаг_данные_для_передачи_usart} , R31       ' Пишем значение из регистра "R31" в переменную "Флаг_данные_для_передачи_usart"
'-------------  Подымаем флажок, что было прерывание TIMER2  ---------------
        sts {Флаг_было_прерывание_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
'-------------------------------------------------------------------------------------------
      Выход_прерывание_timer2:
' Восстанавливаем ранее сохраненные регистры и выходим из прерывания
        Pop R31
        Out Sreg , R31       ' Восстанавливаем регистры
        Pop R31
    $end Asm
'-------------------------------------------------------------------------------------------
  Return
'=================================================

Весь исходник, не забывайте следить за инструкцией "Nosave"

$regfile = "m88def.dat"       ' Используемый контроллер
  $crystal = 1000000       ' 1 МГц
  $framesize = 32
  $hwstack = 40
  $swstack = 16
  $baud = 4800       '4800     '9600     '19200     '38400

'-------------  Настройка прерывания TIMER2, для работы часов (раскомментировать нужное) -----------------
  Config Timer2 = Timer , Async = On , Prescale = 64 , Compare A = Toggle       ' Делитель 32768 / 64 / 256 = 0,5 сек (прерывание TIMER2 = 2 раза в секунду)
  Const Const_количество_прерыв_timer2 = 2
'---------------------------------------------------------------
'  Config Timer2 = Timer , Async = On , Prescale = 128       ' Делитель 32768 / 128 / 256 = 1 сек (прерывание TIMER2 = 1 раз в секунду)
'  Const Const_количество_прерыв_timer2 = 1       ' Значение константы используется в подпрограмме "Обработка_прерывания_timer2"
'---------------------------------------------------------------
' Ссылка на подпрограмму обработчика прерывания TIMER2, для работы часов
  On Timer2 Обработка_прерывания_timer2 Nosave       ' Ссылка на подпрограмму обработчика прерывания TIMER2
'---------------  Настройка пониженного энергопотребления МК  ---------------
'  Assr.3 = 1 : Waitms 100                         ' Включить НЧ-генератор AS2 и подождать стабилизации амплитуды генератора
'  При включении  бита AS2 (3) в регистре ASSR (ASSR.3), становится возможным применение режима "Powersave" - разновидность спящего режима. Пробуждение МК от TIMER2
'  Mcucr = &B10000000                              ' Разрешаем режим пониженного энергопотребления  Power Idle
'  Mcucr = &B10110000                              ' Разрешаем режим пониженного энергопотребления  Power Save
'-------------------------------------------------------------------------------------------
  Dim Счетчик_секунд As Byte
  Dim Счетчик_прерываний_timer2 As Byte
  Dim Флаг_было_прерывание_timer2 As Byte
  Dim Флаг_данные_для_передачи_usart As Byte
'--------------------  Разрешаем работу нужных прерываний  --------------------
  Enable Timer2
'--------------------  Разрешаем работу всех прерываний  ------------------------
  Enable Interrupts
'=================================================

  Do

      If Флаг_данные_для_передачи_usart = 1 Then
          Print Счетчик_секунд
          Print
          Флаг_данные_для_передачи_usart = 0
      End If

'-----------------------
    Спящий_режим:
'      Power Idle
      Power Powersave
'      Powerdown
'-----------------------
  Loop
End
'=================================================

'               И С П О Л Ь З У Е М Ы Е    П О Д П Р О Г Р А М М Ы

'=================================================

'=================================================
' Подпрограмма обработки прерывания TIMER2, происходит 1 или 2 раза в секунду, в зависимости от настроек TIMER2
'=================================================
  Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------------------
    $asm
'---  Сохраняем регистры, которые используем в обработке прерывания  ---
        Push R31       ' Сохраняем регистры, которые используем в обработке прерывания
        In R31 , Sreg
        Push R31
'------------------  Считаем количество прерываний TIMER2  --------------------
        Lds R31 , {счетчик_прерываний_timer2}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        sts {счетчик_прерываний_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
        Andi R31 , Const_количество_прерыв_timer2       ' Сравниваем полученное значение с значением "Const_количество_прерыв_timer2"
'----------------  Делаем, что надо, по результату сравнения  ------------------
        Breq Выход_прерывание_timer2       ' Перейти если меньше чем "Количество_переменных + 1 "                         если переход на метку тогда 2 такта иначе 1 такт
        clr R31                                     ' Если полученное значение равно значениию "Const_количество_прерыв_timer2", пишем "0" в регистр "R31
        sts {счетчик_прерываний_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
'-------------------------------------------------------------------------------------------
' Подпрограммы и флаги обрабатываемые по значению константы "Const_количество_прерыв_timer2"
'---------------------------  Считаем секунды  ----------------------------------------
        lds R31 , {Счетчик_секунд}       ' Считываем значение переменной "Счетчик_секунд" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        sts {Счетчик_секунд} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_секунд" и идем дальше
'-----------------  Пишем числовое значение поднятых флагов  -----------------
        Ldi R31 , 1       ' Пишем числовое значение (любое байтовое значение (1-255)) в регистр "R31", для последующих операций с флагами
'----------------------  Подымаем нужные флажки  ---------------------------------
'        sts {Флаг_обновить_данные_времени} , R31       ' Пишем значение из регистра "R31" в переменную "Флаг_обновить_данные_времени"
'        sts {Флаг_обновить_индикатор} , R31       ' (STS) Прямое сохранение    ,     Пишем значение из регистра "R31" в переменную "Флаг_обновить_индикатор"
        sts {Флаг_данные_для_передачи_usart} , R31       ' Пишем значение из регистра "R31" в переменную "Флаг_данные_для_передачи_usart"
'-------------  Подымаем флажок, что было прерывание TIMER2  ---------------
        sts {Флаг_было_прерывание_timer2} , R31       ' Заносим значение из регистра "R31" в переменную "Счетчик_прерываний_timer2" и идем дальше
'-------------------------------------------------------------------------------------------
      Выход_прерывание_timer2:
' Восстанавливаем ранее сохраненные регистры и выходим из прерывания
        Pop R31
        Out Sreg , R31       ' Восстанавливаем регистры
        Pop R31
    $end Asm
'-------------------------------------------------------------------------------------------
  Return
'=================================================

0

4

Подпрограмма расчета часов, минут, секунд

Bascom, время выполнения 24 такта, раз в минуту и раз в час, время выполнения увеличивается

'=================================================
'-----------  Подпрограмма расчета времени: часов, минут и секунд  ---------
'=================================================
  Обновить_данные_времени:
'-------------------------------------------------------------------------------------------
    Incr Секунды       ' Плюс секунда

    If Секунды > 59 Then       ' При необходимости
        Секунды = 0 : Goto Обновить_минуты       ' корректируем счетчик секунд и обновляем счетчик минут
    End If

    Goto Обновить_индикатор
'----------------------------------------------------
   Обновить_минуты:
'----------------------------------------------------
    Incr Минуты       ' Плюс минута

    If Минуты > 59 Then       ' При необходимости
        Минуты = 0 : Goto Обновить_часы       ' корректируем счетчик минут и обновляем счетчик часов
    End If

      Goto Обновить_индикатор
'----------------------------------------------------
    Обновить_часы:
'----------------------------------------------------
      Incr Часы       ' Плюс час

      If Часы > 23 Then       ' При необходимости
          Часы = 0       ' корректируем счетчик часов
      End If
'----------------------------------------------------
    Обновить_индикатор:
'----------------------------------------------------
'      Флаг_данные_для_передачи_usart = 1
'      Флаг_обновить_данные_времени = 0
'      Флаг_обновить_индикатор = 1       ' Ставим флаг, что надо обновить индикацию
'-------------------------------------------------------------------------------------------
   Выход_обновить_данные_времени:
'-------------------------------------------------------------------------------------------
  Return
'=================================================

ASM AVR, время выполнения 17 тактов, раз в минуту и раз в час, время выполнения увеличивается

'=================================================
'-----------  Подпрограмма расчета времени: часов, минут и секунд  ---------
'=================================================
  Обновить_данные_времени:
'-------------------------------------------------------------------------------------------
    $asm

        Lds R31 , {секунды}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        Cpi R31 , 60       ' (CPI) Сравнить с константой
        BRSH Обновить_минуты       ' (BREQ) Если равно перейти на метку
        sts {секунды} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"
        Rjmp Выход_обновить_данные_времени

      Обновить_минуты:
        clr R31
        sts {секунды} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"

        Lds R31 , {минуты}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        Cpi R31 , 60       ' (CPI) Сравнить с константой
        BRSH Обновить_часы       ' (BREQ) Если равно перейти на метку
        sts {минуты} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"
        Rjmp Выход_обновить_данные_времени

      Обновить_часы:
        clr R31
        sts {минуты} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"

        Lds R31 , {часы}       ' Считываем значение переменной "Счетчик_прерываний_timer2" в регистр "R31", для последующих операций
        Inc R31       ' Инкриминируем значение переменной в регистре "R31"
        Cpi R31 , 24       ' (CPI) Сравнить с константой
        BRLO Выход_обновить_данные_времени       ' Перейти если меньше
        Ldi R31 , 0
        sts {часы} , R31       ' Пишем значение из регистра "R31" в переменную "Счетчик_прерываний_timer2"

      Выход_обновить_данные_времени:
'        Ldi R31 , 0
'        sts {Флаг_обновить_данные_времени} , R31
'        sts {Флаг_данные_для_передачи_usart} , R31

' Обязательная строчка, возврат из подпрограммы в обрабатываемое прерывание
        Ret       ' Возврат из подпрограммы

    $end Asm
'=================================================

0

5

Вариант использования TIMER2 в ассинхронном режиме (внешний кварц 32768 Гц)

Если большинство времени надо спать, и просыпаться для чего-то раз в пару тройку минут.

При правильном подходе, МК потребляет пару микроампер  мкА

Исходник

$map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m8def.dat"       ' http://www.atmel.com
  $crystal = 8000000       ' 8 МГц
  $framesize = 128       ' Размер области используемой и необходимой для преобразований
  $hwstack = 128       ' Размер аппаратного стека
  $swstack = 128       ' Размер программного стека

  $baud = 38400

  Config Timer2 = Timer , Async = On , Prescale = 1024       ' Делитель 32768 / 1024 / 256 = 8 сек (прерывание TIMER2 = 1 раз в 8 секунд)
' Ссылка на подпрограмму обработчика прерывания TIMER2, для работы часов
  On Timer2 Обработка_прерывания_timer2 Nosave       ' Ссылка на подпрограмму обработчика прерывания TIMER2

  Dim Таймер As Byte
  Dim Значение_таймера As Byte : Значение_таймера = 2       'Необходимое значение * 8 (в секундах)

  Таймер = Значение_таймера

'---------------  Настройка пониженного энергопотребления МК  ------------------

  Assr.3 = 1 : Waitms 100       ' Включить НЧ-генератор AS2 и подождать стабилизации амплитуды генератора
'  При включении  бита AS2 (3) в регистре ASSR (ASSR.3), становится возможным применение режима
' "Powersave" - разновидность спящего режима. Пробуждение МК от TIMER2

'--------------  Разрешаем работу необходимых прерываний  ----------------------
  Enable Timer2
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

      If Таймер = 0 Then

          'Делаете то, что Вам надо
          'Gosub ...............

          Таймер = Значение_таймера

        Else
        'Значение PowerSave для Atmega328P, для Вашего, смотрите документацию!
          Mcucr = &B_0000_1100       'Значение PowerSave для Atmega328P, для Вашего, смотрите документацию!
          Mcucr.se = 1
          sleep
          'Powersave
        'Значение PowerSave для Atmega328P, для Вашего, смотрите документацию!
      End If

'===============================================================================
  Goto Главный_цикл
End
'===============================================================================

'===============================================================================
' Подпрограмма обработки прерывания TIMER2, происходит каждые 8 секунд
'===============================================================================
  Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------
    !Push R16       ' Сохраняем регистры, которые используем в обработке прерывания
    !In R16 , Sreg
    !Push R16

    !lds R16 , {Таймер}
    !cpi R16 , 0
    !breq Выход_прерывание_timer2

    !dec R16
    !sts {Таймер} , R16

   Выход_прерывание_timer2:
    !Pop R16
    !Out Sreg , R16
    !Pop R16

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

http://sd.uploads.ru/t/SldVT.jpg

0

6

TIMER2 в режиме "CTC", стабильные временные интервалы

прерывания 1 ms

$map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       ' http://www.atmel.com/images/Atmel-8272- … asheet.pdf
  $crystal = 8000000       ' 8 МГц
  $framesize = 128       ' Размер области используемой и необходимой для преобразований
  $hwstack = 128       ' Размер аппаратного стека
  $swstack = 128       ' Размер программного стека

  $baud = 38400

'===============================================================================
'   Н А С Т Р О Й К А     TIMER2 для отсчета различных временных интервалов
'===============================================================================
'TIMER2 в режиме CTC, прерывания 1 ms
  Config Timer2 = Counter , Prescale = 64 , Compare A = Disconnect , Clear Timer = 1
  On Compare2a Обработка_прерывания_compare2a Nosave
  Ocr2a = 125

  Dim Таймер_ms As Word
  Dim Значение_таймер_ms As Word : Значение_таймер_ms = 100

  Таймер_ms = Значение_таймер_ms

'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
'--------------  Разрешаем работу необходимых прерываний  ----------------------
  Enable Compare2a
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

      If Таймер_ms = 0 Then

        'Делаем то, что необходимо

          'Gosub ................

          Таймер_ms = Значение_таймер_ms       'Перезапускаем таймер
          Goto Главный_цикл
      End If

   Idle
'===============================================================================
  Goto Главный_цикл
End
'===============================================================================

'===============================================================================
  Обработка_прерывания_compare2a:       'Начинается раньше всех
'-------------------------------------------------------------------------------
    !push R16
    !in R16 , sreg
    !push R16
    !push R30
    !push R31

    !lds R30 , {Таймер_ms}
    !lds R31 , {Таймер_ms + 1}

    !cpi R31 , 0
    !ldi R16 , 0
    !cpc R30 , R16
    !brcs Выход_прерывания_compare2a
    !breq Выход_прерывания_compare2a
    !rjmp Считаем_таймер_ms
    !rjmp Выход_прерывания_compare2a

   Считаем_таймер_ms:
    !sbiw R30 , 1

    !sts {Таймер_ms} , R30
    !sts {Таймер_ms + 1} , R31

   Выход_прерывания_compare2a:
    !pop R31
    !pop R30
    !pop R16
    !out sreg , R16
    !pop R16

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

0

7

Перезапускаемый таймер

$map       ' Получаем карту распределения памяти
  $regfile = "m328pdef.dat"       ' Используемый контроллер - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 1000000       ' 8 МГц
  $framesize = 64       'размер области используемой и необходимой для преобразований
  $hwstack = 64       ' Размер аппаратного стека
  $swstack = 64       ' Размер программного стека

'===============================================================================
'           Н А С Т Р О Й К А     TIMER2 для отсчёта 1 ms
'===============================================================================
  Const Prescale_timer = 64       'Аппаратный делитель TIMER2
  Const Time_sys_isr = 1000       'Прерывания каждые, в мкс

  Const Sys_timer =((_xtal / 1000000) * Time_sys_isr / Prescale_timer) + 0.5

  Config Timer2 = Counter , Prescale = Prescale_timer , Compare A = Disconnect , Compare B = Disconnect , Clear Timer = 1
  On Compare2a Обработка_прерывания_compare2a Nosave

  Stop Timer2
  Timer2 = 0
  Ocr2a = Sys_timer - 1

'===============================================================================
  Dim Знач_период_обновления_lcd As Word : Знач_период_обновления_lcd = 500 - 5       'Значение = время в ms
  Dim Период_обновления_lcd As Word

  Dim Флаг_обновить_lcd As Byte : Флаг_обновить_lcd = 0

'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
'--------------  Разрешаем работу необходимых прерываний  ----------------------

  Enable Compare2a : Start Timer2

'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л

  Главный_цикл:
'===============================================================================

       If Флаг_обновить_lcd > 0 Then

           nop

           Флаг_обновить_lcd = 0
           Goto Главный_цикл
       End If

   Power Idle
  Goto Главный_цикл
End
'===============================================================================

'                        П О Д П Р О Г Р А М М Ы

'===============================================================================



'===============================================================================
  Обработка_прерывания_compare2a:       '19 тактов  при перезапуске 33 такта
'-------------------------------------------------------------------------------
    !push R30
    !in R30 , sreg
    !push R30

    !Lds R30 , {Период_обновления_lcd}
    !cpi R30 , 0
    !breq Restart_счет_обновления_lcd

   Decr_период_обновления_lcd:
    !dec R30
    !rjmp Сохранение_счет_обновления_lcd

    Restart_счет_обновления_lcd:
     !Lds R30 , {Период_обновления_lcd + 1}
     !cpi R30 , 0
     !breq Restart_счет_обновления_lcd_1

     !dec R30
     !sts {Период_обновления_lcd + 1} , R30
     !ldi R30 , 255
     !rjmp Сохранение_счет_обновления_lcd

    Restart_счет_обновления_lcd_1:
     !Lds R30 , {Знач_период_обновления_lcd}
     !sts {Период_обновления_lcd} , R30
     !Lds R30 , {Знач_период_обновления_lcd + 1}
     !sts {Период_обновления_lcd + 1} , R30

     !ldi R30 , 1
     !sts {Флаг_обновить_lcd} , R30
     !rjmp Exit_счет_обновления_lcd

    Сохранение_счет_обновления_lcd:
     !sts {Период_обновления_lcd} , R30

    Exit_счет_обновления_lcd:

   Выход_прерывания_compare2a:
    !pop R30
    !out sreg , R30
    !pop R30

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

+1

8

Задумка здесь

Аппаратно реализована коррекция хода, после подобранной коррекции, 4 месяц пилотная версия идёт сек в сек.

Схемки + платка

http://sg.uploads.ru/t/xjOZD.jpg
http://sg.uploads.ru/t/MWGO6.jpg
http://s9.uploads.ru/t/0LmPE.jpg

исходники + симуляция + soft PC  -  скачать

схема + плата (DipTrace)  -  скачать

+1


Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование TIMER2 (можно сделать программные часы)