?? clock_pic16f877.c
字號:
用c語言寫的一個時鬧鐘程序
單片機用16F877,主時鐘用20MHz,用32768作定時時間。可以實現2路定鬧,每一路都可分別設置和開關,采用4x4鍵盤,16x2的字符型LCD顯示。連線在程序開頭有說明。
程序的功能:
(1)上電后LCD背光打開,并顯示倒計時5秒,然后時鐘開始工作。
(2)用模式鍵(*)切換模式,如顯示時間、日期、鬧鐘1、鬧鐘2等,并且可以用上、下鍵控制加1、減1或是鬧鐘的On、Off。
(3)原程序有16個鍵,包括0~9數字鍵,可以直接輸入要設置的時間值,但后來將數字鍵取消了,你仍然可以通過修改程序的部分注釋恢復此功能。
(4)鬧鐘有2路,時間到后鬧2分鐘,可按任意鍵取消本次鬧鐘。鬧鐘響時有2種音調,是用PIC的PWM實現的。
(5)按任意鍵可打開背光,1分鐘后自動關閉背光。
(6)RA0~RA3為按鍵掃描輸入,應接下拉電阻。
主程序
// FileName: Main.c
// MCU: Microchip PIC16F877
// Tool: CCS-C compiler
// Author: KingEDA, MSN:kingeda@163.com, skype:kingeda, E-mail:kingeda@163.com
// Website: http://www.EDAKING.com
// Description:
// A timer program
// Ver 0.1: 2003-03-31, all clock function with date display, 2 way alarm.
// Ver 0.2: 2003-05-05, (1) Alarm default is on,modify alarm1 time to 7:00:00,
// and alarm2 to 13:30:00.
// (2) Backlight will be enabled when alarming.
// (3) Automatic adjust day(28,30,31).
// (4) Automatic move cursor to next location when set item.
// PIN Connection:
// RC0~1 : 32768Hz crystal
// RC2 : Buzzer
// RC3 : LCD Back Light,drive a PNP BJT
// RD0~RD7 : to LCD DB0~DB7
// RA0~RA3 : keypad col in
// RC4~RC7 : keypad line out
// 7 8 9 #
// 4 5 6 ↑
// 1 2 3 ↓
// 0 ← → *
// RE0 : LCD RS
// RE1 : LCD RW
// RE2 : LCD E
#include "my16f877.h"
#device ICD=true
//#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT
#use delay(clock = 24000000)
//#use fast_io(C)
#use fast_io(E)
#define lcd_busy (lcd_read_addr()&0x80) == 0x80
#define time_start_addr 0x80+0x04
#define time_hourh_addr time_start_addr
#define time_hourl_addr time_start_addr+1
#define time_minuteh_addr time_start_addr+3
#define time_minutel_addr time_start_addr+4
#define time_secondh_addr time_start_addr+6
#define time_secondl_addr time_start_addr+7
#define key_0 0x11
#define key_1 0x21
#define key_2 0x22
#define key_3 0x24
#define key_4 0x41
#define key_5 0x42
#define key_6 0x44
#define key_7 0x81
#define key_8 0x82
#define key_9 0x84
#define key_left 0x12
#define key_right 0x14
#define key_up 0x48
#define key_down 0x28
#define key_mode 0x18
#define key_cancel 0x88
char StrPower1[] = " * Power on * ";
char StrSetTime[] = " * Adjust time* ";
char StrSetDate[] = " * Adjust date* ";
char StrAlarm1[] = " * Set alarm 1* ";
char StrAlarm2[] = " * Set alarm 2* ";
unsigned char PORTC_MAP;
#bit BackLightEn = PORTC_MAP.3
unsigned char BackLightTimer;
int1 led;
#bit lcd_rs = PORTE.0
#bit lcd_rw = PORTE.1
#bit lcd_e = PORTE.2
#byte lcd_bus = PORTD
#byte lcd_dir = TRISD
#define PWM_on 0x0c
#define PWM_off 0x00
#define PWM_period 200
#define PWM_DC 100
unsigned char lcd_addr;
unsigned char KeyLine;
unsigned char KeyOld;
unsigned char KeyNew;
struct mTime {
unsigned char hourh; // hour,0~23
unsigned char hourl;
unsigned char minuteh; // minute,0~59
unsigned char minutel;
unsigned char secondh; // second,0~59
unsigned char secondl;
};
struct mTime CurrentTime = {1,2,0,0,0,0};
struct mTime AlarmTime1 = {0,7,0,0,0,0}; // 07:00:00
struct mTime AlarmTime2 = {1,3,3,0,0,0}; // 13:30:00
unsigned char AlarmStatus;
#bit Alarm1Enable = AlarmStatus.0
#bit Alarm2Enable = AlarmStatus.1
#bit Alarm1Alarm = AlarmStatus.2
#bit Alarm2Alarm = AlarmStatus.3
unsigned char Alarm1Cnt; // alarm1 second count
unsigned char Alarm2Cnt;
unsigned char CurrentMode;
#define mode_time 0
#define mode_set_time 1
#define mode_set_date 2
#define mode_set_alarm1 3
#define mode_set_alarm2 4
unsigned char adjust_item;
struct mDate {
unsigned char year1; //
unsigned char year2;
unsigned char year3;
unsigned char year4;
unsigned char monthh;
unsigned char monthl;
unsigned char dayh;
unsigned char dayl;
};
struct mDate CurrentDate = {2,0,0,3,0,1,0,1};
unsigned char *pStr;
// -------------------------------------------------------
unsigned char lcd_read_addr()
{
unsigned char ch;
lcd_dir = 0xff; // read from lcd
lcd_rs = 0;
lcd_rw = 1; // inst
lcd_e = 1;
#asm
nop
nop
nop
#endasm
ch = lcd_bus;
lcd_e = 0;
lcd_dir = 0x00; // set write to lcd
return ch;
}
// -------------------------------------------------------
unsigned char lcd_write_data(unsigned char ch)
{
while (lcd_busy)
{ restart_wdt(); }
lcd_rs = 1; // data
lcd_rw = 0; // write
lcd_bus = ch; // write out
lcd_e = 1;
#asm
nop
nop
nop
#endasm
lcd_e = 0;
return 'Y';
}
// -------------------------------------------------------
unsigned char lcd_write_inst(unsigned char ch)
{
while (lcd_busy)
{ restart_wdt(); }
lcd_rs = 0; // inst
lcd_rw = 0; // write
lcd_bus = ch;
lcd_e = 1;
#asm
nop
nop
nop
#endasm
lcd_e = 0;
return 'Y';
}
// -------------------------------------------------------
unsigned char lcd_read_data()
{
unsigned char ch;
while (lcd_busy)
{ restart_wdt(); }
lcd_dir = 0xff; // read from lcd
lcd_rs = 1; // data
lcd_rw = 1; // read
lcd_e = 1;
#asm
nop
nop
nop
#endasm
ch = lcd_bus; // read in
lcd_e = 0;
lcd_dir = 0x00; // set write to lcd
return ch;
}
// -------------------------------------------------------
void lcd_init()
{
unsigned char Tempch;
lcd_addr = 0;
delay_ms(100);
Tempch = 0x38; // 1-line mode,5x8 dots
lcd_write_inst(Tempch); // Function set
Tempch = 0x0f; // lcd on,cursor on,blink on
lcd_write_inst(Tempch); // Display on/off
Tempch = 0x06; // Increment mode,Entire shift off
lcd_write_inst(Tempch);
Tempch = 0x01; // clear display
lcd_write_inst(Tempch);
delay_ms(3);
}
// -------------------------------------------------------
//#int_timer1
//void timer1_interrupt(void)
#int_ccp2
void ccp2_interrupt(void)
{
//TMR1H = 0x80;
if (CurrentTime.secondl==9)
{
CurrentTime.secondl=0;
if (CurrentTime.secondh==5)
{
CurrentTime.secondh=0;
if (CurrentTime.minutel==9)
{
CurrentTime.minutel=0;
if (CurrentTime.minuteh==5)
{
CurrentTime.minuteh=0;
if (CurrentTime.hourl==9)
{
CurrentTime.hourl=0;
CurrentTime.hourh++;
}
else if((CurrentTime.hourl==3) && (CurrentTime.hourh==2))
{
CurrentTime.hourl=0;
CurrentTime.hourh=0;
if ((((CurrentDate.dayl == 8) || (CurrentDate.dayl == 9)) && (CurrentDate.dayh == 2) && (CurrentDate.monthl == 2) && (CurrentDate.monthh == 0)) ||
((CurrentDate.dayl == 0) && (CurrentDate.dayh == 3) && ((((CurrentDate.monthl == 4) || (CurrentDate.monthl == 6)
|| (CurrentDate.monthl == 9)) && (CurrentDate.monthh == 0)) || ((CurrentDate.monthl == 1) && (CurrentDate.monthh == 1)))) ||
((CurrentDate.dayl == 1) && (CurrentDate.dayh == 3)))
{
CurrentDate.dayl=1;
CurrentDate.dayh=0;
if ((CurrentDate.monthl == 2) && (CurrentDate.monthh == 1))
{
CurrentDate.monthl = 1;
CurrentDate.monthh = 0;
if (CurrentDate.year4 == 9)
{
CurrentDate.year4 = 0;
if (CurrentDate.year3 == 9)
{
CurrentDate.year3 = 0;
if (CurrentDate.year2 == 9)
{
CurrentDate.year2 = 0;
CurrentDate.year1++;
}
else
CurrentDate.year2++;
}
else
CurrentDate.year3++;
}
else
CurrentDate.year4++;
}
else if(CurrentDate.monthl == 9)
{
CurrentDate.monthl = 0;
CurrentDate.monthh++;
}
else
CurrentDate.monthl++;
}
else if(CurrentDate.dayl == 9)
{
CurrentDate.dayl=0;
CurrentDate.dayh++;
}
else
CurrentDate.dayl++;
}
else
CurrentTime.hourl++;
}
else
CurrentTime.minuteh++;
}
else
CurrentTime.minutel++;
}
else
CurrentTime.secondh++;
}
else
CurrentTime.secondl++;
if ((Alarm1Alarm == false) & (Alarm2Alarm == false))
{
led = 0;
CCP1CON = PWM_off;
}
else
{
if (led == 1)
{
led = 0;
PR2 = PWM_period; // set pwm period
CCPR1L = PWM_DC; // set pwm duty cycle
//CCP1CON = PWM_on;
}
else
{
led = 1;
PR2 = PWM_period/2; // set pwm period
CCPR1L = PWM_DC/2; // set pwm duty cycle
//CCP1CON = PWM_off;
}
}
Alarm1Cnt++;
Alarm2Cnt++;
if (BackLightEn == 0)
if (((BackLightTimer++)>=60) & (Alarm1Alarm == false) & (Alarm1Alarm == false))
BackLightEn = 1; // disable backlight
PORTC = PORTC_MAP;
//TMR1IF = 0;
//PIR1 = PIR2 = 0x00;
CCP2IF = 0;
}
// -------------------------------------------------------
unsigned char get_key(void)
{
unsigned char key_in,tmp;
TRISC = 0x03;
KeyLine = 0xf0;
PORTC = KeyLine | PORTC_MAP;
#asm
nop
nop
nop
#endasm
if ((PORTA & 0x0f) != 0)
{
tmp = 0x10;
for (KeyLine = tmp;KeyLine!=0;KeyLine = tmp)
{
PORTC = KeyLine | PORTC_MAP;
tmp = KeyLine <<1;
#asm
nop
nop
nop
#endasm
key_in = PORTA & 0x0f;
if (key_in != 0)
{
return (key_in | KeyLine);
}
}
return 0;
}
else
return 0;
}
// -------------------------------------------------------
void set_mode(void)
{
if (CurrentMode == mode_set_alarm2)
CurrentMode = mode_time;
else
{
CurrentMode++;
adjust_item = 0;
}
lcd_write_inst(0x01); // clear LCD display
lcd_write_inst(time_start_addr); // set LCD line1
if (CurrentMode == mode_set_time)
{
lcd_write_data(CurrentTime.hourh + '0');
lcd_write_data(CurrentTime.hourl + '0');
lcd_write_data(':');
lcd_write_data(CurrentTime.minuteh + '0');
lcd_write_data(CurrentTime.minutel + '0');
lcd_write_data(':');
lcd_write_data(CurrentTime.secondh + '0');
lcd_write_data(CurrentTime.secondl + '0');
pStr = StrSetTime;
}
else if(CurrentMode == mode_set_date)
{
lcd_write_data(CurrentDate.year1 + '0');
lcd_write_data(CurrentDate.year2 + '0');
lcd_write_data(CurrentDate.year3 + '0');
lcd_write_data(CurrentDate.year4 + '0');
lcd_write_data('/');
lcd_write_data(CurrentDate.monthh + '0');
lcd_write_data(CurrentDate.monthl + '0');
lcd_write_data('/');
lcd_write_data(CurrentDate.dayh + '0');
lcd_write_data(CurrentDate.dayl + '0');
pStr = StrSetDate;
}
else if(CurrentMode == mode_set_alarm1)
{
lcd_write_data(AlarmTime1.hourh + '0');
lcd_write_data(AlarmTime1.hourl + '0');
lcd_write_data(':');
lcd_write_data(AlarmTime1.minuteh + '0');
lcd_write_data(AlarmTime1.minutel + '0');
lcd_write_data(':');
lcd_write_data(AlarmTime1.secondh + '0');
lcd_write_data(AlarmTime1.secondl + '0');
lcd_write_data(' ');
lcd_write_data('O');
if (Alarm1Enable)
{
lcd_write_data('n');
}
else
{
lcd_write_data('f');
lcd_write_data('f');
}
pStr = StrAlarm1;
Alarm1Cnt =0;
}
else if(CurrentMode == mode_set_alarm2)
{
lcd_write_data(AlarmTime2.hourh + '0');
lcd_write_data(AlarmTime2.hourl + '0');
lcd_write_data(':');
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -