AVR Урок 19. Собираем часы на микросхеме DS1307 и LCD 1602



Урок 19

Собираем часы на микросхеме DS1307 и LCD 1602

 

Сегодня, набравшись уже опыта по программирования шины I2С, а также изучив микросхему реального времени DS1307, мы сможем приступить к программированию простейших часов и выводить их показания уже не в компьютер, а в жидкокристаллический дисплей. Я думаю, это будет намного наглядней и красивее, чем просматривать это в терминальной программе на ПК.

С дисплеем 16х2 мы работать также умеем, поэтому мы практически в данном занятии соединим два прошлых занятия, а также лишний раз повторим пройденный материал.

Будем считать, что модуль с микросхемой у нас уже присоединён к отладочной плате с контроллером Atmega8A, Присоединим к ней также модуль дисплея. Вот упрощённая схема из протеуса (нажмите на картинку для увеличения изображения)

image00_0500

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

А вот так всё будет выглядеть на деле (нажмите на картинку для увеличения изображения)

image01_0500

Дисплей подключен у нас будет подключин также в 4-битном режиме и к тем же ножкам портов, как и в уроке 12.

Проект был создан с именем MyClock1307LCD. Все файлы, кроме главного скопированы туда и впоследствии подключены из проекта урока 17 MyClock1307.

Также к проекту подключены файлы для работы с дисплеем lcd.c и lcd.h. из проекта Test12, где мы работали с шиной USART.

Перейдём в главный модуль MyClock1307LCD.c. Код у нас здесь пока стандартный

#include «main.h»

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

int main(void)

{

  while(1)

  {

  }

}

Зайдём в файл lcd.c и исправим там функцию sendchar в sencharlcd во избежания совпадения имен с другими модулями

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

void sendcharlcd(unsigned char c)

Также добавим для неё прототип и ещё прототип для функции очистки дисплея в файл lcd.h

void str_lcd (char str1[]);

void clearlcd(void);

void sendcharlcd(unsigned char c);

Теперь можно начать писать код в главном модуле. Причём почти весь его можно скопировать с предыдущих проектов.

Функцию инициализации порта возьмём из урока по дисплею

#include «main.h»

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

void port_ini(void)

{

PORTD=0x00;

DDRD=0xFF;

}

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

 

 

Оттуда же возьмём в main() код инициализации порта и дисплея, а заодно его сразу и очистим

int main(void)

