PIC单片机之时钟设置
PIC16F887时钟课设
《PIC单片机》课程设计学生姓名:学生学号:指导教师:鲍光海二○一三年5月16 日目录1. 课程设计目的 (2)2. 课程设计题目和要求 (2)3. 课程设计报告内容 (3)3.1 硬件原理图 (3)3.2 软件原理框图 (6)3.3 功能实现 (7)4. 课设中存在的问题以及解决方法 (8)5 设计体会 ........................................................................................ 错误!未定义书签。
6 参考文献 (8)7 附录 (9)7.1 仿真原理图 (9)7.2 部分程序 (9)7.2.1 秒表程序 (9)7.2.2 闹钟程序 (12)1.课程设计目的《PIC单片机课程设计》是电气工程及其自动化专业及相近专业的一门重要的专业实践课,本课程设计是在《PIC 单片机》课程的基础上,通过硬件设计与软件编程与调试的实践,进一步掌握PIC单片机的应用方法,熟练PIC单片机的C程序的编写与调试,是毕业设计前的一次重要实践,为今后走上工作岗位打下坚实的单片机应用基础。
通过本次课程设计:熟悉PCB板的焊接流程,熟练运用Proteus进行原理图设计与仿真,熟练运用MPLAB和ICD2进行软件编程与调试熟练掌握PIC16F887 TC74模块(IIC接口的温度传感器)、实时时钟芯片DS1307、定时器、中断的编程方法;熟练掌握LCD YB1602A、按键模块的应用与编程设计掌握单片机应用的一般设计方法,熟悉开发一单片机应用系统的全过程,为今后从事相应的工作打下基础。
学会用C语言编写一个完整的程序,掌握程序的设计方法,拓展编程思维。
2. 课程设计题目和要求本次课程设计我的设计题目为《多功能数字钟》,通过在PROTEUS仿真及在开发板上调试,功能实现。
设计内容:采用DS1307芯片和单片机进行IIC通信,将时钟芯片中的数据读出来,然后送到LCD1602中去显示,然后设置秒表功能,闹钟功能,还有温度显示功能,通过按键的切换来实现各个功能。
基于PIC16F887单片机的温度、时钟显示以及闹钟功能
基于PIC16F887单片机的温度、时钟显示以及闹钟功能一、课程设计的目的《PIC 单片机课程设计》是电气工程及其自动化专业及相近专业的一门重要的专业实践课,本课程在《PIC 单片机》课程的基础上,通过硬件设计与软件编程与调试的实践,进一步掌握PIC 单片机的应用方法,熟练PIC 单片机的C 程序的编写与调试,是毕业设计前的一次重要的实践,为今后走上工作岗位打下坚实的单片机应用基础。
二、设计内容1 Proteus 线路图绘制根据所设计的线路图,绘制与之一致的,能用于仿真的Proteus 线路图。
要求所绘的线路图美观、紧凑,参数要与课设一致。
2、软件编制与调试根据所设计的线路图制相应的单片机C 程序,要求所制的程序符合C 语言格式并加上注解。
每编一段即进行译,有错及时修改,并先在Proteus 上仿真,基本正确后再用PICkit3 在线调试,最后应脱机运行。
三、设计目标1该设计包括数字钟及数字温度计:按键的使用.LCD.蜂鸣器时钟芯片DS1307和温度传感器TC74。
2功能;此设计可以感测环境的温度,显示当前的时间,及闹钟。
温度与时间都显示在LCD显示屏上,以及如何调整闹钟界面四硬件设计及说明1复位按键2时钟芯片DS1307及附属接线时钟芯片DS1307用于产生时间,它提供了秒、分、时、日、年、和星期等数据,能算只瑞年2100年,时钟的晶振是典型的32.768Hz。
(1)其引脚作用如下:2(2)DS1307的读写如下;1写DS1307 的步骤如下:a) 发送启始位;b) 发送DS1307 的7位地址+0 (写),即0b11010000;c) 发送要写入DS1307 的地址,地址见图16,如要修改分,此值为1;d) 发送要写入DS1307 的数,如要把分修改为十进制数37,则此数为0x37;e) 发送停止位;2读DS1307 的步骤如下:a) 发送启始位;b) 发送DS1307 的7位地址+0 (写),即0b11010000;c) 发送要读的DS1307 的起始地址,如要从秒读起,为0;d) 发送停止位;e) 发送重新开始位;f) 发送DS1307 的7位地址+1 (读),即0b11010001;g) 发送读使能位,接收一个数据,单片机发送应答位;h) 发送读使能,接收下一个数据(地址会自动+1),单片机发送应答位,直到读数完成,接收最后一个数时单片机不发送应答位;i) 发送停止位;注意在DS1307仿真的时候七位地址为0b1001101 而实际为0b1001000 ;(3)功能是;提供时间通过pic16F877送入LCD中显示。
PIC单片机的时钟模式
PIC单片机的时钟模式
任何一个单片机要工作都需要一个时钟使单片机按给定的时钟节拍一步一步的执行程序。
对于这样一个时钟,在PIC 单片机上有多种工作配置方式,比起传统的51 系列单片机,其时钟模式得到了极大的丰富,然而这给初学者带
来了一定的困难。
单片机标准时钟模式:用石英晶体或陶瓷振荡器产生工作时钟,如图1 所示。
图1 PIC 单片机晶体振荡原理图与普通单片机相比,PIC 晶体振荡模式的最大特点是内部振荡电路放大器的增益是可调的。
如图1,Rf 为增益调节电阻。
主要原因是不同振荡频率的晶体,为保证其可靠振荡而所需的激励功率是完全不一样的。
按常规,振荡器频率越低,其所需的激励功率越小。
如果振荡器输出给晶体的激励功率不符合晶体自身的工作特性要求,可能就会有以下两种结果出现:1、激励功率过大,振荡波形就会发生畸变,晶体可能
会震到其高次谐波上去,更糟糕的是晶体可能会被震碎(如音叉型的32768Hz 晶体);2、激励过小,晶体起振困难,起振时间很长,长时间工作还可能出现停振现象等等。
PIC 振荡电路的这种可调增益使用户能够灵活合理地配置其设计的晶体振荡电路。
PIC 有三种增益模式:振荡模式增益量适用器件参考振荡频率范围LP 最低低频晶体2MHz 要强调,作为设计者在选择恰当的振荡模式时不能机械的按表查找,不同厂家生产的晶体品质差异较大。
同样是4MHz 的晶振,有的配置成XT 模式即能正常工作,有的需要配制成HS 才稳定可靠。
tips:感谢大家的阅读,本文由我司收集整编。
仅供参阅!。
用C语言写的一个PIC16F877的时闹钟程序
用C语言写的一个PIC16F877的时闹钟程序单片机用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@, skype:kingeda, E-mail:kingeda@// Website: // 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 0x88char 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.3unsigned 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 100unsigned char lcd_addr;unsigned char KeyLine;unsigned char KeyOld;unsigned char KeyNew;struct mTime {unsigned char hourh; // hour,0~23unsigned char hourl;unsigned char minuteh; // minute,0~59unsigned char minutel;unsigned char secondh; // second,0~59unsigned 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.3unsigned 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 4unsigned 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 lcdlcd_rs = 0;lcd_rw = 1; // instlcd_e = 1;#asmnopnopnop#endasmch = lcd_bus;lcd_e = 0;lcd_dir = 0x00; // set write to lcdreturn ch;}// ------------------------------------------------------- unsigned char lcd_write_data(unsigned char ch) {while (lcd_busy){ restart_wdt(); }lcd_rs = 1; // datalcd_rw = 0; // writelcd_bus = ch; // write outlcd_e = 1;#asmnopnopnop#endasmlcd_e = 0;return 'Y';}// ------------------------------------------------------- unsigned char lcd_write_inst(unsigned char ch) {while (lcd_busy){ restart_wdt(); }lcd_rs = 0; // instlcd_rw = 0; // writelcd_bus = ch;lcd_e = 1;#asmnopnopnop#endasmlcd_e = 0;return 'Y';}// ------------------------------------------------------- unsigned char lcd_read_data(){unsigned char ch;while (lcd_busy){ restart_wdt(); }lcd_dir = 0xff; // read from lcdlcd_rs = 1; // datalcd_rw = 1; // readlcd_e = 1;#asmnopnopnop#endasmch = lcd_bus; // read inlcd_e = 0;lcd_dir = 0x00; // set write to lcdreturn ch;}// ------------------------------------------------------- void lcd_init(){unsigned char Tempch;lcd_addr = 0;delay_ms(100);Tempch = 0x38; // 1-line mode,5x8 dotslcd_write_inst(Tempch); // Function setTempch = 0x0f; // lcd on,cursor on,blink onlcd_write_inst(Tempch); // Display on/offTempch = 0x06; // Increment mode,Entire shift offlcd_write_inst(Tempch);Tempch = 0x01; // clear displaylcd_write_inst(Tempch);delay_ms(3);}// -------------------------------------------------------//#int_timer1//void timer1_interrupt(void)#int_ccp2void 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++;}elseCurrentDate.year2++;}elseCurrentDate.year3++;}elseCurrentDate.year4++;}else if(CurrentDate.monthl == 9){CurrentDate.monthl = 0;CurrentDate.monthh++;}elseCurrentDate.monthl++;}else if(CurrentDate.dayl == 9){CurrentDate.dayl=0;CurrentDate.dayh++;}elseCurrentDate.dayl++;}elseCurrentTime.hourl++;}elseCurrentTime.minuteh++;}elseCurrentTime.minutel++;}elseCurrentTime.secondh++;}elseCurrentTime.secondl++;if ((Alarm1Alarm == false) & (Alarm2Alarm == false)){led = 0;CCP1CON = PWM_off;}else{if (led == 1){led = 0;PR2 = PWM_period; // set pwm periodCCPR1L = PWM_DC; // set pwm duty cycle//CCP1CON = PWM_on;}else{led = 1;PR2 = PWM_period/2; // set pwm periodCCPR1L = 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;#asmnopnopnop#endasmif ((PORTA & 0x0f) != 0){tmp = 0x10;for (KeyLine = tmp;KeyLine!=0;KeyLine = tmp){PORTC = KeyLine | PORTC_MAP;tmp = KeyLine <<1;#asmnopnopnop#endasmkey_in = PORTA & 0x0f;if (key_in != 0){return (key_in | KeyLine);}}return 0;}elsereturn 0;}// -------------------------------------------------------void set_mode(void){if (CurrentMode == mode_set_alarm2)CurrentMode = mode_time;else{CurrentMode++;adjust_item = 0;}lcd_write_inst(0x01); // clear LCD displaylcd_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(':');lcd_write_data(AlarmTime2.minuteh + '0');lcd_write_data(AlarmTime2.minutel + '0');lcd_write_data(':');lcd_write_data(AlarmTime2.secondh + '0');lcd_write_data(AlarmTime2.secondl + '0');lcd_write_data(' ');lcd_write_data('O');if (Alarm2Enable){lcd_write_data('n');}else{lcd_write_data('f');lcd_write_data('f');}pStr = StrAlarm2;Alarm2Cnt = 0;}lcd_write_inst(0xc0); // set LCD line2 if (CurrentMode != mode_time){for (;*pStr!=0;pStr++){ // write hint messagelcd_write_data(*pStr);}lcd_write_inst(0x0f); // LCD cursor onlcd_write_inst(time_start_addr); // move cursor to start }else // time mode,write date to second line{lcd_write_inst(0x0c); // LCD sursor off/* lcd_write_inst(0xc0 + 3); // set date start address 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');*/ }if (CurrentMode == mode_set_time){lcd_write_inst(time_start_addr); // move cursor to start }else if (CurrentMode == mode_set_date){lcd_write_inst(time_start_addr); // move cursor to start }else if (CurrentMode == mode_set_alarm1){lcd_write_inst(time_secondl_addr+3);adjust_item = 6;}else if (CurrentMode == mode_set_alarm2){lcd_write_inst(time_secondl_addr+3);adjust_item = 6;}else{lcd_write_inst(0x0c); // LCD cursor off}}// ------------------------------------------------------- void set_date(void){if (adjust_item == 0) // adjust year{if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year1 = KeyNew;lcd_write_data(CurrentDate.year1 + '0');//lcd_write_inst(time_start_addr);adjust_item ++;}else if (KeyNew == key_left){adjust_item = 7;lcd_write_inst(time_start_addr + 9);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 1);}}else if(adjust_item == 1){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year2 = KeyNew;lcd_write_data(CurrentDate.year2 + '0');//lcd_write_inst(time_start_addr + 1);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 0);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 2);}}else if(adjust_item == 2){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year3 = KeyNew;lcd_write_data(CurrentDate.year3 + '0');//lcd_write_inst(time_start_addr + 2);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 1);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 3);}}else if(adjust_item == 3){if ((KeyNew >=0) & (KeyNew <= 9)){CurrentDate.year4 = KeyNew;lcd_write_data(CurrentDate.year4 + '0');//lcd_write_inst(time_start_addr + 3);adjust_item ++;lcd_write_inst(time_start_addr + 5);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 2);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 5);}}else if(adjust_item == 4)if (((CurrentDate.monthl>2) & (KeyNew == 0)) | ((CurrentDate.monthl == 0) & (KeyNew == 1))| (((CurrentDate.monthl == 1) | (CurrentDate.monthl == 2)) & (KeyNew <2))) {CurrentDate.monthh = KeyNew;lcd_write_data(CurrentDate.monthh + '0');//lcd_write_inst(time_start_addr + 5);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 3);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 6);}}else if(adjust_item == 5){if (((CurrentDate.monthh == 3) & (KeyNew <2)) | ((CurrentDate.monthh != 3) & (KeyNew >=0) & (KeyNew <=9))){CurrentDate.monthl = KeyNew;lcd_write_data(CurrentDate.monthl + '0');//lcd_write_inst(time_start_addr + 6);adjust_item ++;lcd_write_inst(time_start_addr + 8);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 5);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 8);}}else if(adjust_item == 6)if (((CurrentDate.dayl>1) & ((KeyNew == 1) | (KeyNew == 2))) | ((CurrentDate.dayl == 0) & (KeyNew >0) & (KeyNew<4))| ((CurrentDate.dayl == 1) & (KeyNew <4))){CurrentDate.dayh = KeyNew;lcd_write_data(CurrentDate.dayh + '0');//lcd_write_inst(time_start_addr + 8);adjust_item ++;}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 6);}else if (KeyNew == key_right){adjust_item ++;lcd_write_inst(time_start_addr + 9);}}else if(adjust_item == 7){if (((CurrentDate.dayh == 3) & (KeyNew <2)) | ((CurrentDate.dayh != 3) & (KeyNew >=0) & (KeyNew <=9))){CurrentDate.dayl = KeyNew;lcd_write_data(CurrentDate.dayl + '0');//lcd_write_inst(time_start_addr + 9);adjust_item ++;lcd_write_inst(time_start_addr + 0);}else if (KeyNew == key_left){adjust_item --;lcd_write_inst(time_start_addr + 8);}else if (KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_start_addr + 0);}}}// -------------------------------------------------------void set_time(void){if (adjust_item == 0) // set hourh{if (((CurrentTime.hourl <4) & (KeyNew < 3)) | ((CurrentTime.hourl >3) & (KeyNew <2))){CurrentTime.hourh = KeyNew;lcd_write_data(CurrentTime.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 5;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((CurrentTime.hourh == 2) & (KeyNew < 4)) | ((CurrentTime.hourh < 2) & (KeyNew <=9))){CurrentTime.hourl = KeyNew;lcd_write_data(CurrentTime.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){CurrentTime.minuteh = KeyNew;lcd_write_data(CurrentTime.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){CurrentTime.minutel = KeyNew;lcd_write_data(CurrentTime.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){CurrentTime.secondh = KeyNew;lcd_write_data(CurrentTime.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;&nb, sp; lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){CurrentTime.secondl = KeyNew;lcd_write_data(CurrentTime.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item = 0;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void set_alarm1(void){if (adjust_item == 0) // set hourh{if (((AlarmTime1.hourl <4) & (KeyNew < 3)) | ((AlarmTime1.hourl >3) & (KeyNew <2))){AlarmTime1.hourh = KeyNew;lcd_write_data(AlarmTime1.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 6;lcd_write_inst(time_secondl_addr + 3);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((AlarmTime1.hourh == 2) & (KeyNew < 4)) | ((AlarmTime1.hourh < 2) & (KeyNew <=9))){AlarmTime1.hourl = KeyNew;lcd_write_data(AlarmTime1.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){AlarmTime1.minuteh = KeyNew;lcd_write_data(AlarmTime1.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime1.minutel = KeyNew;lcd_write_data(AlarmTime1.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){AlarmTime1.secondh = KeyNew;lcd_write_data(AlarmTime1.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime1.secondl = KeyNew;lcd_write_data(AlarmTime1.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr+3);}}else if (adjust_item == 6) // set on/off{if ((KeyNew == key_up) | (KeyNew == key_down)){if (Alarm1Enable){Alarm1Enable =false; // disable alarm1lcd_write_data('f');lcd_write_data('f');}else{Alarm1Enable =true; // enable alarm1lcd_write_data('n');lcd_write_data(' ');}//lcd_write_inst(time_secondl_addr+3);adjust_item = 0;lcd_write_inst(time_hourh_addr);Alarm1Cnt = 0;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void set_alarm2(void){if (adjust_item == 0) // set hourh{if (((AlarmTime2.hourl <4) & (KeyNew < 3)) | ((AlarmTime2.hourl >3) & (KeyNew <2))){AlarmTime2.hourh = KeyNew;lcd_write_data(AlarmTime2.hourh + '0'); // refresh hourh//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item = 6;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_hourl_addr);}}else if (adjust_item == 1) // set hourl{if (((AlarmTime2.hourh == 2) & (KeyNew < 4)) | ((AlarmTime2.hourh < 2) & (KeyNew <=9))){AlarmTime2.hourl = KeyNew;lcd_write_data(AlarmTime2.hourl + '0'); // refresh hourl//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minuteh_addr);}}else if (adjust_item == 2) // set minuteh{if (KeyNew <6){AlarmTime2.minuteh = KeyNew;lcd_write_data(AlarmTime2.minuteh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_hourl_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_minutel_addr);}}else if (adjust_item == 3) // set minutel{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime2.minutel = KeyNew;lcd_write_data(AlarmTime2.minutel + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minuteh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondh_addr);}}else if (adjust_item == 4) // set secondh{if (KeyNew <6){AlarmTime2.secondh = KeyNew;lcd_write_data(AlarmTime2.secondh + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_minutel_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr);}}else if (adjust_item == 5) // set secondl{if ((KeyNew >=0) & (KeyNew <=9)){AlarmTime2.secondl = KeyNew;lcd_write_data(AlarmTime2.secondl + '0');//lcd_write_inst(0x10); // move cursor backadjust_item ++;lcd_write_inst(time_secondl_addr+3);}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondh_addr);}else if(KeyNew == key_right){adjust_item ++;lcd_write_inst(time_secondl_addr+3);}}else if (adjust_item == 6) // set on/off{if ((KeyNew == key_up) | (KeyNew == key_down)){if (Alarm2Enable){Alarm2Enable =false; // disable alarm2lcd_write_data('f');lcd_write_data('f');}else{Alarm2Enable =true; // enable alarm2lcd_write_data('n');lcd_write_data(' ');}//lcd_write_inst(time_secondl_addr+3);adjust_item = 0;lcd_write_inst(time_hourh_addr);Alarm2Cnt = 0;}else if(KeyNew == key_left){adjust_item --;lcd_write_inst(time_secondl_addr);}else if(KeyNew == key_right){adjust_item = 0;lcd_write_inst(time_hourh_addr);}}}// -------------------------------------------------------void main(void){unsigned char cnt;TRISC = 0x03; // PORTC.3 drive led,low activePORTC_MAP = 0x00;led = 0;BackLightEn = 0;BackLightTimer = 0;PORTC = PORTC_MAP;TRISA = 0xff; // low half byte as keyscan inTRISE = 0x00;ADCON0 = 0x00;ADCON1 = 0x06; // all digital I/Oslcd_init();INTCON = 0x00;lcd_write_inst(0x80); // set lcd ddram addressfor (pStr = StrPower1;*pStr!=0;pStr++){lcd_write_data(*pStr);}lcd_write_inst(0x0c); // LCD cursor offPIR1 = PIR2 = 0x00;T1CON = 0x0f; // T1CON: -- T1CKPS1 T1CPS0 T1OSCEN /T1SYNC TMR1CS TMR1ONTMR1H = 0x80;TMR1L = 0x00;。
PIC单片机在ICD做lcd显示时钟演示程序
PIC单片机在ICD做lcd显示时钟演示程序include <p16f877.inc>;*----; 定义LCD数据& 控制I/O口LCD_DA TA equ PORTBLCD_CNTL1 equ PORTBLCD_CNTL2 equ PORTA; 定义 LCD控制相应的I/O引脚RS equ 1E equ 5; LCD 模块命令DISP_ON EQU 0x00C ; 开显示DISP_ON_C EQU 0x00E ; 开显示, 开指针DISP_ON_B EQU 0x00F ; 开显示, 开指针,开闪烁DISP_OFF EQU 0x008 ; 关显示CLR_DISP EQU 0x001 ; 清显示的操作数ENTRY_INC EQU 0x006 ; 操作数ENTRY_INC_S EQU 0x007 ; 操作数ENTRY_DEC EQU 0x004 ; 操作数ENTRY_DEC_S EQU 0x005 ; 操作数DD_RAM_ADDR EQU 0x080 ; 初始化第一行显示的操作数DD_RAM_UL EQU 0x0c0 ; 初始化第二行显示的操作数; 设置显示相关寄存器Byte EQU 20HCount EQU 21HCount1 EQU 22HCount2 EQU 23HLCD_DATA1 EQU 24HPORTDB EQU 25HTemp EQU 26HTempH EQU 27HTempL EQU 28HINTSIG EQU 29HRTCCSIG1 EQU 2AHRTCCSIG EQU 2BHALRSIG EQU 2CHHour EQU 2DHHourH EQU 2EHHourL EQU 2FHHourL1 EQU 30HHourH1 EQU 31HMins EQU 32HMins1 EQU 33HMinsH EQU 34HMinsL EQU 35HMinsH1 EQU 36HMinsL1 EQU 37HSecs EQU 38HSecsH EQU 39HSecsL EQU 3AHALRH1 EQU 3BHALRM1 EQU 3CHALRH2 EQU 3DHALRM2 EQU 3EHALRH3 EQU 3FHALRM3 EQU 40H_WREG EQU 41H_STATUS EQU 42HHour1 EQU 43HADRESB EQU 44HBKM EQU 45H;*----org 0nopgoto startorg 4goto ISRorg 10CalTablebcf STATUS,RP0bcf PCLATH,0movlw 0x66 ; 进行校准处理subwf Temp,w ;addwf PCL,f ; 将补偿结果与 PCL相加dt 0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5dt 6,6,6,7,7,7,8,8,8,9,9,0xa,0xa,0xb,0xb,0xc,0xcdt 0xd,0xd,0xe,0xe,0xf,0xf,0xf,0x10,0x10,0x10dt 0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x14,0x14,0x14 dt 0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x18,0x18 dt 0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1cdt 0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20dt 0x21,0x21,0x22,0x22,0x23,0x23,0x24,0x24,0x25,0x25dt 0x26,0x26,0x27,0x28,0x29,0x29,0x2a,0x2a,0x2b,0x2b dt 0x2c,0x2d,0x2e,0x2f,0x30,0x32startcall InitLCDclrf RTCCSIGclrf RTCCSIG1clrf INTSIGclrf Hourclrf Hour1clrf Minsclrf Mins1clrf Secsclrf ALRSIGmovlw 20hmovwf BKMmovlw b'10001111'movwf PORTDBmovlw 0ffhmovwf TMR0movlw 00movwf TMR1Lmovlw 80hmovwf TMR1Hmovlw b'00001111'movwf T1CONbsf STATUS,RP0bsf PIE1,TMR1IEbcf STATUS,RP0movlw b'10111111'OPTIONmovlw b'11110000'movwf INTCONmainmovlw 80hcall SendCmdcall DisplayTime ;显示时间movlw 0c0hcall SendCmdmovlw 'H'call putcLCDmovlw 'e'call putcLCDmovlw 'l'call putcLCDmovlw 'l'call putcLCDmovlw 'o'call putcLCDmovlw ' 'call putcLCDmovlw '!'call putcLCDmovlw ' 'call putcLCDmovlw ':'call putcLCDmovlw ')'call putcLCDmovlw ' 'call putcLCDmovlw ' 'call putcLCDcall BkLight ;背光控制call TempM ;显示温度btfsc ALRSIG,1call ALR1btfsc ALRSIG,2call ALR2btfsc ALRSIG,3call ALR3bcf STATUS,RP0bcf PCLATH,0movf RTCCSIG,Waddwf PCL,1goto maingoto RtccS1goto RtccS2goto Rtccs3goto Rtccs4clrf RTCCSIGclrf RTCCSIG1goto main;*=====ALR1 bcf STATUS,RP0 movf Hour,Wxorwf ALRH1,Wbtfss STATUS,Zmovf Mins,Wxorwf ALRM1,Wbtfss STATUS,Zgoto ALRENDbsf STATUS,RP0clrf TRISDbcf STATUS,RP0bcf STATUS,Crlf PORTDB,1btfsc STATUS,Cbsf PORTDB,0movf PORTDB,W movwf PORTDreturn;*---ALR2 bcf STATUS,RP0 movf Hour,Wxorwf ALRH2,Wbtfss STATUS,Zgoto ALRENDmovf Mins,Wxorwf ALRM2,Wbtfss STATUS,Zgoto ALRENDbsf STATUS,RP0clrf TRISDbcf STATUS,RP0bcf STATUS,Crlf PORTDB,1btfsc STATUS,Cbsf PORTDB,0movf PORTDB,W movwf PORTDreturn;*----ALR3 bcf STATUS,RP0 movf Hour,Wxorwf ALRH3,Wbtfss STATUS,Zgoto ALRENDmovf Mins,Wxorwf ALRM3,Wbtfss STATUS,Zbsf STATUS,RP0clrf TRISDbcf STATUS,RP0bcf STATUS,Crlf PORTDB,1btfsc STATUS,Cbsf PORTDB,0movf PORTDB,Wmovwf PORTDreturn;*---ALRENDbsf STATUS,RP0movlw 0ffhmovwf TRISDreturn;*=====RtccS1movlw 80hcall SendCmdcall DisplayTimecall LongDelaymovlw 0c0hcall SendCmd ;line2, 00 movlw 'S'call putcLCDmovlw 'e'call putcLCDmovlw 't'call putcLCDmovlw ' 'call putcLCDmovlw 'T'call putcLCDmovlw 'i'call putcLCDmovlw 'm'call putcLCDmovlw 'e'call putcLCD ;show "Set Time" movlw ' 'call putcLCDmovlw ' 'call putcLCD movlw ' 'call putcLCD movlw ' 'call putcLCD bsf PCLATH,0 movf RTCCSIG1,W addwf PCL,1 goto SetHour goto SetMins clrf INTSIGincf RTCCSIG clrf RTCCSIG1 goto main;*----SetHourmovlw 80hcall Selshow movlw d'24' subwf INTSIG,W btfsc STATUS,C goto $+4movf INTSIG,w movwf Hourgoto RtccS1clrf INTSIG movwf Hourgoto RtccS1;*----SetMinsmovlw 83hcall Selshow movlw d'60' subwf INTSIG,W btfsc STATUS,C goto $+4movf INTSIG,w movwf Minsgoto RtccS1clrf INTSIG movwf Minsgoto RtccS1;*=====RtccS2bcf STATUS,RP0 movlw 0c0hcall SendCmdcall Alarm movlw '1'call putcLCD movlw ' 'call putcLCDS2 movlw 80hcall SendCmdcall DisplayTime call DispTime call LongDelay bsf PCLATH,0 movf RTCCSIG1,W addwf PCL,1goto SetAlH2 goto SetAlM2 movf Hour1,w movwf ALRH1 movf Mins1,w movwf ALRM1clrf INTSIGclrf RTCCSIG1 incf RTCCSIG goto main;*---SetAlH2movlw 0c7hcall Selshow movf INTSIG,W btfss STATUS,Z bsf ALRSIG,1 movf INTSIG,W movwf Hour1 movlw d'24' subwf Hour1,W btfss STATUS,C goto S2clrf INTSIGclrf Hour1goto S2SetAlM2movlw 0cahcall Selshow movf INTSIG,W btfss STATUS,Z bsf ALRSIG,1 movf INTSIG,W movwf Mins1 movlw d'60' subwf Mins1,W btfss STATUS,C goto S2clrf INTSIGclrf Mins1goto S2;*----Alarm movlw 'A' call putcLCD movlw 'l'call putcLCD movlw 'a'call putcLCD ; movlw 'r'call putcLCD movlw 'm'call putcLCD ; return;*----Selshowcall SendCmd movlw ' 'call putcLCD movlw ' 'call putcLCD call LongDelay return;*=====Rtccs3bcf STATUS,RP0 movlw 0c0hcall SendCmd call Alarm movlw '2'call putcLCD movlw ' 'call putcLCDS3 movlw 80hcall SendCmdcall DisplayTime call DispTime call LongDelay bsf PCLATH,0 movf RTCCSIG1,w addwf PCL,1goto SetAlH3 goto SetAlM3 movf Hour1,w movwf ALRH2 movf Mins1,w movwf ALRM2clrf INTSIGclrf RTCCSIG1 incf RTCCSIG goto main;*---SetAlH3movlw 0c7hcall Selshow movf INTSIG,W btfss STATUS,Z bsf ALRSIG,2 movf INTSIG,W movwf Hour1 movlw d'24' subwf Hour1,W btfss STATUS,C goto S3clrf INTSIGclrf Hour1goto S3SetAlM3movlw 0cahcall Selshow movf INTSIG,W btfss STATUS,Z bsf ALRSIG,1 movf INTSIG,W movwf Mins1 movlw d'60' subwf Mins1,Wgoto S3clrf INTSIGclrf Mins1goto S3;*=====Rtccs4movlw 80hcall SendCmdcall DisplayTime bcf STATUS,RP0 movlw 0c0hcall SendCmdcall Alarm movlw '3'call putcLCD movlw ' 'call putcLCDS4 call DispTime call LongDelay bsf PCLATH,0 movf RTCCSIG1,w addwf PCL,1goto SetAlH4 goto SetAlM4 movf Hour1,w movwf ALRH3 movf Mins1,w movwf ALRM3clrf INTSIGclrf RTCCSIG1 incf RTCCSIG goto main;*---SetAlH4movlw 0c7hcall Selshow movf INTSIG,W btfss STATUS,Z bsf ALRSIG,3 movf INTSIG,W movwf Hour1 movlw d'24' subwf Hour1,Wgoto S4clrf INTSIGclrf Hour1goto S4SetAlM4movlw 0cahcall Selshowmovf INTSIG,Wbtfss STATUS,Zbsf ALRSIG,1movf INTSIG,Wmovwf Mins1movlw d'60'subwf Mins1,Wbtfss STATUS,Cgoto S4clrf INTSIGclrf Mins1goto S4;*=====ISRPushmovwf _WREG ; 存 WREG状态swapf STATUS,W ; 存 STATUS movwf _STATUS;*----bcf STATUS,RP0btfsc PIR1,TMR1IFcall TimeAdjbtfsc INTCON,INTFcall IntDealbtfsc INTCON,T0IFcall RtccDeal;*----Popswapf _STATUS,W ; Restore STATUS movwf STATUSswapf _WREG,F ; Restore WREG w/o swapf _WREG,W ; affecting STATUS retfie;*=====TimeAdjbcf PIR1,TMR1IFmovlw 00hmovwf TMR1Lmovlw 80hmovwf TMR1Hincf Secs,1movlw d'60'xorwf Secs,Wbtfss STATUS,Zgoto TEclrf Secsincf Mins,1movlw d'60'xorwf Mins,Wbtfss STATUS,Zgoto TEclrf Minsincf Hourmovlw d'24'xorwf Hour,Wbtfss STATUS,Zgoto TEclrf HourTEreturn;*=====IntDealbcf INTCON,INTFbsf PORTB,0btfsc PORTB,0 ;\goto $+5 ; \call Delaybsf PORTB,0 ; 按键去抖动btfsc PORTB,0goto $+2 ; /incf INTSIGreturn;*=====RtccDealbcf STATUS,RP0movlw 0ffh ;movwf TMR0bcf INTCON,T0IFbsf PORTA,4btfsc PORTA,4 ;\goto RtcWr ; \call Delaybsf PORTA,4 ; 按键去抖动btfsc PORTB,4goto RtcWr ; /movf RTCCSIG,Wsublw 04hbtfss STATUS,Cgoto WRONGmovf RTCCSIG1,Wsublw 03hbtfss STATUS,Cgoto WRONGmovf RTCCSIG,Waddwf RTCCSIG1,Wbtfsc STATUS,Zgoto $+3incf RTCCSIG1goto RtcWrincf RTCCSIGgoto RtcWrWRONGclrf RTCCSIGclrf RTCCSIG1RtcWr return;*=====BkLightbsf STATUS,RP0bcf ADCON1,ADFM ;ADRESH all 8-bit,H bcf STATUS,RP0movlw b'01010001'movwf ADCON0 ;select AD2,Fosc/8 decfsz BKMgoto $-1bsf ADCON0,GObtfss PIR1,ADIFgoto $-1bcf PIR1,ADIF;READ ADRES---movf ADRESH,Wmovwf ADRESBbsf STATUS,RP0bcf TRISE,0 ;SELECT RE0 OUTPUTbcf STATUS,RP0movlw b'10000000' ;critical value of lightness subwf ADRESB,Wbtfss STATUS,Cgoto $+4 ;c=0,ADRESB<criticalbcf STATUS,RP0bsf PORTE,0 ;c=1,backlight ongoto $+3bcf STATUS,RP0bcf PORTE,0movlw 20hmovwf BKMreturn;*=====TempM ;temprature measurebsf STATUS,RP0bcf ADCON1,ADFM ;ADRESH all 8-bitbcf STATUS,RP0movlw b'01001001' ;select AD1,FOSC/8movwf ADCON0decfsz BKMgoto $-1bsf ADCON0,GObtfss PIR1,ADIFgoto $-1bcf PIR1,ADIF;bsf STATUS,RP0movf ADRESH,W;bcf STATUS,RP0movwf Tempcall CalTablemovwf Tempcall Bin2BCDT ; 进行BCD码调整movlw 08ah ; 从第一行的第0A个位置开始call SendCmdmovf TempH,W ; 显示温度call putcLCDmovf TempL,Wcall putcLCDmovlw 'C' ; 显示“C”(表示摄氏度)call putcLCDmovlw 20hmovwf BKMreturn;************************************************ ;* Bin2BCDT - 将 Temp 寄存器内的二进制数转 *;* 换为相应的 ASCII 码并存为 TempH:TempL 的形式 * ;************************************************ Bin2BCDTbcf STATUS,RP0clrf TempH ; Initialize variablesmovf Temp,Wmovwf TempLTtenth ; Subtract 10 from low variablemovlw .10 ; until result is < 0. On eachsubwf TempL,W ; subtraction, increment thebtfss STATUS,C ; temperature high byte.goto Over0movwf TempLincf TempH,Fgoto TtenthOver0movlw 0x30 ; Make decimal ASCII by addingaddwf TempH,F ; '0' to high and low byteaddwf TempL,Freturn;************************************************* ;* DisplayTime - 将显示指针移至第一行,调用Bin2BCD* ;* 子程序将Secs 和 Mins寄存器内的数据转换为相应的* ;* ASCII 码, 然后送 LCD显示. *;************************************************* DisplayTimebcf STATUS,RP0call Bin2BCD ; 调用二进制与bcd码转换子程序movf HourH,W ; 显示小时高位call putcLCD ;movf HourL,W ; 显示小时低位call putcLCD ;movlw ':'call putcLCD ; 显示 ':'movf MinsH,W ; 显示分钟高位call putcLCD ;movf MinsL,W ; 显示分钟低位call putcLCD ;movlw ':' ; 显示 ':'call putcLCDmovf SecsH,W ; 显示秒钟高位call putcLCD ;movf SecsL,W ; 显示秒钟低位call putcLCD ;return;************************************************ ;* Bin2BCD - 将 Secs & Mins 寄存器内的二进制数转* ;* 换为相应的 ASCII 码并存为 SecsH:SecsL 及 *;* MinsH:MinsL,HourH:HourL的形式. *;************************************************ Bin2BCDbcf STATUS,RP0clrf HourH ; 初始化变量movf Hour,W ; 转换“时”movwf HourLHourth ; Loop to subtract 10movlw .10 ; from low byte andsubwf HourL,W ; increment high bytebtfss STATUS,C ; while low byte is > 0goto Nextmovwf HourLincf HourH,Fgoto HourthNextclrf MinsH ; 初始化变量movf Mins,W ; 转换“分”movwf MinsLMtenth ; Loop to subtract 10movlw .10 ; from low byte andsubwf MinsL,W ; increment high bytebtfss STATUS,C ; while low byte is > 0goto Next1movwf MinsLincf MinsH,Fgoto MtenthNext1clrf SecsH ; 初始化变量movf Secs,W ; 转换“秒”movwf SecsLStenth ; Loop to subtract 10movlw .10 ; from low byte andsubwf SecsL,W ; increment high bytebtfss STATUS,C ; while low byte is > 0goto Overmovwf SecsLincf SecsH,Fgoto StenthOvermovlw 0x30 ;addwf HourH,F ;addwf HourL,F ; Add 0x30 ('0') to all addwf MinsH,F ; variables to convertaddwf MinsL,F ; a number 0 - 9 to anaddwf SecsH,F ; ASCII equivalentaddwf SecsL,F ; '0' to '9'return;*====DispTimebcf STATUS,RP0movlw 0c7hcall SendCmdcall Bin2BCa ; 调用二进制与bcd码转换子程序movf HourH1,W ; 显示小时高位call putcLCD ;movf HourL1,W ; 显示小时低位call putcLCD ;movlw ':' ; 显示 ':'call putcLCDmovf MinsH1,W ; 显示分钟高位call putcLCD ;movf MinsL1,W ; 显示分钟低位call putcLCD ;return;*----Bin2BCabcf STATUS,RP0clrf HourH1 ; 初始化变量movf Hour1,W ; 转换“时”movwf HourL1Hourth1 ; Loop to subtract 10movlw .10 ; from low byte andsubwf HourL1,W ; increment high bytebtfss STATUS,C ; while low byte is > 0 goto Nextamovwf HourL1incf HourH1,Fgoto Hourth1Nextaclrf MinsH1 ; 初始化变量movf Mins1,W ; 转换“分”movwf MinsL1Mtenth1 ; Loop to subtract 10movlw .10 ; from low byte andsubwf MinsL1,W ; increment high bytebtfss STATUS,C ; while low byte is > 0goto Over1movwf MinsL1incf MinsH1,Fgoto Mtenth1Over1movlw 0x30 ;addwf HourH1,F ;addwf HourL1,F ; Add 0x30 ('0') to alladdwf MinsH1,F ; variables to convertaddwf MinsL1,F ; a number 0 - 9 to anreturn ; ASCII equivalent;******************************************************************* ;* LCD 模块子程序 *;******************************************************************* ;InitLCD——初始化LCD模块 *;******************************************************************* InitLCDbcf STATUS,RP0 ; Bank 0bcf STATUS,RP1clrf LCD_DATA ; 清 LCD 数据 & 控制位bsf STATUS,RP0 ; Bank 1movlw 0xc1 ; 设置RB1~RB5为输出movwf LCD_DATAbcf TRISA,5bcf STATUS,RP0 ;movlw 0x00 ;movwf LCD_DATAbsf LCD_CNTL2, Ebcf LCD_CNTL2, Emovlw 0x08 ;movwf LCD_DATAbsf LCD_CNTL2, Ebcf LCD_CNTL2, Ecall LongDelaycall LongDelaymovlw b'00101000'call SendCmdmovlw DISP_ON ; 开显示call SendCmdmovlw ENTRY_INC ; 设置指针移动方式call SendCmdmovlw DD_RAM_ADDR ; 设置起始地址call SendCmdInitLCDEnd ;bcf STATUS,RP0 ;movlw CLR_DISP ;call SendCmdreturn;******************************************************************* ;*putcLCD——将字符数据送入 LCD *;* 本程序将字符数据分成了高半字节和低半字节分别输入 *;* 先送入的是高半字节 *;******************************************************************* putcLCDbcf STATUS,RP0movwf Byte ; 存 WREG 到 Byte 寄存器swapf Byte,W ; 写入高半字节movwf LCD_DATA1rlf LCD_DATA1,1rlf LCD_DATA1,1movlw 0x3candwf LCD_DATA1,1movf LCD_DATA1,wmovwf LCD_DATAbsf LCD_CNTL1, RS ; 设置为送数据模式bsf LCD_CNTL2, E ; 发送数据信号bcf LCD_CNTL2, Emovf Byte,W ; 接着送低半字节movwf LCD_DATA1rlf LCD_DATA1,1rlf LCD_DATA1,1movlw 0x3candwf LCD_DATA1,1movf LCD_DATA1,wmovwf LCD_DATAbsf LCD_CNTL1, RS ; 设置为送数据模式bsf LCD_CNTL2, E ; 发送数据信号bcf LCD_CNTL2, Ecall Delayreturn;******************************************************************* ;* SendCmd - 送命令到 LCD *;* 本程序将命令数据分成了高半字节和低半字节分别输入 *;* 先送入的是高半字节 *;******************************************************************* SendCmdbcf STATUS,RP0movwf Byte ; 存 WREG 到 Byte 寄存器swapf Byte,W ; 送入命令的高字节movwf LCD_DATA1rlf LCD_DATA1,1rlf LCD_DATA1,1movlw 0x3candwf LCD_DATA1,1movf LCD_DATA1,wmovwf LCD_DATAbcf LCD_CNTL1,RS ; 设置为送命令模式bsf LCD_CNTL2,E ; 发送数据信号bcf LCD_CNTL2,Emovf Byte,W ; 接着送命令的低字节movwf LCD_DATA1rlf LCD_DATA1,1rlf LCD_DATA1,1movlw 0x3candwf LCD_DATA1,1movf LCD_DATA1,wmovwf LCD_DATAbcf LCD_CNTL1,RS ; 设置为送命令模式bsf LCD_CNTL2,E ; 发送数据信号bcf LCD_CNTL2,Ecall Delayreturn;******************************************************************* ;* Delay - 延时子程序 *;******************************************************************* Delay ; call指令占用2个指令周期bcf STATUS,RP0clrf Count ; 清 Count占用1个指令周期Dloopdecfsz Count,f ; 这两行指令将延时goto Dloop ; (256 * 3) -1 个指令周期return ; return占用2个指令周期;******************************************************************* ;* LongDelay - 长延时子程序 *;******************************************************************* LongDelaybcf STATUS,RP0clrf Countclrf Count1movlw 0x03movwf Count2LDloopdecfsz Count,fgoto LDloopdecfsz Count1,fgoto LDloopdecfsz Count2,fgoto LDloopreturn;*------END。
用PIC单片机制作LED数字钟
该电路采用9v成品电源适配器供电输出电流为looma再通过三踹稳压模块78lo5降压给电路供电闹钟输出部分是低电平有效通过vt5输出驱动自带振荡电路的bc发声实现闹钟功能
用PIC单片机制作LED数字钟
本文介绍的LED数字钟是利用PICl6F84A单片机实现如下图所示,它走其电路图见图2。该电路采用9V成品电源适配器供电,输出电流为lOOmA,再通过三踹稳压模块78LO5降压给电路供电,闹钟输出部分是低电平有效,通过VT5输出驱动自带振荡电路的BC发声实现闹钟功能。如将BC换成继电器就可以实现对其他家用电器的控制。
PIC单片机配置位
PIC单片机配置位在嵌入式系统的世界里,PIC 单片机以其出色的性能和灵活性备受青睐。
而要充分发挥 PIC 单片机的潜力,理解和正确配置其配置位至关重要。
PIC 单片机的配置位就像是为单片机定制的一系列规则和设置,决定了单片机的工作方式、性能特点以及与外部世界的交互方式。
它们犹如幕后的指挥家,默默影响着单片机的每一个动作。
首先,让我们来谈谈时钟配置位。
时钟对于单片机来说就如同心跳,决定了其运行的节奏。
通过配置位,可以选择内部振荡器还是外部时钟源作为单片机的“动力源泉”。
内部振荡器虽然方便,但精度可能有限;而外部时钟源则能提供更高的精度和稳定性,但需要额外的硬件支持。
在存储配置方面,配置位决定了程序存储器和数据存储器的访问方式和保护级别。
比如,可以设置是否允许程序在运行时自我修改,或者对特定的存储区域进行读写保护,以防止误操作或恶意篡改。
中断配置位也是不容忽视的一部分。
中断是单片机高效处理外部事件的重要手段。
通过配置位,可以决定哪些外部事件能够触发中断,以及中断的优先级。
这就像是在繁忙的交通路口设置信号灯,确保重要的事件能够优先得到处理。
电源管理配置位则关乎单片机的能耗控制。
在电池供电的应用中,合理配置电源管理位可以让单片机在不同的工作状态下切换电源模式,实现节能的目的。
例如,在待机模式下降低功耗,延长电池寿命。
再来说说端口配置位。
单片机的端口是与外部设备连接的接口,配置位决定了端口的输入输出方向、驱动能力以及上拉下拉电阻的状态。
这就好比为每个端口设定好角色和能力,以便与各种外部设备顺利通信。
还有一些配置位用于设置单片机的看门狗功能。
看门狗就像是单片机的“保镖”,在程序出现异常时能够及时复位单片机,保证系统的稳定性和可靠性。
在实际应用中,正确配置 PIC 单片机的配置位需要对项目的需求有清晰的了解。
如果是一个对实时性要求很高的系统,可能需要优先考虑中断配置和时钟配置;而对于注重功耗的应用,则要精心设置电源管理配置位。
PIC24系列单片机原理与开发 第3章 时钟和系统管理
设所需的配置为: 禁双速启动,使用主振荡器和 PLL 四倍频, OSC1 与 OSC2 引脚接 8MHz 的 XT 晶振,禁时钟切换和保护监视。 在程序中加入下面的芯片配置字 2 的宏便可实现所需配 置。 _CONFIG2(IESO_OFF & FNOSC_PRIPLL & FCKSM_CSDCMD & POSCMOD_ XT) 若配置改为使用片内快速RC振荡器(8MHz,不分频) 和PLL四倍频, 禁止主振荡器, 其余不 变,则芯片配置字2的宏为: _CONFIG2(IESO_OFF & POSCMOD_NONE & FCKSM_CSDCMD & FNOSC_FRCPLL) 因为没有启用主振荡器,因此 OSC1 与 OSC2 引脚可作 I/O 用。 说明:1. 当配置为禁止主振荡器时(POSCMD<1:0> = 11,宏定义为POSCMOD_NONE) ,引脚 OSC1 和 OSC2自动配置成数字I/O功能(RC12和RC15)。 2. 当主振荡器配置为 外部时钟 的EC 模式时 (POSCMD<1:0> = 00,宏定义为 POSCMOD_EC),外部时钟接OSC1引脚,若将 OSCIOFCN位(配置字2<5>)编程为0或引用 宏定义OSCIOFNC_ON,OSC2引脚仍可以为数字I/O,否则OSC2引脚上为Fosc/2 时钟输出, 可用于系统时钟测试或同步。
PIC24 系列单片机原理与开发
by
Zeng
2012-6-9
如下: (1)在 OSCCON 寄存器解锁和写序列期间禁止中断 。 (2)用两条字节传送指令将 78h 和 9Ah 写入 OSCCON<15:8>, 以执行 OSCCON 高字节的 解锁序列。 (3)紧接上面解锁序列之后将新的振荡器源写入 NOSC<2:0>。。 (4)用两条字节传送指令将 46h 和 57h 写入 OSCCON<7:0>,以执行 OSCCON 低字节的 解锁序列。 (5)紧接着将 OSWEN 位置 1。 (6)调用软件延时,使选中的振荡器和/或 PLL 启动并稳定。 (7)检查 OSWEN 位是否为 0,如果为 0,则说明切换成功。 下面是解锁 OSCCON 寄存器和启动时钟切换的核心序列 。 例 3-1:时钟切换的基本代码序列 .global _Exam3_1 _Exam3_1: ;W0<2:0>为新的振荡器选择 PUSH SR ;状态寄存器入栈 MOV #0x0e0,w1 ;准备使 IPL<2:0>=0b111, MOV w1,SR ;CPU 中断优先级 7,禁止所有可屏蔽中断 MOV #OSCCONH,w1 ;OSCCONH (OSCCON 寄存器的高字节) 解锁序列 MOV #0x78, w2 MOV #0x9A, w3 MOV.b w2, [w1] MOV.b w3, [w1] MOV.b WREG, OSCCONH ;设置新的振荡器选择 MOV #OSCCONL,w1 ;OSCCONL(OSCCON 寄存器的低字节) 解锁序列 MOV #0x46, w2 MOV #0x57, w3 MOV.b w2, [w1] MOV.b w3, [w1] BSET OSCCON,#0 ; 启动时钟切换 POP SR ; 恢复状态寄存器 RETURN 上面的汇编子程序作为 C 函数调用的格式为: void Exam3_1(int X)。参数 X 的 bit2:0= 新振荡器选择位 NOSC<2:0>。例如将系统时钟切换成带分频的 FRC 为: Exam3_1(0b 111); 在基本序列完成后,系统时钟硬件按以下方式自动响应 : (1)若 COSC<2:0>位与 NOSC<2:0>位的值相同,则不进行切换操作,OSWEN 位自动清零, 时钟切换终止。 (2)如果启动了有效的时钟切换,则 LOCK 位(OSCCON<5>)和 CF 位(OSCCON<3>)清零。 (3)如果新的振荡器当前未运行 ,硬件会自动启动它。如果启动晶体振荡器,则硬件将等 待到振荡器起振定时器( OST)计时期满。如果新的振荡器源使用 PLL,则硬件将等待 到 PLL 锁定(位 LOCK = 1)。 (4)硬件等待新的时钟源达到稳定 ,然后执行时钟切换。 (5)硬件清零 OSWEN 位,指示时钟切换成功,并且 COSC<2:0>更新成 NOSC<2:0>位的值。 (6 ) 关闭旧时钟源。但是若旧时钟源是下面两种情况时例外 :若闪存配置字 1 中使能 WDT
PIC单片机C语言精确控制时间
PIC单片机C语言精确控制时间很多朋友说C不能精确控制延时时间,不能像汇编那样直观。
其实不然,对延时函数深入了解一下就能设计出一个理想的框架出来。
一般我们都用for(VX=100;--X;){;}此句等同于X=100;while(--X){;};或Vfor(x=0;x<100;x++){;};来写一个延时函数。
在这里要注意:X=100,并不是表示只运行100个指令就跳出循环。
可以看看编译后的汇编:X=100;while(--x){;}汇编后:movlw 100bcf 3,5bcf 3,6movwf _delayl2 decfsz _delaygoto 12return从代码中可以看出总的指令是303个,其公式是8+3*(x-1).注意其中循环周期是X-1,为99个。
这里总结的是X为char类型的循环体,当X为int的时候,其中受X值影响较大。
建议设计一个char类型的循环体,然后再用一个循环体来调用它,可以实现精确的长时间延时。
下面给出一个能精确控制延时的函数,此函数的汇编代码是最简洁,最能精确控制指令时间的:void delay (char x,char y){Char z;Do{z=y;do {;}while(--z);} while (--x);}其指令时间为:7+(3*(Y-1)+7)*(X-1)。
如果再加上函数调用的call指令,页面设定,传递函数花掉的7个指令,则是:14+(3*(Y-1)+7)*(X-1)。
如果要求不是特别严格的延时,可以用这个函数:void delay()unsigned int d=1000;while(--d){;)}此函数在4M晶体下产生10003US的延时,也就是10MS。
如果把d改成2000,就是20003US,以此类推。
有朋友不明白,为什么不用while(x--)后减量,来设定X值是多少就循环多少次呢?现在我们看看它的汇编代码:bcf 3,5bcf 3,6movlw 10movwf _delay12decf _delayincfsz _delay,wgoto 12return可以看出循环体中多了一条指令,不简洁。
PIC单片机自学笔记之TMR0数字钟
PIC自学笔记之TMR0数字时钟实验环境:Proteus编程语言:汇编编程环境:MPLAB单片机:PIC16F877晶振:4MHz首先声明一点:该数字时钟并不能精确地显示时间,因为定时器置初值的过程中会造成无法弥补的误差。
虽然如此,该文作为一篇针对对TMR0定时器应用,键盘扫描模块和数码管显示模块的一个整合应用,我想应该还算得上比较成功的一次实验。
因而传上来,希望能为刚接触PIC单片机的朋友们做个参考。
功能说明:该数字时钟实验,以定时器0为时钟源,采用1/256预分频,初始时间设定在了该实验完成的那一刻。
时钟的显示是通过八个七段数码管,由八个74HC573来驱动,在驱动器的选择上,选择了74HC138译码器,通过PORTE 的三个I/O口来控制,键盘模块在主程序中,通过循环扫描的方式来获取键盘信息,其中,KEY1是总控制键,按一下可进入分钟的设置,按两下进入小时的设置,按三下退出设置;KEY2和KEY3分别是‘加’和‘减’操作键。
操作流程为,首先按KEY1选择设置分钟还是小时,然后通过KEY2或KEY3调整其值(注:单纯的按KEY2或KEY3不会对时钟进行设置)Proteus仿真图键盘电路仿真效果图部分程序源代码list p=16f877INCLUDE P16F877.INCSECOND equ 20hMINUTE equ 21hHOUR equ 22hBSTA TUS equ 23hBW equ 24hBPCH equ 25hBFSR equ 26hD20 equ 27hCOM0 EQU 28H;公共单元COM1 EQU 29HCOM2 EQU 2AHCOM3 EQU 2BHCOM4 EQU 2CHCOM5 EQU 2DHCOM6 EQU 2EHDIS0 EQU 2FH;显示寄存器单元DIS1 EQU 30HDIS2 EQU 31HDIS3 EQU 32HDIS4 EQU 33HDIS5 EQU 34HDISC EQU 35HDELA Y1 EQU 36H;延时寄存器单元DELA Y2 EQU 37HKEYCOM0 EQU 38H;键盘键值单元KEYCOM1 EQU 39HFLAG EQU 3AH;键盘标志单元KEYDELY EQU 3BHORG 000HGOTO MAINORG 004H;中断入口,此处只用了定时器0的中断TMR0INT:MOVWF BWSW APF STA TUS,0CLRF STA TUSMOVWF BSTA TUSMOVF FSR,0MOVWF BFSRMOVF PCLA TH,0MOVWF BPCHCLRF PCLA TH;以上是入中断前的现场保护;************************BCF STA TUS,RP1;以下开始为时钟计算单元BCF STA TUS,RP0BTFSS INTCON,5;判断定时器0的中断是否被允许,也可以不要,但又的话更稳定GOTO INTOUTBTFSS INTCON,2;判断定时器0溢出标志位GOTO INTOUTBCF INTCON,2;清定时器0中断标志位MOVLW H'3C';定时器0赋初值MOVWF TMR0DECFSZ D20GOTO INTOUTMOVLW D'20';一秒定时到MOVWF D20INCF SECONDMOVLW D'60'XORWF SECOND,0BTFSS STA TUS,ZGOTO DISW;显示CLRF SECONDINCF MINUTEMOVLW D'60'XORWF MINUTE,0BTFSS STA TUS,ZGOTO DISWCLRF MINUTEINCF HOURMOVLW D'24'XORWF HOUR,0BTFSS STA TUS,ZGOTO DISWCLRF HOURDISW:CALL DIS;显示子程序;************************INTOUT: MOVF BPCH,0;中断返回,恢复现场MOVWF PCLA THMOVF BFSR,0MOVWF FSRSW APF BSTA TUS,0MOVWF STA TUSSW APF BW,1SW APF BW,0RETFIEMAIN:BANKSEL PORTA;初始化各相关寄存器clrf PORTAclrf PORTDCLRF PORTEMOVLW H'F0'MOVWF PORTBmovlw h'a0'movwf INTCONMOVLW H'3C'MOVWF TMR0MOVLW D'21'MOVWF D20CLRF SECONDMOVLW D'17';设置开机显示时间小时值MOVWF HOURMOVLW D'24';设置开机显示分钟值MOVWF MINUTECLRF DIS0;CLRF DIS1MOVLW D'4'MOVWF DIS2MOVLW D'2'MOVWF DIS3MOVLW D'7'MOVWF DIS4MOVLW D'1'MOVWF DIS5BANKSEL TRISAMOVLW H'07';定时器0设置为内部时钟源,1/256预分频MOVWF OPTION_REGCLRF TRISECLRF TRISDMOVLW H'F0'MOVWF TRISBCLRF PIE1CLRF PIE2BANKSEL PORTAMOVLW H'02'MOVWF PORTE;数码管选择MOVLW H'40'MOVWF PORTDMOVLW H'05'MOVWF PORTECALL DISGOTO KEYKEYDIS: BTFSS FLAG,0GOTO KEYCALL DISGOTO KEYDIS: MOVF SECOND,0;显示处理MOVWF COM3CALL DIV10;除10子程序,商在COM3中,余数在COM5中MOVF COM5,0MOVWF DIS0MOVF COM3,0MOVWF DIS1MOVF MINUTE,0MOVWF COM3CALL DIV10MOVF COM5,0MOVWF DIS2MOVF COM3,0MOVWF DIS3MOVF HOUR,0MOVWF COM3CALL DIV10MOVF COM5,0MOVWF DIS4MOVF COM3,0MOVWF DIS5MOVLW DIS0MOVWF FSRCLRF DISCDISLOOP: MOVF DISC,0MOVWF PORTEMOVF INDF,0CALL LEDISMOVWF PORTDINCF DISCINCF FSRMOVF DISC,0MOVWF PORTEMOVF INDF,0CALL LEDISMOVWF PORTDINCF DISCINCF DISCINCF FSRMOVLW D'9'XORWF DISC,0BTFSS STA TUS,ZGOTO DISLOOPRETURNLEDIS:ADDWF PCLRETLW H'3F';0RETLW H'06';1RETLW H'5B';2RETLW H'4F';3RETLW H'66';4RETLW H'6D';5RETLW H'7D';6RETLW H'07';7RETLW H'7F';8RETLW H'6F';9KEY: MOVLW KEYCOM0;键盘扫描程序CALL KEYREAD;调用读PORTB状态程序BTFSC STA TUS,ZGOTO KEYCALL DELA Y5MS;延时5MS消抖MOVLW KEYCOM0CALL KEYREADBTFSC STA TUS,ZGOTO KEYBTFSC KEYCOM0,7;确认有键按下后,进而判断是哪个键被按下GOTO KEY0;KEY1处理子程序BTFSC KEYCOM0,6GOTO KEY ADD;加处理BTFSS KEYCOM0,5GOTO KEYGOTO KEYSUB;减处理KEY0: BTFSS PORTB,7GOTO KEY0;等待按键释放BTFSC FLAG,0;FLAG,0在KEY1第一次被按下后被置一,在第三次按下时清零GOTO KEY1BSF FLAG,0BCF INTCON,5BCF INTCON,2KEYLP: BTFSS FLAG,2GOTO KEYGOTO KEYOUTKEY1: INCF FLAGBSF FLAG,0GOTO KEYLPKEY ADD: BTFSS FLAG,0GOTO KEYKADD: BTFSS PORTB,6GOTO KADDMOVLW MINUTEBTFSC FLAG,1MOVLW HOURMOVWF FSRINCF INDFMOVLW D'60'BTFSC FLAG,1;FLAG,1是分和时区分标志MOVLW D'24'XORWF INDF,0BTFSC STA TUS,ZCLRF INDFGOTO KEYDISKEYSUB: BTFSS FLAG,0GOTO KEYKSUB: BTFSS PORTB,5GOTO KSUBMOVLW MINUTEBTFSC FLAG,1MOVLW HOURMOVWF FSRDECF INDFMOVLW D'59'BTFSC FLAG,1MOVLW D'23'BTFSC INDF,7MOVWF INDFCLRWGOTO KEYDISDIV10: MOVLW D'10';除十子程序MOVWF COM4CLRF COM5MOVLW D'8'MOVWF COM6DIV101: BCF STA TUS,CRLF COM3RLF COM5BSF COM3,0MOVF COM4,0SUBWF COM5BTFSS STA TUS,CCALL ADDDECFSZ COM6GOTO DIV101RETURNADD:MOVF COM4,0ADDWF COM5BCF COM3,0RETURNDELA Y5MS:;5MS延时MOVLW D'75'MOVWF DELA Y1DLOOP: MOVLW D'100'MOVWF DELA Y2DLOOP1: DECFSZ DELA Y2GOTO DLOOP1DECFSZ DELA Y1GOTO DLOOPRETURNKEYREAD:MOVWF FSR;读PORTB状态MOVF PORTB,0ADDLW H'F0'XORLW H'F0'MOVWF INDFRETURNKEYOUT: CLRF FLAGBSF INTCON,5GOTO KEYEND。
基于PIC16F887单片机的数字钟完整c程序代码
#include <pic.h>__CONFIG (0x20F1);__CONFIG (0x3FFF); //调试用#define LCD_E RD6 //LCD E 读写使能控制#define LCD_RW RD5 //LCD 读(1)/写(0)控制线#define LCD_RS RD4 //LCD 寄存器选择数据(1)指令(0)//RD4-RD7分别接DB4-DB7,RD7为忙标志#define COM 0 //在LCD_WRITE()中的第2参数为0表示写命令#define DAT 1 //在LCD_WRITE()中的第2参数为1表示写数据#define mod RB3//模式选择(时间、闹钟、温度、秒表)#define set RB0//选择按键#define add RB1//加按键#define miu RB2//减按键#define RTR 0b00000000 //TC74的读温度命令#define TC74_ADD 0b1001101 //TC74的7位地址#define LINE1 0b10000000#define LINE2 0b11000000signed char hourt,mint,sect;//闹钟设置位int f;//闹钟显示清零判断char flag=0;//按键标志位char WW,QW,BW,SW,GW,M;char table[]="Mon Tue Wed Thu Fri Sat Sun ";//星期signed char year,month,day,week,hour,min,sec,a,T;bank1 char DD[16]; //一行LCD显示数据暂存char A[7];//DS1307读数//====LCD程序void CSH(void); //初始化void LCD_CSH(void); //LCD初始化void LCD_BUSY(void); //检测LCD是否忙char LCD_READ(void); //读LCD,忙检测用void LCD_WRITE(char,char); //LCD写1字节,命令或数据void LCD_WRITE_4(char,char); //LCD写半字节void DISP_C(char); //在指定行中显示字符,字符在数组DD中void DISP_MENU(const char *); //由常数数组显示整屏字符void DELAY_US(char);void DELAY(unsigned int);void delaynms(unsigned int);//===DS1307void IIC_SEND(char);void IIC_CSH(void);void READ_DS1307(char addr,char n);void write_DS1307(char addr,char data);void DS1307_CSH(void);//DS1307初始化void MENU_DS1307(void);//==温度void DISP_T(signed char R1); //温度在R1 signed char READ_T(void); void clock();//闹钟void set_time(void);//按键void bcd_dec(char adr,char R);char dec_bcd(char dec);void BCD(unsigned int R1);void guangbiao(void);//光标//========主程序void main(){CSH();READ_DS1307(0,7);//读DS1307 if(A[0]&0x80)DS1307_CSH();//判断是否初始化while(1){clock();set_time();//按键检测delaynms(50);if(flag==0){ READ_DS1307(0,7);//读DS1307 MENU_DS1307();//显示DS1307T=READ_T();//读温度DISP_T(T);//显示温度}}}//========初始化端口void CSH(void){TRISD=0b00000000; //控制LCD1604,全为输出RD7=1; //背光TRISB=0x0FF;RBPU=0;WPUB=0x0FF;ANSELH=0;PORTB=0x00;//===PWM设置TRISC1=0; //RC1为输出RC1=0;PR2=124; //周期为1msCCPR2L=0x32;CCP2CON=0b00000000;//关闭PWMT2CON=0b00000110; //TMR2预分频1:16,开始工IIC_CSH();LCD_CSH();}//LCD模块初始化void LCD_CSH(void){ DELAY(20); //延时20msLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0010,COM); //4位数据格式LCD_BUSY(); //LCD忙检测LCD_WRITE(0b00101000,COM); //4位数据格式,2行,5×7点阵LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁LCD_WRITE(0b00000001,COM); //清除显示DELAY(2); //延时2msLCD_WRITE(0b00000110,COM); //输入模式,I/D(d1)=1:地址加1,S(d0)=1:显示移位关闭}//========读LCD状态char LCD_READ(void){ unsigned char R1;TRISD|=0X0F; //LCD数据线为输入LCD_RS=0; //寄存器选择LCD_RW=1;NOP(); //读为1LCD_E=1;NOP(); //使能R1=0; //短延时R1=(PORTD<<4 )& 0xF0; //读数据的高4位给R1高四位LCD_E=0;NOP(); //读数据结束LCD_E=1;NOP(); //使能R1 |= (PORTD & 0x0F); //读PORTD的低4位,R1的高4位不变! LCD_E=0;NOP(); //读数据结束LCD_RW=0;return (R1);}//写一字节数R1,FLAG为写命令或数据选择,0为写命令,1为写数据//写之前先检查是否忙,写完后延时100us,分二次写4位数据/命令void LCD_WRITE(char R1,char FLAG){ char R2;TRISD&=0XF0;LCD_BUSY();R2=R1 & 0xF0; //低4位清0R2=R2>>4; //取高4位LCD_WRITE_4(R2,FLAG); //先写高4位R2=(R1 & 0x0F); //高4位清0,取低4位LCD_WRITE_4(R2,FLAG); //再送低4位DELAY_US(10); //延时100us}//写R1的低4位,FLAG为寄存器选择,1为命令,0为数据void LCD_WRITE_4(char R1,char FLAG){ TRISD&=0XF0;LCD_RW=0;NOP(); //写模式LCD_RS=FLAG;NOP(); //寄存器选择PORTD &= 0xF0;NOP(); //RD低4位先清0LCD_E=1;NOP(); //使能R1=(R1&0x0F); //R1低4位送至低4位PORTD |=R1;NOP(); //送4位LCD_E=0;NOP(); //数据送入有效,下降沿送入LCD_RS=0;NOP();PORTD &= 0xF0; //RD低4位清0}//========检测LCD是否忙void LCD_BUSY(void){ unsigned char R1;while(1){ R1=LCD_READ(); //读寄存器if ((R1 & 0x80)==0x00) //最高位为忙标志位break; };}//======延时(n)msvoid DELAY(unsigned int n){unsigned int j;char k;for (j=0;j<n;j++)for (k=246;k>0;k--) NOP();}//======延时(n)msvoid delaynms(unsigned int n){unsigned int j;char k;for (j=0;j<n;j++)for (k=246;k>0;k--) NOP();}//======延时(n×10)usvoid DELAY_US(char n){ char j;for (j=0;j<n;j++){NOP();NOP();}}//=======DS1307有关子程序//===DS1307初始化void DS1307_CSH(){write_DS1307(0x00,0X00);//秒钟设置write_DS1307(0x01,0x01);//分钟设置write_DS1307(0x02,0x01);//小时设置write_DS1307(0x03,0X01);//星期天设置write_DS1307(0x04,0x01);//日月设置write_DS1307(0x05,0x05);//月设置write_DS1307(0x06,0x12);//年设置write_DS1307(0x07,0x70);//7脚方波允许,输出1HZ}//==IIC初始化void IIC_CSH(){ TRISC =0b00011000; //SDA,SCL设置为输入SSPCON=0b00101000; //同步串口使能(SSPEN),主控方式SMP=0; //使能高速模式(400 kHz) 的压摆率控制SSPADD=4; //主控模式为波特率值,每位时间T=(SSPADD+1)/Tcy=5us } //发送数R并等待发送完成,收到从机的应答信号void IIC_SEND(char R){ SSPBUF=R; //发送while (RW==1); //在主动模式下,判断发送是否完成while (SSPIF==0); //等待发送完成while (ACKSTA T==1); //等待从机发送应答信号NOP();}//====读写DS1307程序void write_DS1307(char addr,char data){SEN=1; //发送起始位while(SEN==1); //检测起始位完成IIC_SEND(0b11010000); //送DS1307的七位地址和写功能IIC_SEND(addr); //发送要写入的地址IIC_SEND(data); //发送要写入的数PEN=1; //发送停止位while (PEN==1); //检查停止位结束}//===读DS1307void READ_DS1307(char addr,char n){char i;SEN=1; //产生起始位while (SEN==1); //检测起始位完成IIC_SEND(0b11010000); //送DS1307的7位地址IIC_SEND(addr); //此值为DS1307要读的地址PEN=1; //发送停止位while (PEN==1);//检查停止位结束NOP();RSEN=1; //发送重新启始位while(RSEN==1); //检测重新起始位完成IIC_SEND(0b11010001); //读数据for (i=0;i<n;i++) //读字节个数{ RCEN=1;while (RCEN==1);A[i]=SSPBUF; //读1字节if (i<n-1){ ACKDT=0;ACKEN=1;while (ACKEN==1);}else{ ACKDT=1;ACKEN=1;while (ACKEN==1);} //最后一字节不应答}PEN=1;while (PEN==1);}//=====显示DS1307void MENU_DS1307(void){ LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁char i;LCD_WRITE(LINE1,COM); //DDRAM地址,第1行的第1个字符LCD_WRITE(' ',DAT);LCD_WRITE('2',DAT);LCD_WRITE('0',DAT);LCD_WRITE((A[6]>>4)+0x30,DA T);LCD_WRITE((A[6]&0x0F)+0x30,DA T);LCD_WRITE('-',DAT);LCD_WRITE((A[5]>>4)+'0',DA T);LCD_WRITE((A[5]&0x0F)+'0',DAT);LCD_WRITE('-',DAT);LCD_WRITE((A[4]>>4)+'0',DA T);LCD_WRITE((A[4]&0x0F)+'0',DAT);LCD_WRITE(' ',DAT);i=A[3]&0x07;LCD_WRITE(table[(i-1)*4],DA T);LCD_WRITE(table[(i-1)*4+1],DAT);LCD_WRITE(table[(i-1)*4+2],DAT);LCD_WRITE(table[(i-1)*4+3],DAT);//LCD_WRITE(' ',DAT);LCD_WRITE(LINE2,COM); //DDRAM地址,第2行的第1个字符LCD_WRITE(' ',DAT);LCD_WRITE((A[2]>>4)+'0',DA T);LCD_WRITE((A[2]&0x0F)+'0',DAT);LCD_WRITE(0x3A,DA T);LCD_WRITE((A[1]>>4)+'0',DA T);LCD_WRITE((A[1]&0x0F)+'0',DAT);LCD_WRITE(0x3A,DA T);LCD_WRITE((A[0]>>4)+'0',DA T);LCD_WRITE((A[0]&0x0F)+'0',DAT);LCD_WRITE(' ',DAT);}char dec_bcd(char dec){char bcd;bcd= 0;while(dec >= 10){dec -= 10;bcd++;}bcd <<= 4;bcd |= dec;return (bcd);}void bcd_dec(char adr,char R) { SW=A[adr]>>4;GW=A[adr]&0x0F;while(SW>0){R=R+10;SW--;}R+=GW;}//====按键程序void set_time(){if(mod==0){delaynms(30);if(mod==0){while(!mod);//等待M++;if(M==3){ M=0;flag=0;f=0;a=0; }}}if(M==1)//设置时间{if(set==0){delaynms(30);if(set==0){while(!set);a++;if(a==8)a=0;}}guangbiao();//光标定位,闪烁if(a==1) {if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(0,sec);sec++;if(sec==60)sec=0;write_DS1307(0,dec_bcd(sec)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(0,sec);sec--;if(sec==-1)sec=59;write_DS1307(0,dec_bcd(sec)); }}}if(a==2){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(1,min);min++;if(min==60)min=0;write_DS1307(1,dec_bcd(min)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(1,min);min--;if(min==-1)min=59;write_DS1307(1,dec_bcd(min)); }}}if(a==3){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(2,hour);hour++;if(hour==24)hour=0;write_DS1307(2,dec_bcd(hour)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(2,hour);hour--;if(hour==-1)hour=23;write_DS1307(2,dec_bcd(hour)); }}}if(a==4){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(3,week);week++;if(week==8)week=1;write_DS1307(3,dec_bcd(week)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(3,week);week--;if(week==0)week=7;write_DS1307(3,dec_bcd(week)); }}}if(a==5){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(4,day);day++;if(day==32)day=1;write_DS1307(4,dec_bcd(day));}}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(4,day); day--;if(day==0)day=31;write_DS1307(4,dec_bcd(day)); }}}if(a==6){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(5,month);month++;if(month==13)month=1;write_DS1307(5,dec_bcd(month)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(5,month);month--;if(month==0)month=12;write_DS1307(5,dec_bcd(month)); }}}if(a==7){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(6,year);year++;if(year==99)year=0;write_DS1307(6,dec_bcd(year)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);year--;if(year==-1)year=99;bcd_dec(6,year);write_DS1307(6,dec_bcd(year)); }}}READ_DS1307(0,7);//读DS1307}//====闹钟按键设置else if(M==2){f++;flag=1;if(f==1){a=0;LCD_WRITE(LINE2+1,COM);//显示上次闹铃时间BCD(hourt); LCD_WRITE(SW+'0',DAT);LCD_WRITE(GW+'0',DAT);LCD_WRITE(LINE2+4,COM);BCD(mint);LCD_WRITE(SW+'0',DAT);LCD_WRITE(GW+'0',DAT);LCD_WRITE(LINE2+7,COM);BCD(sect);LCD_WRITE(SW+'0',DAT); LCD_WRITE(GW+'0',DAT);}if(set==0) //设置时间{delaynms(30);if(set==0){while(!set);a++;if(a==4)a=0;}}guangbiao();//光标定位,闪烁if(a==1){if(add==0){delaynms(30);if(add==0){while(!add);sect++;if(sect==60)sect=0;BCD(sect);LCD_WRITE(LINE2+7,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);sect--;if(sect==-1)sect=59;BCD(sect);LCD_WRITE(LINE2+7,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}if(a==2){if(add==0){delaynms(30);if(add==0){while(!add);mint++;if(mint==60)mint=0;BCD(mint);LCD_WRITE(LINE2+4,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);mint--;if(mint==-1)mint=59;BCD(mint);LCD_WRITE(LINE2+4,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}if(a==3){if(add==0){delaynms(30);if(add==0){while(!add);hourt++;if(hourt==24)hour=0;BCD(hourt);LCD_WRITE(LINE2+1,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);hourt--;if(hourt==-1)hourt=23;BCD(hourt);LCD_WRITE(LINE2+1,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}}}//====光标定位void guangbiao(void){switch(a){case(1):LCD_WRITE(0b11001000,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁case(2):LCD_WRITE(0b11000101,COM);LCD_WRITE(0b00001111,COM);break;/ /定位分,光标打开,B(d0)=1:光标闪烁case(3):LCD_WRITE(0b11000010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位时,光标打开,B(d0)=1:光标闪烁case(4):LCD_WRITE(0b10001110,COM);LCD_WRITE(0b00001111,COM);break;/ /定位星期,光标打开,B(d0)=1:光标闪烁case(5):LCD_WRITE(0b10001010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位日,光标打开,B(d0)=1:光标闪烁case(6):LCD_WRITE(0b10000111,COM);LCD_WRITE(0b00001111,COM);break;/ /定位月,光标打开,B(d0)=1:光标闪烁case(7):LCD_WRITE(0b10000100,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁case(8):LCD_WRITE(0b10000010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁}}//=====读TC74的温度值signed char READ_T(void){ signed char R1;SEN=1; //开始条件while (SEN==1); //检测开始条件是否完成?IIC_SEND(TC74_ADD<<1); //送TC74地址(写)IIC_SEND(RTR); //写RTR命令(写)RSEN=1; //重新开始条件while (RSEN==1); //等待重新开始条件结束IIC_SEND((TC74_ADD<<1)+1);//发送TC74地址(读)RCEN=1; //接收使能while (RCEN==1); //等待接收完成R1=SSPBUF; //接收数据存入R1PEN=1; //停止位while(PEN==0);return(R1);}//从R1双字节数转换为十进制数万位-个位:WW,QW,BW,SW,GW void BCD(unsigned int R1){ WW=0;QW=0;BW=0;SW=0;GW=0;while(R1>=10000){R1-=10000;WW++;}while(R1>=1000){R1-=1000;QW++;}while(R1>=100){R1-=100;BW++;}while(R1>=10){R1-=10; SW++;}GW=R1;}//===温度显示void DISP_T(signed char R1) //温度在R1{ char R2;if (R1>=0)BCD(R1);else{ R2=~(R1)+1;BCD(R2);}if (R1<0){LCD_WRITE(LINE2+10,COM); //DDRAM地址,第1行的第5个字符LCD_WRITE('-',DAT);}if (R1>=0) //只在温度为正时才显示百位LCD_WRITE(BW+0x30,DAT); //显示百位,数字加上0x30即为相应的ASCII码,下同LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位LCD_WRITE(0xDF,DA T); //°LCD_WRITE('C',DAT);LCD_WRITE(' ',DAT);}//====闹钟void clock(){ if(!mod||!set||!add||!miu){delaynms(30);if(!mod||!set||!add||!miu);CCP2CON=0b00000000; //关PWM模式}BCD(sect);if(SW==(A[0]>>4)&&GW==(A[0]&0x0F)) {BCD(mint);if(SW==(A[1]>>4)&&GW==(A[1]&0x0F)) {BCD(hourt);if(SW==(A[2]>>4)&&GW==(A[2]&0x0F)) CCP2CON=0b00001100; //开PWM模式}}}。
PIC单片机电子时钟设计
PIC单片机电子时钟设计摘要单片机是一种集成电路芯片,采用超大规模技术把具有数据处理能力(如算术运算,逻辑运算、数据传送、中断处理)的微处理器(CPU),随机存取数据存储器(RAM),只读程序存储器(ROM),输入输出电路(I/O口),可能还包括定时计数器,串行通信口(SCI),显示驱动电路(LCD或LED驱动电路),脉宽调制电路(PWM),模拟多路转换器及A/D转换器等电路集成到一块单块芯片上,构成一个最小然而完善的计算机系统。
这些电路能在软件的控制下准确、迅速、高效地完成程序设计者事先规定的任务液晶显示器(LCD)具有功耗低、体积小、重量轻、超薄等许多其他显示器无法比拟的优点,近年来被广泛用于单片机控制的智能仪器、仪表和低功耗电子产品中。
LCD可分为段式LCD、字符式LCD和点阵式LCD。
其中,段式LCD和字符式LCD只能用于字符和数字的简单显示,不能满足图形曲线和汉字显示的要求;而点阵式LCD不仅可以显示字符、数字,还可以显示各种图形、曲线以及汉字、动画,并且可以实现屏幕滚动、反转、闪烁等功能,用途十分广泛。
电子时钟主要由单片机芯片(AT89C52)、实时钟芯片(DS1302)、LCD显示器、键盘等组成。
设计思路硬件设计:结构框图实时钟芯片DS1302主控模块单片机AT89C52液晶显示器LCD键盘模块电池供电蜂鸣器(闹钟功能)主要模块、单片机AT89C52参数介绍:表1-189c52的主要性能参数主要性能参数:与MCS-51产品指令和引脚完全兼容8k字节可重擦写Flah闪速存储器1000次擦写周期全静态操作:0Hz—24MHz三级加密程序存储器256某8字节内部RAM32个可编程I/O口线3个16位定时/计数器8个中断源可编程串行UART通道低功耗空闲和掉电模式表1-2AT89C52的极限参数工作温度储藏温度任一引脚对地电压最高工作电压-55℃to+125℃-65℃to+150℃-1.0Vto+7.0V6.6V实时钟芯片DS1302主要性能简介:a.实时钟能够计算时间的时、分、秒,年、月、星期、日的功能,也具有调整闰年的能力。
利用单片机的定时器设计一个数字时钟
利用单片机的定时器设计一个数字时钟数字时钟是我们日常生活中常见的计时工具,可以准确地显示当前的时间。
而单片机的定时器则可以提供精准的定时功能,因此可以利用单片机的定时器来设计一个数字时钟。
本文将介绍如何使用单片机的定时器来设计一个基于数字显示的时钟,并提供基本的代码实现。
一、时钟电路设计利用单片机设计一个数字时钟,首先需要设计一个合适的时钟电路。
时钟电路一般由电源电路、晶振电路、单片机复位电路和显示电路组成。
1. 电源电路:为电路提供工作所需的电源电压,一般使用稳压电源芯片进行稳定的供电。
2. 晶振电路:利用晶振来提供一个稳定的时钟信号,常用的晶振频率有11.0592MHz、12MHz等。
3. 单片机复位电路:用于保证单片机在上电或复位时能够正确地初始化,一般使用降低复位电平的电路。
4. 显示电路:用于将单片机输出的数字信号转换成七段数码管可以识别的信号,一般使用BCD码和译码器进行实现。
二、单片机定时器的应用单片机的定时器具有精准的定时功能,可以帮助实现时钟的计时功能。
单片机的定时器一般分为定时器0和定时器1,根据具体的应用需求选择使用。
在设计数字时钟时,可以将定时器0配置成定时器模式,设置一个适当的定时时间。
当定时器0计时达到设定时间时,会触发一个中断信号,通过中断处理程序可以实现时钟的计时功能。
以下是一个基于单片机的定时器的伪代码示例:```void Timer0_Init(){// 设置定时器0为工作在定时器模式下// 设置计时时间// 开启定时器0中断}// 定时器0中断处理程序void Timer0_Interrupt_Handler(){// 更新时钟显示}void main(){Timer0_Init();while(1){// 主循环}}```在上述伪代码中,Timer0_Init()函数用于初始化定时器0的相关设置,包括工作模式和计时时间等。
Timer0_Interrupt_Handler()函数是定时器0的中断处理程序,用于处理定时器0计时到达设定时间时的操作,例如更新时钟显示。
(完整word版)基于PIC16F877A的数字钟设计
电子工程系项目考核(报告)项目名称:数字时钟项目姓名班级学号课程名称一、项目要求:数码管默认显示00:00。
数码管1,2 表示小时,数码管3,4 表示分钟。
如此,实现时钟功能.要求能够整点报时、闹钟提示;并附带有秒表功能。
按键可以调整时钟时间、切换显示页面和设定闹钟时间等。
二、项目原理分析在项目用的单片机开发板上单片机的IO 口接四位数码管的各段。
同时开发板共阴数码管的阴极由138 译码器的输出端控制。
在该项目中我采用了数码管的动态显示,即每位数码管点亮2ms 时间左右,由于人的视觉暂留现象及发光二极管的余辉效应,只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O 端口,而且功耗更低。
在实现了数码管的动态显示的基础上在主程序中通过计算定时器1的中断次数,从而得到计时时间和秒表时间的基准时间。
同时在主程序中添加按键处理程序,实现时钟的开始、中断和校时,同时实现闹钟定时和切换显示等功能,还有秒表计时功能。
三、硬件电路图以及原理3。
1 硬件电路图如下:3。
2硬件原理:该项目中,主要的功能模块有:数码管显示模块;按键模块;蜂鸣器模块。
数码管显示模块主要是由芯片PIC16F877A内部的定时器1的定时中断实现数码管的动态显示.按键模块主要利用矩阵式按键实现多按键功能,矩阵式按键原理是在一端加高电平,然后检测另一端是否为高电平来判断按键是否按下,通过不同的定义可以让按键实现不同的功能。
蜂鸣器模块通过三极管的开关作用和驱动作用由芯片控鸣叫与否。
四、程序说明以及程序流程图该时钟默认显示页面为时钟计时页面,按键SW1 控制时钟、秒表的开始和中断,按按键SW1一次,如果数码管在显示秒表,则开始计秒功能;否则,开始正常计时;再按一次SW1则实现中断功能.按键SW2实现是数码管的选位,从第一个数码管开始,按一次就选中下一位数码管,循环选择。
SW3实现的是加1功能,每按一次就在SW2选中的位上加1。
PIC单片机实时时钟和日历
RTCC SFR 汇总
Bit 31/23/15/7 — Bit 30/22/14/6 — Bit 29/21/13/5 — Bit 28/20/12/4 — CAL<7:0> — — — — — — RTCOE Bit 27/19/11/3 — Bit 26/18/10/2 — Bit 25/17/9/1 Bit 24/16/8/0
AMASK<3:0>
写入时会将 RTCTIME 中的选定位清零,读取时获得的值未定义 写入时会将 RTCTIME 中的选定位置 1,读取时获得的值未定义 写入时会将 RTCTIME 中的选定位取反,读取时获得的值未定义 YEAR10<3:0> MONTH10<3:0> DAY10<3:0> — — — YEAR01<3:0> MONTH01<3:0> DAY01<3:0> WDAY01<3:0>
DS61125D_CN 第 29-2 页
初稿
© 2010 Microchip Technology Inc.
第 29 章 实时时钟和日历
图 29-1: RTCC 框图
来自 SOSC 振荡器的 32.768 kHz 输入
RTCC 预分频器 0.5s RTCC 定时器 闹钟 事件 RTCVAL 年, 月, 日 星期 小时, 分钟, 秒 比较器 月, 日 比较寄存器 (带掩码) 重复计数器 ALRMVAL 星期 小时, 分钟, 秒
第 29 章 实时时钟和日历
目录
本章包括下列主题: 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 29.10 29.11 29.12 简介 ......................................................................................................................... 29-2 状态和控制寄存器 .................................................................................................... 29-4 工作模式 ................................................................................................................ 29-24 闹钟 ....................................................................................................................... 29-35 中断 ....................................................................................................................... 29-40 节能和调试模式下的操作 ....................................................................................... 29-42 各种复位的影响 ..................................................................................................... 29-43 使用 RTCC 模块的外设 .......................................................................................... 29-43 I/O 引脚控制........................................................................................................... 29-44 设计技巧 ................................................................................................................ 29-45 相关应用笔记 ......................................................................................................... 29-47 版本历史 ................................................................................................................ 29-48
PIC16单片机课设智能时钟报告
《PIC单片机》课程设计学生姓名:学号:0112007XX指导教师:2014年12月30日目录1、硬件介绍 ......................................................................................................................... - 2 -1.1电源模块 ........................................................................................................................ - 2 -1.2 LCD模块 ........................................................................................................................ - 2 -1.3矩阵按键模块 ................................................................................................................ - 4 -1.4时钟模块(DS1307)+温度模块(TC74) ................................................................ - 4 -1.4.1时钟模块(DS1307) ................................................................................................ - 4 -1.4.2温度模块(TC74)...................................................................................................... - 5 -1.6 PROTEUS仿真图............................................................................................................. - 6 -2、软件介绍 ......................................................................................................................... - 7 -2.1 Main程序........................................................................................................................ - 8 -2.2 初始化............................................................................................................................ - 8 -2.3 自定义字符 .................................................................................................................... - 9 -2.4 显示欢迎语 .................................................................................................................. - 10 -2.5 时间及温度显示 .......................................................................................................... - 11 -2.6 中断设置...................................................................................................................... - 12 -2.6.1按键功能说明............................................................................................................ - 13 -2.6.2按键修改说明............................................................................................................ - 15 -2.6.3光标移动说明............................................................................................................ - 16 -2.7蜂鸣器设置音乐 ........................................................................................................... - 16 -3、设计结果 ....................................................................................................................... - 16 -4、设计体会 ....................................................................................................................... - 17 -1、硬件介绍这次课设所用到的硬件模块有,PIC16F887单片机芯片,LCD1602芯片,4×4键盘,DS1307时钟芯片,TC74温度计芯片,还有PWM控制的蜂鸣器模块。
PIC16F877A数字时钟时钟程序
;Digit clock;-----------------------------------------------;DA TE :20101205;Author:Tang HS;M C U :PIC16F877A;FileName : ClockPIC.ASM;-----------------------------------------------------------;Date: {2010/12/07.14:35}-V er01--CS-ICD:0xAFCE---ISP:0xb7ce----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义;------------------------------------------------------------;-----------------------------------------------------------;Date: {2010/12/07.22:15}-V er01--CS-ICD:0xAFCE---ISP:0xb7ce----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义; 2.RB0-SET_KEY;RB1-ADD_KEY;RB2-SUB_KEY;RB3-EXIT_KEY;------------------------------------------------------------;Date: {2010/12/09.18:06}-V er02--CS-ICD:0xAFCE---ISP:0xef0e----;************************************************************;Date: {2010/12/10.00:47}-V er03--CS-ICD:0xb08d---ISP:0xfaa7----;功能: 1.LED显示:时分秒;格式:[ hh mm ss ] 备注:按键未定义; 2.RB0-SET_KEY;RB1-ADD_KEY;RB2-SUB_KEY;RB3-EXIT_KEY 都OK ; 3.MOVLW 纠正MOVV REG,1 引起的SUB_不良;;--------------------------------------------------------------;Date: {2010/12/10.13:10}-V er03.1--CS-ICD:0xb08b---ISP:0xfaa4----; 4.时差。
PIC单片机系统程序设计举例
系统程序设计举例
一、设计要求实现的功能
1.设计一个时钟,显示时分。
2.时间设定,使用K0、K2、K3三键进行设定。
K0键功能:为加1键。
K2键功能:第一次按K2键进入时间设定状态,分个位闪,表示对该位赋值,用K0调整该位数值;第二次按K2键,确定分十位值,……,第五次按K2键结束时钟设定状态,回到实时时钟状态。
3.按K3键,进入实时通道0电压显示状态。
再按K2键返回实时时钟显示状态。
4.上电时,进入显示测试模块,按K0键,进入实时时钟模块。
二、系统流程图
1.系统程序
总流程图如图1所示,有如下几个显著特点。
模块化结构、复位分为两部分、散转结构,可实现无扰动重入、在RAM建立各控制量的映射,方便各功能模块的编程,方便修改。
图1:系统流程图
2. 功能模块
DSBIT :位选指针,每2.5ms 加1;DSFL :位闪控制寄存器;FLON :闪烁总控位,=1有效。
实时时钟模块
时钟设定模块 ① ①。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
PIC单片机之时钟设置
什么时钟?
首先我们先讲讲什么是时钟。
时钟就是单片机的心脏。
每跳动一下。
整个单片机的各个电路就同步的动作一下。
就好像我们做广播体操的时候广播上喊的节拍1234 2234 3234。
然后我们全部的同学就按照这个节奏进行一个个动作。
节拍越快我们动作越快。
节拍越慢我们动作的越慢。
内部时钟和外部时钟?
PIC单片机有许多型号可以设置成用外部时钟(如外部接个4MHZ 的石英晶振),也可以设置成用内部RC时钟。
而且还有许多型号可以选择多种频率的时钟。
如PICLF1823 内部时钟最高可以到达32MHZ 最低可以达到31kHz. 这事实上提供了一条降低功耗的新路子。
一般的单片机降低功耗常常用的睡眠,而睡眠期间CPU是什么都不做。
如果希望降低功耗,而且CPU也能工作。
降低时钟频率无疑是个非常好的选择。
时钟的设置?
时钟设置一般只和两处有关一个是配置字,一个是振荡器控制寄存器OSCCON 下面我们以PICLF1823为例子进行讲解。
PICLF1823 配置字设置中与时钟有关的就是FOSC<2:0>:振荡器选择位,和PLLEN:PLL使能位。
OSCCON 是有关内部时钟频率选择,如果只用外部时钟一般不理会。
以下是数据手册中OSCCON寄存器的详细介绍。
实例讲解:
使用内部时钟将时钟频率设置成8MHZ
开发环境:MPLAB X IDE
芯片型号:PICLF1823
#include<pic.h>
__CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_ON&MCLRE_OFF &CP_ON&CPD_OFF&BOREN_ON&CLKOUTEN_OFF&IESO_ON&FC MEN_ON);
__CONFIG(PLLEN_OFF&LVP_OFF) ;//将FOSC<2:0>:振荡器选择位
设置成INTOSC,
void init_fosc(void)
{
OSCCON = 0x70;//8MHZ IRCF<3:0>时钟频率选择位设置成8MHZ }
int main(int argc, char** argv) {
init_fosc();
while(1);
}
PLL是用来做什么的呢?他的作用就是能将8MHZ的时钟频率X4变成32MHZ,记住只有8MHZ可以,其他频率是不行的。
使用内部时钟将时钟频率设置成32MHZ
开发环境:MPLAB X IDE
芯片型号:PICLF1823
#include<pic.h>
__CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_ON&MCLRE_OFF &CP_ON&CPD_OFF&BOREN_ON
&CLKOUTEN_OFF&IESO_ON&FCMEN_ON);//这个要放到上一行去
__CONFIG(PLLEN_ON&LVP_OFF) ;//将FOSC<2:0>:振荡器选择位设置成INTOSC,使能PLLEN
void init_fosc(void)
{
OSCCON = 0xF0;//32MHZ IRCF<3:0>时钟频率选择位设置成8MHZ ,使能4XPLL
}
int main(int argc, char** argv) {
init_fosc();
while(1); }。