《PIC单片机-多功能万年历电子钟.pdf》由会员分享,可在线阅读,更多相关《PIC单片机-多功能万年历电子钟.pdf(15页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、PIC 单片机-多功能万年历电子钟;*LIST P=PIC16F72#INCLUDE;*#DEFINE DIO_APORTA;RA 端口寄存器#DEFINE DIO_BPORTB;RB 端口寄存器#DEFINE DIO_CPORTC;RC 端口寄存器#DEFINE SIO_ATRISA;RA 端口输入、输出设定#DEFINE SIO_BTRISB;RB 端口输入、输出设定#DEFINE SIO_CTRISC;RC 端口输入、输出设定;=数码管共脚位定义=#DEFINE HOUH_LEDPORTB,3;数码管位选#DEFINE HOUL_LEDPORTB,2;数码管位选#DEFINE MINH_
2、LEDPORTB,1;数码管位选#DEFINE MINL_LEDPORTB,0;数码管位选#DEFINE SEC_LEDPORTB,4;LED 位选;=按键脚位定义=#DEFINE SETUP_KEYPORTA,3;时钟设置键#DEFINE INCREASE_KEY PORTA,4;时间加键#DEFINE DECREASE_KEY PORTA,5;时间减键;=DS1302 引脚定义=#DEFINE T_CLKPORTA,0;1302 时钟-7#DEFINE T_IOPORTA,1;1302 数据输入/输出-6#DEFINE T_RSTPORTA,2;1302 使能位-5#DEFINE SET_
3、IOTRISA,1;设定 1302I_O;=#DEFINE FLAG_10SFLAG,7;#DEFINE FLAG_SETUPFLAG,6;#DEFINE FLAG_500MSFLAG,5;#DEFINE FLAG_250MSFLAG,4;#DEFINE FLAG_MINUTEFLAG,3;#DEFINE FLAG_HOURFLAG,2;#DEFINE FLAG_TIMEFLAG,1;#DEFINE FLAG_DATEFLAG,0;=#DEFINE FLAG_YEARFLAG1,7;#DEFINE FLAG_DAYFLAG1,6;#DEFINE FLAG_DATAFLAG1,5;*寄存器定义*
4、ID_TEMPEQU72HW_TEMPEQU73HSTATUS_TEMPEQU74HPCLATH_TEMPEQU75H1/1 ERRORLEVEL-302 CBLOCK 020HSEC;秒寄存器MINUTE;分寄存器HOUR;小时寄存器DATE;日寄存器MONTH;月寄存器DAY;星期寄存器YEAR;年寄存器WRITE_ENABLED;写使能寄存器DS1302_RX;保存接受的 1 个数据DS1302_TX;准备写入到 DS1302 的一个数据BYTE_COUNT;字节数寄存器BIT_COUNT;BIT 数寄存器TEMP1;转换进制用TIMER0;TIMER1;定时用TIMER2;/;-FLA
5、GFLAG1FSR_TEMPCOUNTCOUNT1;显示数据位数COUNT2;显示数据表中位置COUNT3;显示位置COUNT4CNTCNT0CNT1CNT2SHOW_MINSHOW_HOUDATA_INCDATEPC1;C2;C3;ENDC;*宏定义*BANK1 MACRO;体 1BSRSTATUS,RP0BCRSTATUS,RP1ENDM1/1BANK0 MACRO;体 0BCRSTATUS,RP0BCRSTATUS,RP1ENDM;-;子程序名:;功能:中断服务主程序入口;功能说明:;-INTERMIT_SERVE:;-现场保护-STWRW_TEMP;SWAPRSTATUS,W;CLRR
6、STATUS;STWRSTATUS_TEMP;LDRPCLATH,W;STWRPCLATH_TEMP;CLRRPCLATH;-中断服务-INCRTIMER0,F;LDWI .100;XORWRTIMER0,W;判断是否到 250MSBTSSSTATUS,Z;/LJUMPAAA;ON,LDWIB00010000;每到 250MS 取反一次标志位 1XORWRFLAG,F;/CLRRTIMER0INCRTIMER1,F;LDWI .2;XORWRTIMER1,W;判断是否到 500MSBTSSSTATUS,Z;/LJUMPAAA;ON,LDWIB00100000;每到 500MS 取反一次标志位
7、1XORWRFLAG,F;/CLRRTIMER1;YES,INCRTIMER2,F;LDWI .20;XORWRTIMER2,W;判断是否到 5SBTSSSTATUS,Z;/LJUMP$+3;/CLRRTIMER2;YES,BSRFLAG_10S;DP_SECLCALLPLAY_SEC1/1MOVFWDIO_BANDWI0F0HSTWRDIO_BCLRRDIO_CINCRCOUNT,FLDWI01H;XORWRCOUNT,WBTSCSTATUS,ZLCALLPLAY_HOUR_H;LDWI02H;XORWRCOUNT,WBTSCSTATUS,ZLCALLPLAY_HOUR_L;LDWI03H;
8、XORWRCOUNT,WBTSCSTATUS,ZLCALLPLAY_MINUTE_H;LDWI04H;XORWRCOUNT,WBTSSSTATUS,ZLJUMP$+3CLRRCOUNTLCALLPLAY_MINUTE_L;LDWI0D9H;STWRTMR0;/写入 TMR0 初始值BCRINTCON,T0IF;清 TMR0 中断标志;-恢复现场-LDRPCLATH_TEMP,W;STWRPCLATH;SWAPRSTATUS_TEMP,F;STWRSTATUS;SWAPRW_TEMP,F;SWAPRW_TEMP,W;RTFI;中断返回;.;子程序名:;功能:清寄存器;功能说明:;.CLR_RAM
9、:LDWI20HSTWRFSRCLRRINDFINCRFSR,F1/1BTSSFSR,7LJUMP$-3RTIW00H;-;子程序名:;功能:查表子程序;功能说明:用于显示 0-9 时钟数据字型码,共阳 LED 无小数点;-TABLE:ADDWRPCL,FRTIWB11001111;0RTIWB00000101;1RTIWB11011100;2RTIWB10011101;3RTIWB00010111;4RTIWB10011011;5RTIWB11011011;6RTIWB00001101;7RTIWB11011111;8RTIWB10011111;9;.Program Initializati
10、on.;子程序名:单片机复位进入点;功能:;功能说明:;.PORT_INIT:CLRRINTCON;清除中断BANK1;LDWIB00000000;STWRSIO_C;RC 口设为输出LDWIB11100000;STWRSIO_B;/RB 口设为输入LDWIB11111000;STWRSIO_A;LDWI06H;STWRADCON1;A 口配置为普通数字 I/OLDWIB10000101;设 TMR0 分频 1:64STWROPTION_REG;/RB 口同时输入、出时不能上拉BANK0;-CLRRDIO_A;清控制位CLRRDIO_BCLRRDIO_C;关闭显示LDWI0DAH;写入 TMR
11、0 初始值1/1STWRTMR0;/2.5MS 中断一次LDWIB10100000;开 TMR0 中断使能位STWRINTCON;/LCALLCLR_RAM;-清寄存器LCALLDS1302_INIT;-初始化 DS1302LCALLREAD_DS1302;CALLDATE_INIT;CALLWRITE_DS1302;/写数据LCALLQINDON_INITMOVFWDATESTWRDATEP;%;程序名:;功能:;功能说明:;%MAIN_PROGRAM:BTSCFLAG_SETUPLJUMP$+3;NOP;NOPLCALLDELAY250MSLCALLREAD_DS1302;BTSSFLAG
12、_10S;检测是否到 5SLJUMP$+3;CLRRFLAG;3S 到,退出校正时间状态CLRRFLAG1;MOVFWDATEXORWRDATEP,WBTSCSTATUS,ZLJUMPTEST_KEYLDWI030HSUBWRSEC,WBTSSSTATUS,ZLJUMPTEST_KEY;-检测按键LDWI005HSUBWRSEC,FLCALLWRITE_DS1302;写入设置的数据MOVFWDATESTWRDATEPLJUMPMAIN_PROGRAM;循环;%TEST_KEY:NOP;1/1LDRDIO_A,W;ANDWIB00111000;XORWIB00111000;检测是否有按键按下?B
13、TSCSTATUS,Z;/LJUMPMAIN_PROGRAM;/BCRFLAG_10S;YES,重新启动 5S 到标记CLRRTIMER2;/;-BTSCFLAG_DATA;显示日期时禁止调整LJUMPMAIN_PROGRAM;/BTSSSETUP_KEY;检测是否按时间设置键?LJUMPSETUP;YES,跳设置键处理程序BTSSINCREASE_KEY;检测是否按增键?LJUMPINCREASE;YES,BTSSDECREASE_KEY;检测是否按减键?LJUMPDECREASE;YES,LJUMPMAIN_PROGRAM;时间设置键处理SETUP:LCALLDELAY_10MS;BTSS
14、SETUP_KEY;检测设置键是否松开?LJUMP$-2;/LCALLDELAY_10MS;LDWISHOW_HOU;STWRFSR;第一个调整单元LDWI24HSTWRDATA_INC;调整最大值BSRFLAG_SETUPBSRFLAG_HOURBSRFLAG_TIMELJUMPTEST_KEYDEC_MIN:INCRCOUNT2,FLDWI01H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC_MON;02HLDWISHOW_MINSTWRFSR;调整单元地址LDWI60HSTWRDATA_INC;调整最大值BSRFLAG_MINUTEBCRFLAG_HOURDEC_M
15、ON1/1LDWI02H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC_DATE;03HBSRFLAG_HOURBCRFLAG_MINUTEBSRFLAG_DATEBCRFLAG_TIMEDEC_DATELDWI03H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC_YEAR;04HLDWISHOW_MINSTWRFSR;调整单元地址LDWI32HSTWRDATA_INC;调整最大值BSRFLAG_MINUTEBCRFLAG_HOURDEC_YEARLDWI04H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC_DAY;05HMOV
16、FWSHOW_HOUSTWRMONTHMOVFWSHOW_MINBCRFLAG_MINUTEBSRFLAG_YEARBCRFLAG_DATEDEC_DAYLDWI05H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC_END;06HLDWISHOW_MINSTWRFSR;调整单元地址LDWI08HSTWRDATA_INC;调整最大值BSRFLAG_MINUTEBCRFLAG_HOURBSRFLAG_DAYBCRFLAG_YEARDEC_END1/1LDWI06H;XORWRCOUNT2,WBTSSSTATUS,ZLJUMPDEC1;MOVFWSHOW_HOUSTWRYEAR
17、MOVFWSHOW_MINSTWRDAYCLRRCOUNT2;清BCRFLAG_SETUP;清标示BCRFLAG_DAYBCRFLAG_MINUTELCALLWRITE_DS1302;写入设置的数据DEC1LJUMPTEST_KEY;增加键处理+INCREASE:LCALLDELAY_10MS;BTSSINCREASE_KEY;检测是否松开加键?LJUMP$-2;/LCALLDELAY_10MS;BTSSFLAG_SETUP;检测是否已进入设置状态?LJUMP$+8;YES,处理数据调整LCALLBCD_B;先 BCD 数据转换成 2 进制,INCRINDF,F;当前地址数据加 1LCALLB
18、_BCD;再将 2 进制数据转换成 BCD 码,写如该单元;判断调整到上限?MOVFWDATA_INC;XORWRINDF,W;判断当前地址数据变量大小BTSCSTATUS,Z;/CLRRINDF;/LJUMPMAIN_PROGRAM;/;减少键处理=DECREASE:LCALLDELAY_10MS;BTSSDECREASE_KEY;检测是否松开减键?LJUMP$-2;/LCALLDELAY_10MS;BTSSFLAG_SETUP;检测是否已进入设置状态?LJUMP$+7;YES,处理数据调整LCALLBCD_B;BCD 码转 2 进制LDRINDF,W;BTSCSTATUS,Z;判断下限减到
19、 0?LJUMPMAIN_PROGRAM;/1/1DECRINDF,F;LCALLB_BCD;2 进制转 BCD 码LJUMPMAIN_PROGRAM;返回主程序;.Program Initialization.;子程序名:;功能:启动 DS1302 开始计时;功能说明:;.QINDON_INITBCRT_CLK;BCRT_RST;先禁止LDWIB10000000;发送写使能寄存器命令STWRDS1302_TX;B7 必须为 1BSRT_RST;LCALLSEND_BYTE;-发送一个字节数据BCRSEC,7MOVFWSEC;允许写使能命令STWRDS1302_TX;/LCALLSEND_BY
20、TE;-发送一个字节的数据BCRT_RST;-DS1302 复位RET;.Program Initialization.;子程序名:;功能:写 DS1302 初始数据;功能说明:写入 10 年 09 月 19 日 10 时 05 分 00 秒;.DATE_INIT:LDWIB00000000;B7=0 表示启动时钟震荡,B7=1 表示暂停时钟震荡STWRSEC;/B6B4 表示秒十位,B3-B0 表示秒个位;秒寄存器,BCD 码格式,初始 00 秒LDWI05H;STWRMINUTE;/;分钟寄存器,BCD 码格式,00-59LDWIB00010000;B7=0 表示 24 小时方式,B7=1
21、 表示 12 小时方式,当选 12 小时方式下STWRHOUR;B6=未用,B5=1 表示下午 B5=0 表示上午,B4=小时高位 B3-B0 小时低位;小时寄存器,BCD 码格式,00-59LDWI19HSTWRDATE;日;日期寄存器,BCD 码格式,00-31LDWI09HSTWRMONTH;月;月份寄存器,BCD 码格式,00-12LDWI07H1/1STWRDAY;星期;星期寄存器,BCD 码格式,0-7LDWI10H;STWRYEAR;年;年寄存器,BCD 码格式,00-99RET;-;子程序名:DS1302_INI;功能:初始化 1302,先禁止 RST,允许写使能;功能说明:;
22、-DS1302_INIT:BCRT_CLK;BCRT_RST;先禁止LDWIB10001110;发送写使能寄存器命令STWRDS1302_TX;B7 必须为 1,B6=1 表示对 RAM 进行操作 B6=0 表示读写时钟/日历数据;B5B1 为寄存器地址位,B0 为 0 表示写,为 1 表示读BSRT_RST;LCALLSEND_BYTE;-发送一个字节数据LDWIB00000000;允许写使能命令STWRDS1302_TX;/;B7=1 为写保护,B7=0 为写允许,B0B6=0 固定为 0LCALLSEND_BYTE;-发送一个字节的数据BCRT_RST;-DS1302 复位;-LDWIB
23、10010000;90H 设定充电方式命令STWRDS1302_TX;写入缓冲BSRT_RST;-允许操作 DS1302LCALLSEND_BYTE;BCRT_RST;-DS1302 复位RET;-;子程序名:SEND_BYTE;功能:调用一次发送一个字节的数据;功能说明:数据从低位开始发送,用于发送 1302 的控制命令或发送一个数据;-SEND_BYTE:LDWID8;写入 BIT 数STWRBIT_COUNT;/SEND_LOOP:BCRT_IO;BCRT_CLK;-BIT 数在 T_CLK 低电平时变化BTSCDS1302_TX,0;检测发送缓冲寄存器位 0,是 1 就发 1.是 0
24、就发 01/1BSRT_IO;/RRRDS1302_TX,F;向右移 1 位,为发送下一个 BIT 准备BSRT_CLK;确定发送有效DECRSZBIT_COUNT,F;检测是否发送完 8 个 BIT?LJUMPSEND_LOOP;继续发送下一位BCRT_CLK;返回RTIW00H;发送完 8BIT 数返回;-;子程序名:READ_BYTE;功能:调用一次读出一个字节的数据;功能说明:数据从低位开始发送,用于发送 1302 的控制命令或发送一个数据;-READ_BYTE:BANK1BSRSET_IO;I_O 设置为输入BANK0NOPLDWID8;读 8 个 BIT 数据STWRBIT_COU
25、NT;/READ_LOOP:BCRT_CLK;下降沿读取BCRSTATUS,C;BTSCT_IO;接收一个 BITBSRSTATUS,C;/RRRDS1302_RX,FBSRT_CLK;恢复高电平DECRSZBIT_COUNT,F;检测是否读完 8BIT?LJUMPREAD_LOOP;-循环读出BANK1BCRSET_IO;I_O 恢复为输出BANK0BCRT_CLKRETNOP;*;子程序名:READ_DS1302;功能:突发模式读 DS1302;说明:1.FLAG_RAM=1 读 RAM14 个字节定时数据;2.FLAG_RAM=0 读 7 个字节日历/时钟数据;*READ_DS1302:
26、BSRT_RST;-启动 DS1302LDWIB10111111;-ON,读日历/时钟突发模式命令多字节STWRDS1302_TX;-写入发送寄存器1/1LCALLSEND_BYTE;-发送LDWISEC;-ON,准备接收 DS1302 时钟数据的首地址STWRFSR;写入间接寻址寄存器LDWID7;-,ON,1 次读出 7 个字节日历/时钟数据STWRBYTE_COUNT;-写入字节计数器READ_BITLCALLREAD_BYTELDRDS1302_RX,W;将 8BIT 数据写入数据保存处STWRINDF;/INCRFSR,F;数据保存处地址加 1,为下一个数据提供地址DECRSZBYT
27、E_COUNT,F;检测是否读完数据?LJUMPREAD_BIT;-否,循环BCRT_RST;-DS1302 复位,禁止操作RET;读完 7 个日历/时钟数据,返回;*;子程序名:WRITE_DS1302;功能:突发模式写 DS1302;说明:1.定时标志 FLAG_TIMER=1 写 14 个字节定时数据-RAM;2.定时标志 FLAG_TIMER=0 写 7 个字节日历/时钟数据/写使能命令;*WRITE_DS1302:LDWIB10111110;-ON,写时钟多字节命令STWRDS1302_TX;BSRT_RST;发送突发模式写时钟命令LCALLSEND_BYTE;/;-;BCFT_CL
28、K;BCFT_IO;LDWISEC;-ON,准备写时钟/日历数据首地址STWRFSR;LDWID8;-ON,准备写时钟的字节数STWRBYTE_COUNT;/WRITE_BYTE:LDRINDF,W;拷贝地址数据内容到发送缓冲STWRDS1302_TX;/LCALLSEND_BYTEINCRFSR,F;-数据发送地址加 1,为下一个数据提供地址DECRSZBYTE_COUNT,F;检测是否写完数据?LJUMPWRITE_BYTE ;BCRT_RST;-DS1302 复位,禁止操作RET;写完数据,返回;%;子程序名:显示 LED;功能:1/1;功能说明:;%PLAY_SEC:;显示秒闪烁BTS
29、SFLAG_500MS;检测闪烁频率LJUMP$+3 ;/BSRSEC_LED ;RETBCRSEC_LED ;RET;=;显示分 L 位 MLMLMLMLMLMLMLMLMLMLMLMLMLMLMLMLMMLMLMLMLMPLAY_MINUTE_L:BSRMINL_LED ;BTSSFLAG_MINUTE;-检测是否要闪烁当前单元?LJUMP$+3 ;BTSSFLAG_250MS;检测闪烁频率LJUMP$+0AH ;/LDRSHOW_MIN,W;ANDWI0FH ;LCALLTABLE ;STWRDIO_C;ADDWRDIO_C,FRETBTSSFLAG_DAY;指示灯不跟着闪烁LJUMP$
30、+4MOVFWDIO_CXORWIB00100000STWRDIO_CRET;显示分 H 位 MHMHMHMHMHMHMHMHMHMHMHMHMHMHMHPLAY_MINUTE_H:BSRMINH_LED;BTSSFLAG_MINUTE;-检测是否要闪烁当前单元?LJUMP$+3 ;BTSSFLAG_250MS;检测闪烁频率LJUMP$+0AH ;/SWAPRSHOW_MIN,W;ANDWI0FH;LCALLTABLE ;STWRDIO_C;BTSSFLAG_YEARBTSSFLAG_YEARLJUMP$+41/1MOVFWDIO_CXORWIB00100000STWRDIO_CRET;显示时
31、 L 位 HLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLPLAY_HOUR_L:BSRHOUL_LED;BTSSFLAG_HOUR;-检测是否要闪烁当前单元?LJUMP$+3 ;BTSSFLAG_250MS;检测闪烁频率LJUMP$+0AH ;/LDRSHOW_HOU,WANDWI0FH;LCALLTABLE ;STWRDIO_C;MOVFWDIO_CXORWIB00100000STWRDIO_CRET;显示时 H 位 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHPLAY_HOUR_H:BSRHOUH_LED;BTSSFLAG_HOUR;-检测是否要闪烁当前单元?LJUMP$+3 ;BTSSFLAG_250MS;检测闪烁频率LJUMP$+0AH ;/SWAPRSHOW_HOU,W;ANDWI0FH;LCALLTABLE ;STWRDIO_C;MOVFWDIO_CXORWIB00100000STWRDIO_CRETEND1/1