Простой кухонный таймер на ATtiny2313
- Главная|
- Устройства|
- AVR
- Просмотров: 15852
Таймер Семисегментный индикатор ATtiny2313 Энкодер
Опытные хозяйки всё отмеряют на глаз и чувствуют время «внутренними» часами, но люди склонны впадать в задумчивость и отвлекаться на другие дела. Очень часто так случается, что и у опытных хозяек с любовью подготовленные к выпечке пироги превращаются в несъедобный углерод. Результат — испорченное настроение, зря потраченное время и срыв намеченных планов.
При разработке таймера ставилась задача использования минимального количества деталей, простоты управления, простоты повторения устройства, возможности питания таймера как от трёх батареек АА (LR6) по 1,5 В, так и от внешнего адаптера.
Возможности и основные характеристики таймера:
1. Время установки таймера от 1 до 90 мин.
2. Звуковая сигнализация включения и выключения таймера.
3. Звуковая сигнализация окончания установленного времени.
4. Принудительное выключение таймера до истечения установленного времени.
6. Питание устройства как от трёх батареек, так и от внешнего адаптера напряжением от 7 до 10 В.
7. Ток потребления таймера в выключенном состоянии в несколько раз меньше тока саморазряда пальчиковых батареек.
Алгоритм работы таймера
Таймер включается нажатием кнопки энкодера. На индикаторе высвечивается минимально возможное время выдержки, равное 1 мин. Вращением ручки энкодера вправо происходит увеличение времени выдержки, а при вращении ручки энкодера влево — уменьшение времени, начиная с 90 мин. Таймер выключится самостоятельно, если в течение 10 с после установки времени не была нажата кнопка запуска. Для запуска отсчёта времени необходимо снова нажать кнопку энкодера. При этом таймер начинает отсчёт установленного времени, а на индикаторе единиц минут с периодом в 1 с будет мигать децимальная точка, индицирующая режим обратного отсчёта. По истечении установленного времени на индикаторе таймера высветится цифра 0 и прозвучат 5 тональных сигналов. После этого цифра 0 погаснет, а децимальная точка будет мигать ещё 10 с. По истечении и этого времени, в напоминание, снова прозвучат 5 тональных сигналов, и таймер выключится.
Схема, конструкция и детали таймера
Принципиальная схема кухонного таймера показана на рис.1. «Мозгом» устройства является микроконтроллер (МК) IC1 типа ATtiny2313 фирмы ATMEL в корпусе DIP20. Микроконтроллер ATtiny2313 тактируется от внутреннего генератора частотой 8 МГц с выключенным предделителем на 8.
Рисунок 1
Для управления таймером применён инкрементный энкодер с кнопкой фирмы Bourns типа
Предусмотрена также возможность установки в этом таймере индикаторов с общим анодом (ОА) без изменения принципиальной схемы и платы. Для этого необходимо при программировании МК использовать другую прошивку, разработанную автором специально под индикаторы с ОА, В качестве звукового извещателя используется зуммер (Magnetic Buzzer) типа КХ-1205 фирмы King-state.
Таймер собран на односторонней печатной плате из фольгированного текстолита размерами 48×56 мм с использованием нескольких перемычек, которые размещены со стороны установки деталей. Чертёж печатной платы таймера под ЛУТ показан на рис.2.
Рисунок 2
Для питания таймера от внешнего адаптера применён линейный интегральный стабилизатор 78L05 в корпусе SOP-8. Схема дополнительной платы для внешнего адаптера показана на рис.З, а чертёж печатной платы под ЛУТ — на рис.4. Её размеры 48×66 мм. Батарейный отсек для трёх гальванических элементов изготовлен из фольгированного текстолита. Причём его обратная сторона — это дополнительная плата внешнего адаптера питания. Если в питании устройства от сети нет необходимости, то собирать дополнительную плату не нужно, а вместо нее следует установить плату из фольгированного стеклотекстолита того же размера.
Рисунок 3
Рисунок 4
При сборке платы таймера в первую очередь необходимо установить соответствующие перемычки. После прошивки микроконтроллера собранный из исправных деталей таймер в настройке не нуждается. В связи с присутствием в воздухе во время приготовления пищи паров воды и жира, рекомендую платы таймера после сборки промыть спиртом и покрыть акриловым лаком.
Архив для статьи «Простой кухонный таймер на ATtiny2313» | |
Описание: Файл прошивки микроконтроллера, макет печатной платы Eagle | |
Размер файла: 99.86 KB Количество загрузок: 1 224 | Скачать |
Понравилась статья? Поделиться с друзьями:
- Назад
- Вперед
Timer/Counter0 (Таймер/счётчик0) в ATtiny2313.
Описание регистров.TCNT0
TCNT0 — восьмиразрядный счётный регистр.
Когда таймер работает, в зависимости от режима его работы, содержимое счётного регистра сбрасывается, увеличивается или уменьшается по каждому импульсу тактового сигнала таймера/счётчика clkT0.
В любой момент времени регистр доступен как для чтения так и для записи.
OCR0A/OCR0B
OCR0A/OCR0B — регистры сравнения.
Во время работы таймера/счётчика каждый такт происходит непрерывное сравнение этих регистров с счётным регистром TCNT0. В случае равенства содержимого этих регистров в следующем такте устанавливается флаг OCF0A/OCF0B в соответствующем регистре флагов и, если разрешено, генерируется прерывание. Также в этом случае может изменяться состояние вывода OC0A/OC0B микроконтроллера.
Регистр доступен как для чтения, так и для записи.
TCCR0A/TCCR0B
Регистры TCCR0A и TCCR0B предназначены для управления модулем таймера/счётчика0.
Бит | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | TCCR0A |
COM0A1 | COM0A0 | COM0B1 | COM0B0 | — | — | WGM01 | WGM00 | ||
Чтение(R)/Запись(W) | R/W | R/W | R/W | R/W | R | R | R/W | R/W | |
Начальные значения | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Биты 7, 6 — COM0A1, COM0A0 — определяют состоянии вывода OC0A при наступлении события «Совпадение».
Биты 5, 4 — COM0B1, COM0B0 — определяют состоянии вывода OC0B при наступлении события «Совпадение».
В Нормальном и CTC режимах
COM0A1 (COM0B1) | COM0A0 (COM0B0) | Описание |
0 | 0 | Нормальная работа вывода. Вывод OC0A (OC0B) отключен от таймера/счётчика T0. |
0 | 1 | Инвертировать состояние вывода. |
1 | 0 | Сбросить при совпадении в 0. |
1 | 1 | Установить 1 при совпадении. |
COM0A1 (COM0B1) | COM0A0 (COM0B0) | Описание |
0 | 0 | Нормальная работа вывода. Вывод OC0A (OC0B) отключен от таймера/счётчика T0. |
0 | 1 | OC0A: WGM02 = 0 — Вывод OC0A отключен от таймера/счётчика T0. WGM02 = 1 — Инвертирование состояния вывода. OC0B: — |
1 | 0 | Сбрасывается при совпадении в 0. Устанавливается в 1 при достижении счётчиком максимального значения (неинвертированный ШИМ сигнал). |
1 | 1 | Устанавливается 1 при совпадении. Сбрасывается в 0 при достижении счётчиком максимального значения (инвертированный ШИМ сигнал). |
Биты 1,0 — WGM01, WGM00 — совместно с WGM02 из регистра TCCR0B определяют режим работы таймера/счётчикаT0.
WGM02 | WGM01 | WGM00 | Описание |
Нормальный режим | |||
1 | Phase Correct PWM (ШИМ с точной фазой) | ||
1 | CTC (Сброс при совпадении) | ||
1 | 1 | Fast PWM | |
1 | — | ||
1 | 1 | Phase Correct PWM (ШИМ с точной фазой) | |
1 | 1 | — | |
1 | 1 | 1 | Fast PWM |
Бит | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | TCCR0B |
FOC0A | FOC0B | — | — | WGM02 | CS02 | CS01 | CS00 | ||
Чтение(R)/Запись(W) | W | W | R | R | R/W | R/W | R/W | R/W | |
Начальные значения | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Бит 7 — FOC0A — принудительное изменение состояния вывода OC0A.
Этот бит активен, только когда биты WGM установлены в Нормальный режим работы таймера. Однако, для обеспечения совместимости (переносимости) с будущими моделями он должен быть сброшен в 0 в PWM (ШИМ) режимах.
При установке 1 состояние вывода OC0A меняется в зависимости от битов COM0A1 и COM0A0. При этом не генерируется прерывание и таймер не сбрасывается в CTC режиме.
При чтении всегда возвращает 0.
Бит 6 — FOC0B — принудительное изменение состояния вывода OC0B.
Этот бит активен, только когда биты WGM установлены в Нормальный режим работы таймера. Однако, для обеспечения совместимости (переносимости) с будущими моделями он должен быть сброшен в 0 в PWM (ШИМ) режимах.
При установке 1 состояние вывода OC0B меняется в зависимости от битов COM0B1 и COM0B0. При этом не генерируется прерывание и таймер не сбрасывается в CTC режиме.
При чтении всегда возвращает 0.
Бит 3 — WGM02 — совместно с WGM01 и WGM00 из регистра TCCR0A определяет режим работы таймера/счётчикаT0.
Биты 2, 1, 0 — CS02, CS01, CS00 — определяют источник тактового сигнала для таймера, счётчика T0
CS02 | CS01 | CS00 | Описание |
Таймер/счётчик остановлен | |||
1 | Системный тактовый сигнал (clkT0=clkI/O) | ||
1 | clkI/O/8 (с предделителем) | ||
1 | 1 | clkI/O/64 (с предделителем) | |
clkI/O/256 (с предделителем) | |||
clkI/O/1024 (с предделителем) | |||
Внешний сигнал — по ниспадающему фронту импульсов на выводе таймера T0 | |||
1 | 1 | 1 | Внешний сигнал — по нарастающему фронту импульсов на выводе таймера T0 |
TIMSK
TIMSK — регистр масок прерываний таймеров/счётчиков T0 и T1.
Для разрешения прерывания от таймера/счётчика необходимо установить 1 в соответствующий бит регистра TIMSK и бит I регистра SREG.
Бит | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | TIMSK |
TOIE1 | OCIE1A | OCIE1B | — | ICIE1 | OCIE0B | TOIE0 | OCIE0A | ||
Чтение(R)/Запись(W) | R/W | R/W | R/W | R | R/W | R/W | R/W | R/W | |
Начальные значения | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Бит 7 — TOIE1 — разрешение прерывания по переполнению таймера/счётчика T1.
Бит 6 — OCIE1A — разрешение прерывания по событию «Совпадение А» таймера/счётчика T1.
Бит 5 — OCIE1B — разрешение прерывания по событию «Совпадение B» таймера/счётчика T1.
Бит 3 — ICIE1 — разрешение прерывания по событию «Захват» таймера/счётчика T1.
Бит 2 — OCIE0B — разрешение прерывания по событию «Совпадение B» таймера/счётчика T0.
Бит 1 — TOIE0 — разрешение прерывания по переполнению таймера/счётчика T0.
Бит 0 — OCIE0A — разрешение прерывания по событию «Совпадение А» таймера/счётчика T0.
TIFRTIFR — регистр флагов прерываний таймеров/счётчиков T0 и T1.
При наступлении какого-либо события соответствующий флаг регистра TIFR устанавливается в 1. При запуске подпрограммы обработки прерывания он аппаратно сбрасывается в 0. Любой флаг также может быть сброшен программно записью в него 1.
Бит | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | TIFR |
TOV1 | OCF1A | OCF1B | — | ICF1 | OCF0B | TOV0 | OCF0A | ||
Чтение(R)/Запись(W) | R/W | R/W | R/W | R | R/W | R/W | R/W | R/W | |
Начальные значения | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Бит 7 — TOV1 — флаг прерывания по переполнению таймера/счётчика T1.
Бит 6 — OCF1A — флаг прерывания по событию «Совпадение А» таймера/счётчика T1.
Бит 5 — OCF1B — флаг прерывания по событию «Совпадение B» таймера/счётчика T1.
Бит 3 — ICF1 — флаг прерывания по событию «Захват» таймера/счётчика T1.
Бит 2 — OCF0B — флаг прерывания по событию «Совпадение B» таймера/счётчика T0.
Бит 1 — TOV0 — флаг прерывания по переполнению таймера/счётчика T0.
Бит 0 — OCF0A — флаг прерывания по событию «Совпадение A» таймера/счётчика T0.
GTCCR
Бит | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | GTCCR |
— | — | — | — | — | — | — | PSR10 | ||
Чтение(R)/Запись(W) | R | R | R | R | R | R | R | R/W | |
Начальные значения | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Бит 0 — PSR10 — сброс предделителей таймеров счётчиков.
При установке 1 в этот бит предделители таймеров T0 и T1 сбрасываются. После сброса в нём аппаратно устанавливается 0.
Таймер с ATtiny2313
; ; ************************************************* ; * Таймер ATtiny2313 с 7-сегментным дисплеем * ; * Четырехзначный мультиплексированный выход, цифровой ключ * ; * (C) 2012, avr-asm-tutorial.net * ; ************************************************* ; ; Включенный заголовочный файл для целевого типа AVR ATtiny2313 .НОЛИСТ .INCLUDE "tn2313def.inc" ; Заголовок для AT90S2313 .СПИСОК ; ; ============================================ ; H A R D W A R E I N F O R M A T I O N ; ============================================ ; ; _____________ ; / | ; Сбросить о--| |--ö + 3 В ; Ключ 1 Dwn o--| |--o Светодиоды активны, низкий уровень ; Клавиша 2 Вверх о--| |--o Сегмент g ; S2A Cnt-мод о--| A T |--o Сегмент f ; Выход о--| |--o Сегмент e ; Ключ 3 Идти--| t i n y |--o Сегмент d ; Анод Dig1 o--| |--o Сегмент c ; Анод Dig2 o--| 2 3 1 3 |--o Участок б ; Анод Dig3 o--| |--o Сегмент а ; Земля о--| |--o Анод Dig4 ; |______________| ; ; ========================== ; КАК ЭТО РАБОТАЕТ ; ========================== ; ; Описание: ; Это обеспечивает таймер с четырехзначным 7-сегментным ; отображать. Он может считать вниз или вверх, в зависимости от ; переключатель 2А. Во время активного счета два ; Светодиоды между минутами и секундами мигают ; быстро, а выходной контакт имеет высокий активный уровень. ; ; Внутреннее функционирование ; 0: Процессор ; Работает с внутренним RC-генератором по умолчанию, ; тактовая частота 1 Мвыб/с ; ; 1. 16-битный таймер 1 ; Работает с внутренними часами, предварительно масштабированными на 8, и ; в режиме CTC с ICR1, установленным на 625, поэтому ; прерывание происходит каждые 0,005 секунды для привода ; мультиплексор из четырех цифр с частотой 50 Гц. ; Таймер устанавливает флаг f5ms. Если секунда ; таймер дополнительно устанавливает флаг f1s. ; ; 2. Флаги ; 2а) флаг 5 мс: ; Неактивный режим (счетчик не запущен): ; Если установлено после таймера int, процедура ; сканирует ключевые входы. Если один из ключей ; нажата, вызывается соответствующая процедура: ; - Клавиша Вниз нажата: это уменьшает тревогу ; время на 5 секунд. Новое время будильника ; записывается в EEPROM. ; - Клавиша вверх нажата: это увеличивает тревогу ; время на 5 секунд. Новое время будильника ; записывается в EEPROM. ; - Нажата клавиша Go: запуск таймера. Если ; выбран обратный отсчет (переключатель 2A выключен) ; время установлено на время будильника. Если до- ; выбран счет (переключатель 2A вкл.) ; время очищается. Выходной контакт A0 установлен ; на высокий, двойной светодиод в середине ; дисплеи мигают. Каждый второй импульс ; увеличивает счет времени. Если время достигает ; ноль (счет вниз) соотв. время будильника (до ; считая) выходной контакт A0 выключен. ; Активный режим (счетчик запущен): ; - Нажата клавиша вниз: истекшее время ; уменьшилось на 5. ; - Клавиша вверх нажата: прошедшее время увеличивается ; на 5. ; - Нажата клавиша Go: счетчик перезапускается. ; Любой активный ключ блокирует дальнейшую обработку ключа ; пока ни одна из клавиш не будет нажата в течение как минимум ; длительность 20 мс. ; 2б) 1 с флаг: ; Если не активирован, счетчик неактивного времени ; уменьшается. Если он достигает нуля (после 20 ; секунд) цифровые индикаторы выключены ; и два светодиода в середине переключаются ; до 1/4 для экономии энергии. ; Если активировано: прошедшее время увеличивается ; на единицу и сравнивается со временем будильника. ; Если время будильника достигнуто, выходной контакт ; выключен (ноль). ; ; ============================================ ; П О Р Т С А Н Д П И Н С ; ============================================ ; .EQU ppSegment = PORTB ; выходной порт сегментов .EQU pdSegment = DDRB ; порт направления сегментов .EQU ppAnodes = PORTD ; порт драйвера анода .EQU pdAnodes = DDRD ; анодный драйвер и направление ввода клавиш .EQU PiKeys = ПИН-код ; порт ввода ключа .EQU biKey1 = 0 ; ключ 1 входной бит .EQU biKey2 = 1 ; ключ 2 входной бит .EQU biKey3 = 2 ; ключ 3 входной бит .EQU ppOutput = ПОРТ ; выходной порт .EQU pdOutput = DDRA ; выходной порт направления .EQU boOutput = 0 ; выходной бит .EQU piJumper = PINA ; входной порт перемычки .EQU biJumper = 1 ; входной бит перемычки ; ; ============================================ ; C O N S T A N T S T O C A N G E ; ============================================ ; . EQU cMux = 50 ; Частота MUX для всех четырех цифр ; ; ============================================ ; F I X + D E R I V E D C O N S T A N T S ; ============================================ ; .EQU cClock = 1000000 ; часы процессора .EQU cPresc = 8 ; прескалер TC1 .EQU cTc1Clk = cClock / cPresc ; часы TC1 .EQU cCtc = cTc1Clk / cMux / 4 ; Значение CTC TC1 .EQU c1s = 4 * cMux ; ; ============================================ ; РЕГИСТРАЦИЯ ; ============================================ ; ; используется: R0..R1 для 7-сегментного преобразования ; б/у: R2..R9как хранилище последовательностей MUX ; бесплатно: R10..R12 .DEF rDOff = R13 ; downcounter для выключения дисплея .DEF rDisp = R14 ; счетчик для отображения времени будильника вместо времени .DEF rSreg = R15 ; Сохранить регистр SREG .DEF об/мин = R16 ; Многоцелевой регистр .DEF обод = R17 ; Многоцелевые внутренние прерывания .DEF rFlg = R18 ; Регистр флага .EQU f5ms = 0 ; 5 мс над флагом .EQU f1s = 1 ; 1 секунда над флагом .EQU факт = 2 ; счет и вывод активны . EQU fKey = 3 ; ключ заблокирован .DEF rTimeL = R19 ; счетчик времени .DEF rTimeH = R20 ; .DEF rAlrmL = R21 ; хранение времени будильника .DEF rAlrmH = R22 .DEF rKey = R23 ; для подсчета ключей .DEF rC1sL = R24 ; счетчик секунд .DEF rC1sH = R25 ; используется: X (XH:XL) как указатель мультиплексора на SRAM ; использовал; Y (YH:YL) для преобразования в 7-сегментный ; б/у: Z (ZH:ZL) многоцелевые внешние целые ; ; ============================================ ; С Р А М Д Е Ф И Н И Т И О Н С ; ============================================ ; ; (нет, SRAM используется только для операций со стеком) ; ; ============================================ ; Р Е С Е Т И Н Т В Е К Т О Р С ; ============================================ ; .CSEG .ОРГ $0000 rjmp Главная ; Вектор сброса рети; Вектор INT0 рети; Вектор INT1 rjmp Tc1CaptIsr ; Вектор захвата TC1 рети; Вектор TC1COMPA рети; Вектор TC1OVF рети; Вектор TC0OVF рети; Вектор USART-RX рети; Вектор USART-UDRE рети; Вектор USART-TX рети; АНАКОМП вектор рети; Вектор PCINT рети; TC1COMPB вектор рети; TC0COMPA вектор рети; TC0COMPB вектор рети; Вектор УЗИ-СТАРТ рети; Вектор УЗИ-ОВФ рети; EE-READY вектор рети; Вектор ВДТ-ОВФ ; ; ============================================ ; И Н Т Е Р У П Т С Е Р В И Ц Е С ; ============================================ ; ; TC1 ICF Isr (мультиплексор и синхронизация) Tc1CaptIsr: в rSreg,SREG ; сохранить SREG лди обод,0b01111111 ; чистые анодные драйверы вне ppAnodes, Rimp ld обод,X+ ; прочитать следующие байты мультиплексирования бст rC1sL,5 ; скопировать бит 7 секундного счетчика в T sbrc rFlg,fAct корп. обод,7; скопируйте флаг T в бит 7, чтобы мигать вне ppSegment,rimp ; вывод в сегменты ld обод,X+ ; читать следующий драйвер анода вне ppAnodes,rimp ; установить анодные драйверы sbr rFlg,1<rDisp вкл. rDisp перезвонить Перезагрузить ; X - счетчик положения мультиплексора ldi XH, ВЫСОКИЙ (2) LDI XL, НИЗКИЙ(2) ldi rC1sH,HIGH(c1s) ; начать новый счетчик ldi rC1sL, НИЗКИЙ (c1s) ; Инициализация и запуск таймера ldi rmp,HIGH(cCtc) ; установить регистр ICR1 выход ICR1H, об/мин ldi rmp, LOW (cCtc) выход ICR1L, об/мин ldi об/мин,0 ; установить режим вне TCCR1A, об/мин ldi rmp,(1< rKey вкл. rKey вкл. rKey вкл. rKey sbr rFlg,1< rDisp вкл. rDisp rjmp Перезагрузить Флаг5msKey2: лди об/мин,5 добавить rAlrmL,rmp лди об/мин, 0 adc rAlrmH,rmp cpi rAlrmL, LOW (3599) brcs Flag5msОбновление cpi rAlrmH, ВЫСОКИЙ (3599) brcs Flag5msОбновление LDI rAlrmL,НИЗКИЙ(3599) ldi rAlrmH, ВЫСОКИЙ (3599) rjmp Flag5msUpdate Флаг5msKey3: перезвонить Перезагрузить ldi rC1sH,HIGH(c1s) ; начать новый счетчик ldi rC1sL, НИЗКИЙ (c1s) sbr rFlg,1< rTimeH Flag1sEq: cp rTimeL,rAlrmL ; сравнить со временем будильника brne UpDateDisplay cp rTimeH,rAlrmH brne UpDateDisplay клрВремяL ; перезапустить новый clrTimeH cbr rFlg,1< ; ZH:ZL — вычитатель (ZH:ZL = 600 или 60) ; ПолучитьЦифра2: клр рмп ; rmp это счетчик ПолучитьDigit2Count: суб R0,ZL ; вычесть младший бит sbc R1,ZH ; вычесть старший бит brcs GetDigit2Ok вкл. об/мин rjmp GetDigit2Count ПолучитьDigit2Ok: добавить R0,ZL ; восстановить последний адк R1,ZH Преобразовать цифру: ldi ZH,HIGH(2*SegTab) ; точка Z на 7-сегментную таблицу ldi ZL, LOW (2 * SegTab) добавить ZL,rmp ; добавить число цифр л/мин об/мин, Z ; прочитать результат из таблицы ст Y,rmp ; запись в регистр MUX адив YL,2 ; указать на следующую позицию отображения рет ; преобразовать предпоследнюю цифру (ZL = 10) ПолучитьЦифра1: клр рмп ; rmp это счетчик ПолучитьDigit1Count: суб R0,ZL ; вычесть числовое основание brcs GetDigit1Ok вкл. об/мин rjmp GetDigit1Count ПолучитьDigit1Ok: добавить R0,ZL ; добавить базу цифр rjmp ConvertDigit ; преобразовать последнюю цифру Получить цифру: мов об/мин,R0 ; скопировать последнюю цифру rjmp ConvertDigit ; ; Перезапустить счетчик ; Перезапуск: sbis piJumper,biJumper ; запускать? rjmp RestartZero ; нет, вниз mov rTimeL,rAlrmL ;время перезапуска мов rTimeH,rAlrmH rjmp RestartMux Перезапустить с нуля: клрВремяL ; ясное значение для прямого счета clrTimeH ; Преобразование времени в буфер в SRAM РестартМукс: вызвать UpdateDisplay ; преобразовать в 7-сегментный лди рмп,0b00111111 ; отображать цифру 1 движение R9, об/мин лди рмп,0b01011111 ; отображать цифру 2 мов R7, об/мин лди рмп,0b01101111 ; отображать цифру 3 мов R5, об/мин лди рмп,0b01110111 ; отображать цифру 4 мов R3, об/мин рет ; ; Семисегментный стол ; ; 0: _gFEDCBA 01000000 ; --- 1: _gfedCBa 01111001 ; ф/г/б 2: _GfEDcBA 00100100 ; --- 3: _GfeDCBA 00110000 ; д//с 4: _GFedCBa 00011001 ; --- 5: _GFeDCbA 00010010 ; д 6: _GFEDCba 00000011 ; 7: _gfedCBA 01111000 ; 8: _GFEDCBA 00000000 ; 9: _GFedCBA 00011000 Сегментная вкладка: . DW 0b0111100101000000 ; 1, 0 .DW 0b0011000000100100 ; 3, 2 .DW 0b0001001000011001 ; 5, 4 .DW 0b0111100000000011 ; 7, 6 .DW 0b0001100000000000 ; 9, 8 ; ; Содержимое EEPROM для запуска ; .EQU cAlrm = 1*60+30 ; запуск в 01:30 .ESEG .ОРГ 0x0000 .DB LOW(cAlrm), HIGH(cAlrm) ; ; Конец исходного кода ;
time — Прерывание таймера Attiny не делает прерывание каждые 1000 мс
Я вижу три проблемы с этим подходом.
Во-первых, вы используете некалиброванное время очень низкого качества. источник. Частота внутреннего RC-генератора хороша с точностью до всего несколько процентов. Он также очень нестабилен и сильно зависит от температура. Использование внешнего керамического генератора с частотой 16 МГц должно дать вам частоту, которая не хуже, чем 0,5% от, с типичным ошибка около 0,1%. Однако он все еще несколько нестабилен. Если вы вместо этого используют кристалл осциллятор , то можно ожидать погрешность порядка десяти раз меньше (в диапазоне 100 ppm), и очень хорошая стабильность. В зависимости от ваших требований к качеству, 100 стр/мин может быть недостаточно. достаточно хорошо, и в этом случае у вас все еще есть возможность измерить скорость дрейфа и откалибруйте ее (см. ниже).
Вторая проблема, которую уже поднимал 6v6g, заключается в том, что ваш таймер считает от нуля до 122 включительно, что дает период 123 такта таймера. Посмотрите на временные диаграммы в техпаспорт, если вам нужно убедить себя в этом. Если вы хотите период из 122, вы должны установить для OCR0A значение 121.
Третья проблема заключается в том, что вы сбрасываете таймер с помощью ISR. Этот может работать в этой программе, но это очень хрупкий подход, который стоит избегая. Проблема в том, что все, что делает микроконтроллер, занимает время, и ваш ISR может даже быть задержан другим прерыванием. Если таймер увеличивается после поднятия флага прерывания, но до того, как вы сбросьте его, вам не хватает одного счета. Если вы хотите иметь непрерывный шкала времени, никогда не сбрасывать таймер. Вы можете:
позволить ему работать непрерывно, без помех (и выполнить
OCR0A += 122
в течение ИСР),или позволить ему сбросить себя, используя соответствующую генерацию сигнала режим (CTC или быстрый PWM).
Наконец, вот трюк, который вы можете использовать для калибровки секундомера. Вместо подсчета прерываний до тех пор, пока счетчик не достигнет 8 (что предполагает период прерывания ровно 1/8 с), увеличьте a счетчик наносекунд внутри ISR и считать одну секунду, как только у вас есть один миллиард наносекунд:
const uint32_t nanoseconds_per_interrupt = 124928000; ISR(TIMER0_COMPA_vect) { статический uint32_t наносекунд; наносекунды += наносекунды_на_прерывание; если (наносекунд >= 1000000) { наносекунды -= 1000000; секунды++; // затем обновить минуты, часы... если необходимо } }
Это будет увеличивать секунды каждые восемь прерываний… время. Однако время от времени потребуется девять прерываний. Этот добавляет немного джиттера, но предотвращает ошибки синхронизации накапливаются и заставляют часы дрейфовать. Если дрожание видно, вы можно уменьшить, сократив период прерывания.
Значение 124928000, которое я написал выше, предполагает, что ISR вызывается каждый раз. 122×1024 цикла тактовой частоты 1 МГц. Вы можете изменить его, чтобы он соответствовал другую тактовую частоту или другую настройку OCR0A. Хитрость заключается в следующем: как только вы измерите скорость дрейфа секундомера, вы сможете настроить это число, чтобы удалить этот дрейф. Например, если вы измеряете секундомер и обнаружите, что он работает на 0,04% медленнее, тогда вы увеличиваете это число на 0,04% (что дало бы 124977971) и дрейф пропал.
Редактировать : В комментарии 6v6gt указал на четвертую проблему в вашем коде, что, вероятно, является самой большой проблемой. Ваша логика подсчета прерываний это:
если (intr_count == 8) { intr_count = 0; } еще { intr_count++; }
Счет от 0 до 8 включительно и зацикливание с периодом 9 прерываний.