基于PIC16F887单片机的数字钟完整c程序代码

合集下载

PIC16F887时钟课设

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中去显示,然后设置秒表功能,闹钟功能,还有温度显示功能,通过按键的切换来实现各个功能。

单片机数码时钟设计C语言程序

单片机数码时钟设计C语言程序

//实例66:#include<reg51.h> // 包含51单片机寄存器定义的头文件unsigned char Tab[ ]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //control shape unsigned char port[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};unsigned char int_time ; //中断次数计数变量unsigned char second; //秒计数变量unsigned char minute; //分钟计数变量unsigned char hour; //小时计数变量/////////////////////////////////////////////////////void delay(void) //延时函数,延时约0.6ms{unsigned char j;for(j=0;j<200;j++);}/******************************************************************函数功能:显示秒的子程序入口参数:s********************************************************************/void DisplaySecond(unsigned char s){P2=0xbf; //P2.6引脚输出低电平,DS6点亮P0=Tab[s/10]; //显示十位delay();P2=0x7f; //P2.7引脚输出低电平,DS7点亮P0=Tab[s%10]; //显示个位delay();P2=0xff; //关闭所有数码管}/******************************************************************函数功能:显示分钟的子程序入口参数:m********************************************************************/void DisplayMinute(unsigned char m){P2=0xf7; // P2.3引脚输出低电平,DS3点亮P0=Tab[m/10];//显示个位delay();P2=0xef; // P2.4引脚输出低电平,DS4点亮P0=Tab[m%10];delay();P2=0xdf; //P2.5引脚输出低电平,DS5点亮P0=0xbf; //分隔符“-”的段码delay();P2=0xff; //关闭所有数码管}/****************************************************************** 函数功能:显示小时的子程序入口参数:h********************************************************************/ void DisplayHour(unsigned char h){P2=0xfe; //P2.0引脚输出低电平,DS0点亮P0=Tab[h/10]; //显示十位delay();P2=0xfd; //P2.1引脚输出低电平,DS1点亮P0=Tab[h%10]; //显示个位delay();P2=0xfb; //P2.2引脚输出低电平,DS2点亮P0=0xbf; //分隔符“-”的段码delay();P2=0xff; //关闭所有数码管}/****************************************************************** 函数功能:主函数********************************************************************/void main(void){TMOD=0x01; //使用定时器T0EA=1; //开中断总允许ET0=1; //允许T0中断TH0=(65536-46083)/256; //定时器高八位赋初值TL0=(65536-46083)%256; //定时器低八位赋初值TR0=1;int_time=0; //中断计数变量初始化second=0; //秒计数变量初始化minute=0; //分钟计数变量初始化hour=0; //小时计数变量初始化while(1){DisplaySecond(second); //调用秒显示子程序delay();DisplayMinute(minute); //调用分钟显示子程序delay();DisplayHour(hour);delay();}}/******************************************************************函数功能:定时器T0的中断服务子程序********************************************************************/void interserve(void ) interrupt 1 using 1 //using Time0{int_time++;if(int_time==20){int_time=0; //中断计数变量清0second++; //秒计数变量加1}if(second==60){second=0; //如果秒计满60,将秒计数变量清0minute++; //分钟计数变量加1}if(minute==60){minute=0; //如果分钟计满60,将分钟计数变量清0hour++; //小时计数变量加1}if(hour==24){hour=0; //如果小时计满24,将小时计数变量清0}TH0=(65536-46083)/256; //定时器重新赋初值TL0=(65536-46083)%256;}。

基于单片机的数字钟毕业设计(附程序全)

基于单片机的数字钟毕业设计(附程序全)

基于单片机的数字钟毕业设计(附程序全) 电子时钟设计随着现代人类生活节奏的加快,人们越来越重视起了时间观念,可以说是时间和金钱划上了等号。

对于那些对时间把握非常严格和准确的人或事来说,时间的不准确会带来非常大的麻烦,所以以数码管为显示器的时钟比指针式的时钟表现出了很大的优势。

数码管显示的时间简单明了而且读数快、时间准确性更高~数字钟是采用数字电路实现对“时”、“分”、“秒”数字显示的计时装置。

数字钟的精度、稳定度远远超过老式机械钟。

在这次设计中,我们采用LED数码管显示时、分、秒,以24小时计时方式,根据数码管动态显示原理来进行显示,用12MHz的晶振产生振荡脉冲,并且由单片机的定时器计数。

在此次设计中,电路具有显示时间的其本功能,还可以实现对时间的调整。

数字钟是其小巧,价格低廉,走时精度高,使用方便,功能多,便于集成化而受广大消费的喜爱,因此得到了广泛的使用。

关键词:数字钟;单片机;数码管;时间;准确性1目录第一章绪论1. 数字电子钟的意义和应用…………………………………………………………………… 3 第二章整体设计方案2.1 单片机的选择…………………………………………………………………………… 3 2.2 单片机的基本结构……………………………………………………………………… 5 第三章数字钟的硬件设计3.1 最小系统设计…………………………………………………………………………… 9 3.2 LED显示电路…………………………………………………………………………… 12 3.3 键盘控制电路…………………………………………………………………………… 14 第四章数字钟的软件设计4.1 系统软件设计流程图…………………………………………………………………… 15 4.2 数字电子钟的原理图…………………………………………………………………… 18 4.3 主程序…………………………………………………………………………………… 19 4.4 时钟设置子程序………………………………………………………………………… 20 4.5 定时器中断子程序……………………………………………………………………… 20 4.6 LED显示子程序………………………………………………………………………… 21 4.7 按键控制子程序………………………………………………………………………… 23 第五章系统仿真5.1 PROTUES软件介绍................................................................................. 24 5.2 电子钟系统PROTUES仿真........................................................................ 24 结束语. (2)5 参考文献 (26)2第一章绪论1.数字电子钟的意义和应用数字钟是采用数字电路实现对时、分、秒数字显示的计时装置,广泛用于个人家庭、车站、码头、办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表, 钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。

