- Необходимые материалы:
- Предварительные условия:
- Принципиальная электрическая схема:
- Программирование будильника:
- Моделирование:
- Работа цифрового будильника с использованием PIC16F877A:
Цифровая революция, начавшаяся в 1950 году, превратила все существующие механические и аналоговые электронные структуры в цифровые компьютеры. Поскольку рост цифровой электроники был экспоненциальным, сегодня человеку практически невозможно устоять перед использованием любого электронного оборудования. Начиная от будильника, который будит вас, и тостера, который подает вам завтрак, все - это вклад цифровой электроники. Думая обо всем этом, действительно интересно программировать наши собственные вещи, которые могли бы выполнять простые, но полезные задачи, например, будильник, который мы собираемся построить в этом проекте с микроконтроллером PIC. Ранее мы создавали будильник с другими микроконтроллерами:
- Будильник Raspberry Pi с использованием модуля RTC DS1307
- Цифровые часы на базе Arduino с будильником
- Будильник на микроконтроллере ATmega32
Этот будильник будет иметь ЖК-дисплей 16x2, на котором будет отображаться текущее время и установленное время. Мы будем использовать несколько кнопок для установки времени будильника, когда это необходимо. Текущее время будет отслеживаться с помощью модуля DS3231 RTC, и мы будем использовать связь IIC для получения этих значений из модуля RTC. Мы уже узнали о модуле RTC и о том, как его взаимодействовать с PIC. Поэтому рекомендуется прочитать это руководство, мы пропустим большую часть информации, содержащейся в этом руководстве.
Необходимые материалы:
- Хлебная доска - 2Nos
- PIC16F877A
- Источник питания 5 В - Модуль питания
- Кристалл 20 МГц
- Конденсатор 33pf - 2Nos
- Модуль DS3231 RTC
- Модуль ЖК-дисплея 16 * 2
- 10K POT
- Резисторы 10 кОм и 1 кОм
- Кнопки - 5Nos
- Зуммер
- Соединительные провода
Предварительные условия:
Этот проект требует, чтобы вы знали немного основ о микроконтроллере PIC и о том, как его программировать. В этом проекте мы будем использовать GPIO, ЖК-дисплей и модуль RTC. Так что лучше заранее научиться пользоваться этими модулями. Следующие ссылки помогут вам узнать то же самое
- Написание вашей первой программы с помощью микроконтроллера PIC
- Сопряжение ЖК-дисплея с PIC
- Связь I2C с использованием PIC
- DS3231 RTC интерфейс с PIC
Принципиальная электрическая схема:
Принципиальная схема этого проекта будильника на основе PIC, созданного с помощью программного обеспечения Proteus, показана ниже. Они также будут использоваться для моделирования в дальнейшем в этом проекте.
Пять кнопок будут действовать как вход для установки будильника на необходимое время. Таким образом, один конец всех кнопок подключен к земле, а другой конец подключен к выводу PORTB, на этих выводах будет использоваться внутренний подтягивающий резистор, чтобы контакты не смещались. Зуммер будет действовать как выход и издаст звуковой сигнал, когда сработает сигнал тревоги и будет подключен к выводу PORT S. Текущее время всегда отслеживается модулем DS3231 RTC, от которого PIC получает данные по шине I2C, поэтому контакты SCL и SDA модуля RTC подключены к контактам SCL и SDA контроллера PIC. К PORTD PIC прикреплен ЖК-дисплей, который используется для отображения текущего времени и установленного времени. Узнайте больше об использовании модуля DS3231 RTC с PIC здесь.
Полную схему можно построить на макете. Поскольку нужно подключить пару десятков проводов, просто наберитесь терпения и убедитесь, что соединения правильные. Когда я закончил с подключениями, мои аппаратные настройки выглядели примерно так, как показано ниже.
Я использовал макетный модуль и адаптер на 12 В для питания модуля. Это мой источник напряжения питания + 5В. Также мне пришлось использовать две макетные платы, чтобы схема оставалась чистой. Вы также можете припаять всю схему к монтажной плате, если хотите создать более надежный проект.
Программирование будильника:
Полная программа ПОС для этого проекта Clock Alarm можно найти в нижней части этой страницы. Для этого проекта также требуются три библиотеки для использования LCD, I2C и RTC с PIC. Полный код с заголовочными файлами можно загрузить из ZIP-файла здесь и открыть с помощью MPLABX после распаковки. Ниже я просто объясняю основной файл c в виде небольших фрагментов. Вы можете вернуться к вышеупомянутым руководствам, если хотите узнать, как работают файлы заголовков.
Перед тем, как перейти к основной программе, мы должны определить контакты, которые мы использовали, с более значимыми именами. Так их будет легко использовать при программировании. Контакты, определенные в нашей программе, показаны ниже.
// Определение выводов ЖК-дисплея #define RS RD2 // Сброс вывода ЖК-дисплея #define EN RD3 // Разрешение вывода ЖК-дисплея #define D4 RD4 // Бит 0 данных ЖК-дисплея #define D5 RD5 // Бит данных 1 ЖК-дисплея #define D6 RD6 // Бит данных 2 ЖК-дисплея #define D7 RD7 // Бит данных 3 ЖК-дисплея // Определение кнопок #define MB RB1 // Средняя кнопка #define LB RB0 // Левая кнопка #define RB RB2 // Правая кнопка # define UB RB3 // Верхняя кнопка #define BB RB4 // Нижняя кнопка // Определить Buzz #define BUZZ RD1 // Зуммер подключен к RD1
Внутри основной функции мы начинаем с объявления входных и выходных контактов. В нашем проекте PORTB используется для кнопок, которые являются устройством ввода, поэтому мы устанавливаем их контакты как входы, а PORTD используется для ЖК-дисплея и зуммера, поэтому мы устанавливаем их контакты как Output. Кроме того, контакт никогда не должен оставаться плавающим, что означает, что контакты ввода / вывода всегда должны быть подключены либо к земле, либо к напряжению +5 В. В нашем случае для кнопок контакты не будут ни к чему подключены, когда кнопка не нажата, поэтому мы используем внутренний подтягивающий резистор, который устанавливает для контакта высокий уровень, когда он не используется. Это делается с помощью регистров управления, как показано ниже.
TRISD = 0x00; // Делаем выводы порта D выходом для интерфейса LCD TRISB = 0xFF; // Переключатели объявлены как входные контакты OPTION_REG = 0b00000000; // Включить подтягивающий резистор на порте B для коммутаторов BUZZ = 0; // Выключить зуммер
Поскольку у нас есть файл заголовка LCD и I2C, связанный с основной программой, мы можем запустить инициализацию LCD, вызвав простую функцию. То же самое можно сделать и для инициализации I2C. Здесь мы запускаем связь I2C на частоте 100 кГц, поскольку модуль RTC работает с частотой 100 кГц.
Lcd_Start (); // Инициализировать ЖК-модуль I2C_Initialize (100); // Инициализируем I2C Master с частотой 100 кГц
Приведенная ниже функция используется для установки времени и даты в модуле RTC, после установки времени и даты удалите эту строку. Иначе каждый раз, когда вы запускаете программу, время и дата будут устанавливаться снова и снова.
// Удаляем ниже линии раз время и дата будет установлена в первый раз. Set_Time_Date (); // устанавливаем время и дату в модуле RTC
Чтобы указать, что программа запускается, мы отображаем небольшой вводный экран, на котором отображается название проекта и название веб-сайта, как показано ниже.
// Вывести вводное сообщение на ЖК-дисплей Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String («Будильник»); Lcd_Set_Cursor (2,1); Lcd_Print_String ("-Дайджест схемы"); __delay_ms (1500);
Далее внутри в то время цикла, мы должны прочитать текущее время и дату из модуля RTC, это может быть сделано просто вызов ниже функции.
Update_Current_Date_Time (); // Считываем текущую дату и время из модуля RTC
Вызов вышеуказанной функции обновит переменные sec, min и hour с текущим значением. Чтобы отобразить их на ЖК-экране, мы должны разделить их на отдельные символы, используя приведенный ниже код.
// Разделение на символы для отображения на ЖК- дисплее char sec_0 = sec% 10; char sec_1 = (сек / 10); char min_0 = min% 10; char min_1 = мин / 10; char hour_0 = час% 10; char hour_1 = час / 10;
Затем мы обновляем значения на ЖК-экране. Текущее время будет отображаться в первой строке, а установленное время, в которое должен сработать сигнал тревоги, отображается во второй строке. Код, который делает то же самое, показан ниже.
// Отображение текущего времени на ЖК-экране Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("ВРЕМЯ:"); Lcd_Print_Char (час_1 + '0'); Lcd_Print_Char (час_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (min_1 + '0'); Lcd_Print_Char (min_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (sec_1 + '0'); Lcd_Print_Char (sec_0 + '0'); // Отображение даты на ЖК-экране Lcd_Set_Cursor (2, 1); Lcd_Print_String ("Тревога:"); Lcd_Print_Char (значение_тревоги + '0'); Lcd_Print_Char (значение_тревоги + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (alarm_val + '0 '); Lcd_Print_Char (значение_тревоги + '0');
Теперь мы отобразили время и установили время на ЖК-дисплее, чтобы проверить, пытается ли пользователь установить время будильника. Для этого пользователь должен нажать среднюю кнопку, поэтому мы проверим, нажата ли средняя кнопка, и переключим переменную, чтобы войти в режим установки будильника. Эта же кнопка будет нажата еще раз, чтобы подтвердить, что значения установлены, и в этом случае мы должны выйти из режима установки будильника. Поэтому мы используем приведенную ниже строку кода, чтобы изменить статус переменной set_alarm .
// Используйте среднюю кнопку, чтобы проверить , нужно ли устанавливать будильник if (MB == 0 && set_alarm == 0) {// Если средняя кнопка нажата и будильник не включен, пока (! MB); // Подождите, пока кнопка не будет отпущена set_alarm = 1; // начинаем устанавливать значение сигнала тревоги } if (MB == 0 && set_alarm == 1) {// Если средняя кнопка нажата и будильник не выключен while (! MB); // Ждем, пока кнопка не будет отпущена set_alarm = 0; // прекращаем установку значения сигнала тревоги }
Если пользователь нажал среднюю кнопку, значит, он пытается установить время будильника. В этом случае программа переходит в режим установки будильника, используя указанный выше код. В режиме установки будильника, если пользователь нажимает левую или правую кнопку, это означает, что мы должны переместить курсор влево или вправо. Для этого мы просто увеличиваем или уменьшаем значение позиции, в которую должен быть помещен курсор.
if (LB == 0) {// Если нажата левая кнопка while (! LB); // Дождемся отпускания кнопки pos--; // Затем переместите курсор влево } if (RB == 0) {// Если правая кнопка нажата while (! RB); // Подождите, пока кнопка не будет отпущена pos ++; // Перемещаем курсор вправо }
При использовании кнопки с микроконтроллером или микропроцессором возникает одна общая проблема. Эта проблема называется подскакиванием переключателя. То есть, когда кнопка нажата, он может подавать шумные импульсы на MCU / MPU, которые могут подделать MCU для нескольких записей. Эта проблема может быть решена путем добавления конденсатора к переключателю или использования функции задержки при обнаружении нажатия кнопки. Этот тип решения называется устранением подпрыгивания. Здесь мы использовали то время как цикл, чтобы держать программу на месте, пока кнопка не будет отпущена. Это не лучшее решение для устранения подпрыгивания, но для нас оно подойдет.
пока (! RB);
Подобно левой и правой кнопкам, у нас также есть верхняя и нижняя кнопки, которые можно использовать для увеличения или уменьшения значения времени будильника. Код, позволяющий сделать то же самое, показан ниже. Обратите внимание, что каждый символ установленного времени будильника адресуется значением индекса массива. Таким образом, мы можем легко получить доступ к требуемому символу, значения которого нужно изменить.
if (UB == 0) {// Если верхняя кнопка нажата во время (! UB); // Подождите, пока кнопка не будет отпущена alarm_val ++; // Увеличиваем это конкретное значение char } if (BB == 0) {// Если нижняя кнопка нажата while (! UB); // Дождемся отпускания кнопки alarm_val--; // Уменьшаем это конкретное значение char }
Как только время будильника будет установлено, пользователь снова нажмет среднюю кнопку. Затем мы можем начать сравнивать текущее время с установленным временем. Сравнение путем проверки того, что каждый символ текущего времени равен символу установленного времени. Если значения равны, мы запускаем тревогу, устанавливая переменную trigger_alarm, иначе мы просто сравниваем, пока она не станет равной.
// ЕСЛИ установлен сигнал тревоги. Проверяем, соответствует ли установленное значение текущему значению if (set_alarm == 0 && alarm_val == hour_1 && alarm_val == hour_0 && alarm_val == min_1 && alarm_val == min_0) trigger_alarm = 1; // Включаем триггер при совпадении значений
Если будильник установлен, мы должны подать звуковой сигнал, чтобы предупредить пользователя о тревоге. Это можно сделать, просто периодически переключая зуммер, как показано ниже.
if (trigger_alarm) {// Если сработала тревога // Звуковой сигнал BUZZ = 1; __delay_ms (500); BUZZ = 0; __delay_ms (500); }
Моделирование:
Эту программу также можно смоделировать с помощью программного обеспечения Proteus. Просто воссоздайте схему, показанную выше, и загрузите шестнадцатеричный файл в PIC. Шестнадцатеричный код этого проекта можно найти в файле ZIP, ссылка на который есть здесь. Снимок экрана, сделанный во время моделирования, показан ниже.
Моделирование становится очень полезным, когда вы пытаетесь добавить новые функции в проект. Вы также можете использовать модуль отладчика I2C, чтобы проверить, какие данные входят и исходят через шину I2C. Вы можете попробовать нажимать кнопки, а также установить время будильника. Когда установленное время будет равно текущему времени, зуммер станет высоким.
Работа цифрового будильника с использованием PIC16F877A:
Соберите схему на макетной плате, получите код по ссылке для скачивания и скомпилируйте его с помощью компилятора MplabX и XC8. Если вы загрузили код из предоставленного здесь ZIP-файла, у вас не должно возникнуть проблем с его компиляцией, поскольку файлы заголовков уже прикреплены.
После компиляции загрузите программу на ваше оборудование с помощью программатора PicKit3. Подключение для подключения программатора Pickit к PIC IC также показано на принципиальной схеме. После загрузки программы вы должны увидеть начальный экран, а затем отображаемое время. Затем вы можете использовать кнопки для установки времени будильника. Настройка моего оборудования при включении выглядит следующим образом.
Когда время будильника совпадает с текущим временем, зуммер начнет подавать звуковой сигнал, чтобы предупредить пользователя. Полную работу можно посмотреть на видео ниже. У проекта есть множество вариантов, на которые можно опираться. Модуль RTC может отслеживать любое время и дату, поэтому вы можете выполнить запланированную задачу в любое время / дату. Вы также можете подключить устройство переменного тока, например вентилятор или свет, и запланировать его включение или выключение при необходимости. Есть еще много чего, что вы можете построить на этом проекте, дайте мне знать, какая идея придет вам в голову в качестве обновления этого проекта, и я буду рад услышать от вас.
Надеюсь, вы поняли проект и узнали что-то полезное из этого процесса. Если у вас есть какие-либо сомнения в этом проекте, используйте раздел комментариев, чтобы опубликовать их, или используйте форумы для любой технической помощи.
Полный код PIC с заголовочными файлами можно найти здесь