Исследование TIMER2 (можно сделать программные часы)
Исследование TIMER2 (можно сделать программные часы)
Сообщений 1 страница 8 из 8
Поделиться22014-01-18 06:24:06
Софтовые часы на 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 ByteDim Время_работы_часы As Byte
Dim Время_работы_минуты As Byte
Dim Время_работы_секунды As ByteDim Флаг_работа_окончена As Byte
Dim Осталось_работать_часы As Byte
Dim Осталось_работать_минуты As Byte
Dim Осталось_работать_секунды As ByteDim Счетчик_прерываний_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 IfIf Флаг_данные_для_передачи_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 IfGoto Выход_обновить_данные_времени
'----------------------------------------------------
Обновить_минуты:
'----------------------------------------------------
Incr Минуты ' Плюс минутаIf Минуты > 59 Then ' При необходимости
Минуты = 0 : Goto Обновить_часы ' корректируем счетчик минут и обновляем счетчик часов
End IfGoto Выход_обновить_данные_времени
'----------------------------------------------------
Обновить_часы:
'----------------------------------------------------
Incr Часы ' Плюс часIf Часы > 23 Then ' При необходимости
Часы = 0 ' корректируем счетчик часов
End If
'-------------------------------------------------------------------------------
Выход_обновить_данные_времени:
'-------------------------------------------------------------------------------
Return
'==============================================================================='===============================================================================
Расчет_времени_работы:
'-------------------------------------------------------------------------------
nop
Incr Время_работы_секунды ' Плюс секундаIf Время_работы_секунды > 59 Then ' При необходимости
Время_работы_секунды = 0 : Goto Обновить_время_работы_минуты ' корректируем счетчик секунд и обновляем счетчик минут
End IfGoto Выход_расчет_времени_работы
'----------------------------------------------------
Обновить_время_работы_минуты:
'----------------------------------------------------
Incr Время_работы_минуты ' Плюс минутаIf Время_работы_минуты > 59 Then ' При необходимости
Время_работы_минуты = 0 : Goto Обновить_время_работы_часы ' корректируем счетчик минут и обновляем счетчик часов
End IfGoto Выход_расчет_времени_работы
'----------------------------------------------------
Обновить_время_работы_часы:
'----------------------------------------------------
Incr Время_работы_часы ' Плюс часIf Время_работы_часы > 23 Then ' При необходимости
Время_работы_часы = 0 ' корректируем счетчик часов
End IfВыход_расчет_времени_работы:
nop
'-------------------------------------------------------------------------------
Return
'==============================================================================='===============================================================================
Расчет_осталось_работать:
'-------------------------------------------------------------------------------
nop
If Осталось_работать_секунды = 0 Then ' При необходимости
Осталось_работать_секунды = 59 : Goto Обновить_осталось_работать_мин ' корректируем счетчик секунд и обновляем счетчик минут
End IfDecr Осталось_работать_секунды ' Минус секунда
Goto Выход_расчет_осталось_работать
'----------------------------------------------------
Обновить_осталось_работать_мин:
'----------------------------------------------------
If Осталось_работать_минуты = 0 Then ' При необходимости
Осталось_работать_минуты = 59 : Goto Обновить_осталось_работать_часы ' корректируем счетчик минут и обновляем счетчик часов
End IfDecr Осталось_работать_минуты ' Минус минута
Goto Расчет_осталось_работать
'----------------------------------------------------
Обновить_осталось_работать_часы:
'----------------------------------------------------
If Осталось_работать_часы = 0 And Осталось_работать_минуты = 0 And Осталось_работать_секунды = 0 Then ' При необходимости
Флаг_работа_окончена = 1
' Осталось_работать_часы = 0 ' корректируем счетчик часов
End IfDecr Осталось_работать_часы ' Минус час
Выход_расчет_осталось_работать:
nop
'-------------------------------------------------------------------------------
Return
'==============================================================================='===============================================================================
'--- Подпрограмма обработки вывода на компьютер (аппаратный USART)
'===============================================================================
Передача_uart:
'-------------------------------------------------------------------------------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 "Осталось работать - " ; Осталось_работать_часы ; ":" ; Осталось_работать_минуты ; ":" ; Осталось_работать_секунды
'-------------------------------------------------------------------------------
Return
'===============================================================================
Симуляция в Протеус 7.10 + исходники (Bascom 2.0.7.1) - скачать
Поделиться32014-01-18 06:24:32
Секундные прерывания TIMER2 с выводом секундных импульсов на OC2A
'=================================================
' Подпрограмма обработки прерывания TIMER2, происходит 1 или 2 раза в секунду, в зависимости от настроек TIMER2
'=================================================
Обработка_прерывания_timer2:
'-------------------------------------------------------------------------------------------
Incr Счетчик_прерываний_timer2
If Счетчик_прерываний_timer2 < Const_количество_прерыв_timer2 Then Goto Выход_прерывание_timer2Incr Счетчик_секунд
Счетчик_прерываний_timer2 = 0
Флаг_было_прерывание_timer2 = 1
Флаг_данные_для_передачи_usart = 1
'-----------------------------------
Выход_прерывание_timer2:
'-------------------------------------------------------------------------------------------
Return
'=================================================
'=================================================
' Подпрограмма обработки прерывания 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
'=================================================
$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 Счетчик_секунд
Флаг_данные_для_передачи_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
'=================================================
Поделиться42014-01-18 06:25:16
Подпрограмма расчета часов, минут, секунд
'=================================================
'----------- Подпрограмма расчета времени: часов, минут и секунд ---------
'=================================================
Обновить_данные_времени:
'-------------------------------------------------------------------------------------------
Incr Секунды ' Плюс секундаIf Секунды > 59 Then ' При необходимости
Секунды = 0 : Goto Обновить_минуты ' корректируем счетчик секунд и обновляем счетчик минут
End IfGoto Обновить_индикатор
'----------------------------------------------------
Обновить_минуты:
'----------------------------------------------------
Incr Минуты ' Плюс минутаIf Минуты > 59 Then ' При необходимости
Минуты = 0 : Goto Обновить_часы ' корректируем счетчик минут и обновляем счетчик часов
End IfGoto Обновить_индикатор
'----------------------------------------------------
Обновить_часы:
'----------------------------------------------------
Incr Часы ' Плюс часIf Часы > 23 Then ' При необходимости
Часы = 0 ' корректируем счетчик часов
End If
'----------------------------------------------------
Обновить_индикатор:
'----------------------------------------------------
' Флаг_данные_для_передачи_usart = 1
' Флаг_обновить_данные_времени = 0
' Флаг_обновить_индикатор = 1 ' Ставим флаг, что надо обновить индикацию
'-------------------------------------------------------------------------------------------
Выход_обновить_данные_времени:
'-------------------------------------------------------------------------------------------
Return
'=================================================
'=================================================
'----------- Подпрограмма расчета времени: часов, минут и секунд ---------
'=================================================
Обновить_данные_времени:
'-------------------------------------------------------------------------------------------
$asmLds 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
'=================================================
Поделиться52016-06-02 17:33:52
Вариант использования 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 ' Ссылка на подпрограмму обработчика прерывания TIMER2Dim Таймер 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
'===============================================================================
Поделиться62016-06-02 17:44:20
TIMER2 в режиме "CTC", стабильные временные интервалы
$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 = 125Dim Таймер_ms As Word
Dim Значение_таймер_ms As Word : Значение_таймер_ms = 100Таймер_ms = Значение_таймер_ms
'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
'-------------- Разрешаем работу необходимых прерываний ----------------------
Enable Compare2a
'------------ Разрешаем работу всех включенных прерываний --------------------
Enable Interrupts
'===============================================================================' Г Л А В Н Ы Й Ц И К Л
Главный_цикл:
'===============================================================================If Таймер_ms = 0 Then
'Делаем то, что необходимо
'Gosub ................
Таймер_ms = Значение_таймер_ms 'Перезапускаем таймер
Goto Главный_цикл
End IfIdle
'===============================================================================
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
'===============================================================================
Поделиться72017-04-14 01:30:13
$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 NosaveStop Timer2
Timer2 = 0
Ocr2a = Sys_timer - 1'===============================================================================
Dim Знач_период_обновления_lcd As Word : Знач_период_обновления_lcd = 500 - 5 'Значение = время в ms
Dim Период_обновления_lcd As WordDim Флаг_обновить_lcd As Byte : Флаг_обновить_lcd = 0
'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
'-------------- Разрешаем работу необходимых прерываний ----------------------Enable Compare2a : Start Timer2
'------------ Разрешаем работу всех включенных прерываний --------------------
Enable Interrupts
'===============================================================================' Г Л А В Н Ы Й Ц И К Л
Главный_цикл:
'===============================================================================If Флаг_обновить_lcd > 0 Then
nop
Флаг_обновить_lcd = 0
Goto Главный_цикл
End IfPower Idle
Goto Главный_цикл
End
'===============================================================================' П О Д П Р О Г Р А М М Ы
'===============================================================================
'===============================================================================
Обработка_прерывания_compare2a: '19 тактов при перезапуске 33 такта
'-------------------------------------------------------------------------------
!push R30
!in R30 , sreg
!push R30!Lds R30 , {Период_обновления_lcd}
!cpi R30 , 0
!breq Restart_счет_обновления_lcdDecr_период_обновления_lcd:
!dec R30
!rjmp Сохранение_счет_обновления_lcdRestart_счет_обновления_lcd:
!Lds R30 , {Период_обновления_lcd + 1}
!cpi R30 , 0
!breq Restart_счет_обновления_lcd_1!dec R30
!sts {Период_обновления_lcd + 1} , R30
!ldi R30 , 255
!rjmp Сохранение_счет_обновления_lcdRestart_счет_обновления_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} , R30Exit_счет_обновления_lcd:
Выход_прерывания_compare2a:
!pop R30
!out sreg , R30
!pop R30!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================