用C语言写的一个PIC16F877的时闹钟程序

用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;。

基于PIC16F887单片机的温度、时钟显示以及闹钟功能

基于PIC16F887单片机的温度、时钟显示以及闹钟功能

基于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中显示。

毕业设计-基于PIC16F877A单片机字符液晶显示数字时钟设计

毕业设计-基于PIC16F877A单片机字符液晶显示数字时钟设计

贵港职业学院毕业设计(论文)姓名:覃正杨学号:200930112126专业班级:电机系09级应用电子技术班论文题目:基于PIC16F877A字符液晶数字时钟指导教师:------二零一一年六月基于PIC16F877A单片机字符液晶显示数字时钟摘要近年来,随着电子产品的发展,人们对数字钟的要求越来越高,针对人们的这一需求设计了一种有单片机控制的智能化数字时钟,功能强大,界面友好,更好的满足了人们对它的智能化要求。

本文设计并实现了一款基于字符液晶显示的单片机数字钟,详细叙述了系统硬件、软件的具体实现过程。

论文重点阐述了数字钟硬件模块、时钟模块和相关控制模块等的模块化设计与制作;软件同样采用模块化的设计,包括读取模块、显示模块、时间调整模块设计,并采用汇编言语编写实现。

本设计实现了年、月、日和时间的显示功能、日期和时间修改功能。

设计方案已通过仿真软件验证,证明了设计的合理性。

关键词:单片机;数字钟;液晶显示;仿真目录目录 (3)引言 (4)第一章方案对比与选择 (5)方案1 (5)方案2 (5)方案选择 (5)第二章16F877A单片机概述 (6)2.1 单片机的用途与发展 (6)2.2 PIC16F877A单片机的结构与特点 (6)2.2.1 PIC16F877A单片机引脚结构 (6)2.2.2 PIC16F877A的内部结构 (7)2.2.3单片机的特点 (7)本章小结 (8)第三章LCD 1602A字符液晶显示说明 (9)3.1 LCD 1602A字符液晶显示的优势 (9)3.2 LCD 1602A字符液晶引脚说明 (9)本章小结 (9)第四章整体设计方案 (10)4.1 硬件选择 (10)4.3 PIC16F877A单片机电路 (10)4.4 LCD 1602A字符液晶显电路 (11)4.5 电源电路 (11)4.6 轻触按键电路 (11)4.7 整体电路图 (12)4.8 程序主流程图 (12)4.9 LCD 1602A字符液晶程序流程图 (13)本章小结 (13)第五章在线调式 (14)5.1 MPLAB ICD 2 在线调试器 (14)5.2 使用ICD 2 进行调试 (14)5.4 ICD2在线调式结果 (15)本章小结 (15)第六章结束语 (16)参考文献 (17)致谢 (17)附录字符液晶数字时钟程序 (18)引言现在是一个知识爆炸的新时代。

第三章 PIC16F887功能及编程

第三章 PIC16F887功能及编程

0:计时
01-1:4
… 1111-1:16
1X-1:16
福州大学电气工程与自动化学院
• TMR0是个8位计数/定时器,有可编程预分频率 器,可对外部脉冲计数或对内部指令脉冲计数的 功能。
• 当对外部脉冲计数时,符合一定要求的外部脉冲 送到RA4/T0CKI,且OPTION_REG(<T0CS>)要 置1,且该口(RA4)要设置为输入。
• TMR0寄存器的地址在01H、101H。 • TMR0有溢出中断功能。
中断 信接收 信发送 行通信 模块 溢出 溢出 使能 中断 中断 中断 中断 中断 中断
使能 使能 使能 使能 使能 使能
福州大学电气工程与自动化学院
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- ADIF RCIF TXTF SSPIF CCP1IF TMR2IF TMR1IF - AD转换 串行通 串行通 同步串 CCP1 TMR2 TMR1
• 恢复被保护的相关寄存器 • 程序执行到”RETFIE”时后入先出的原则,从堆栈
中弹出地址给PC,GIE=1,程序返回到中断前 要执行的程序,程序恢复中断前程序的运行状 态。
福州大学电气工程与自动化学院
PIC16F887有17个中断源,每个中断源都有自 己的使能控制位(IE)和中断标志位(IF)。包括:
• 假设当前TRM1H、TMR1L=0x01FF,则在读取TMR1时 就可能发生错误:
• 如先读低字节,得到0xFF,假设此时发生进位,则再读 高字节时得到0x02,总的结果是0x2FF,显然是错误的。
• 如先读高字节,得到0x01,假设此时发生进位,则再读低 字节得到0x00,总的结果是0x100,也是错误的。

(完整word版)基于PIC16F877A的数字钟设计

(完整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。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#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);//读DS1307if(A[0]&0x80)DS1307_CSH();//判断是否初始化while(1){clock();set_time();//按键检测delaynms(50);if(flag==0){ READ_DS1307(0,7);//读DS1307MENU_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模式}}}。

相关文档
最新文档