{

  port_ini(); //Инициализируем порты

  LCD_ini(); //Инициализируем дисплей

  clearlcd(); //Очистим дисплей

Из главного модуля проекта из урока по часовой микросхемы возьмём инициализацию I2C

port_ini(); //Инициализируем порты

I2C_Init(); //Инициализируем шину I2C

LCD_ini(); //Инициализируем дисплей

Оттуда же возьмём глобальные переменные для хранения показаний регистров

#include «main.h»

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

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

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

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

clearlcd(); //Очистим дисплей

//Устанавливаем время

// I2C_StartCondition();

// I2C_SendByte(0b11010000);

// I2C_SendByte(0);//Переходим на 0x00

// I2C_SendByte(RTC_ConvertFromBinDec(0)); //секунды

// I2C_SendByte(RTC_ConvertFromBinDec(31)); //минуты

// I2C_SendByte(RTC_ConvertFromBinDec(20)); //часы

// I2C_SendByte(RTC_ConvertFromBinDec(5)); //день недели

// I2C_SendByte(RTC_ConvertFromBinDec(29)); //дата

// I2C_SendByte(RTC_ConvertFromBinDec(1)); //месяц

// I2C_SendByte(RTC_ConvertFromBinDec(16)); //год

// I2C_StopCondition();

while(1)

 

 

Также возьмём пока всё полностью и из бесконечного цикла

while(1)

while(1)

{

  //Читаем время

  I2C_SendByteByADDR(0,0b11010000); //переходим на адрес 0

  _delay_ms(300);

  I2C_StartCondition(); //Отправим условие START

  I2C_SendByte(0b11010001); //отправим в устройство бит чтения

  sec = I2C_ReadByte();

  min = I2C_ReadByte();

  hour = I2C_ReadByte();

  day = I2C_ReadByte();

  date = I2C_ReadByte();

  month = I2C_ReadByte();

  year = I2C_ReadLastByte();

  I2C_StopCondition(); //Отправим условие STOP

  sec = RTC_ConvertFromDec(sec); //Преобразуем в десятичный формат

  min = RTC_ConvertFromDec(min); //Преобразуем в десятичный формат

  hour = RTC_ConvertFromDec(hour); //Преобразуем в десятичный формат

  day = RTC_ConvertFromDec(day); //Преобразуем в десятичный формат

  year = RTC_ConvertFromDec(year); //Преобразуем в десятичный формат

  month = RTC_ConvertFromDec(month); //Преобразуем в десятичный формат

  date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

  USART_Transmit(date/10+0x30);//Преобразуем число в код числа

  USART_Transmit(date%10+0x30);//Преобразуем число в код числа

  USART_Transmit('.');

  USART_Transmit(month/10+0x30);//Преобразуем число в код числа

  USART_Transmit(month%10+0x30);//Преобразуем число в код числа

  USART_Transmit('.');

  USART_Transmit(year/10+0x30);//Преобразуем число в код числа

  USART_Transmit(year%10+0x30);//Преобразуем число в код числа

  USART_Transmit(' ');

  USART_Transmit('-');

  USART_Transmit(day+0x30);//Преобразуем число в код числа

  USART_Transmit('-');

  USART_Transmit(' ');

  USART_Transmit(' ');

  USART_Transmit(hour/10+0x30);//Преобразуем число в код числа

  USART_Transmit(hour%10+0x30);//Преобразуем число в код числа

  USART_Transmit(':');

  USART_Transmit(min/10+0x30);//Преобразуем число в код числа

  USART_Transmit(min%10+0x30);//Преобразуем число в код числа

  USART_Transmit(':');

  USART_Transmit(sec/10+0x30);//Преобразуем число в код числа

  USART_Transmit(sec%10+0x30);//Преобразуем число в код числа

  USART_Transmit(0x0d);//переход в начало строки

  USART_Transmit(0x0a);//перевод каретки

}

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

date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

setpos(0,0); //Ставим курсор на начало координат

Заменим в коде USART_Transmit на sendcharlcd пока там, где работаем с датой ,не со временем, а также перед показаниями года добавим «20», чтобы год смотрелся посолидней

setpos(0,0); //Ставим курсор на начало координат

sendcharlcd(date/10+0x30);//Преобразуем число в код числа

sendcharlcd(date%10+0x30);//Преобразуем число в код числа

sendcharlcd('.');

sendcharlcd(month/10+0x30);//Преобразуем число в код числа

sendcharlcd(month%10+0x30);//Преобразуем число в код числа

sendcharlcd('.');

sendcharlcd('2');

sendcharlcd('0');

sendcharlcd(year/10+0x30);//Преобразуем число в код числа

sendcharlcd(year%10+0x30);//Преобразуем число в код числа

sendcharlcd(' ');

sendcharlcd('-');

sendcharlcd(day+0x30);//Преобразуем число в код числа

sendcharlcd('-');

Так как мы с показаниями времени не влезем на 1 строку, поэтому переведём перед этим строку, а затем также исправим везде вызов функции на sendcharlcd, также уберём перевод строки и возврат каретки.

setpos(0,1); //Ставим курсор на начало координат

sendcharlcd(hour/10+0x30);//Преобразуем число в код числа

sendcharlcd(hour%10+0x30);//Преобразуем число в код числа

sendcharlcd(':');

sendcharlcd(min/10+0x30);//Преобразуем число в код числа

sendcharlcd(min%10+0x30);//Преобразуем число в код числа

sendcharlcd(':');

sendcharlcd(sec/10+0x30);//Преобразуем число в код числа

sendcharlcd(sec%10+0x30);//Преобразуем число в код числа

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

Наши часы отлично ходят!

image02

 

 

Предыдущий урок Программирование МК AVR Следующий урок

Исходный код

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

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

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

Дисплей LCD 16×2

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

AVR Собираем часы на микросхеме DS1307 и LCD 1602

4 комментария на “AVR Урок 19. Собираем часы на микросхеме DS1307 и LCD 1602
  1. Віктор С:

    Привіт. Зараз багато хто використовує ds3231. Ви з нею працювали? Не хотіли би зробити урок для AVR по цій мікросхемі? Дякую.

    • W4d1m:

      Так а там, по-моему, всё также как и у ds1307. В уроке по DS3231 в разделе STM32 это видно. Пробовал под STM32F407. У себя на макетке менял местами DS3231 и DS1307 — всё работало!

  2. Sergio:

    Вы так много дали, что я нашел скучным использовать параллельный интерфейс для вывода даты и времени на LCD. Сразу все зарядил через TWI. Единственное что нашел неудобным — день недели — цифрой. У некоторых неделя начинается с Воскресенья. Вывел сокращения функцией send_string. Все работает! Спасибо!!!

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

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

*