时钟加闹钟c语言程序,[课程设计]可设置8个闹钟时间的智能时钟(C)

程序清单

本程序用C语言编写,经Keil C51编译成二进制码后写入89C51内的EPROM内即可。

#i nclude "atmel\at89x51.h"

#i nclude "intrins.h"

unsigned char hour,min,sec,year,month,day,weekday

unsigned int count_down

bit LED_on

unsigned char display[8]

unsigned char attr

bit flash

unsigned char show_status

// 0:设置闹钟数据

// 1:显示当前日期及星期

// 2:显示当前时间

// 3:设置当前日期

// 4:设置当前时间

bit km

bit kp

bit sound

bit alarm_stop

struct { unsigned char h

unsigned char m

} alarm[8]

unsigned char alarm_en

unsigned char alarm_wk

unsigned char cur_alarm_set

unsigned char cur_alarm_active

bit new_alarm_info

sbit sound_output = P1^5

sbit SDA_PIN = P1^6

sbit SCL_PIN = P1^7

void I2cDelay() //EEPROM操作时需要的延时函数

{ _nop_()

_nop_()

}

void DelayX1ms(unsigned char count) //延迟函数,参数为毫秒数

{unsigned char i,j

for(i=0

for(j=0

}

void Start() //I2C启动,24C08使用I2C方式

{ SDA_PIN=1

SCL_PIN=1

SDA_PIN=0

SCL_PIN=0

}

void Stop() //I2C停止

{ I2cDelay()

I2cDelay()

I2cDelay()

I2cDelay()

}

bit SendByte(unsigned char value) //发送1字节数据给EEPROM

{unsigned char i

bit no_ack=0

for(i=0

{ I2cDelay()

if(value&0x80) SDA_PIN=1

else SDA_PIN=0

value=value<<1

I2cDelay()

I2cDelay()

I2cDelay()

}

I2cDelay()

I2cDelay()

I2cDelay()

if(SDA_PIN==1) no_ack=1

I2cDelay()

return no_ack

}

void mywrite(unsigned char address,unsigned char value) //向EEPROM写1字节

{ Start()

SendByte(value)

}

unsigned char ReadByte() //从EEPROM接收1字节

{unsigned char i,bval

bval=0

for(i=0

{ I2cDelay()

SDA_PIN=1

I2cDelay()

I2cDelay()

I2cDelay()

}

I2cDelay()

I2cDelay()

I2cDelay()

I2cDelay()

return(bval)

}

unsigned char myread(unsigned char address) //从EEPROM读入1字节数据

{unsigned char tmp

Start()

Start()

Stop()

return(tmp)

}

void Timer0ISR(void) interrupt 1 using 3 //定时器0中断程序,用于走时,1/8000秒一次

{unsigned char tmp,tmp_days

count_down--

if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)

{ flash=~flash

if(sound && flash) sound_output=0

else sound_output=1

return

}

if(count_down==3000)

{ if(year==0) weekday=5

else { tmp=(year-1)/4+1

weekday=(tmp+5)%7

}

tmp_days=0

for(tmp=1

if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)

tmp_days=tmp_days+31

else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)

tmp_days=tmp_days+30

else if(tmp==2)

{ if(year%4==0) tmp_days=tmp_days+29

else tmp_days=tmp_days+28

}

tmp_days=tmp_days+day-1

return

}

if(count_down==5000)

{ if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) //触发后1分钟

{ alarm_stop=0

if(sound==0 && alarm_stop==0) //没有已触发的闹钟项

for(tmp=0

{ if(((alarm_en>>tmp)&1)==0) continue

if(((alarm_wk>>tmp)&1)==1) //该闹钟项周末有效

{ if(weekday!=6 && weekday!=7) continue

else

{ if(weekday==6 || weekday==7) continue

if(alarm[tmp].h==hour && alarm[tmp].m==min) //比较当前时间与该

{ sound=1

}

return

}

if(count_down==0) //过了一秒钟

{ count_down=8000

sec++

if(sec==60)

{ sec=0

min++

if(min==60)

{ min=0

hour++

if(hour==24)

{ hour=0

switch(day)

{ case 29: if(month==2 && year%4) { day=1

break

case 30: if(month==2 && year%4==0) { day=1

break

case 31: if(month==4 || month==6 || month==9 || month==11)

{ day=1

break

case 32: day=1

if(month==13) { month=1

}

}

}

}

}

}

void Timer1ISR(void) interrupt 3 using 2 //定时器2中断,用于按键扫描

{unsigned char keytmp

char tmp

TH1=0x15

if(show_status==0) //当前正在设置闹钟项

{ display[0]=cur_alarm_set

display[2]=alarm[cur_alarm_set].h/10

display[4]=alarm[cur_alarm_set].m/10

display[6]=(alarm_wk>>cur_alarm_set)&1

}

if(show_status==1 || show_status==3) //当前显示或设置日期

{ display[0]=year/10

display[3]=month%10

display[6]=0xf

}

if(show_status==2 || show_status==4) //当前显示或设置时间

{ display[0]=hour/10

display[3]=min%10

display[6]=0xf

}

keytmp=~(P1) & 0x0f

if(keytmp==0) { km=0

else

{ if(km==0) km=1

else

{ if(kp==0)

{ kp=1

if(keytmp==1) //第一个按钮

{ if(sound) { alarm_stop=1

else if((show_status==1 || show_status==2) && led_on) //正显示日期或时间

{ show_status=0

else if(show_status==0) //如正在设置闹钟时间项

{ show_status=2

return

}

if(keytmp==2 && led_on) //第二个按钮,仅当数码管打开时有效

{ switch(attr)

{ case 0xff: if(show_status==1) show_status=2

else if(show_status==2) show_status=1

break

case 0x3f: if(show_status==0) cur_alarm_set=(cur_alarm_set+1)%8

else if(show_status==3)

year=(year+1)%50

else if(show_status==4)

hour=(hour+1)%24

break

case 0xcf: if(show_status==0) //闹钟设置的“时”加1

alarm[cur_alarm_set].h=(alarm[cur_alarm_set].h+1)%24

else if(show_status==3)

{ month++

if(month==13) month=1

else if(show_status==4)

min=(min+1)%60

break

case 0xf3: if(show_status==0)

alarm[cur_alarm_set].m=(alarm[cur_alarm_set].m+1)%60

else if(show_status==3)

{day++

if(day==32) day=1

else if(show_status==4)

{count_down=8000

sec=(sec+1)%60

break

case 0xfd: if(show_status==0)

alarm_wk^=0x1<

break

case 0xfe: if(show_status==0)

alarm_en^=0x1<

} //end of switch(attr)

return

} //end of if(keytmp==1)

if(keytmp==4) //第三个按钮

{ switch(attr)

{ case 0xff: if(show_status==1 || show_status==2)

led_on=~led_on

break

case 0x3f: if(show_status==0) //如果正在设置闹钟

{ if(cur_alarm_set==0) cur_alarm_set=7

else cur_alarm_set--

else if(show_status==3) //当前日期的“年”减1

{ if(year==0) year=49

else if(show_status==4) //当前时间的“时”减1

{ tmp=hour-1

break

case 0xcf: if(show_status==0) //闹钟设置的“时”减1

{ tmp=alarm[cur_alarm_set].h-1

if(tmp<0) alarm[cur_alarm_set].h=23

else alarm[cur_alarm_set].h=tmp

}

else if(show_status==3)

{ month--

if(month==0) month=12

else if(show_status==4)

{ tmp=min-1

if(tmp<0) min=59

break

case 0xf3: if(show_status==0) //闹钟设置的“分钟”减1

{ tmp=alarm[cur_alarm_set].m-1

if(tmp<0) alarm[cur_alarm_set].m=59

else alarm[cur_alarm_set].m=tmp

}

else if(show_status==3)

{ day--

if(day==0) day=31

else if(show_status==4)

{ tmp=sec-1

count_down=8000

if(tmp<0) sec=59

break

case 0xfd: if(show_status==0) //切换周末标志

alarm_wk^=0x1<

break

case 0xfe: if(show_status==0) //切换启用标志

alarm_en^=0x1<

} //end of switch(attr)

return

} //end of if(keytmp==2)

if(keytmp==8 & led_on) //第四个按钮,仅当数码管打开时有效

{ switch(attr)

{ case 0xff: if(show_status==1) //如果当前显示日期

show_status=3

else if(show_status==2) //如果当前显示时间

show_status=4

attr=0x3f

case 0x3f: attr=0xcf

case 0xcf: attr=0xf3

case 0xf3: if(show_status==0) attr=0xfd

else if(show_status==3)

{ show_status=1

else if(show_status==4)

{ show_status=2

break

case 0xfd: if(show_status==0) attr=0xfe

break

case 0xfe: if(show_status==0) attr=0x3f

}

} // end of if(keytmp==4)

} // end of if(kp==0)

} // end of if(km==0)

} // end of if(keytmp!=0)

}

main()

{unsigned char i

hour=23

count_down=8000

flash=0

km=0

new_alarm_info=0

for(i=0

{ alarm[i].h=myread(i*2)

alarm_en=myread(i*2)

IE=0

TMOD=0x12

TH0=6

TH1=0x15

TR0=1

ET0=1

while(1)

{ if(led_on)

for(i=0

{ P2=0

if(flash || attr&(0x80>>i))

{ P0=display[i]

}

else P2=0

if(new_alarm_info)

{ P2=0

new_alarm_info=0

for(i=0

mywrite(i*2,alarm_en)

}

}

}

唯样商城-电子元器件采购网(www.oneyac.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。

唯样自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值