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

 

 

 

 

Урок 23

Часть 11

 

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

 

 

В прошлой части урока мы научили кнопку переводить все оставшиеся показатели регистров микросхемы DS1307 кроме показаний будильника.

Ну. в принципе, показания и настройки будильника у нас и не хранятся в регистрах данной микросхемы, а хранить мы их будем во внутренней энергонезависимой памяти EEPROM нашего контроллера.

Подключаем файлы eeprom.h и eeprom.c из старого проекта test014 урока по программированию внутренней памяти EEPROM для энергонезависимого хранения данных будильника и флага включенного или отключенного будильника. Соответственно подключаем ее в main.h

 

#include "button.h"

#include "eeprom.h"

 

Значения мы будем хранить в 1, 2 и 3 ячейках памяти EEPROM.

Почему три, а не две? Во 2 и 3 ячейках будет время, а в первой — режим. Если ноль — будильник отключен, а если один — включен.

Теперь в main() проверим наш EEPROM на предмет того, что мы его включили не первый раз и унас там наши показатели валидны.

Подробнее всё рассказано в комментариях

 

button_cnt = 0; //измеритель времени нажатия кнопки

if(EEPROM_read(1)>1) EEPROM_write(1,0); //если в ячейке число более 1 (либо ни разу не использовалось,

//либо какие то странные значения, либо использовалось в других целях), то установим туда 0

I2C_Init();

 

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

Также нам нужно добавить переменную задействования будильника, можно в main.h

 

unsigned int button_cnt;

unsigned char clockeditmode,clockincmode,alarmmode;

 

В этой переменной будет флаг задействования будильника. Занесём в него значение из 1 ячейки памяти EEPROM

 

//либо какие то странные значения, либо использовалось в других целях), то установим туда 0

alarmmode = EEPROM_read(1); //считаем флаг задействования будильника из памяти EEPROM

 

В качестве индикатора, который нам будет проверять работу будильника, мы сегодня пока подключим светодиод через токоограничивающий резистор от ножки PC1 контроллера

 

image44

 

image45

 

Также проверим остальные 2 ячейки памяти EEPROM на валидность, если там что-то не то, то занесём туда первоначальные значения часов и минут будильника

 

alarmmode = EEPROM_read(1); //считаем флаг задействования будильника из памяти EEPROM

if(EEPROM_read(2)>23) EEPROM_write(2,0); //если в ячейке число более 23 (либо ни разу не использовалось,

//либо какие то странные значения, либо использовалось в других целях), то установим туда 0

if(EEPROM_read(3)>59) EEPROM_write(3,0); //если в ячейке число более 59 (либо ни разу не использовалось,

//либо какие то странные значения, либо использовалось в других целях), то установим туда 0

I2C_Init();

 

В главном модуле добавим переменные для часов и минут будильника

 

unsigned char sec,min,hour,day,date,month,year,alarmhour,alarmmin;

 

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

 

tt = converttemp(dt_check());

//считаем показания будильника

alarmhour = EEPROM_read(2);

alarmmin = EEPROM_read(3);

if((alarmmin==min)&&(alarmhour==hour)&&(clockeditmode==MODENONEEDIT))

 

В функцию отображения результатов редактирования будильника тоже внесем изменение, так как там у нас в качестве заглушки отображается ноль

 

else if ((clockeditmode==MODEALARMMINEDIT)||(clockeditmode==MODEALARMHOUREDIT))

{

  ledprint(alarmhour*100+alarmmin,MODETIMEVIEW);

}

 

Можно здесь собрать код, прошить контроллер и проверить, отображаются ли показания будильника в режиме его редактирования, редактироваться они само собой пока не могут.

 

 

Если всё у нас работает, то мы и добавим возможность редактирования будильника в функции ModifyRTC

 

case MODEALARMHOUREDIT: // часы будильника

  if(alarmhour<23) EEPROM_write(2,alarmhour+1);

  else EEPROM_write(2,0);

break;

case MODEALARMMINEDIT: // минуты будильника

  if(alarmmin<59) EEPROM_write(3,alarmmin+1);

  else EEPROM_write(3,0);

break;

 

Я думаю, тут всё просто и комментариев не нужно.

Теперь проверим, как у нас редактируется будильник, собрав код и прошив контроллер

 

7image46 image47

 

Теперь займёмся работой будильника в момент совпадения значений будильника со значением текущего времени. Для этого добавим ещё одну переменную в main.h

 

unsigned char clockeditmode,clockincmode,alarmmode,alarmcmp;

 

Проинициализируем ее в main()

 

clockincmode=MODENOINC;

alarmcmp=0;

 

Ну и теперь проверим совпадение значений будильника со значением реального времени и при совпадении включим флаг, также в этом условии мы проверим, что мы в данный момент не занимаемся редактированием, чтобы в момент редактирования у нас будильник не пищал. Я думаю, это логично, будильник нужен, чтобы проснуться, и когда мы спим, мы точно не занимаемся редактированием показателей

 

alarmmin = EEPROM_read(3);

if((alarmmin==min)&&(alarmhour==hour)&&(clockeditmode==MODENONEEDIT)) alarmcmp=1;

 

В функции port_ini() инициализируем лапку порта для самого будильника

 

PORTC &= ~(1<<PORTC3);

DDRC |= (1<<DDRC1); // ножку PORTC1 на выход

PORTC |= (1<<PORTC1); //логическая 1

 

Также добавим функцию в главный модуль, которая будет вызываться при активном состоянии будильника, то есть когда будильник должен будет уже пищать

 

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

void alarm(void)

{

  PORTC |= (1<<PORTC1); //логическая 1

}

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

 

Пока у нас, конечно, ничего пищать не будет, будет только загораться светодиод, ну да ничего, ещё запищит.

Вызовем её в самом конце бесконечного цикла при необходимости

 

  else if ((clockeditmode==MODEALARMMINEDIT)||(clockeditmode==MODEALARMHOUREDIT))

  {

    ledprint(alarmhour*100+alarmmin,MODETIMEVIEW);

  }

  if(alarmcmp==1) alarm();

  else PORTC&=~(1<<PORTC1);

}

 

Как мы видим, мы заодно тут и сбросим пищалку, если мы в обычном режиме.

Также нам необходимо где-то сбрасывать alarmcmp, скорей всего вот тут, где мы её и установили, то есть мы её будем сбрасывать при несовпадении показателей. Поэтому подправим данное место в бесконечном цикле

 

if((alarmmin==min)&&(alarmhour==hour)&&(clockeditmode==MODENONEEDIT)) alarmcmp=1;

else alarmcmp=0;

 

То есть, будильник у нас будет звенеть или пищать практически ровно минуту, так как если начнётся следующая минута, у нас уже соответственно совпадения не будет.

Проверим работу нашего кода

 

image48

 

Будильник нормально срабатывает.

Через минуту светодиод светиться перстаёт

 

image49

 

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

 

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

 

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

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

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

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

 

 

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

 

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

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

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

*