Начинающим: счетчик на микроконтроллере с шагом 2/3 микросекунды и переполнением в несколько суток
Начинающим: счетчик на микроконтроллере с шагом 2/3 микросекунды и переполнением в несколько суток
Часто при работе микроконтроллерного устройства есть необходимость отсчитывать «антропоморфное» время – сколько долей секунды светиться светодиоду, максимальный промежуток времени double-click и т. д. В общем, отсчитывать не только нано- и микросекунды, но и десятки миллисекунд, а то и секунды, минуты и даже часы (боюсь сказать о сутках…).
В то же время в микроконтроллерах нередко нужно одновременно с этим иметь дело с микросекундами – периоды импульсов, антидребезговое ожидание и т. п.
Есть также устройства, которые работают непрерывно многие часы и даже сутки – авиационная техника, автомобильная, скважинные устройства (там речь идет иной раз о непрерывной работе несколько дней). В этих случаях недопустимо переполнение таймеров и 8-битных переменных.
Хотелось бы это все объединить в одно изящное и универсальное решение – иметь средство измерения времени с точностью до микросекунды, не переполняющееся несколько дней.
Почему бы и нет? Помучился я некоторое время и родил решение для 8-битных микроконтроллеров AVR. Для этого я задействовал 8-битный таймер-счетчик и 4х-байтную переменную. С PIC-ами и AT89 я сейчас не работаю, а с другими embedded-платформами не дружу. Впрочем, если читатели помогут – сделаю и для них.
Достоинства – код в высшей степени повторяемый (я уже 5-ое устройство с ним делаю); простота в работе (не используются прерывания для клиентской части работы); клиентская часть кода условно платформенно-независимая; в прерывании – одна операция суммирования (но, правда, для 4-хбайтной величины); нет внешнего устройства — таймера реального времени.
Недостаток я нашел один – занят один такой полезный и всегда нужный таймер…
Статья будет интересна в первую очередь начинающим — Америку я тут не открыл.
Теория
- берем 12 MHz от кварца и берем коэффициент деления на 8 – получаем частоту 1500 KHz;
- берем режим CTC (сброс при совпадении) и ставим прерывание на совпадение с 150 – получаем частоту срабатывания прерывания 10 KHz;
- на этом самом прерывании инкрементируем переменную (получается инкремент каждые 0.1 миллисекунды);
- если это беззнаковая 32х-битная величина, то она переполнится приблизительно после
- 429496729.6 миллисекунд;
- 42949.7 секунд;
- 7158.3 минут;
- 119.3 часов;
- 4.97 суток.
- считаю длительности свечения и пауз между ними светодиодов;
- учитываю timeouts при работе с UART, USB;
- задаю всевозможные ситуации в тестовом оборудовании – сложные пространственно-временнЫе комбинации;
- выдерживаю заданные промежутки времени при опросе АЦП и прочих датчиков;
- сообщаю компьютеру время своей (устройства) работы и с заданным интервалом времени передаю информацию;
- с учетом счетчика до микросекунды я осуществляю антидребезговый контроль при нажатии клавиш, анализ импульсов в протяженных линиях.
Настройка для AVR
Как это все сделать в AVR?
Прежде всего, заводим внешнюю переменную, которую я называю «ДециМиллиСекунда»:
Как верно подметил @no-smoking, эта переменная должна быть volatile, чтобы ее компилятор не попытался оптимизировать.
Инициализацию этой переменной я делаю в функции:
Далее я задаю режим работы таймера 0:
При этом в каком-нибудь MCU_init.h объявляю все, что надо:
Ну и далее, когда можно, разрешаю прерывания:
Осталось описать прерывание. Это проще, чем все предыдущее:
Все, таймер описан, настроен и запущен!
Настройка для PIC
Вот что мне подсказали уважаемые PICоманы:
На пиках это легко повторяется при помощи модуля Timer2. Именно в нем есть аналогичная функция прерывания по совпадению.
PR2 = 75 — значение, при котором таймер обнулится и сгенерирует прерывание
T2CON.T2CKPS = 2 — прескалер 1:16
T2CON.T2OUTPS = 0 — без постскалера
T2CON.TMR2ON = on — таймер включен
IPR1.TMR2IP = 1 —высокоприоритетное прерывание
PIR1.TMR2IF = off —сбрасываем флаг прерывания
PIE1.TMR2IE = on —включаем прерывание по совпадению TMR2 и PR2
INTCON.GIE = on —включаем обработку прерываний
Как видно, прескалер тут в 2 раза больше, потому PR2 в 2 раза меньше.
Данные настройки будут генерировать прерывания с частотой 10 kHz при системной частоте в 48 MHz (на таймер идет Fosc/4) — стандартная частота для USB Full Speed.
Использование
Код для клиента этого таймера получается кросс-платформенным (если не считать обращения к значению таймера 0 в AVR).
Вот фрагмент кода обмена по USB:
Макрофункции RECEIVE_BYTE, RECEIVE_WORD, RECEIVE_DWORD реализуют процедуры чтения с учетом timeout для данной фазы обмена. В итоге, если чего зависло на другой стороне, то микроконтроллер не впадет в «спячку». Обратите внимание – WatchDog не понадобился! И все благодаря переменной/константе max_USB_timeout, которая задает timeout с точностью до 0.1 миллисекунды.
Точно также реализуется анализ «тишины в эфире» переменной next_USB_timeout. Это позволяет микроконтроллеру 1) узнать, что компьютер куда-то исчез, 2) как-то об этом сигнализировать (в моем случае загорается светодиод «ошибка»). Константа/переменная MaxSilence_PC_DEV позволяет варьировать понятие «тишины» в широчайших пределах – от доли миллисекунды до нескольких суток.
Аналогично реализуются все остальные моменты.
Если же вам нужно использовать счетчик микросекунд, то там появляется функция сравнения:
Функции передается предыдущий момент времени – предыдущее значение dmsec и таймера 0.
Вначале мы макросом GetUSec останавливаем прерывания, чтобы в момент копирования не испортилось значение dmsec и счетчика. И копируем текущее время.
Далее мы приводим разницу во времени к формату 2/3 микросекунды с учетом переполнения.
Ну и возвращаем это время.
А далее мы это используем в обычном if для контроля антидребезга и прочих мероприятий. Только не забудьте также приостановить прерывания при засекании текущего момента времени – а лучше используйте макрос GetUSec.
8-битный микроконтроллер AVR Atmel с 2/4/8 Кбайт внутрисистемной программируемой флеш-памятью Руководство пользователя
VCC: Объем поставкиtage.
GND: Основание.
Порт B (PB5: PB0): Порт B — это 6-битный двунаправленный порт ввода-вывода с внутренними подтягивающими резисторами (выбираемыми для каждого бита). Выходные буферы порта B обладают симметричными характеристиками привода с высокой пропускной способностью как приемника, так и источника. В качестве входов контакты порта B, которые внешне подтянуты к низкому уровню, будут давать ток, если активированы подтягивающие резисторы. Контакты порта B имеют тройное обозначение, когда условие сброса становится активным, даже если часы не работают.
Порт B также выполняет функции различных специальных функций ATtiny25 / 45/85, перечисленных в списке.
На ATtiny25 программируемые порты ввода-вывода PB3 и PB4 (контакты 2 и 3) меняются местами в режиме совместимости с ATtiny15 для поддержки обратной совместимости с ATtiny15.
СБРОС: Сбросить вход. Низкий уровень на этом выводе, превышающий минимальную длину импульса, вызовет сброс, даже если часы не работают и вывод сброса не был отключен. Минимальная длительность импульса указана в Таблица 21-4 на странице 165 . Более короткие импульсы не гарантируют сброса.
Вывод сброса также может использоваться как (слабый) вывод ввода / вывода.
Обзор
ATtiny25 / 45/85 — это маломощный 8-битный CMOS-микроконтроллер, основанный на архитектуре RISC, улучшенной AVR. Выполняя мощные инструкции за один такт, ATtiny25 / 45/85 достигает пропускной способности, приближающейся к 1 MIPS на МГц, что позволяет разработчику системы оптимизировать энергопотребление в зависимости от скорости обработки.
Блок-схема 
Ядро AVR сочетает в себе богатый набор команд с 32 рабочими регистрами общего назначения. Все 32 регистра напрямую подключены к Арифметико-логическому устройству (ALU), что позволяет получить доступ к двум независимым регистрам в одной инструкции, выполняемой за один такт. Результирующая архитектура более эффективна с точки зрения кода и обеспечивает до десяти раз более высокую пропускную способность, чем обычные микроконтроллеры CISC.
ATtiny25 / 45/85 обеспечивает следующие функции: 2/4 / 8K байт программируемой внутри системы флэш-памяти, 128/256/512 байт EEPROM, 128/256/256 байт SRAM, 6 линий ввода / вывода общего назначения, 32 общих целевые рабочие регистры, один 8-битный таймер / счетчик с режимами сравнения, один 8-битный высокоскоростной таймер / счетчик, универсальный последовательный интерфейс, внутренние и внешние прерывания, 4-канальный 10-битный АЦП, программируемый сторожевой таймер с внутренним Осциллятор и три режима энергосбережения, выбираемые программным способом. В режиме ожидания процессор останавливается, позволяя продолжать работу SRAM, таймеру / счетчику, АЦП, аналоговому компаратору и системе прерывания. В режиме пониженного энергопотребления сохраняется содержимое регистра, отключая все функции микросхемы до следующего прерывания или аппаратного сброса. В режиме шумоподавления АЦП останавливается ЦП и все модули ввода / вывода, кроме АЦП, чтобы минимизировать шум переключения во время преобразования АЦП.
Устройство изготовлено с использованием технологии энергонезависимой памяти высокой плотности Atmel. Встроенная флэш-память ISP позволяет перепрограммировать программную память в системе через последовательный интерфейс SPI, с помощью обычного программатора энергонезависимой памяти или встроенного загрузочного кода, выполняемого на ядре AVR.
AVR ATtiny25 / 45/85 поддерживается полным набором программных и системных средств разработки, включая компиляторы C, сборщики макросов, программный отладчик / симуляторы и оценочные комплекты.
О нас
Ресурсы
Полный набор инструментов разработки, заметки по применению и таблицы данных доступны для загрузки на http://www.atmel.com/avr.
Код Exampле
Эта документация содержит простой код exampВ файлах кратко показано, как использовать различные части устройства. Этот код exampПредполагается, что конкретный заголовок file включается перед компиляцией. Имейте в виду, что не все поставщики компиляторов C включают определения битов в заголовок. files и обработка прерываний в C зависит от компилятора. Для получения дополнительных сведений обратитесь к документации компилятора C.
Для регистров ввода / вывода, расположенных в расширенной карте ввода / вывода, инструкции «IN», «OUT», «SBIS», «SBIC», «CBI» и «SBI» должны быть заменены инструкциями, которые обеспечивают доступ к расширенному I / O. Обычно это означает «LDS» и «STS» в сочетании с «SBRS», «SBRC», «SBR» и «CBR». Обратите внимание, что не все устройства AVR включают расширенную карту ввода-вывода.
Емкостное сенсорное управление
Библиотека Atmel QTouch представляет собой простое в использовании решение для сенсорных интерфейсов микроконтроллеров Atmel AVR. Библиотека QTouch включает поддержку QTouch ® и QMatrix ® методы приобретения.
Сенсорное распознавание легко добавляется в любое приложение путем связывания библиотеки QTouch и использования интерфейса прикладного программирования (API) библиотеки для определения сенсорных каналов и датчиков. Затем приложение вызывает API для получения информации о канале и определения состояния сенсорного датчика.
Библиотека QTouch бесплатна и может быть загружена с сайта Atmel. webсайт. Для получения дополнительной информации и подробностей реализации обратитесь к Руководству пользователя библиотеки QTouch, которое также можно получить на сайте Atmel. webсайт.
Хранение Данных
Результаты аттестации надежности показывают, что прогнозируемая частота отказов при хранении данных намного меньше 1 PPM в течение 20 лет при 85 ° C или 100 лет при 25 ° C.
Ядро процессора AVR
Введение
В этом разделе обсуждается архитектура ядра AVR в целом. Основная функция ядра ЦП — обеспечение правильного выполнения программы. Поэтому ЦП должен иметь доступ к памяти, выполнять вычисления, управлять периферийными устройствами и обрабатывать прерывания.
Архитектурный Overview 
Чтобы максимизировать производительность и параллелизм, AVR использует архитектуру Гарварда — с отдельной памятью и шинами для программы и данных. Команды в программной памяти выполняются с одноуровневой конвейерной обработкой. Пока выполняется одна инструкция, следующая инструкция предварительно выбирается из памяти программ. Эта концепция позволяет выполнять инструкции в каждом тактовом цикле. Программная память — это внутрисистемная перепрограммируемая флэш-память.
Реестр быстрого доступа File содержит 32 x 8-битных рабочих регистра общего назначения с временем доступа в один такт. Это позволяет работать с арифметико-логическим блоком (ALU) за один цикл. В типичной работе ALU два оператора и выводятся из Регистра File, операция выполняется, и результат сохраняется в регистре. File — за один такт.
Шесть из 32 регистров могут использоваться в качестве трех 16-битных указателей регистров косвенного адреса для адресации пространства данных, что позволяет эффективно вычислять адреса. Один из этих адресных указателей может также использоваться в качестве адресного указателя для таблиц поиска во флэш-памяти программ. Эти добавленные функциональные регистры представляют собой 16-битные регистры X, Y и Z, описанные далее в этом разделе.
ALU поддерживает арифметические и логические операции между регистрами или между константой и регистром. Операции с одним регистром также могут выполняться в АЛУ. После арифметической операции регистр состояния обновляется, чтобы отразить информацию о результате операции.
Выполнение программы обеспечивается инструкциями условного и безусловного перехода и вызова, которые могут напрямую адресовать все адресное пространство. Большинство инструкций AVR имеют формат единственного 16-битного слова, но есть также 32-битные инструкции.
Во время прерываний и вызовов подпрограмм в стеке сохраняется программный счетчик адреса возврата (ПК). Стек эффективно выделяется в SRAM общих данных, и, следовательно, размер стека ограничивается только общим размером SRAM и использованием SRAM. Все пользовательские программы должны инициализировать SP в процедуре сброса (перед выполнением подпрограмм или прерываний). Указатель стека (SP) доступен для чтения и записи в пространстве ввода-вывода. Доступ к SRAM данных можно легко получить с помощью пяти различных режимов адресации, поддерживаемых архитектурой AVR.
Все пространства памяти в архитектуре AVR представляют собой линейные и обычные карты памяти.
У гибкого модуля прерывания есть свои регистры управления в пространстве ввода-вывода с дополнительным битом разрешения глобального прерывания в регистре состояния. Все прерывания имеют отдельный вектор прерывания в таблице векторов прерываний. Прерывания имеют приоритет в соответствии с положением их вектора прерывания. Чем ниже адрес вектора прерывания, тем выше приоритет.
Область памяти ввода-вывода содержит 64 адреса для периферийных функций ЦП, таких как регистры управления, SPI и другие функции ввода-вывода. Доступ к памяти ввода / вывода можно получить напрямую или в качестве ячеек пространства данных, следующих за местоположениями в регистре. File, 0x20 — 0x5F.
ALU — Арифметико-логический блок
Высокопроизводительный AVR ALU напрямую связан со всеми 32 рабочими регистрами общего назначения. В пределах одного такта выполняются арифметические операции между регистрами общего назначения или между регистром и непосредственным значением. Операции ALU делятся на три основные категории — арифметические, логические и битовые функции. Некоторые реализации архитектуры также предоставляют мощный умножитель, поддерживающий как знаковое / беззнаковое умножение, так и дробный формат. См. Подробное описание в разделе «Набор команд».
Регистр статуса
Регистр состояния содержит информацию о результате последней выполненной арифметической инструкции. Эта информация может использоваться для изменения потока программы для выполнения условных операций. Обратите внимание, что регистр состояния обновляется после всех операций ALU, как указано в Справочнике по набору команд. Во многих случаях это устраняет необходимость использования специальных инструкций сравнения, что приводит к более быстрому и компактному коду.
Регистр состояния не сохраняется автоматически при входе в программу обработки прерывания и не восстанавливается при возврате из прерывания. Это должно выполняться программным обеспечением.