始于1950年的數字革命將所有現有的機械和模擬電子結構轉變為數字計算機。由于數字電子產品的增長呈指數級增長,今天一個人幾乎不可能抗拒使用任何電子設備。從叫醒你的鬧鐘和為你提供早餐的烤面包機開始,一切都是數字電子產品的貢獻。考慮到所有這些,對我們自己的東西進行編程真的很令人興奮,這些東西可以完成簡單而有用的任務,比如我們將在這個項目中使用PIC 微控制器構建的鬧鐘。
該鬧鐘將有一個 16x2 LCD 顯示屏,將顯示當前時間和設置時間。我們將在需要時使用幾個按鈕來設置鬧鐘時間。使用DS3231RTC模塊可以跟蹤當前時間,我們將使用IIC通信從RTC模塊獲取這些值。我們已經了解了 RTC 模塊以及如何將其與 PIC 接口。因此,建議通讀該教程,我們將跳過該教程中涵蓋的大部分信息。
所需材料:
面包板 – 2Nos
PIC16F877A
20兆赫晶體
33pf 電容器 – 2 常開
DS3231 RTC 模塊
16*2液晶顯示模塊
10K 鍋
10k 和 1K 電阻
按鈕 – 5 否
蜂鳴器
連接線
先決條件:
本項目要求您了解一些有關PIC微控制器以及如何對其進行編程的基礎知識。我們將在這個項目中使用GPIO,LCD顯示器和RTC模塊。因此,最好事先學習如何使用這些模塊。
電路圖:
這個基于PIC的鬧鐘項目的電路圖如下所示,該項目是使用proteus軟件創建的。該項目還將用于進一步的仿真。
五個按鈕將作為輸入,用于將鬧鐘設置為所需時間。因此,所有按鈕的一端接地,另一端連接到PORTB引腳,這些引腳上將使用內部上拉電阻,以避免引腳浮動。蜂鳴器將充當輸出,并在警報被觸發并連接到 PORT S 引腳時給我們發出嗶嗶聲。當前時間始終由DS3231RTC模塊跟蹤,PIC通過I2C總線從該模塊接收數據,因此RTC模塊的SCL和SDA引腳連接到PIC控制器的SCL和SDA引腳。LCD顯示器連接到PIC的PORTD,用于顯示當前時間和設定時間。在此處了解有關DS3231 RTC模塊與PIC配合使用的更多信息。
整個電路可以構建在面包板上。由于有幾十根電線要連接,所以請耐心等待并確保連接正確。完成連接后,我的硬件設置如下所示
我使用面包板模塊和 12V 適配器為模塊供電。這是我的+5V電源電壓源。此外,我還必須使用兩個面包板來保持電路清潔。如果您希望制作更強大的項目,您還可以將整個電路焊接到性能板上。
鬧鐘編程:
此鬧鐘項目的完整PIC程序可以在此頁面底部找到。該項目還需要三個庫來使用LCD,I2C和RTC和PIC。
在進入主程序之前,我們必須定義使用更有意義的名稱使用的引腳。這樣,在編程過程中就很容易使用它們。我們程序中定義的引腳如下所示
//Define the LCD pins
#define RS RD2 //Reset pin of LCD
#define EN RD3 //Enable pin of LCD
#define D4 RD4 //Data bit 0 of LCD
#define D5 RD5 //Data bit 1 of LCD
#define D6 RD6 //Data bit 2 of LCD
#define D7 RD7 //Data bit 3 of LCD
//Define Buttons
#define MB RB1 //The middle button
#define LB RB0 //Left button
#define RB RB2 //Right button
#define UB RB3 //Upper Button
#define BB RB4 //Bottom button
//Define Buzz
#define BUZZ RD1 //Buzzer is connected to RD1
在 main 函數中,我們首先聲明輸入和輸出引腳。在我們的項目中,PORTB 用于按鈕,這是一個輸入設備,因此我們將它們的引腳設置為輸入,PORTD 用于 LCD 和蜂鳴器,因此我們將它們的引腳設置為輸出。此外,引腳不應懸空,I/O引腳應始終連接到地或+5V電壓。在我們的例子中,對于按鈕,當按鈕未按下時,引腳不會連接到任何東西,因此我們使用內部上拉電阻器,該電阻器在不使用時將引腳設置為高電平。這是使用控制寄存器完成的,如下所示
TRISD = 0x00; //Make Port D pins as outptu for LCD interfacing
TRISB = 0xFF; //Switchs are declared as input pins
OPTION_REG = 0b00000000; //Enable pull up Resistor on port B for switchs
BUZZ = 0; //Turn of buzzer
由于我們有與主程序鏈接的LCD和I2C頭文件,因此我們可以通過調用一個簡單的函數來開始LCD初始化。I2C初始化也可以這樣做。在這里,我們以 100kHz 開始 I2C 通信,因為 RTC 模塊以 100kHz 工作。
Lcd_Start(); // Initialize LCD module
I2C_Initialize(100); //Initialize I2C Master with 100KHz clock
下面的函數用于在RTC模塊上設置時間和日期,一旦設置了時間和日期,請刪除此行。否則,每次啟動程序時,都會一次又一次地設置時間和日期
//Remove the below line once time and date is set for the first time.
Set_Time_Date(); //set time and date on the RTC module
為了指示程序正在啟動,我們顯示一個小的介紹屏幕,其中顯示項目名稱和網站名稱,如下所示
//Give an intro message on the LCD
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Alarm Clock");
Lcd_Set_Cursor(2,1);
Lcd_Print_String(" -Circuit Digest");
__delay_ms(1500);
接下來在 while 循環中,我們需要從 RTC 模塊讀取當前時間和日期,這可以通過調用以下函數來完成。
Update_Current_Date_Time(); //Read the current date and time from RTC module
調用上述函數將使用當前值更新變量 sec、min 和 hour。為了在LCD屏幕上顯示它們,我們必須使用以下代碼將它們拆分為單個字符。
//Split the into char to display on lcd
char sec_0 = sec % 10;
char sec_1 = (sec / 10);
char min_0 = min % 10;
char min_1 = min / 10;
char hour_0 = hour % 10;
char hour_1 = hour / 10;
接下來,我們更新LCD屏幕上的值。當前時間將顯示在第一行,必須觸發警報的設置時間顯示在第二行。執行相同操作的代碼如下所示。
//Display the Current Time on the LCD screen
Lcd_Clear();
Lcd_Set_Cursor(1, 1);
Lcd_Print_String("TIME: ");
Lcd_Print_Char(hour_1 + '0');
Lcd_Print_Char(hour_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');
//Display the Date on the LCD screen
Lcd_Set_Cursor(2, 1);
Lcd_Print_String("Alarm: ");
Lcd_Print_Char(alarm_val[0] + '0');
Lcd_Print_Char(alarm_val[1] + '0');
Lcd_Print_Char(':');
Lcd_Print_Char(alarm_val[2] + '0');
Lcd_Print_Char(alarm_val[3] + '0');
現在,我們已經在LCD上顯示了時間和設置時間,我們必須檢查用戶是否正在嘗試設置鬧鐘時間。為此,用戶必須按下中間按鈕,因此我們將檢查是否按下中間按鈕并切換變量以進入警報設置模式。將再次按下相同的按鈕以確認已設置值,在這種情況下,我們必須退出警報設置模式。因此,我們使用下面的代碼行來更改變量set_alarm的狀態。
//Use middle button to check if alarm has to be set
if (MB == 0 && set_alarm == 0) { //If middle button is pressed and alarm is not turned on
while (!MB); //Wait till button is released
set_alarm = 1; //start setting alarm value
}
if (MB == 0 && set_alarm == 1) { //If middle button is pressed and alarm is not turned off
while (!MB); //Wait till button is released
set_alarm = 0; //stop setting alarm value
}
如果用戶按下了中間按鈕,則表示他正在嘗試設置鬧鐘時間。在這種情況下,程序使用上面的代碼進入警報設置模式。在警報設置模式下,如果用戶按下左或右按鈕,則意味著我們必須向左或向右移動光標。為此,我們只需遞增遞減光標必須放置的位置值
if (LB == 0) { //If left button is pressed
while (!LB); //Wait till button is released
pos--; //Then move the cursor to left
}
if (RB == 0) { //If right button is pressed
while (!RB); //Wait till button is released
pos++; //Move cursor to right
}
在將按鈕與微控制器或微處理器一起使用時,有一個常見問題需要解決。此問題稱為開關彈跳。也就是說,當按下按鈕時,它可能會給MCU / MPU發出嘈雜的脈沖,這可能會偽造MCU的多個條目。這個問題可以通過在開關上增加一個電容或在檢測到按鈕按下后立即使用延遲功能來解決。這種類型的解決方案稱為去抖動。在這里,我們使用了一個while循環來將程序固定到位,直到按鈕被釋放。這不是最好的去抖動解決方案,但對我們來說,它會很好地工作。
while (!RB);
與左右按鈕類似,我們也有上下按鈕,可用于增加或減少鬧鐘時間的值。執行相同操作的代碼如下所示。請注意,設置的警報時間的每個字符都由數組的索引值尋址。這是我們可以輕松訪問必須更改其值的所需字符。
if (UB == 0) { //If upper button is pressed
while (!UB); //Wait till button is released
alarm_val[(pos - 8)]++; //Increase that particular char value
}
if (BB == 0) { //If lower button is pressed
while (!UB); //Wait till button is released
alarm_val[(pos - 8)]--; //Decrease that particular char value
}
設置鬧鐘時間后,用戶將再次短按中間按鈕。然后我們可以開始將當前時間與設置的時間進行比較。通過檢查當前時間的每個字符是否等于設置時間的字符來進行比較。如果值相等,那么我們通過設置 trigger_alarm 變量來觸發警報,否則我們只是比較直到它相等。
//IF alarm is set Check if the set value is equal to current value
if (set_alarm == 0 && alarm_val[0] == hour_1 && alarm_val[1] == hour_0 && alarm_val[2] == min_1 && alarm_val[3] == min_0)
trigger_alarm = 1; //Turn on trigger if value match
如果設置了警報,我們必須發出蜂鳴器以提醒用戶警報。這可以通過簡單地定期切換蜂鳴器來完成,如下所示。
if (trigger_alarm) { //If alarm is triggered
//Beep the buzzer
BUZZ = 1;
__delay_ms(500);
BUZZ = 0;
__delay_ms(500);
}
模擬:
該程序也可以使用變形蟲軟件進行模擬。只需重新創建上面顯示的電路,并將十六進制文件加載到 PIC 中即可。
模擬期間拍攝的屏幕截圖如下所示
當您嘗試向項目添加新功能時,模擬變得非常有用。您 還 可以 使用 I2C 調試 器 模 塊 來 檢查 哪些 數據 通過 I2C 總 線 進出。您可以嘗試按下按鈕并設置鬧鐘時間。當設定的時間等于當前時間時,蜂鳴器將變高。
使用PIC16F877A的數字鬧鐘工作:
在試驗板上構建電路,從下載鏈接獲取代碼并使用MplabX和XC8編譯器進行編譯。
編譯后,使用PicKit3編程器將程序上傳到您的硬件。電路圖中還顯示了將拾取器編程器連接到PIC IC的連接。程序上傳后,您應該會看到介紹屏幕,然后顯示時間,然后您可以使用按鈕設置鬧鐘時間。通電時的硬件設置如下所示。
當鬧鐘時間與當前時間匹配時,蜂鳴器將開始發出蜂鳴聲以提醒用戶。完整的工作可以在下面的視頻中找到。該項目有很多選擇可以構建。RTC 模塊可以跟蹤任何時間和日期,因此您可以在所需的任何時間/日期執行計劃任務。您還可以連接風扇或燈等交流電器,并在需要時安排其打開或關閉。
/*
* Program: Alarm Clock Using PIC
* Author: B.Aswinth Raj
* More info: www.circuitdigest.com
* Created on 11 May, 2018, 3:02 PM
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 20000000 //We are running on 20MHz crystal
//Define the LCD pins
#define RS RD2 //Reset pin of LCD
#define EN RD3 //Enable pin of LCD
#define D4 RD4 //Data bit 0 of LCD
#define D5 RD5 //Data bit 1 of LCD
#define D6 RD6 //Data bit 2 of LCD
#define D7 RD7 //Data bit 3 of LCD
//Define Buttons
#define MB RB1 //The middle button
#define LB RB0 //Left button
#define RB RB2 //Right button
#define UB RB3 //Upper Button
#define BB RB4 //Bottom button
//Define Buzz
#define BUZZ RD1 //Buzzer is connected to RD1
/*Set the current value of date and time below*/
int sec = 00;
int min = 55;
int hour = 10;
int date = 06;
int month = 05;
int year = 18;
/*Time and Date Set*/
/*Vars for Alarm clock*/
char set_alarm = 0;
char trigger_alarm = 0;
char pos = 8;
char jump = 0;
char alarm_h0 = 0;
char alarm_h1 = 0;
char alarm_m0 = 0;
char alarm_m1 = 0;
int alarm_val[4] = {0, 0, 0, 0};
/*End of var declaration*/
#include
#include "lcd.h" //Header for using LCD module
#include "PIC16F877a_I2C.h" // Header for using I2C protocal
#include "PIC16F877a_DS3231.h" //Header for using DS3231 RTC module
int main() {
TRISD = 0x00; //Make Port D pins as outptu for LCD interfacing
TRISB = 0xFF; //Switchs are declared as input pins
OPTION_REG = 0b00000000; //Enable pull up Resistor on port B for switchs
BUZZ = 0; //Turn of buzzer
Lcd_Start(); // Initialize LCD module
I2C_Initialize(100); //Initialize I2C Master with 100KHz clock
//Remove the below line once time and date is set for the first time.
Set_Time_Date(); //set time and date on the RTC module
//Give an intro message on the LCD
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Alarm Clock");
Lcd_Set_Cursor(2,1);
Lcd_Print_String(" -Circuit Digest");
__delay_ms(1500);
while (1) {
Update_Current_Date_Time(); //Read the current date and time from RTC module
//Split the into char to display on lcd
char sec_0 = sec % 10;
char sec_1 = (sec / 10);
char min_0 = min % 10;
char min_1 = min / 10;
char hour_0 = hour % 10;
char hour_1 = hour / 10;
//Display the Current Time on the LCD screen
Lcd_Clear();
Lcd_Set_Cursor(1, 1);
Lcd_Print_String("TIME: ");
Lcd_Print_Char(hour_1 + '0');
Lcd_Print_Char(hour_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');
//Display the Date on the LCD screen
Lcd_Set_Cursor(2, 1);
Lcd_Print_String("Alarm: ");
Lcd_Print_Char(alarm_val[0] + '0');
Lcd_Print_Char(alarm_val[1] + '0');
Lcd_Print_Char(':');
Lcd_Print_Char(alarm_val[2] + '0');
Lcd_Print_Char(alarm_val[3] + '0');
__delay_ms(50);
//Use middle button to check if alarm has to be set
if (MB == 0 && set_alarm == 0) { //If middle button is pressed and alarm is not turned on
while (!MB); //Wait till button is released
set_alarm = 1; //start setting alarm value
}
if (MB == 0 && set_alarm == 1) { //If middle button is pressed and alarm is not turned off
while (!MB); //Wait till button is released
set_alarm = 0; //stop setting alarm value
}
//If alarm has to be navigate through each digit
if (set_alarm == 1) {
if (LB == 0) { //If left button is pressed
while (!LB); //Wait till button is released
pos--; //Then move the cursor to left
}
if (RB == 0) { //If right button is pressed
while (!RB); //Wait till button is released
pos++; //Move cursor to right
}
if (pos >= 10) //eliminate ":" symbol if cursor reaches there
{
jump = 1; //Jump over the ":" symbol
} else
jump = 0; //get back to normal movement
if (UB == 0) { //If upper button is pressed
while (!UB); //Wait till button is released
alarm_val[(pos - 8)]++; //Increase that particular char value
}
if (BB == 0) { //If lower button is pressed
while (!UB); //Wait till button is released
alarm_val[(pos - 8)]--; //Decrease that particular char value
}
Lcd_Set_Cursor(2, pos + jump);
Lcd_Print_Char(95); //Display "_" to indicate cursor position
}
//IF alarm is set Check if the set value is equal to current value
if (set_alarm == 0 && alarm_val[0] == hour_1 && alarm_val[1] == hour_0 && alarm_val[2] == min_1 && alarm_val[3] == min_0)
trigger_alarm = 1; //Turn on trigger if value match
if (trigger_alarm) { //If alarm is triggered
//Beep the buzzer
BUZZ = 1;
__delay_ms(500);
BUZZ = 0;
__delay_ms(500);
}
__delay_ms(200);//Update interval
}
return 0;
}
-
微控制器
+關注
關注
48文章
7490瀏覽量
151056 -
PIC16F877A
+關注
關注
2文章
43瀏覽量
21782 -
數字鬧鐘
+關注
關注
0文章
6瀏覽量
5442
發布評論請先 登錄
相關推薦
評論