AVR Урок 21. Управление DS1307 кнопками. Часть 3



 

Урок 21

Часть 3

 

Управление DS1307 кнопками

 

Продолжаем нашу работу над кнопками.

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

Поэтому нам нужно опросить на нажатие другие кнопки.

Ищем в коде в бесконечном цикле, участок, в который мы попадаем в случае выбора режима перевода даты и в конце данного участка добавим следующие строки

 

if (clockmode==CLOCKMODEDATE) button1state=0;//сбросим статус

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

 

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

 

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

 

//—————————————-

void ModifyRTC(char index, char direction)

{

}

//—————————————-

 

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

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

 

void ModifyRTC(char index, char direction)

{

  I2C_StartCondition();

  I2C_SendByte(0b11010000);

  I2C_StopCondition();

}

 

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

 

  if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

      ModifyRTC(1,0);//1-дата,0-назад

  if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

      ModifyRTC(1,1);//1-дата,1-вперед

}

 

Как видно из кода, мы задаём, какой имено показатель мы редактируем и в каком направлении.

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

 

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(2,0);//2-месяц,0-назад

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(2,1);//2-месяц,1-вперед

.  .  .  .  .  .  .  .

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(3,0);//3-год,0-назад

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(3,1);//3-год,1-вперед

.  .  .  .  .  .  .  .

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(4,0);//4-день недели,0-назад

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(4,1);//4-день недели,1-вперед

.  .  .  .  .  .  .  .

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(5,0);//5-часы,0-назад

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(5,1);//5-часы,1-вперед

.  .  .  .  .  .  .  .

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(6,0);//6-минуты,0-назад

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(6,1);//6-минуты,1-вперед

.  .  .  .  .  .  .  .

