Казалось-бы, банальное дело, запустить часовой кварц. Какие могут быть проблемы? Есть микроконтроллер и две его ножки, которые специально предназначены для подключения кварца. Есть часовой кварц. Припаять кварц – дело двух секунд. Еще минута нужна для того, чтобы добавить пару строк инициализации таймера в программу. Вот вроде и все. НО, после того как я три дня запускал этот долбанный часовой кварц, я понял, что вопрос не так прост, как я думал.
А предыстория была такой. Друг попросил меня сделать ему простые часики, без наворотов, на 7-сегментных индикаторах. Плевое дело. Микроконтроллер был взят ATmega48 (умеет работать с часовым кварцем), быстренько написана программа, вытравлена печатка. После сборки часов и отладки программы (динамическая индикация, кнопки и т.д.) дошла очередь до часового кварца. До этих часиков я уже пару раз применял часовой кварц в своих проектах и ничего не предвещало беды :), но случилось непредвиденное – часовой кварц наотрез отказался запускаться. Вообще!
В попытках разобраться, что-же мешает заработать моему часовому кварцу я первым делом обратился к даташиту на микроконтроллер (ATmega48). Информации по асинхронному режиму и подключению таймера там оказалось очень мало. Дальше я начал искать решение проблемы на форумах. Вот тут было разнообразие решений и советов вплоть до ритуальных танцев с бубнами, что тоже не особо мне помогло. Пришлось путем проб и ошибок (не путать с «методом тыка»!) самому разбираться, что к чему. В результате героических потугов, наступания на какие только можно грабли и убитых трех дней, родился практический опыт подключения часового кварца, с которым я здесь и поделюсь.
Итак, какие грабли нас ожидают при запуске часового кварца?
1 Схемотехника.
1.1 Конденсаторы.
В даташите на микроконтроллер довольно пространно упоминается то, что к часовому кварцу должны быть подключены конденсаторы, а про их емкость вообще узнать трудно. Часовой кварц, скорей всего, заработает и без конденсаторов, но лучше их поставить это улучшит стабильность частоты и поможет кварцу быстрей запускаться.
Емкость конденсаторов должна быть в пределах 12-22 пФ.
1.2 Разводка дорожек под кварц.
Тут даташит и апноты дают нам четкие указания. Дорожки от ножек микроконтроллера до кварца должны быть минимальной длинны, земляная» дорожка для конденсаторов должна быть отдельной, то есть через нее не должны протекать посторонние токи (особенно это касается сильноточных и высокочастотных цепей).
1.3 Корпус часового кварца.
Железный корпус часового кварца обязательно припаяете к земле (к той к которой припаяны конденсаторы). Незаземленный корпус будет работать как антенна, внося искажения в работу кварца, ухудшая точность хода Ваших часов.
1.4 Грязь на плате.
Часовой кварц довольно нежная штука и сопротивления в пару мегаом между ножками вполне хватит для его остановки. Как показала практика, жидкий флюс, если его плохо смыть, дает достаточное сопротивление, для того чтобы кварц не работал. После пайки тщательно вымойте плату. Очень часто во флюсах содержится кислота, что и дает проводимость между ножками. Для нейтрализации кислоты промойте плату слабым раствором соды (пищевой) и тщательно отмойте чистой водой.
2 Программирование.
2.1 Инициализация асинхронного режима таймера.
Для того чтобы таймер работал от часового кварца, его (таймер) необходимо перевести в асинхронный режим. Для перевода таймера (почти у всех микроконтроллеров это таймер 2) в этот режим нужно записать 1 в бит AS2. Но не все так просто, нужно соблюсти определенный алгоритм запуска. По даташиту процедура включения асинхронного режима для таймера 2 следующая:
1. Запретить прерывания от таймера/счетчика 2 — OCIE2x, TOIE2;
2. Переключить его в асинхронный режим 1 -> AS2;
3. Записать новые значения в регистры TCNT2, OCR2x и TCCR2x;
4. Дождаться сброса флагов TCN2UB, OCR2xUB и TCR2xUB;
5. Сбросить флаги прерываний таймера/счетчика 2;
6. Разрешить прерывания (если требуется).
Обязательно соблюдайте такую последовательность. Вот листинг правильной инициализации асинхронного режима таймера2.
/* запрещаем прерывания */ cli(); /* 1. Запрещаем прерывания Timer/Counter2 обнуляя OCIE2х и TOIE2. */ TIMSK2 &= ~((1<<OCIE2A)|(1<<OCIE2B)|(1<<TOIE2)); /* 2. Переводим Timer/Counter2 в асинхронный режим устанавливая AS2. */ ASSR = (1<<AS2); /* Даем немного времени для стабилизации работы генератора (можно опустить). */ _delay_ms(1000); /* 3. Записываем новые значения TCNT2, OCR2x, and TCCR2B. */ TCNT2 = 0; /* устанавливаем пределитель = 128 32.768 kHz / 128 / 256 = переполнение раз за секунду. */ TCCR2B |= (1<<CS22) | (1<<CS20); /* 4. Чтобы быть уверенным, что часы заработали ждем пока обнулятся биты: TCN2UB, OCR2AUB, OCR2BUB, TCR2AUB и TCR2BUB. */ while(ASSR & 0x1F); /* 5. Обнуляем флаги прерываний Timer/Counter2. */ TIFR2 |= ((1<<OCF2A)|(1<<OCF2B)|(1<<TOV2)); /* 6. Разрешаем прерывание по переполнению таймера 2 */ TIMSK2 |= (1<<TOIE2); /* разрешаем прерывания */ sei(); |
2.2 Пределитель таймера 2.
Для того, чтобы прерывания по переполнению таймера2 происходили раз в секунду, значение пределителя должно быть 128. (128пределитель*256переполнение=32768частота кварца).
2.3 Работа часов в режиме сна PowerSave.
Очень заманчиво в паузах между секундными прерываниями переводить микроконтроллер в режим сна, в этом случае ток микроконтроллера упадет до 6-7мкА. Для такого случая есть режим пониженного потребления PowerSave, в нем таймер2 продолжает работать от часового кварца и пробуждает микроконтроллер прерыванием. Алгоритм такого режима работы простой, после выхода из режима сна по прерыванию от таймера в процедуре обработки прерывания «тикаем» часами, выходим из прерывания и опять даем команду заснуть (SLEEP). Вот тут есть очень важный нюанс. Опять смотрим даташит на микроконтроллер в разделе режимов пониженного потребления и работы асинхронного режима. Для того чтобы таймер после пробуждения начал нормально функционировать и был способен вывести микроконтроллер из сна при следующем прерывании нужно до команды засыпания выждать определенное время. Для того, чтобы убедится в том что генератор работает нормально нужно сделать запись в любой регистр таймера, из тех, которые не нарушат работу часов (например в OCR2x) и дождаться сброса флагов готовности данного регистра (OCR2xUB). После того как флаг сбросился можно смело переводить микроконтроллер в режим сна.
/* Точка выхода с прерывания по переполнению таймера2 */ /* Записываем любое значения в OCR2A. */ OCR2A = 0; /* Дожидаемся пока обнулится OCR2AUB. */ while(ASSR & (1<<OCR2AUB)); /* Дальше можем спокойно засыпать */ |
3 Разное.
3.1 Не используйте дешевые китайские кварцы (в особенности выпаянные со старых сломанных копеечных часов). Даже если они и заработают, точность у них будет никакая.
3.2 Ну и напоследок, имейте под рукой несколько разных кварцев, возможно, Ваш кварц не запускается по причине того, что он спален. Попробуйте его заменить.
Вот, вроде, и все грабли, по которым я потоптался, пока запускал часовой кварц. Или еще что-то добавить?