Урок 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);
Будем считать, что наша микосхема в модуле «ходит» уже с прошлых занятий, поэтому установку мы не делаем и код для неё не переносим, он все равно будет совершенно другим.
Соберём код и прошьём контроллер. Заодно посмотрим и практическую схему подключения
Это у нас не год, а именно время 20:07. Двоеточие мы пока не заводили, поэтому время отображается именно так и это уже неплохо. Но тем не менее нужно, чтобы что-то мигало, для этого мы должны на 3 ножку индикатора что-то подать. Я подумал, и взял для этого сигнал с ножки микросхемы RTC, специально предназначенной для этого. Мы не будем смотреть документацию, всё это мы уже давно изучили. Данный снятый сигнал мы подадим на ножку контроллера PC3, объявим её на вход и будем отслеживать, а с помощью полученного результата на данной ножке будем управлять уже 3 ножкой индикатора определённым образом.
А вот и схема подключения, которая у нас актуальна на данный момент (нажмите на картинку для увеличения изображения)
Здесь мы видим, куда именно идёт сигнал с ножки SQ микросхемы. А на двоеточие сигнал идёт уже с ножки контроллера PD7 через токоограничивающий резистор, которая у нас и осталась свободна.
Теперь начнем писать код для управление двоеточием. Ну у кого-то это может быть точка.
Теперь код. Во-первых убедимся, что она у нас инициализирована на выход, заодно в предыдущей строке добавим комментарий
DDRB = 0b00011111;//3 ножки оставляем на вход для кнопок
PORTD = 0b11111111;
Теперь надо ещё решить вопрос по PC3
PORTD = 0b11111111;
DDRC &= ~(1<<DDRC3);
PORTC &= ~(1<<PORTC3);
Вот так мы и поступим. Мы включим ножку на вход и отключим подтягивающий резистор, который у нас уже присутствует на плате модуля с микросхемой DS1307.
Теперь нам надо ещё в микросхеме данные импульсы включить в регистре, специально для этого предназначенном
Бит SQWE, отвечающий за включение генерации квадратных импульсов, мы должны включить, а биты RS1 и RS0 — сбросить, так как нам нужен 1 Гц
А от бита 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 встаёт в высокий уровень, а так как у нас тут нет никаких задержек, то она тут же отключится, а если наше условие не подтвердится, то просто не отключится.
Соберём код, прошьём контроллер и проверим, работает ли у нас наша задумка
Всё у нас работает. Отлично!
В следующей части мы продолжим дальше работать с кодом. Мы ещё не видим отображения остальных параметров — даты, дня недели, также у нас ничего не редактируется, так что работы ещё с часами непочатый край.
Предыдущая часть Программирование МК AVR Следующая часть
Программатор, модуль RTC DS1307 с микросхемой памяти и индикатор можно приобрести здесь:
Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером
Модуль RTC DS1307 с микросхемой памяти
Семисегментный чертырехразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Здравствуйте у меня возникает ошибка в ходе компиляции кода в этой строчке DDRC &= ~(1<<DDRC3); 'DDRC3' undeclared (first use in this function).
Здравствуйте!
Что-то не подключили.
вместо DDRC3 просто напиши 3
Можно как нибудь по другому записать? Вроде все правильно.