Site Loader

Простой кухонный таймер на ATtiny2313

  1. Главная|
  2. Устройства|
  3. AVR
Просмотров: 15852

Таймер Семисегментный индикатор ATtiny2313 Энкодер

Опытные хозяйки всё отмеряют на глаз и чувствуют время «внутренними» часами, но люди склонны впадать в задумчивость и отвлекаться на другие дела. Очень часто так случается, что и у опытных хозяек с любовью подготовленные к выпечке пироги превращаются в несъедобный углерод. Результат — испорченное настроение, зря потраченное время и срыв намеченных планов.

Избежать подобной ситуации поможет простой кухонный таймер на широко распространённом микроконтроллере ATtiny2313 компании Atmel.

При разработке таймера ставилась задача использования минимального количества деталей, простоты управления, простоты повторения устройства, возможности питания таймера как от трёх батареек АА (LR6) по 1,5 В, так и от внешнего адаптера.

Возможности и основные характеристики таймера:

1. Время установки таймера от 1 до 90 мин.
2. Звуковая сигнализация включения и выключения таймера.
3. Звуковая сигнализация окончания установленного времени.
4. Принудительное выключение таймера до истечения установленного времени.

5. Самостоятельное выключение таймера по истечении 10 с после его включения в случае, если после включения таймера время выдержки не было установлено или не запущен отсчёт времени.
6. Питание устройства как от трёх батареек, так и от внешнего адаптера напряжением от 7 до 10 В.
7. Ток потребления таймера в выключенном состоянии в несколько раз меньше тока саморазряда пальчиковых батареек.

Алгоритм работы таймера

Таймер включается нажатием кнопки энкодера. На индикаторе высвечивается минимально возможное время выдержки, равное 1 мин. Вращением ручки энкодера вправо происходит увеличение времени выдержки, а при вращении ручки энкодера влево — уменьшение времени, начиная с 90 мин. Таймер выключится самостоятельно, если в течение 10 с после установки времени не была нажата кнопка запуска. Для запуска отсчёта времени необходимо снова нажать кнопку энкодера. При этом таймер начинает отсчёт установленного времени, а на индикаторе единиц минут с периодом в 1 с будет мигать децимальная точка, индицирующая режим обратного отсчёта. По истечении установленного времени на индикаторе таймера высветится цифра 0 и прозвучат 5 тональных сигналов. После этого цифра 0 погаснет, а децимальная точка будет мигать ещё 10 с. По истечении и этого времени, в напоминание, снова прозвучат 5 тональных сигналов, и таймер выключится.

Остановить работу таймера можно принудительно в любой момент, нажав кнопку энкодера.

Схема, конструкция и детали таймера

Принципиальная схема кухонного таймера показана на рис.1. «Мозгом» устройства является микроконтроллер (МК) IC1 типа ATtiny2313 фирмы ATMEL в корпусе DIP20. Микроконтроллер ATtiny2313 тактируется от внутреннего генератора частотой 8 МГц с выключенным предделителем на 8.

Рисунок 1

Для управления таймером применён инкрементный энкодер с кнопкой фирмы Bourns типа

РЕС12-4220F-S0024.В качестве индикатора установленного времени применён сдвоенный 7-сегментный индикатор красного свечения с общим катодом (ОК) фирмы SENIOR SEC5244WS.

Предусмотрена также возможность установки в этом таймере индикаторов с общим анодом (ОА) без изменения принципиальной схемы и платы. Для этого необходимо при программировании МК использовать другую прошивку, разработанную автором специально под индикаторы с ОА, В качестве звукового извещателя используется зуммер (Magnetic Buzzer) типа КХ-1205 фирмы King-state.

В таймере использованы SMD-резисторы и конденсаторы типоразмера 0508.

Таймер собран на односторонней печатной плате из фольгированного текстолита размерами 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.

Бит76543210TCCR0A
COM0A1COM0A0COM0B1COM0B0WGM01WGM00
Чтение(R)/Запись(W)R/WR/WR/WR/WRRR/WR/W
Начальные значения00000000

