Урок 23
Часть 5
Собираем часы на DS1307 и LED индикаторе
В прошлой части нашего занятия мы занимались автоматическим реагированием яркости свечения индикатора на условия окружающей освещённости. Нам это удалось.
Сегодня мы попробуем подключить к нашей схеме также датчика температуры 18B20, а также попытаемся отобразить показания не только времени, но и даты, дня недели, а также температуры. А уж как нам это удастся, посмотрим.
Подключим файлы DS18B20.c и DS18B20.h из проекта урока 20 по датчику температуры My1820LCD.
Подключим данную библиотеку также в main.h
#include «led.h»
#include «DS18B20.h»
Также из того же проекта скопируем объявление переменной в main()
int main(void)
{
unsigned int tt=0; //переменная для хранения температуры
Скопируем и вставим также измерение температуры в бесконечный цикл
date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат
tt = converttemp(dt_check());
Теперь нам нужно эту температуру как-то отобразить, хотя бы пока как-то.
Закомментируем пока отображение времени
//ledprint(hour*100+min);
Также можно закомментировать и чтение времени.
И пока мы просто отобразим значение переменной tt
else OCR2=7;
ledprint(tt);
Посмотрим также изменение нашей схемы в связи с подключением датчика температуры (нажмите на картинку для увеличения изображения)
Как видим, термометр у нас своим информационным входом подключен на ножку PC2, поэтому в файле DS18B20.h мы должны внести соответствующие изменения
#define PORTTEMP PORTC
#define DDRTEMP DDRC
#define PINTEMP PINC
#define BITTEMP 2
Вот теперь можно собирать проект и прошивать контроллер
Температура у нас 22 градуса, всё у нас нормально отображается, но температура у нас измеряется 12-битно, это очень расточительно, ибо нужно использовать задержку в 750 милисекунд. Поэтому зайдём в файл DS18B20.c и перенастроим функцию считывания температуры. Как известно, нам достаточно просто изменить задержку, и просто потом не использовать младшие биты
dt_sendbyte(T_CONVERT);//измеряем температуру
_delay_ms(100);//9 битный режим преобразования — 100ms
Так как для вывода целой части температуры, нам достаточно 8 бит, то самый младший бит у нас не используется. Можно его использовать. То есть, если данный бит установлен в 0, то это даёт нам право после запятой поставить 0, а если 1 — то 5. Таким образом мы полностью будем использовать точность микросхемы 0,5. Поэтому данный бит будем использовать и не будем отсекать его в функции converttemp
char converttemp (unsigned int tt)
{
char t =tt>>3;//сдвиг — целую часть получим сдвинутую 1 байт влево, а дробную в самом младшем байте
А потом мы с данной функцией разберёмся. Это ничто иное, как температура с точностью до 0,5, умноженная на 2. Правда у нас ещё отсечется самый старший бит, но он у нас отвечает уже за температуры, которые более 128, у нас необходимости такие температуры измерять нет, поэтому ничего страшного.
Теперь вернёмся в бесконечный цикл функции main() и поработаем там над выводом показаний температуры.
Мы показания сдвинем ещё на 1 бит, чтобы отсечь доли и умножим всё это на 10, чтобы у нас остался разряд справа для показания десятых долей. Потом мы к данному результату прибавим остаток от деления на 2 несдвинутой величины, умноженный на 5 и это у нас покажется в последнем разряде
ledprint((tt>>1)*10+((tt%2)*5));
Соберём проект, прошьём контроллер и посмотрим, что у нас получилось с температурой
Теперь всё правильно. Температура у нас 22,5 градуса. На двоеточие и остутствие разделителя целой и дробной части пока внимание не обращаем, потом мы с этим разберёмся.
Будем считать, что с температурой мы разобрались.
Теперь нам нужно будет все наши считанные данные нормально показать и этим мы сейчас и займёмся.
Поэтому нам нужно придумать какие-нибудь режимы для показа значений и создать для них макросы в главном модуле
#include «main.h»
//—————————————-
#define MODETIMEVIEW 100
#define MODETEMPERVIEW 101
#define MODEDATEVIEW 102
#define MODEDAYVIEW 103
//———————————————
Я думаю, что наименование каждого режима говорит само о себе и в комментариях не нуждается.
Теперь надо придумать, как нам использовать данные режимы. Нам нужно первым делом решить, когда и что мы будем отображать. Ну, я думаю, что время надо отображать почти всегда, на то они и часы. В 30 секунд каждой минуты отобразим температуры, ещё через 4 секунды день недели, и ещё через 4 секунды покажем дату, а потом опять будем показывать время.
Во-первых, создадим для этого переменную, можно даже локальную в main() и сразу проинициализируем её обычным режимом отображения времени
unsigned int tt=0; //переменная для хранения температуры
unsigned char clockmode=MODETIMEVIEW;//обычный режим показаний дисплея
Теперь создадим условия, зависящие от показаний секунд в бесконечном цикле
date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат
if ((sec<30)||(sec>41)) clockmode=MODETIMEVIEW;
else if (sec<34) clockmode=MODETEMPERVIEW;
else if (sec<38) clockmode=MODEDAYVIEW;
else clockmode=MODEDATEVIEW;
Ну вот. Предположим, что режимы у нас вовремя меняются. Теперь надо как-то нашему индикатору на всё это реагировать.
Напишем ещё условия и реакции на них
tt = converttemp(dt_check());
if(clockmode==MODETIMEVIEW) ledprint(hour*100+min);
if(clockmode==MODETEMPERVIEW) ledprint((tt>>1)*10+((tt%2)*5));
if(clockmode==MODEDAYVIEW) ledprint(day*10);
if(clockmode==MODEDATEVIEW) ledprint(month + date*100);
Всё остальное с ledprint, что было до этого написано в бесконечном цикле удалим.
Пока здесь всё будет происходить коряво и с мигающим двоеточием. Потом нам надо будет погасить ненужные цифры, день недели мы сдвинули к десяткам для того чтобы справа и слева показать чёрточки.
Ну, давайте хотя бы так посмотрим. Соберём для этого проект и прошьём контроллер
Пока вот так. У нас время 18:12, 23 градуса, 4 день недели или четверг и 17 марта.
Согласитесь, уже неплохо! У нас меняются режимы отображения. Но смотреть так неудобно с постоянно мигающим двоеточием. кучей нулей вокруг. А вот этим вопросом мы займёмся в следующей части нашего урока.
Предыдущая часть Программирование МК AVR Следующая часть
Программатор, модуль RTC DS1307 с микросхемой памяти и индикатор можно приобрести здесь:
Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером
Модуль RTC DS1307 с микросхемой памяти
Семисегментный чертырехразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Все бы хорошо, но при работе с датчиком по 1-Wire мы надолго отключаем прерывания, из-за чего сного чего идет прахом… Та же индикация динамическая. Как вы это обошли то? Уже на этапе протеуса видно проблемы — после считывания температуры перестает работать получение по прерываниям ADC
Увеличение картинок не работает. Поправьте пожалуйста!
Видимо, что-то с оригиналами.