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



 

Урок 23

Часть 3

 

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

 

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

Чтобы не нагромождать всё в главный модуль, я убрал все функции по управлению индикацией и оформил их в библиотеку, состояшую из стандартной пары файлов led.c и led.h.

Содержание файла led.h со всеми нужными нам прототипами

 

#ifndef LED_H_

#define LED_H_

#include «main.h»

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

void ledprint(unsigned int number, unsigned char cm);

void timer_ini(void);

#endif /* LED_H_ */

 

Также подключим данный файл в main.h

 

#include «PWM.h»

#include «led.h»

 

На данный момент в файле главного модуля у нас только одна функция main().

Код у нас нормально собирается, это уже хорошо.

Теперь займёмся наконец-то нашей часовой микросхемой. Для этого были с прошлого проекта по данной микросхеме подключены файлы twi.h, twi.c, RTC.h и RTC.c. Также подключены они и в файле main.h

 

#include «PWM.h»

#include «twi.h»

#include «RTC.h»

#include «led.h»

 

Уберем переменную для статуса ШИМ из main(), добавим инициализацию шины I2C

 

int main(void)

{

  I2C_Init();

 

Яркость дисплея поставим пока среднюю

 

init_PWM_timer();

OCR2=150;

 

 

Из бесконечного цикла также уберём всё лишнее

 

while(1)

{

  ledprint(OCR2);

  _delay_ms(50);

}

 

Положим сюда считывание времени из того же проекта

 

while(1)

{

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

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

  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); //Преобразуем в десятичный формат

 

Чтобы этот код работал, нам нужно будет перенести и глобальные переменные

 

#include «main.h»

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

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

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

 

 

Также в бесконечном цикле добавим отображение нашего времени вместо отображения значения OCR2

 

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

ledprint(hour*100+min);

 

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

Соберём код и прошьём контроллер. Заодно посмотрим и практическую схему подключения

 

image15

 

Это у нас не год, а именно время 20:07. Двоеточие мы пока не заводили, поэтому время отображается именно так и это уже неплохо. Но тем не менее нужно, чтобы что-то мигало, для этого мы должны на 3 ножку индикатора что-то подать. Я подумал, и взял для этого сигнал с ножки микросхемы RTC, специально предназначенной для этого. Мы не будем смотреть документацию, всё это мы уже давно изучили. Данный снятый сигнал мы подадим на ножку контроллера PC3, объявим её на вход и будем отслеживать, а с помощью полученного результата на данной ножке будем управлять уже 3 ножкой индикатора определённым образом.

А вот и схема подключения, которая у нас актуальна на данный момент (нажмите на картинку для увеличения изображения)

 

image16_500

 

Здесь мы видим, куда именно идёт сигнал с ножки SQ микросхемы. А на двоеточие сигнал идёт уже с ножки контроллера PD7 через токоограничивающий резистор, которая у нас и осталась свободна.

Теперь начнем писать код для управление двоеточием. Ну у кого-то это может быть точка.

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

 

DDRB = 0b00011111;//3 ножки оставляем на вход для кнопок

PORTD = 0b11111111;

 

Теперь надо ещё решить вопрос по PC3

 

PORTD = 0b11111111;

DDRC &= ~(1<<DDRC3);

PORTC &= ~(1<<PORTC3);

 

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

Теперь нам надо ещё в микросхеме данные импульсы включить в регистре, специально для этого предназначенном

 

image17

 

Бит SQWE, отвечающий за включение генерации квадратных импульсов, мы должны включить, а биты RS1 и RS0 — сбросить, так как нам нужен 1 Гц

 

image18

 

А от бита OUT у нас ничего зависеть не будет, так как он просто инвертирует импульсы.

Я попробовал именно так включить биты в регистре, у меня почему-то ничего не пошло и методом научного тыка было вычисленно, что работать всё будет только вот таким образом

 

sei();

I2C_StartCondition();

I2C_SendByte(0b11010000);

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

I2C_SendByte(0b00010010); //включим SQWE

I2C_StopCondition();

while(1)

 

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

Включить-то мы включили, теперь как-то надо всё это будет отследить. А отследим мы это в файле led.c в обработчике прерываний от таймера в обработке 3 разряда индикатора

 

if(n_count==2)

{

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

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

}

 

Здесь мы при условии низкого уровня на PC3 подаём низкий уровень на ножку D7. Она у нас сначала в вызове функции segchar встаёт в высокий уровень, а так как у нас тут нет никаких задержек, то она тут же отключится, а если наше условие не подтвердится, то просто не отключится.

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

 

image19

 

Всё у нас работает. Отлично!

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

 

 

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

 

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

Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером

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

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

 

 

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

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

 

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

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

4 комментария на “AVR Урок 23. Собираем часы на DS1307 и LED индикаторе. Часть 3
  1. Анатолий:

    Здравствуйте у меня возникает ошибка в ходе компиляции кода в этой строчке DDRC &= ~(1<<DDRC3); 'DDRC3' undeclared (first use in this function).

  2. Анатолий:

    Можно как нибудь по другому записать? Вроде все правильно.

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

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

*