Биты 7, 6 — COM0A1, COM0A0 — определяют состоянии вывода OC0A при наступлении события «Совпадение».
Биты 5, 4 — COM0B1, COM0B0 — определяют состоянии вывода OC0B при наступлении события «Совпадение».

В Нормальном и CTC режимах

COM0A1
(COM0B1)
COM0A0
(COM0B0)
Описание
00

Нормальная работа вывода. Вывод OC0A (OC0B) отключен от таймера/счётчика T0.

01

Инвертировать состояние вывода.

10

Сбросить при совпадении в 0.

11

Установить 1 при совпадении.

В режимах Fast PWM и Phase Correct PWM

COM0A1
(COM0B1)
COM0A0
(COM0B0)
Описание
00Нормальная работа вывода. Вывод OC0A (OC0B) отключен от таймера/счётчика T0.
01OC0A:
WGM02 = 0 — Вывод OC0A отключен от таймера/счётчика T0.
WGM02 = 1 — Инвертирование состояния вывода.
OC0B: —
10Сбрасывается при совпадении в 0. Устанавливается в 1 при достижении счётчиком максимального значения (неинвертированный ШИМ сигнал).
11Устанавливается 1 при совпадении. Сбрасывается в 0 при достижении счётчиком максимального значения (инвертированный ШИМ сигнал).

Биты 1,0 — WGM01, WGM00 — совместно с WGM02 из регистра TCCR0B определяют режим работы таймера/счётчикаT0.

WGM02WGM01WGM00

Описание

 Нормальный режим

1

 Phase Correct PWM (ШИМ с точной фазой)

1

 CTC (Сброс при совпадении)

1

1

Fast PWM

1

1

1

Phase Correct PWM (ШИМ с точной фазой)

1

1

1

1

1

Fast PWM

Бит76543210TCCR0B
FOC0AFOC0BWGM02CS02CS01CS00
Чтение(R)/Запись(W)WWRRR/WR/WR/WR/W
Начальные значения00000000

Бит 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


CS02CS01CS00

Описание

 Таймер/счётчик остановлен

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.


Бит76543210TIMSK
TOIE1OCIE1AOCIE1BICIE1OCIE0BTOIE0OCIE0A
Чтение(R)/Запись(W)R/WR/WR/WRR/WR/WR/WR/W
Начальные значения00000000

Бит 7 — TOIE1 — разрешение прерывания по переполнению таймера/счётчика T1.

Бит 6 — OCIE1A — разрешение прерывания по событию «Совпадение А» таймера/счётчика T1.

Бит 5 — OCIE1B — разрешение прерывания по событию «Совпадение B» таймера/счётчика T1.

Бит 3 — ICIE1 — разрешение прерывания по событию «Захват» таймера/счётчика T1.

Бит 2 — OCIE0B —  разрешение прерывания по событию «Совпадение B» таймера/счётчика T0.

Бит 1 — TOIE0 — разрешение прерывания по переполнению таймера/счётчика T0.

Бит 0 — OCIE0A — разрешение прерывания по событию «Совпадение А» таймера/счётчика T0.

TIFR

TIFR — регистр флагов прерываний таймеров/счётчиков T0 и T1.
При наступлении какого-либо события соответствующий флаг регистра TIFR устанавливается в 1. При запуске подпрограммы обработки прерывания он аппаратно сбрасывается в 0. Любой флаг также может быть сброшен программно записью в него 1.

Бит76543210TIFR
TOV1OCF1AOCF1BICF1OCF0BTOV0OCF0A
Чтение(R)/Запись(W)R/WR/WR/WRR/WR/WR/WR/W
Начальные значения00000000

Бит 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


Бит76543210GTCCR
PSR10
Чтение(R)/Запись(W)RRRRRRRR/W
Начальные значения00000000

Бит 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 прерываний.

alexxlab

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *