/*課程設(shè)計(jì)終于弄完了,總想共享一下源代碼,*/
/*遂在51hei上貼出來,大家看有什么問題吧~如果哪里寫得不好還請(qǐng)眾親們指出哦~*/
/*---附:實(shí)物圖--*/
/*===Chip:STC12C5A32S2======================*/ /*===Software:Keil 4 C51========================*/ /*===Author:梁鵬===================================*/ /*===Organization:廣西民族大學(xué)07自動(dòng)化===========*/ /*===Date:2010年05月26日======================*/ /*===Version:1.0===============================*/ /*===聲明:本程序?qū)僭瓌?chuàng)作品,僅供學(xué)習(xí)交流,不得用于 商業(yè)用途,如需轉(zhuǎn)載,請(qǐng)注明出處,謝謝合作!======*/ /*--------文件名:Supper_clock.C-----------*/ #include#include #include #include #include #include #include #define KEY_PORT P3 //按鍵端口 sbit MODE_KEY=KEY_PORT^3; //模式選擇鍵 sbit HOU_KEY=KEY_PORT^4; //時(shí)增一鍵 sbit MIN_KEY=KEY_PORT^5; //分增一鍵 sbit CLKON_KEY=KEY_PORT^6; //鬧鐘ON/OFF控制鍵 sbit BUZ_OUT=P2^3; //蜂鳴器輸出口 sbit DS18B20_PORT=P2^2; //DS18B20數(shù)據(jù)接口 sbit LAMP_PORT=P2^1; //繼電器控制口 /*=========子函數(shù)的聲明==============*/ void init(); //系統(tǒng)初始化 void display_time(); //顯示時(shí)間的子函數(shù) void display_clk(); //顯示鬧鐘的子函數(shù) void judge(); //判斷秒增量是否大于限定值 void clk_judge(); //檢測(cè)是否到達(dá)鬧鈴時(shí)間 void beep(); //蜂鳴器響子函數(shù) void buzzer(); //鬧鈴響子函數(shù) void get_adc_data(); //AD采樣數(shù)據(jù)及處理子函數(shù) void serial_judge(); //串口數(shù)據(jù)處理子函數(shù) //void delay_ms(uint); //MS級(jí)延時(shí)子程序 /*==========變量的聲明===============*/ bit pause_flags=0,clk_flags=0,clk_on=0,clk_on_or_off=1,flash_flags=0; bit clk1_off=0,clk2_off=0,clk3_off=1; //各鬧鐘是否開啟的變量 bit serial_finish=0; //串口接收結(jié)束標(biāo)志位 uchar com_send,com_get; //串口通信相關(guān)變量 uchar hour,min,sec; //時(shí)間變量 uchar dis_hour_clk,dis_min_clk; //用于顯示鬧鐘時(shí)間的變量 uchar hour_clk1,min_clk1; //鬧鐘1有關(guān)變量 uchar hour_clk2,min_clk2; //鬧鐘2有關(guān)變量 uchar hour_clk3,min_clk3; //鬧鐘3有關(guān)變量 uchar mode_flags; //狀態(tài)標(biāo)志位 uint ovf_cnt=0; //定時(shí)中斷次數(shù)紀(jì)錄 uchar first_on_flags=0; //掉電保存變量 uint ad_data_channal7; //ADC采樣數(shù)據(jù)1 uint ad_data_channal6; //ADC采樣數(shù)據(jù)2 float vol_data,vol_data1; //采樣電壓值轉(zhuǎn)換 uchar send_temp[10],send_i_cnt; //發(fā)送緩沖 /*===================================*/ /*************************************/ /*************************************/ void main() { init(); //程序初始化 LCD_init(); //1602初始化 init_24c02(); //24C02掉電保存初始化 serial_port_init(); //串行通信初始化 first_on_flags=read_add_24c02(2); beep(); if(first_on_flags!=33){ //首次上電,寫首次上電標(biāo)記 write_add_24c02(2,33); } else{ hour =read_add_24c02(3); min =read_add_24c02(4); hour_clk1 =read_add_24c02(5); min_clk1 =read_add_24c02(6); hour_clk2 =read_add_24c02(7); min_clk2 =read_add_24c02(8); hour_clk3 =read_add_24c02(9); min_clk3 =read_add_24c02(10); clk1_off =read_add_24c02(11); clk2_off =read_add_24c02(12); clk3_off =read_add_24c02(13); } while(1) { get_adc_data(); //獲取AD值 display_time(); //時(shí)間顯示 judge(); } } /*************************************/ /*************************************/ void init() { hour=6;min=29;sec=55; //初始化系統(tǒng)時(shí)間 hour_clk1=6;min_clk1=30; //初始化系統(tǒng)時(shí)鐘 hour_clk2=6;min_clk2=31; hour_clk3=6;min_clk3=32; AURX1|=0x04; //AD轉(zhuǎn)換結(jié)果存儲(chǔ)格式控制 P1ASF=1<<7; //模擬通道選擇 P1ASF=1<<6; BUZ_OUT=1; //蜂鳴器不響 LAMP_PORT=0; //繼電器不吸合 P0=255; //LCD數(shù)據(jù)口狀態(tài)初始化 TCON|=0x01; //INT0下降沿觸發(fā) EX0=1; //外部中斷0中斷允許 INT0=1; //P3.2置位 TMOD|=0x02; //定時(shí)器0工作在方式1 TH0=5; //250us計(jì)數(shù)初值高八位 TL0=5; //250us計(jì)數(shù)初值低八位 ET0=1; //定時(shí)器0中斷允許 EA=1; //全局中斷允許 TR0=1; //定時(shí)器0開啟 } /**************************/ void display_time() { Locate(1,1); if((mode_flags==1)&&flash_flags) LCD_str_(" "); else LCD_str_("Time: "); //調(diào)整模式下,“Time:”閃爍 LCD_2char(hour); //顯示時(shí) if(flash_flags&&(!pause_flags)) LCD_char(' '); else LCD_char(':'); //非暫停模式下,“:”閃爍 LCD_2char(min); //顯示分 if(flash_flags&&(!pause_flags)) LCD_char(' '); else LCD_char(':'); LCD_2char(sec); //顯示秒 LCD_str_(" "); if(mode_flags>0){display_clk();} //暫停時(shí),顯示鬧鐘 else{ Locate(2,1); LCD_float_(vol_data,2); LCD_str_("V "); LCD_4char(ad_data_channal7); LCD_str_(" "); Locate(2,13); if(!clk_on_or_off)LCD_str_(" ON"); //全局顯示鬧鐘的ON/OFF else LCD_str_(" OFF"); } } void display_clk() { Locate(2,1); if(flash_flags&&(mode_flags>1))LCD_str_(" ");//調(diào)整模式下,“Clkx:”閃爍 else{ if(mode_flags>0&&mode_flags<3) {LCD_str_("Clk1: ");dis_hour_clk=hour_clk1;dis_min_clk=min_clk1;} if(mode_flags==3) {LCD_str_("Clk2: ");dis_hour_clk=hour_clk2;dis_min_clk=min_clk2;} if(mode_flags==4) {LCD_str_("Clk3: ");dis_hour_clk=hour_clk3;dis_min_clk=min_clk3;} }//根據(jù)不同的狀態(tài),顯示不同的鬧鐘時(shí)間 LCD_2char(dis_hour_clk); LCD_char(':'); LCD_2char(dis_min_clk); LCD_str_(" "); Locate(2,13); if(mode_flags<2){ //調(diào)整時(shí)間的模式下,全局顯示鬧鐘的開或者關(guān) if(!clk_on_or_off)LCD_str_(" ON"); else LCD_str_(" OFF"); } /*根據(jù)不同調(diào)鬧和開關(guān)狀態(tài)顯示指定鬧鐘的開關(guān)*/ if( (mode_flags==2&&!clk1_off)|| (mode_flags==3&&!clk2_off)|| (mode_flags==4&&!clk3_off)) LCD_str_(" ON"); else LCD_str_(" OFF"); } /**************************/ void judge() { if(sec>=60){ //秒增量是否超過限定的判斷 sec=0; if(++min>=60){ min=0; if(++hour>=24)hour=0; } } if(mode_flags<1) {pause_flags=0;} //是否暫停的判斷 else {pause_flags=1;} /*以下為時(shí)限判斷*/ if(hour>23)hour=0; //調(diào)整時(shí)增量是否超限的判斷 if(min>59)min=0; if(hour_clk1>23) hour_clk1=0; if(min_clk1>59) min_clk1=0; if(hour_clk2>23) hour_clk2=0; if(min_clk2>59) min_clk2=0; if(hour_clk3>23) hour_clk3=0; if(min_clk3>59) min_clk3=0; /*以上為時(shí)限判斷*/ /*鬧鈴是否開啟判斷*/ if(!clk1_off||!clk2_off||!clk3_off) clk_on_or_off=0; else clk_on_or_off=1; /*蜂鳴器是否響判斷*/ if(!pause_flags&&!clk_on_or_off){clk_judge();} //非暫停模式下,鬧鐘打開情況下,檢測(cè)鬧鐘 if (!clk_flags) //使用clk_flags和clk_on檢測(cè)是否鬧鈴 { if(((hour!=hour_clk1)||(min!=min_clk1))&& ((hour!=hour_clk2)||(min!=min_clk2))&& ((hour!=hour_clk3)||(min!=min_clk3)))clk_flags=1;clk_on=0;BUZ_OUT=1; } else { if(clk_on){buzzer();BUZ_OUT=1;}} //滿足鬧鈴響所需的所有條件,發(fā)出鬧鈴聲 /*以下為EEPROM操作*/ if(sec==5){//一分鐘存一次 write_add_24c02(3,hour); LCD_delay(100); write_add_24c02(4,min); LCD_delay(100); write_add_24c02(5,hour_clk1);LCD_delay(100); write_add_24c02(6,min_clk1);LCD_delay(100); write_add_24c02(7,hour_clk2);LCD_delay(100); write_add_24c02(8,min_clk2);LCD_delay(100); write_add_24c02(9,hour_clk3);LCD_delay(100); write_add_24c02(10,min_clk3);LCD_delay(100); write_add_24c02(11,clk1_off);LCD_delay(100); write_add_24c02(12,clk2_off);LCD_delay(100); write_add_24c02(13,clk3_off);LCD_delay(100); } /*以下為串口接收完成處理*/ if(serial_finish){ serial_judge(); //串口數(shù)據(jù)處理 serial_finish=0; //清0接收結(jié)束標(biāo)志 } } void clk_judge() { if(((hour==hour_clk1)&&(min==min_clk1)&&!clk1_off)|| ((hour==hour_clk2)&&(min==min_clk2)&&!clk2_off)|| ((hour==hour_clk3)&&(min==min_clk3)&&!clk3_off))clk_on=1; else{clk_on=0;} } void beep() { uchar beep_cnt; for(beep_cnt=0;beep_cnt<60;beep_cnt++){ BUZ_OUT=0; LCD_delay(2); BUZ_OUT=1; //確保每次鬧鈴結(jié)束后蜂鳴器不響 LCD_delay(1); } } void buzzer() { uchar i; for(i=0;i<2;i++){ beep(); LCD_delay(500); } } /**************************/ void INT0_isr() interrupt 0 { LCD_delay(30); if(!INT0){ beep(); if(!MODE_KEY){ /*MODE_KEY*/ if(++mode_flags>=5){ pause_flags=0; mode_flags=0; flash_flags=0; } } if(!HOU_KEY){ /*HOU_KEY*/ if(mode_flags==1){++hour;} if(mode_flags==2){++hour_clk1;} if(mode_flags==3){++hour_clk2;} if(mode_flags==4){++hour_clk3;} } if(!MIN_KEY){ /*MIN_KEY*/ if(mode_flags==1){++min;} if(mode_flags==2){++min_clk1;} if(mode_flags==3){++min_clk2;} if(mode_flags==4){++min_clk3;} } if(!CLKON_KEY){ if(mode_flags==2)clk1_off=~clk1_off; if(mode_flags==3)clk2_off=~clk2_off; if(mode_flags==4)clk3_off=~clk3_off; } clk_flags=0; /*鬧鐘發(fā)生時(shí),按下任意鍵停止*/ } INT0=1; } //================================ void timer0_ovf_isr() interrupt 1 { if(ovf_cnt==1846)flash_flags=~flash_flags; if(++ovf_cnt==3691){ //12MHZ自動(dòng)重載4000次為1s,11.071692HZ下為3691 ovf_cnt=0; if(!pause_flags)sec++; //非暫停模式下,秒增一 flash_flags=~flash_flags; } //每間隔半秒flash_flags取反一次 } //================================ void receive_uart() interrupt 4 { if(RI){ RI=0; com_get=SBUF; serial_finish=1; } else{ TI=0; } } //================================ void serial_judge() { switch(com_get){ case 0x31: Uart_send_int(hour,2); Uart_send_(':'); Uart_send_int(min,2); Uart_send_(':'); Uart_send_int(sec,2); Uart_send(" \n"); break; case 0x32: Uart_send("The brightness:"); Uart_send_flt(vol_data1,3); Uart_send("V \n"); break; case 0x33: Uart_send("The voltage:"); Uart_send_flt(vol_data,3); Uart_send("V \n"); break; case 0x34:LAMP_PORT=!LAMP_PORT;break; default : Uart_send("Command Error! \n"); Uart_send("1->To get the system time. \n"); Uart_send("2->To get the brightness. \n"); Uart_send("3->To get the voltage. \n"); Uart_send("4->To control the 220V light ON/OFF. \n\n"); } com_get=0; } //================================ void get_adc_data() { ad_data_channal7=ADC_GET(7); LCD_delay(1000); ad_data_channal6=ADC_GET(6); LCD_delay(1000); vol_data=(float)ad_data_channal6/1024; vol_data*=5.0; vol_data1=(float)ad_data_channal7/1024; vol_data1*=5.0; } //================================ /*void delay_ms(uint xms) { uint i,j; for(i=0;i< xms;i++) for(j=0;j< 990;j++); }*/ //================================
上面是主程序,已經(jīng)調(diào)試通過,下面是部分.h文件,限于篇幅,完整的代碼大家可從下面的鏈接下載
http://www.zg4o1577.cn/ziliao/file/naozhong1602.rar , 只要更改一下端口便可適應(yīng)于其他電路.
/*--------文件名:CLK_LCD1602.H-------*/ #ifndef _CLK_LCD1602_H_ #define _CLK_LCD1602_H_ #define uint unsigned int #define uchar unsigned char #define LCM_P P2 //LCD的控制端口 #define LCM_DATA P0 //LCD的數(shù)據(jù)口 #define LCM_RS_0 LCM_P&=~(1<<5) #define LCM_RS_1 LCM_P|= 1<<5 #define LCM_RW_0 LCM_P&=~(1<<6) #define LCM_RW_1 LCM_P|= 1<<6 #define LCM_EN_0 LCM_P&=~(1<<7) #define LCM_EN_1 LCM_P|= 1<<7 /*========================================*/ #define LCD_str(x,y,s) Locate(x,y);LCD_str_(s); #define LCD_float(x,y,flt) Locate(x,y);LCD_float_(flt); /*========================================*/ void LCD_init(); //LCM1602的初始化函數(shù),在使用1602之前都必須調(diào)用 void Locate(uchar,uchar); //顯示定位函數(shù) void LCD_half(uchar); //送半字節(jié)函數(shù) void LCD_char(uchar); //寫一個(gè)字符函數(shù) void LCD_2char(uchar); //顯示兩個(gè)字符 void LCD_4char(uint); //顯示四個(gè)字符 void LCD_cmd(uchar); //寫命令函數(shù) void LCD_str_(uchar str[]); //寫字符串?dāng)?shù)據(jù)函數(shù) void LCD_float_(float,uchar); //寫浮點(diǎn)數(shù)據(jù)函數(shù) void LCD_delay(uint); //延時(shí)子函數(shù) /******************************************/ /*-函數(shù)功能:液晶使用初始化---------------*/ /*-入口參數(shù):無*/ /******************************************/ void LCD_init() { LCD_cmd(0x01); LCD_delay(10); LCD_cmd(0x28); //4位數(shù)據(jù)、雙行顯示、5*7(0x38為八位) LCM_EN_1;_nop_();_nop_();_nop_(); LCM_EN_0; /*此處必須加上這兩句*/ LCD_delay(10); LCD_cmd(0x28); LCD_cmd(0x06); LCD_cmd(0x0c); LCD_cmd(0x01); LCD_delay(10); } /******************************************/ /*-函數(shù)功能:顯示數(shù)據(jù)定位函數(shù)-------------*/ /*-入口參數(shù):行坐標(biāo)x、列坐標(biāo)y-------------*/ /******************************************/ void Locate(uchar x,uchar y) { x&=0x01; LCD_cmd((x==0)?(y+0xbf):(y+0x7f)); } /******************************************/ /*-函數(shù)功能:送半字節(jié)函數(shù)-----------------*/ /*-入口參數(shù):要寫到液晶指令或數(shù)據(jù)寄存器的-*/ /* 字節(jié)的高四位或低四位---------*/ /******************************************/ void LCD_half(uchar dataw_) { LCM_DATA=(LCM_DATA&0x0f)|(dataw_); LCM_EN_1;_nop_();_nop_();_nop_(); LCM_EN_0; LCD_delay(1);//實(shí)際使用中加上10ms的延時(shí) } /******************************************/ /*-函數(shù)功能:寫一位數(shù)據(jù)函數(shù)---------------*/ /*-入口參數(shù):數(shù)據(jù)內(nèi)容---------------------*/ /******************************************/ void LCD_char(uchar dataw) { LCM_RS_1;LCM_RW_0;LCM_EN_0;_nop_(); LCD_half(dataw&0xf0); LCD_half(dataw<<4); } /*========================================*/ void LCD_cmd(uchar cmd) { LCM_RS_0;LCM_RW_0;LCM_EN_0;_nop_(); LCD_half(cmd&0xf0); LCD_half(cmd<<4); } /*========================================*/ void LCD_str_(uchar *str) { while(*str)LCD_char(*str++); } /*========================================*/ void LCD_2char(uchar num_2) { uchar num_temp; num_temp=num_2/10; LCD_char(num_temp+0x30); num_temp=num_2%10; LCD_char(num_temp+0x30); } void LCD_4char(uint num_4) { uint num_tmp; num_tmp=num_4/1000; LCD_char(num_tmp+0x30); num_tmp=num_4/100; num_tmp=num_tmp%10; LCD_char(num_tmp+0x30); num_tmp=num_4/10; num_tmp=num_tmp%10; LCD_char(num_tmp+0x30); num_tmp=num_4%10; LCD_char(num_tmp+0x30); } /*========================================*/ void LCD_float_(float flt,uchar n) { uchar counter=0,num_str[10],neg_flags=0,n_; long int num; n_=n; while(n_){n_--;flt*=10;} num=flt; if(!num)num_str[counter++]=0x30; if(num<0){num=-num,neg_flags=1;} while(num!=0) { num_str[counter++]=num%10+0x30; num/=10; if(counter==n)num_str[counter++]='.'; } if(neg_flags){num_str[counter++]='-';} while(counter--)(LCD_char(num_str[counter])); } /*========================================*/ void LCD_delay(uint xus) { uint i=0,j=0; for(i=0;i< xus;i++) for(j=0;j< 123;j++); } /*========================================*/ #endif /*----------文件名:SERIAL_UART.H-------------*/ #ifndef _SERIAL_UART_H_ #define _SERIAL_UART_H_ #define uint unsigned int #define uchar unsigned char #define Fosc 11059200 #define Baud 9600 #define Reload (256-((2*Fosc)/12/32/Baud)) //SMOD==1 //#define Reload (256-(Fosc/12/32/Baud)) //SMOD==0 sfr AUXR = 0x8e; sfr AUXR1 = 0xA2; sfr BRT = 0x9c; //獨(dú)立波特率發(fā)生器重裝載寄存器 void serial_port_init(); void Uart_send_(uchar); void Uart_send(uchar *); void Uart_send_int(int,uchar); /*=================================*/ void serial_port_init() { SCON=0x50; //串口控制第七第六方式控制,第四位允許接收 PCON|=0x80; //第七位SMOD AUXR=0x11; //第四位置位允許獨(dú)立波特率發(fā)生器運(yùn)行 BRT=Reload; //獨(dú)立波特率發(fā)生器賦值 AUXR1=0x80; //選擇串口位置 ES=1; //允許串口中斷 // EA=1; //允許全局中斷 } /*========================================*/ void Uart_send(uchar *str) { while(*str)Uart_send_(*str++); } /*========================================*/ void Uart_send_int(int num_send,uchar n_cnt) { uchar num_str[7],num_cnt=0,neg_flags=0; if(num_send<0){num_send=-num_send;neg_flags=1;} do{ num_str[num_cnt++]=num_send%10+0x30; num_send/=10; }while(num_send); while(num_cnt< n_cnt)num_str[num_cnt++]=0x30; if(neg_flags)num_str[num_cnt++]='-'; while(num_cnt--)Uart_send_(num_str[num_cnt]); } /*========================================*/ void Uart_send_flt(float flt,uchar n) { long int num; uchar counter=0,num_str[10],n_temp; bit small_1=0,neg_flags=0; n_temp=n; if(flt< 1.0)small_1=1; while(n_temp){n_temp--;flt*=10;} num=flt; if(num< 0){num=-num,neg_flags=1;} do{ num_str[counter++]=num%10+0x30; num/=10; if(counter==n)num_str[counter++]='.'; }while(num!=0); if(small_1)num_str[counter++]=0x30; if(neg_flags){num_str[counter++]='-';} while(counter--)(Uart_send_(num_str[counter])); } /*========================================*/ void Uart_send_(uchar dat) { ES=0; TI=0; SBUF=dat; while(!TI); TI=0; ES=1; } /*========================================*/ #endif