51单片机超级闹钟程序设计(有图)
/*课程设计终于弄完了,总想共享一下源代码,*/
/*遂在51hei上贴出来,大家看有什么问题吧~如果哪里写得不好还请众亲们指出哦~*/
/*---附:实物图--*/
/*===Chip:STC12C5A32S2======================*//*===Software:Keil 4 C51========================*//*===Author:梁鹏===================================*//*===Organization:广西民族大学07自动化===========*//*===Date:2010年05月26日======================*//*===Version:1.0===============================*//*===声明:本程序属原创作品,仅供学习交流,不得用于商业用途,如需转载,请注明出处,谢谢合作!======*//*--------文件名: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; //时增一键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数据接口sbit LAMP_PORT=P2^1; //继电器控制口 /*=========子函数的声明==============*/void init(); //系统初始化void display_time(); //显示时间的子函数void display_clk(); //显示闹钟的子函数void judge(); //判断秒增量是否大于限定值void clk_judge(); //检测是否到达闹铃时间void beep(); //蜂鸣器响子函数void buzzer(); //闹铃响子函数void get_adc_data(); //AD采样数据及处理子函数void serial_judge(); //串口数据处理子函数//void delay_ms(uint); //MS级延时子程序/*==========变量的声明===============*/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; //串口接收结束标志位uchar com_send,com_get; //串口通信相关变量uchar hour,min,sec; //时间变量uchar dis_hour_clk,dis_min_clk; //用于显示闹钟时间的变量uchar hour_clk1,min_clk1; //闹钟1有关变量uchar hour_clk2,min_clk2; //闹钟2有关变量uchar hour_clk3,min_clk3; //闹钟3有关变量uchar mode_flags; //状态标志位uint ovf_cnt=0; //定时中断次数纪录uchar first_on_flags=0; //掉电保存变量uint ad_data_channal7; //ADC采样数据1uint ad_data_channal6; //ADC采样数据2float vol_data,vol_data1; //采样电压值转换uchar send_temp[10],send_i_cnt; //发送缓冲/*===================================*//*************************************//*************************************/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){ //首次上电,写首次上电标记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(); //时间显示judge();}}/*************************************//*************************************/void init(){ hour=6;min=29;sec=55; //初始化系统时间hour_clk1=6;min_clk1=30; //初始化系统时钟hour_clk2=6;min_clk2=31;hour_clk3=6;min_clk3=32;AURX1|=0x04; //AD转换结果存储格式控制 P1ASF=17; //模拟通道选择P1ASF=16;BUZ_OUT=1; //蜂鸣器不响LAMP_PORT=0; //继电器不吸合P0=255; //LCD数据口状态初始化TCON|=0x01; //INT0下降沿触发EX0=1; //外部中断0中断允许 INT0=1; //P3.2置位TMOD|=0x02; //定时器0工作在方式1TH0=5; //250us计数初值高八位TL0=5; //250us计数初值低八位ET0=1; //定时器0中断允许EA=1; //全局中断允许TR0=1; //定时器0开启}/**************************/void display_time(){Locate(1,1);if((mode_flags==1)flash_flags) LCD_str_(" ");else LCD_str_("Time: "); //调整模式下,“Time:”闪烁LCD_2char(hour); //显示时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();} //暂停时,显示闹钟 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/OFFelse LCD_str_(" OFF");} }void display_clk(){Locate(2,1);if(flash_flags(mode_flags>1))LCD_str_(" ");//调整模式下,“Clkx:”闪烁else{ if(mode_flags>0mode_flags3){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;}}//根据不同的状态,显示不同的闹钟时间LCD_2char(dis_hour_clk);LCD_char(':');LCD_2char(dis_min_clk);LCD_str_(" ");Locate(2,13);if(mode_flags2){ //调整时间的模式下,全局显示闹钟的开或者关if(!clk_on_or_off)LCD_str_(" ON");else LCD_str_(" OFF");}/*根据不同调闹和开关状态显示指定闹钟的开关*/ 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_flags1) {pause_flags=0;} //是否暂停的判断else {pause_flags=1;}/*以下为时限判断*/if(hour>23)hour=0; //调整时增量是否超限的判断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;/*以上为时限判断*/ /*闹铃是否开启判断*/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();}
//非暂停模式下,闹钟打开情况下,检测闹钟if (!clk_flags) //使用clk_flags和clk_on检测是否闹铃{ 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;}} //满足闹铃响所需的所有条件,发出闹铃声/*以下为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(); //串口数据处理serial_finish=0; //清0接收结束标志}}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_cnt60;beep_cnt++){BUZ_OUT=0; LCD_delay(2);BUZ_OUT=1; //确保每次闹铃结束后蜂鸣器不响LCD_delay(1); }}void buzzer(){uchar i;for(i=0;i2;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; /*闹钟发生时,按下任意键停止*/}INT0=1;}//================================void timer0_ovf_isr() interrupt 1{if(ovf_cnt==1846)flash_flags=~flash_flags;if(++ovf_cnt==3691){ //12MHZ自动重载4000次为1s,11.071692HZ下为3691ovf_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(" ");break;case 0x32:Uart_send("The brightness:");Uart_send_flt(vol_data1,3);Uart_send("V ");break;case 0x33:Uart_send("The voltage:");Uart_send_flt(vol_data,3);Uart_send("V ");break;case 0x34:LAMP_PORT=!LAMP_PORT;break;default :Uart_send("Command Error! ");Uart_send("1->To get the system time. ");Uart_send("2->To get the brightness. ");Uart_send("3->To get the voltage. ");Uart_send("4->To control the 220V light ON/OFF. ");}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++);}*///================================
上面是主程序,已经调试通过,下面是部分.h文件,限于篇幅,完整的代码大家可从下面的链接下载
http://www.51hei.com/ziliao/file/naozhong1602.rar, 只要更改一下端口便可适应于其他电路.
/*--------文件名: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的数据口#define LCM_RS_0 LCM_P=~(15)#define LCM_RS_1 LCM_P|= 15#define LCM_RW_0 LCM_P=~(16)#define LCM_RW_1 LCM_P|= 16 #define LCM_EN_0 LCM_P=~(17)#define LCM_EN_1 LCM_P|= 17/*========================================*/#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的初始化函数,在使用1602之前都必须调用void Locate(uchar,uchar); //显示定位函数void LCD_half(uchar); //送半字节函数void LCD_char(uchar); //写一个字符函数void LCD_2char(uchar); //显示两个字符void LCD_4char(uint); //显示四个字符void LCD_cmd(uchar); //写命令函数void LCD_str_(uchar str[]); //写字符串数据函数void LCD_float_(float,uchar); //写浮点数据函数void LCD_delay(uint); //延时子函数/******************************************//*-函数功能:液晶使用初始化---------------*//*-入口参数:无*//******************************************/void LCD_init(){LCD_cmd(0x01);LCD_delay(10);LCD_cmd(0x28); //4位数据、双行显示、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);}/******************************************//*-函数功能:显示数据定位函数-------------*//*-入口参数:行坐标x、列坐标y-------------*//******************************************/ void Locate(uchar x,uchar y){x=0x01;LCD_cmd((x==0)?(y+0xbf):(y+0x7f));}/******************************************//*-函数功能:送半字节函数-----------------*//*-入口参数:要写到液晶指令或数据寄存器的-*//* 字节的高四位或低四位---------*//******************************************/void LCD_half(uchar dataw_){LCM_DATA=(LCM_DATA0x0f)|(dataw_);LCM_EN_1;_nop_();_nop_();_nop_();LCM_EN_0;LCD_delay(1);//实际使用中加上10ms的延时}/******************************************//*-函数功能:写一位数据函数---------------*//*-入口参数:数据内容---------------------*//******************************************/void LCD_char(uchar dataw){LCM_RS_1;LCM_RW_0;LCM_EN_0;_nop_();LCD_half(dataw0xf0);LCD_half(dataw4); }/*========================================*/void LCD_cmd(uchar cmd){ LCM_RS_0;LCM_RW_0;LCM_EN_0;_nop_();LCD_half(cmd0xf0);LCD_half(cmd4);} /*========================================*/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(num0){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==0sfr AUXR = 0x8e; sfr AUXR1 = 0xA2;sfr BRT = 0x9c; //独立波特率发生器重装载寄存器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; //第四位置位允许独立波特率发生器运行BRT=Reload; //独立波特率发生器赋值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_send0){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
51单片机相关文章:51单片机教程
单片机相关文章:单片机教程
c++相关文章:c++教程
单片机相关文章:单片机视频教程
单片机相关文章:单片机工作原理
蜂鸣器相关文章:蜂鸣器原理
评论