AVR Урок 23. Собираем часы на DS1307 и LED индикаторе. Часть 6

 

 

 

 

Урок 23

Часть 6

 

Собираем часы на DS1307 и LED индикаторе

 

 

В прошлой части нашего занятия мы подключли к нашей схеме также датчика температуры 18B20, а также научились отображать показания не только времени, но и даты, дня недели, а также температуры. Причем отображаем мы это в определённое время и в определенном порядке.

Хотя выглядит это пока не так красиво, но уже круто!

А красотой займёмся уже в этой части занятия.

Занятия красотой в основном у нас будут происходить в файле led.c и, чтобы нам в данном файле знать, в каком именно мы режиме находимся в данный момент, способов существует очень много. Мы знаем способ видимости глобальной переменной, но это не всегда хорошо и лишает библиотеку автономности. Есть ещё один способ, тоже достаточно распространенный — передача параметра в качестве входного аргумента в функции. Вот его мы и будем использовать.

Поэтому исправим немного входные параметры функции ledprint

 

void ledprint(unsigned int number, unsigned char cm)

{

 

То же самое надо проделать и с прототипом.

 Ещё объявим переменную в файле led.c наверху такую же как и в главном модуле для режимов, а также скопируем туда все дефайны этих режимов

 

#include "led.h"

//———————————————

#define MODETIMEVIEW 100

#define MODETEMPERVIEW 101

#define MODEDATEVIEW 102

#define MODEDAYVIEW 103

//———————————————

unsigned char R1=0, R2=0, R3=0, R4=0;

unsigned char clockmode;

 

Считаем значение переменной в функции ledprint

 

void ledprint(unsigned int number, unsigned char cm)

{

  clockmode=cm;

 

Также в бесконечном цикле в функции main() нам будет необходимо в качестве параметра передать определённое значение режима, для этого мы исправим наши вызовы функции ledprint

 

if(clockmode==MODETIMEVIEW) ledprint(hour*100+min,MODETIMEVIEW);

if(clockmode==MODETEMPERVIEW) ledprint((tt>>1)*10+((tt%2)*5),MODETEMPERVIEW);

if(clockmode==MODEDAYVIEW) ledprint(day*10,MODEDAYVIEW);

if(clockmode==MODEDATEVIEW) ledprint(month + date*100,MODEDATEVIEW);

 

Для задуманной нами красоты отображения показаний нам уже символов цифр в функции segchar нам будет недостаточно, поэтому добавим туда ещё три

 

  case 0: PORTD = 0b11000000; break;

  case 10: PORTD = 0b10111111; break; // знак —

  case 11: PORTD = 0b11111111; break; // пустое место

  case 12: PORTD = 0b11000110; break; // буква С для показаний температуры

}

 

И теперь начнём колдовать с кодом в функции-обработчике таймера.

Сначала попробуем обеспечить мигание двоеточие только во время показа времени. Для этого мы к условию по логическому "И" добавим ещё одно. То есть будем следить, что у нас не только импульс пришёл, а что ещё и режим отображения времени

 

if ((!(PINC&0b00001000))&&(clockmode==MODETIMEVIEW)) PORTD&=~(1<<PORTD7);

 

Соберём код, прошьём контроллер и увидим, что двоеточие у нас в дополнительных режимах не мигает и вообще не светится.

Колдуем с двоеточием дальше. Нам теперь нужно, чтобы когда у нас отображалась дата, двоеточие горело постоянно, так как во втором разряде у нас нет точки, лучше бы конечно она бы была. Но раз её нет, то нам все равно надо как-то сделать различие между временем и датой. Поэтому когда будет дата, то двоеточие будет постоянно светиться.

Здесь нам поможет логический оператор "ИЛИ". Мы его применим во второй половине условия, чтобы иногда двоеточие светилось независимо от присутствия сигнала на PC2

 

if (((!(PINC&0b00001000))&&(clockmode==MODETIMEVIEW))||(clockmode==MODEDATEVIEW)) PORTD&=~(1<<PORTD7);

 

Вот такое вот многофункциональное условие. Но это ещё не самое трудное.

 

 

Теперь нам нужно придумать такой код, чтобы когда мы показываем температуру, у нас между целыми показаниями и дробными появилась точка. Для этого мы не будем повторно смотреть схему. Точка работает у индикатора также по 3 ножке, но только она работает с другим анодом. В соответствующее место мы и напишем отслеживание режима температуры и попытаемся данную точку зажечь

 

if(n_count==1)

{

  PORTB&=~(1<<PORTB1);PORTB|=(1<<PORTB0)|(1<<PORTB2)|(1<<PORTB4);segchar(R2);

  if (clockmode==MODETEMPERVIEW) PORTD&=~(1<<PORTD7);

}

 

Здесь тоже, в принципе не очень тяжело. Все трудности у нас впереди. Но не пугайтесь, всё мы решим.

Соберём код, прошьём контроллер и увидим, что во время отображения температуры у нас светится точка, разделяя целое и доли

 

image32

 

Ну вот. Всё как надо.

Теперь по нашей задумке во время отображения дня недели вместо двух нулей, находящихся слева и справа от показателя дня недели мы покажем минусы или чёрточки. Тут нам придется поработать уже с двумя разрядами. Начнем с самого правого разряда

 

if(n_count==0)

{

  PORTB&=~(1<<PORTB0);PORTB|=(1<<PORTB1)|(1<<PORTB2)|(1<<PORTB4);

  if (clockmode==MODEDAYVIEW) segchar(10); // знак —

  else segchar(R1);

}

 

Вот так вот это и делается. В случае режима показа даты мы покажем знак "-", а в остальных. то что и показывали.

И то же самое мы проделаем с третьим анодом, только здесь будет посложней ибо у нас тут уже куча условий. Но мы всё проделаем до них

 

if(n_count==2)

{

  PORTB&=~(1<<PORTB2);PORTB|=(1<<PORTB0)|(1<<PORTB1)|(1<<PORTB4);

  if (clockmode==MODEDAYVIEW) segchar(10); // знак —

  else segchar(R3);

  if (((!(PINC&0b00001000))&&(clockmode==MODETIMEVIEW))||(clockmode==MODEDATEVIEW)) PORTD&=~(1<<PORTD7);

 

Соберём код, прошьём контроллер и проверим работу нашего кода

 

image33

 

Как мы видим, код работает правильно. Это хорошо.

Но нам мешает ноль слева. Его надо убрать, а то непорядок.

Тогда мы работаем уже с четвертым анодом. Заодно и букву "C" изобразим в случае показаний температуры

 

if(n_count==3)

{

  PORTB&=~(1<<PORTB4);PORTB|=(1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);

  if (clockmode==MODETEMPERVIEW) segchar(12); // буква С

  else if (clockmode==MODEDAYVIEW) segchar(11); // пустое место

  else segchar(R4);

}

 

Конечно, лучше бы буква "C" была бы в конце, но здесь проблема из-за отсутсвия точки между 2 и 3 разрядами, ну и так нормально.

Проверим наш код, собрав его и прошив контроллер

 

image34 image35

 

Всё у нас правильно. Но у нас ещё много есть нерешённого. Мы ещё не переводим показания, поэтому в следующей части занятия мы продолжим заниматься нашим кодом, совершенствуя наши часы, а также, что в разы главнее всех часов, совершенствовать наши навыки в программировании.

 

Предыдущая часть Программирование МК AVR Следующая часть

 

Программатор, модуль RTC DS1307 с микросхемой памяти и индикатор можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Модуль RTC DS1307 с микросхемой памяти

Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

AVR Собираем часы на DS1307 и LED индикаторе

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

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

*