if(!(BUTTONPIN&(1<<BUTTONPIN2)//Кнопка 2 нажата

ModifyRTC(7,0);//7-секунды,0-установка 30

if(!(BUTTONPIN&(1<<BUTTONPIN3)//Кнопка 3 нажата

ModifyRTC(7,1);//7-секунды,1-установка 0

 

С секундами мы поступили следующим образом. Раз уж у нас две кнопки, то будем их использовать обе. Одна будет сбрасывать их на 0, а другая на 30 секунд.

 

 

Теперь можно продолжить начатую функцию модификации показаний. Добавим в нее отслеживание режимов с помощью оператора switch

 

I2C_SendByte(0b11010000);

switch(index){

  case 1: //число даты

    break;

  case 2: //месяц

    break;

  case 3: //год

    break;

  case 4: //день недели

    break;

  case 5: //часы

    break;

  case 6: //минуты

    break;

  case 7: //секунды

    break;

}

I2C_StopCondition();

 

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

 

case 1: //число даты

  I2C_SendByte(4);//Переходим на 0x04 — байт числа даты

 

Добавим далее отслеживание направление перевода даты

 

I2C_SendByte(4);//Переходим на 0x04 — байт числа даты

//вперед

if (direction==1)

{

}

//назад

if (direction==0)

{

}

break;

 

 

Пока поработаем с направлением «вперёд». Будет ещё условия, так как у нас существуют варианты различного количества дней в различных месяцах

 

if (direction==1)

{

  if (month==2) //февраль

  {

  }

  else if ((month==4)|(month==6)|(month==9)|(month==11))

  {

  }

  else

  {

  }

}

 

Вот такие варианты. У нас есть февраль, в котором дней будет или 28 или 29, есть ещё апрель, июнь, сентябрь и ноябрь, в которых 30 дней, и есть остальные месяцы, в которых дней у нас 31. С этим учётом мы и добавили условия.

Работаем с февралём. Тут прийдётся ещё отследить, високосный у нас год или обычный

 

if (month==2) //февраль

{

  if(year%4==0) //високосный год

  {

  }

  else

  {

  }

}

 

Здесь мы поступили оригинальным способом, используя остаток от деления величины года на 4, если делится, то год високосный, если нет — обычный.

Ну вот теперь уже конкретное изменение показаний. У нас февраль и год високосный

 

if(year%4==0) //високосный год

{

  if(date<29) I2C_SendByte(RTC_ConvertFromBinDec(date+1));

  else I2C_SendByte(RTC_ConvertFromBinDec(1));

}

 

Мы здесь инкрементируем показания до тех пор, пока не дойдём до 29, Если у нас уже 29, то мы дальше прибавлять не можем так как 30 февраля не бывает даже в високосном году, поэтому мы в этом случае установим 1 число месяца.

Теперь обработаем февраль невисокосного года подобным образом

 

else

{

  if(date<28) I2C_SendByte(RTC_ConvertFromBinDec(date+1));

  else I2C_SendByte(RTC_ConvertFromBinDec(1));

}

 

Здесь просто вместо 29 будет 28, так как в обычный год в феврале, как водится, 28 дней.

Теперь подобным образом обработаем месяцы, в которых 30 дней

 

else if ((month==4)|(month==6)|(month==9)|(month==11))

{

  if(date<30) I2C_SendByte(RTC_ConvertFromBinDec(date+1));

  else I2C_SendByte(RTC_ConvertFromBinDec(1));

}

 

Ну и, соответственно, остальные месяцы

 

else

{

  if(date<31) I2C_SendByte(RTC_ConvertFromBinDec(date+1));

  else I2C_SendByte(RTC_ConvertFromBinDec(1));

}

 

Здесь нам может показаться, что мы уже закончили с показаниями даты. Но не тут то было, у нас ещё перевод назад. Добавим туда также отслеживание вариантов месяцев

 

//назад

if (direction==0)

{

  if (month==2) //февраль

  {

    if(year%4==0) //високосный год

    {

    }

    else

    {

    }

  }

  else if ((month==4)|(month==6)|(month==9)|(month==11))

  {

  }

  else

  {

  }

}

break;

 

Обработаем високосный февраль

 

if(year%4==0) //високосный год

{

  if(date>1) I2C_SendByte(RTC_ConvertFromBinDec(date-1));

  else I2C_SendByte(RTC_ConvertFromBinDec(29));

}

 

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

Таким же образом обработаем невискокосный февраль и все остальные месяцы

 

    else

    {

      if(date>1) I2C_SendByte(RTC_ConvertFromBinDec(date-1));

      else I2C_SendByte(RTC_ConvertFromBinDec(28));

    }

  }

  else if ((month==4)|(month==6)|(month==9)|(month==11))

  {

    if(date>1) I2C_SendByte(RTC_ConvertFromBinDec(date-1));

    else I2C_SendByte(RTC_ConvertFromBinDec(30));

  }

  else

  {

    if(date>1) I2C_SendByte(RTC_ConvertFromBinDec(date-1));

    else I2C_SendByte(RTC_ConvertFromBinDec(31));

  }

 

Ну вот мы и закончили с алгоритмом изменения даты.

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

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

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

 

 

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

 

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

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

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

Дисплей LCD 16×2

 

 

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

 

AVR Управление DS1307 кнопками

Один комментарий на “AVR Урок 21. Управление DS1307 кнопками. Часть 3
  1. Игорь:

    запутавшись в начале решил далее урок не читать и попробовать придумать алгоритм самому и написать код. За главную идею был взят таймер1 с частотой прерываний 2 Гц. Прерывание таймера1 читает показания часов и выводит на экран. 2 Гц для того, чтобы можно было организовать моргание параметра(сек, мин, часы и т.д.), которого выбрали и изменяем. Бесконечный цикл лишь опрашивает нажатия трех кнопок. А уже в самих кнопках посредством оператора switch происходят выбор параметра и его коррекция. Так же на таймер1 организован таймаут, если моргает параметр а кнопки не нажимаются — моргание прекращается. ))) Это мой первый серьезный проект. Автору уроков ОГРОМАДНОЕ СПАСИБИЩЕ!!! Учусь по вашим урокам далее…

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

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

*