|
楼主 |
发表于 2014-5-4 10:09:21
|
显示全部楼层
这是完整代码,真的是奇怪
- #include <tiny85.h>
- #include<delay.h>
- // Declare your global variables here
- unsigned char mima[5],ysmima[5],mimajishu,shucuo,j,cnt; //密码计数,录入密码数组,原始密码数组,长按标志 // 2位密码计数单元
- unsigned char ershimiao_counter,ermiao_counter,shucuo_counter,yimiao_counter,key_stime_counter,status,shangdengcishu; // 时间计数单元,闪灯次数
- unsigned char ershimiao_ok,shucuo_ok,ermiao_ok,yimiao_ok,key_stime_ok,kaidengduibi; //第一次开关未完成时,第二次开灯指令的识别
- unsigned int shangdengtime,guangdengtime; //闪灯开的时间,闪灯关的时间
- unsigned char huifu[5]={1,2,3,4,5}; //初始密码
- // External Interrupt 0 service routine
- interrupt [EXT_INT0] void ext_int0_isr(void)
- {
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- TIMSK=0x10; // 允许T/C0比较匹配中断
- PORTB ^= 1<<5; //中断唤醒监测
- GIMSK=0x00; //禁用INT0中断,等合适的时候再打开
- //GICR = 0x00; //禁用INT0中断
- WDTCR=0x18; //开看门狗约为16ms
- WDTCR=0x08;
-
- MCUCR &=~(1<<SE); // 禁止睡眠使能,在需要休眠时再打开0
- }
- // Timer 0 output compare A interrupt service routine , Timer 0 比较匹配中断服务,2ms定时
- interrupt [TIM0_COMPA] void timer0_compa_isr(void)
- {
- if (++key_stime_counter >=5)
- {
- key_stime_counter = 0;
- key_stime_ok = 1; // 10ms到
- if (++yimiao_counter >= 100)
- {
- yimiao_counter = 0;
- yimiao_ok = 1; // 1s到
- if (++ermiao_counter >= 2)
- {
- ermiao_counter = 0;
- ermiao_ok = 1; // 2s到
- if (++ershimiao_counter >= 15)
- {
- ershimiao_counter = 0;
- ershimiao_ok = 1; // 30s到
- if (++shucuo_counter >= 10)
- {
- shucuo_counter = 0;
- shucuo_ok = 1; // 300s到
- }
- }
- }
- }
- }
- }
- #define key_input PINB.1 // 按键输入口兼INTO中断唤醒
- #define key_state_0 0
- #define key_state_1 1
- #define key_state_2 2
- #define key_state_3 3
- #define key_state_4 4
- void qingling(void) //清零
- {
- yimiao_counter = 0; //因为是最后一次按键清零后过了1秒,才开始第一位密码识别的,不清零的话后面第一个10ms过后就会把第二位密码记上了,
- yimiao_ok = 0; //这会让你没有机会输入第二次密码
- ermiao_counter = 0;
- ermiao_ok = 0;
- ershimiao_counter = 0;
- ershimiao_ok = 0;
- shucuo_counter = 0;
- shucuo_ok = 0; // 300s到
- }
-
- void shangdeng(void) //闪灯
- {
- static unsigned char status=1,kaidengbiaozhi;
- static unsigned int i,j,h;
- if(shangdengcishu >0) //闪灯次数 类似倒计时程序
- {
- if(kaidengduibi==1) //开灯比对,有新的开灯指令时为1
- {
- status=0;
- }
- switch (status)
- {
- case 0:
- kaidengduibi=0; //开灯对比,对比结束
- if(kaidengbiaozhi == 1) //上一次开灯程序未完成标志
- {
- if (++h >= 3000-j) //按键关灯时间,实现第一次正在开灯,或者正在关灯时,若第二次开灯指令就来了,就先执行关灯
- {
- j=0;
- h=0;
- status=1;
- i=0;
-
- }
- }
- else status=1;
- break;
- case 1:
-
- PORTB |=( 1<<0); //PD7输出高
- PORTB &=~( 1<<1); //INT0拉低
- DDRB = 0x3B;
- qingling(); //清零
- kaidengbiaozhi=1; //开灯标志,表示开灯任务开始
- if (++i >= shangdengtime) //按键开灯时间
- {
- status=2;
- i=0;
- }
- break;
- case 2:
- if (++j >= guangdengtime) //按键关灯时间
- {
- j=0;
- status=0;
- --shangdengcishu ;
- kaidengbiaozhi=0; //开灯标志,标示开灯任务结束,准备好第二次开关了
- }
- if(j>=3000) //灭灯时间达到设定值时,把开关标志清零,也就是可以再次接受新的开灯指令了,这样再开灯时就能及时看到亮灯
- {
- kaidengbiaozhi=0; //开灯标志,标示开灯任务结束,准备好第二次开关了
- }
- break;
- }
- }
- }
-
- unsigned char read_key_n(void)
- {
- static unsigned char key_state = 0, key_time = 0;
- unsigned char key_press, key_return = 0;
-
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- //PORTB=0x3A;
- //DDRB=0x39;
- key_press = key_input; // 读按键I/O电平
- switch (key_state)
- {
- case key_state_0: // 按键初始态
- if (!key_press) key_state = key_state_1; // 键被按下,状态转换到键确认态
- break;
- case key_state_1: // 按键确认态
- if (!key_press)
- {
- key_state = key_state_2; // 按键仍按下,状态转换到计时1
- key_time = 0; // 清另按键时间计数器
- }
- else
- key_state = key_state_0; // 按键已抬起,转换到按键初始态
- break;
- case key_state_2:
- if (key_press)
- {
- key_state = key_state_0; // 按键已释放,转换到按键初始态
- key_return = 1; // 输出"1" ,表示单击
- key_time = 0;
- shangdengcishu = 1; //开短闪灯 ,告知按下按键成功短按一次
- shangdengtime = 3000; //设置闪灯时间
- guangdengtime = 0; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- if (++mimajishu >9)
- {
- mimajishu = 0;
- }
- }
- else if (++key_time >= 100) // 长按1秒按键时间计数
- {
- key_state = key_state_3; // 按下时间>1s,状态转换到计时2
- key_time = 0; // 清按键计数器
- key_return = 2; // 长按超过1秒后输出"2" ,
- shangdengcishu = 1; //开短闪灯 ,告知按下按键已经有1秒 ,此后3秒内松开手就关门
- shangdengtime = 60000; //设置闪灯时间
- guangdengtime = 0; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- qingling(); //清零
- break;
- case key_state_3:
- if (key_press)
- {
- key_state = key_state_0; //按键已释放,转换到按键初始态
- key_time = 0; // 清按键计数器
- }
- else if (++key_time >= 250) // 长按达到3.5秒按键时间计数
- {
- key_state = key_state_4; // 按下时间>3.5s,状态转换到计时2
- key_time = 0; // 清按键计数器
- key_return = 3; //长按2秒,进入设置界面
- shangdengcishu = 3; //开长闪灯
- shangdengtime = 65000; //设置长闪灯时间
- guangdengtime = 10000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- qingling(); //清零
- break;
- case key_state_4:
- if (key_press)
- {
- key_state = key_state_0; //按键已释放,转换到按键初始态
- }
- qingling(); //清零
- break;
-
- }
- return key_return;
- }
- unsigned char read_key_driver(void) //按键密码输入记录部分
- {
- static unsigned char i = 0,aj_state = 0;
- unsigned char key_return = 0;
- #asm("WDR") //喂狗
- if (key_stime_ok) // 10ms到,键处理
- {
- key_stime_ok = 0;
- read_key_n();
- switch (aj_state)
- {
- case 0:
- if (ermiao_ok)
- {
- if(i < 5) //密码位数设置
- {
- mima[i] = mimajishu; //记录第一位密码
- mimajishu =0;
- PORTB ^= 1<<5; //观察第一位密码识别
- aj_state = 1;
- qingling(); //清零
- i=++i;
- shangdengcishu = i; //开短闪灯标示刚才输入一位密码成功
- shangdengtime = 3000; //设置闪灯时间
- guangdengtime = 17000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- }
- break;
- case 1:
- if (i == 5) //密码识别位数确认 ,闪2次标示密码输完
- {
- i=0;
- aj_state = 0;
- key_return = 1;
- }
- else
- aj_state = 0;
- break;
- }
- return key_return;
- }
- }
- void main(void)
- {
- // Declare your local variables here
- // Crystal Oscillator division factor: 1
- #pragma optsize-
- CLKPR=0x80;
- CLKPR=0x00;
- #ifdef _OPTIMIZE_SIZE_
- #pragma optsize+
- #endif
- // Input/Output Ports initialization
- // Port B initialization
- // Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
- // State5=T State4=T State3=T State2=T State1=T State0=0
- //PORTB = 0xE6; //11100110
- //DDRB = 0x39; //00100001,PB.0和5配置为输出,其它位为输入
- PORTB=0x3A;
- DDRB=0x39;
- delay_ms(100);
- /*上电恢复初始密码*/
- PORTB |=( 1<<0); //PD7输出高
- DDRB &=~( 1<<0); //PD7设置成输入
- if(PINB.0 == 0) //若PD7拉低就把密码恢复出厂设置
- {
- shangdengcishu = 5; //开短闪灯标示刚才输入一位密码成功
- shangdengtime = 15000; //设置闪灯时间
- guangdengtime = 10000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- for(j=0;j<5;j++) //写入新设置密码
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EECR = (0<<EEPM1)|(0<<EEPM0);
- EEARL = j+10;
- EEDR = huifu[j]; //恢复默认密码
- EECR |=(1 <<EEMPE);
- EECR |=(1 <<EEPE);
- ysmima[j] = huifu[j]; //密码立即生效
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
- }
- //delay_ms(5000);
-
- }
- //while(PIND.7 == 0) {;}
- //PORTB = 0xE6; //11100110
- //DDRB = 0x39; //00100001,PB.0和5配置为输出,其它位为输入 // PD7为输出方式,默认输出低电平
- PORTB=0x3A;
- DDRB=0x39;
-
- #asm("cli")
- #asm("sei")
-
- for(j=0;j<5;j++) //读出原密码
- {
- while(EECR &(1 <<EEPE));
- EEARL = j+10;
- EECR |=(1<<EERE);
- ysmima[j]=EEDR;
- delay_ms(10);
- }
-
- #asm("cli")
- // Timer/Counter 0 initialization
- // Clock source: System Clock
- // Clock value: 125.000 kHz
- // Mode: CTC top=OCR0A
- // OC0A output: Disconnected
- // OC0B output: Disconnected
- TCCR0A=0x02;
- TCCR0B=0x03;
- TCNT0=0x00;
- OCR0A=0xF9;
- OCR0B=0x00;
- // Timer/Counter 1 initialization
- // Clock source: System Clock
- // Clock value: Timer1 Stopped
- // Mode: Normal top=0xFF
- // OC1A output: Disconnected
- // OC1B output: Disconnected
- // Timer1 Overflow Interrupt: Off
- // Compare A Match Interrupt: Off
- // Compare B Match Interrupt: Off
- PLLCSR=0x00;
- TCCR1=0x00;
- GTCCR=0x00;
- TCNT1=0x00;
- OCR1A=0x00;
- OCR1B=0x00;
- OCR1C=0x00;
- // External Interrupt(s) initialization
- // INT0: On
- // INT0 Mode: Low level
- // Interrupt on any change on pins PCINT0-5: Off
- GIMSK=0x00; //禁用INT0中断,等合适的时候再打开
- MCUCR=0x00;
- GIFR=0x40;
- // Timer(s)/Counter(s) Interrupt(s) initialization
- TIMSK=0x10;
- // Universal Serial Interface initialization
- // Mode: Disabled
- // Clock source: Register & Counter=no clk.
- // USI Counter Overflow Interrupt: Off
- USICR=0x00;
- // Analog Comparator initialization
- // Analog Comparator: Off
- ACSR=0x80;
- ADCSRB=0x00;
- DIDR0=0x00;
- // ADC initialization
- // ADC disabled
- ADCSRA=0x00;
- // Watchdog Timer initialization
- // Watchdog Timer Prescaler: OSC/2k
- // Watchdog Timer interrupt: Off
- #pragma optsize-
- #asm("wdr")
- WDTCR=0x18;
- WDTCR=0x08;
- #ifdef _OPTIMIZE_SIZE_
- #pragma optsize+
- #endif
- // Global enable interrupts
- #asm("sei") // 开放全局中断
- while (1)
- {
- switch (status)
- {
- case 0:
- if (key_stime_ok) // 10ms到,键处理
- {
- key_stime_ok = 0;
- switch(read_key_n())
- {
- case 0:
- status = 0;
- break;
- case 1:
- status = 1;
- break;
-
- case 2:
- PORTB &= ~(1<<3);
- PORTB |= (1<<4); //关门
- DDRB = 0x39;
- break;
- }
-
- }
- break;
- case 1:
- if (read_key_driver() ==1 )
- {
- qingling(); //清零
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- //PORTB ^= 1<<3;
- status = 3;
- shucuo=0;
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;/*mima[1] = 0; mima[0] = 0;*/ //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- PORTB &=~(1<<5);
- PORTB &=~(1<<4);
- PORTB |=(1<<3); //开门
- DDRB = 0x39;
- }
- else {status = 2;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
- case 2:
- while(shucuo==3) //输错3次就锁死300秒
- {
- #asm("WDR") //喂狗
- if(shucuo_ok)
- {
- qingling(); //清零
- status = 0;
- shucuo =0 ; //执行输错后也要清零,不然以后再错就没法执行了
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- }
- }
- status = 0; //输错3次前继续放回等待输入命令,注意如果之后没有按键转入掉电模式后是否记忆之前输错的次数,以防产生BUG,不然输错两次,
- break; //等转入掉电模式后,又可以唤醒继续输入,这样就惨了!
- case 3:
- if (read_key_n() == 3) //长按3.5秒进入密码设置部分
- {
- status = 12;
- }
- else if (ermiao_ok) {status = 0;}
- break;
- case 12: //老密码输入对,开始第一次输入新密码
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++)
- {
- ysmima[j]=mima[j];
- }
- status = 13;
- }
- break;
- case 13: //开始第二次输入新密码,并和第一次的对比
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- //PORTB ^= 1<<3;
- status = 14;
- shucuo=0;
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- //mima[1] = 0; mima[0] = 0;
- } //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- else {status = 16;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
- case 14: //开始第三次输入新密码,并和第一次的对比
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- PORTB ^= 1<<5; //观察
- status = 15;
- shucuo=0;
- shangdengcishu = 3;
- shangdengtime = 50000;
- guangdengtime = 10000;
- kaidengduibi=1;
- //mima[1] = 0; mima[0] = 0;
- } //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- else {status = 16;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
-
- case 15: //第三次输对新密码后,开始记录
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- for(j=0;j<5;j++) //写入新设置密码
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EECR = (0<<EEPM1)|(0<<EEPM0);
- EEARL = j+10;
- EEDR = mima[j];
- EECR |=(1 <<EEPM1);
- EECR |=(1 <<EEPM0);
- ysmima[j] = mima[j]; //密码立即生效
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
-
- }
- status = 0;
- break;
- case 16:
- if(shucuo==3) //设置密码输错3次,重设密码失败就执行某行动
- {
- for(j=0;j<5;j++) //读出原密码继续使用
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EEARL = j+10;
- EECR |=(1<<EERE);
- ysmima[j]=EEDR;
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
- }
- shucuo =0 ; //执行输错后也要清零,不然以后再错就没法执行了
- PORTB ^= 1<<5; //某行动
- status = 0;
- }
- else status = 12;
- break;
- }
- if (ershimiao_ok) //20秒无动作后休眠
- {
- shucuo=0; //2次输错密码,若没有再输入密码,进入休眠就清除记录
- qingling(); //清零
- //PORTB = 11100110; //11100110进入休眠前关所有灯
- //DDRB = 00100001; //00100001,PB.0和5配置为输出,其它位为输入
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- TIMSK = 0x00; //关闭T/C0比较匹配中断
- /*关闭看门狗省电*/
- //#asm("cli") //关闭全局中断
- #asm("WDR") //喂狗
- //MCUSR = 0x00;
- //WDTCR |= (1<<WDCE) | (1<<WDE);
- //WDTCR = 0x00;
- MCUSR &= ~(1<<WDRF);
- WDTCR |= (1<<WDCE) | (1<<WDE);
- WDTCR &= ~(1<<WDE);
- #asm("sei") // 开放全局中断
- /*使能INT0中断*/
- GIMSK=0x40;
- MCUCR=0x00;
- GIFR=0x40;
- MCUCR |= (1<<SM1) | (0<<SM0); // 掉电模式
- MCUCR |= (1<<SE); //睡眠使能
- #asm("sleep") //休眠
- PORTB ^= 1<<5; //唤醒后监测
- }
- #asm("WDR") //喂狗
- shangdeng(); //扫描闪灯
- }
- }
- #include <tiny85.h>
- #include<delay.h>
- // Declare your global variables here
- unsigned char mima[5],ysmima[5],mimajishu,shucuo,j,cnt; //密码计数,录入密码数组,原始密码数组,长按标志 // 2位密码计数单元
- unsigned char ershimiao_counter,ermiao_counter,shucuo_counter,yimiao_counter,key_stime_counter,status,shangdengcishu; // 时间计数单元,闪灯次数
- unsigned char ershimiao_ok,shucuo_ok,ermiao_ok,yimiao_ok,key_stime_ok,kaidengduibi; //第一次开关未完成时,第二次开灯指令的识别
- unsigned int shangdengtime,guangdengtime; //闪灯开的时间,闪灯关的时间
- unsigned char huifu[5]={1,2,3,4,5}; //初始密码
- // External Interrupt 0 service routine
- interrupt [EXT_INT0] void ext_int0_isr(void)
- {
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- TIMSK=0x10; // 允许T/C0比较匹配中断
- PORTB ^= 1<<5; //中断唤醒监测
- GIMSK=0x00; //禁用INT0中断,等合适的时候再打开
- //GICR = 0x00; //禁用INT0中断
- WDTCR=0x18; //开看门狗约为16ms
- WDTCR=0x08;
-
- MCUCR &=~(1<<SE); // 禁止睡眠使能,在需要休眠时再打开0
- }
- // Timer 0 output compare A interrupt service routine , Timer 0 比较匹配中断服务,2ms定时
- interrupt [TIM0_COMPA] void timer0_compa_isr(void)
- {
- if (++key_stime_counter >=5)
- {
- key_stime_counter = 0;
- key_stime_ok = 1; // 10ms到
- if (++yimiao_counter >= 100)
- {
- yimiao_counter = 0;
- yimiao_ok = 1; // 1s到
- if (++ermiao_counter >= 2)
- {
- ermiao_counter = 0;
- ermiao_ok = 1; // 2s到
- if (++ershimiao_counter >= 15)
- {
- ershimiao_counter = 0;
- ershimiao_ok = 1; // 30s到
- if (++shucuo_counter >= 10)
- {
- shucuo_counter = 0;
- shucuo_ok = 1; // 300s到
- }
- }
- }
- }
- }
- }
- #define key_input PINB.1 // 按键输入口兼INTO中断唤醒
- #define key_state_0 0
- #define key_state_1 1
- #define key_state_2 2
- #define key_state_3 3
- #define key_state_4 4
- void qingling(void) //清零
- {
- yimiao_counter = 0; //因为是最后一次按键清零后过了1秒,才开始第一位密码识别的,不清零的话后面第一个10ms过后就会把第二位密码记上了,
- yimiao_ok = 0; //这会让你没有机会输入第二次密码
- ermiao_counter = 0;
- ermiao_ok = 0;
- ershimiao_counter = 0;
- ershimiao_ok = 0;
- shucuo_counter = 0;
- shucuo_ok = 0; // 300s到
- }
-
- void shangdeng(void) //闪灯
- {
- static unsigned char status=1,kaidengbiaozhi;
- static unsigned int i,j,h;
- if(shangdengcishu >0) //闪灯次数 类似倒计时程序
- {
- if(kaidengduibi==1) //开灯比对,有新的开灯指令时为1
- {
- status=0;
- }
- switch (status)
- {
- case 0:
- kaidengduibi=0; //开灯对比,对比结束
- if(kaidengbiaozhi == 1) //上一次开灯程序未完成标志
- {
- if (++h >= 3000-j) //按键关灯时间,实现第一次正在开灯,或者正在关灯时,若第二次开灯指令就来了,就先执行关灯
- {
- j=0;
- h=0;
- status=1;
- i=0;
-
- }
- }
- else status=1;
- break;
- case 1:
-
- PORTB |=( 1<<0); //PD7输出高
- PORTB &=~( 1<<1); //INT0拉低
- DDRB = 0x3B;
- qingling(); //清零
- kaidengbiaozhi=1; //开灯标志,表示开灯任务开始
- if (++i >= shangdengtime) //按键开灯时间
- {
- status=2;
- i=0;
- }
- break;
- case 2:
- if (++j >= guangdengtime) //按键关灯时间
- {
- j=0;
- status=0;
- --shangdengcishu ;
- kaidengbiaozhi=0; //开灯标志,标示开灯任务结束,准备好第二次开关了
- }
- if(j>=3000) //灭灯时间达到设定值时,把开关标志清零,也就是可以再次接受新的开灯指令了,这样再开灯时就能及时看到亮灯
- {
- kaidengbiaozhi=0; //开灯标志,标示开灯任务结束,准备好第二次开关了
- }
- break;
- }
- }
- }
-
- unsigned char read_key_n(void)
- {
- static unsigned char key_state = 0, key_time = 0;
- unsigned char key_press, key_return = 0;
-
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- //PORTB=0x3A;
- //DDRB=0x39;
- key_press = key_input; // 读按键I/O电平
- switch (key_state)
- {
- case key_state_0: // 按键初始态
- if (!key_press) key_state = key_state_1; // 键被按下,状态转换到键确认态
- break;
- case key_state_1: // 按键确认态
- if (!key_press)
- {
- key_state = key_state_2; // 按键仍按下,状态转换到计时1
- key_time = 0; // 清另按键时间计数器
- }
- else
- key_state = key_state_0; // 按键已抬起,转换到按键初始态
- break;
- case key_state_2:
- if (key_press)
- {
- key_state = key_state_0; // 按键已释放,转换到按键初始态
- key_return = 1; // 输出"1" ,表示单击
- key_time = 0;
- shangdengcishu = 1; //开短闪灯 ,告知按下按键成功短按一次
- shangdengtime = 3000; //设置闪灯时间
- guangdengtime = 0; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- if (++mimajishu >9)
- {
- mimajishu = 0;
- }
- }
- else if (++key_time >= 100) // 长按1秒按键时间计数
- {
- key_state = key_state_3; // 按下时间>1s,状态转换到计时2
- key_time = 0; // 清按键计数器
- key_return = 2; // 长按超过1秒后输出"2" ,
- shangdengcishu = 1; //开短闪灯 ,告知按下按键已经有1秒 ,此后3秒内松开手就关门
- shangdengtime = 60000; //设置闪灯时间
- guangdengtime = 0; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- qingling(); //清零
- break;
- case key_state_3:
- if (key_press)
- {
- key_state = key_state_0; //按键已释放,转换到按键初始态
- key_time = 0; // 清按键计数器
- }
- else if (++key_time >= 250) // 长按达到3.5秒按键时间计数
- {
- key_state = key_state_4; // 按下时间>3.5s,状态转换到计时2
- key_time = 0; // 清按键计数器
- key_return = 3; //长按2秒,进入设置界面
- shangdengcishu = 3; //开长闪灯
- shangdengtime = 65000; //设置长闪灯时间
- guangdengtime = 10000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- qingling(); //清零
- break;
- case key_state_4:
- if (key_press)
- {
- key_state = key_state_0; //按键已释放,转换到按键初始态
- }
- qingling(); //清零
- break;
-
- }
- return key_return;
- }
- unsigned char read_key_driver(void) //按键密码输入记录部分
- {
- static unsigned char i = 0,aj_state = 0;
- unsigned char key_return = 0;
- #asm("WDR") //喂狗
- if (key_stime_ok) // 10ms到,键处理
- {
- key_stime_ok = 0;
- read_key_n();
- switch (aj_state)
- {
- case 0:
- if (ermiao_ok)
- {
- if(i < 5) //密码位数设置
- {
- mima[i] = mimajishu; //记录第一位密码
- mimajishu =0;
- PORTB ^= 1<<5; //观察第一位密码识别
- aj_state = 1;
- qingling(); //清零
- i=++i;
- shangdengcishu = i; //开短闪灯标示刚才输入一位密码成功
- shangdengtime = 3000; //设置闪灯时间
- guangdengtime = 17000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- }
- }
- break;
- case 1:
- if (i == 5) //密码识别位数确认 ,闪2次标示密码输完
- {
- i=0;
- aj_state = 0;
- key_return = 1;
- }
- else
- aj_state = 0;
- break;
- }
- return key_return;
- }
- }
- void main(void)
- {
- // Declare your local variables here
- // Crystal Oscillator division factor: 1
- #pragma optsize-
- CLKPR=0x80;
- CLKPR=0x00;
- #ifdef _OPTIMIZE_SIZE_
- #pragma optsize+
- #endif
- // Input/Output Ports initialization
- // Port B initialization
- // Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
- // State5=T State4=T State3=T State2=T State1=T State0=0
- //PORTB = 0xE6; //11100110
- //DDRB = 0x39; //00100001,PB.0和5配置为输出,其它位为输入
- PORTB=0x3A;
- DDRB=0x39;
- delay_ms(100);
- /*上电恢复初始密码*/
- PORTB |=( 1<<0); //PD7输出高
- DDRB &=~( 1<<0); //PD7设置成输入
- if(PINB.0 == 0) //若PD7拉低就把密码恢复出厂设置
- {
- shangdengcishu = 5; //开短闪灯标示刚才输入一位密码成功
- shangdengtime = 15000; //设置闪灯时间
- guangdengtime = 10000; //设置关灯时间
- kaidengduibi=1; //判断上一次闪灯是否结束,实现新开灯时能马上看到效果
- for(j=0;j<5;j++) //写入新设置密码
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EECR = (0<<EEPM1)|(0<<EEPM0);
- EEARL = j+10;
- EEDR = huifu[j]; //恢复默认密码
- EECR |=(1 <<EEMPE);
- EECR |=(1 <<EEPE);
- ysmima[j] = huifu[j]; //密码立即生效
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
- }
- //delay_ms(5000);
-
- }
- //while(PIND.7 == 0) {;}
- //PORTB = 0xE6; //11100110
- //DDRB = 0x39; //00100001,PB.0和5配置为输出,其它位为输入 // PD7为输出方式,默认输出低电平
- PORTB=0x3A;
- DDRB=0x39;
-
- #asm("cli")
- #asm("sei")
-
- for(j=0;j<5;j++) //读出原密码
- {
- while(EECR &(1 <<EEPE));
- EEARL = j+10;
- EECR |=(1<<EERE);
- ysmima[j]=EEDR;
- delay_ms(10);
- }
-
- #asm("cli")
- // Timer/Counter 0 initialization
- // Clock source: System Clock
- // Clock value: 125.000 kHz
- // Mode: CTC top=OCR0A
- // OC0A output: Disconnected
- // OC0B output: Disconnected
- TCCR0A=0x02;
- TCCR0B=0x03;
- TCNT0=0x00;
- OCR0A=0xF9;
- OCR0B=0x00;
- // Timer/Counter 1 initialization
- // Clock source: System Clock
- // Clock value: Timer1 Stopped
- // Mode: Normal top=0xFF
- // OC1A output: Disconnected
- // OC1B output: Disconnected
- // Timer1 Overflow Interrupt: Off
- // Compare A Match Interrupt: Off
- // Compare B Match Interrupt: Off
- PLLCSR=0x00;
- TCCR1=0x00;
- GTCCR=0x00;
- TCNT1=0x00;
- OCR1A=0x00;
- OCR1B=0x00;
- OCR1C=0x00;
- // External Interrupt(s) initialization
- // INT0: On
- // INT0 Mode: Low level
- // Interrupt on any change on pins PCINT0-5: Off
- GIMSK=0x00; //禁用INT0中断,等合适的时候再打开
- MCUCR=0x00;
- GIFR=0x40;
- // Timer(s)/Counter(s) Interrupt(s) initialization
- TIMSK=0x10;
- // Universal Serial Interface initialization
- // Mode: Disabled
- // Clock source: Register & Counter=no clk.
- // USI Counter Overflow Interrupt: Off
- USICR=0x00;
- // Analog Comparator initialization
- // Analog Comparator: Off
- ACSR=0x80;
- ADCSRB=0x00;
- DIDR0=0x00;
- // ADC initialization
- // ADC disabled
- ADCSRA=0x00;
- // Watchdog Timer initialization
- // Watchdog Timer Prescaler: OSC/2k
- // Watchdog Timer interrupt: Off
- #pragma optsize-
- #asm("wdr")
- WDTCR=0x18;
- WDTCR=0x08;
- #ifdef _OPTIMIZE_SIZE_
- #pragma optsize+
- #endif
- // Global enable interrupts
- #asm("sei") // 开放全局中断
- while (1)
- {
- switch (status)
- {
- case 0:
- if (key_stime_ok) // 10ms到,键处理
- {
- key_stime_ok = 0;
- switch(read_key_n())
- {
- case 0:
- status = 0;
- break;
- case 1:
- status = 1;
- break;
-
- case 2:
- PORTB &= ~(1<<3);
- PORTB |= (1<<4); //关门
- DDRB = 0x39;
- break;
- }
-
- }
- break;
- case 1:
- if (read_key_driver() ==1 )
- {
- qingling(); //清零
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- //PORTB ^= 1<<3;
- status = 3;
- shucuo=0;
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;/*mima[1] = 0; mima[0] = 0;*/ //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- PORTB &=~(1<<5);
- PORTB &=~(1<<4);
- PORTB |=(1<<3); //开门
- DDRB = 0x39;
- }
- else {status = 2;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
- case 2:
- while(shucuo==3) //输错3次就锁死300秒
- {
- #asm("WDR") //喂狗
- if(shucuo_ok)
- {
- qingling(); //清零
- status = 0;
- shucuo =0 ; //执行输错后也要清零,不然以后再错就没法执行了
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- }
- }
- status = 0; //输错3次前继续放回等待输入命令,注意如果之后没有按键转入掉电模式后是否记忆之前输错的次数,以防产生BUG,不然输错两次,
- break; //等转入掉电模式后,又可以唤醒继续输入,这样就惨了!
- case 3:
- if (read_key_n() == 3) //长按3.5秒进入密码设置部分
- {
- status = 12;
- }
- else if (ermiao_ok) {status = 0;}
- break;
- case 12: //老密码输入对,开始第一次输入新密码
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++)
- {
- ysmima[j]=mima[j];
- }
- status = 13;
- }
- break;
- case 13: //开始第二次输入新密码,并和第一次的对比
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- //PORTB ^= 1<<3;
- status = 14;
- shucuo=0;
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- //mima[1] = 0; mima[0] = 0;
- } //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- else {status = 16;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
- case 14: //开始第三次输入新密码,并和第一次的对比
- if (read_key_driver() ==1 )
- {
- for(j=0;j<5;j++) //密码对比识别
- {
- if (mima[j]==ysmima[j])
- {
- cnt++;
- }
- }
- if (cnt==5)
- {
- cnt=0;
- PORTB ^= 1<<5; //观察
- status = 15;
- shucuo=0;
- shangdengcishu = 3;
- shangdengtime = 50000;
- guangdengtime = 10000;
- kaidengduibi=1;
- //mima[1] = 0; mima[0] = 0;
- } //密码输对后PORTB = 0xFD; //执行开门,PB1拉低
- else {status = 16;++shucuo;cnt=0;/*mima[1] = 0; mima[0] = 0;*/} //即使密码不对,也得清零,不然会影响下一次正确密码的判断
- }
- break;
-
- case 15: //第三次输对新密码后,开始记录
- shangdengcishu = 1;
- shangdengtime = 50000;
- guangdengtime = 0;
- kaidengduibi=1;
- for(j=0;j<5;j++) //写入新设置密码
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EECR = (0<<EEPM1)|(0<<EEPM0);
- EEARL = j+10;
- EEDR = mima[j];
- EECR |=(1 <<EEPM1);
- EECR |=(1 <<EEPM0);
- ysmima[j] = mima[j]; //密码立即生效
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
-
- }
- status = 0;
- break;
- case 16:
- if(shucuo==3) //设置密码输错3次,重设密码失败就执行某行动
- {
- for(j=0;j<5;j++) //读出原密码继续使用
- {
- #asm("cli")
- while(EECR &(1 <<EEPE));
- EEARL = j+10;
- EECR |=(1<<EERE);
- ysmima[j]=EEDR;
- #asm("WDR") //喂狗,写得慢,要及时喂狗
- delay_ms(10);
- #asm("sei")
- }
- shucuo =0 ; //执行输错后也要清零,不然以后再错就没法执行了
- PORTB ^= 1<<5; //某行动
- status = 0;
- }
- else status = 12;
- break;
- }
- if (ershimiao_ok) //20秒无动作后休眠
- {
- shucuo=0; //2次输错密码,若没有再输入密码,进入休眠就清除记录
- qingling(); //清零
- //PORTB = 11100110; //11100110进入休眠前关所有灯
- //DDRB = 00100001; //00100001,PB.0和5配置为输出,其它位为输入
- PORTB |=( 1<<1); //置位
- PORTB &=~( 1<<0); //清零
- DDRB = 0x39;
- TIMSK = 0x00; //关闭T/C0比较匹配中断
- /*关闭看门狗省电*/
- //#asm("cli") //关闭全局中断
- #asm("WDR") //喂狗
- //MCUSR = 0x00;
- //WDTCR |= (1<<WDCE) | (1<<WDE);
- //WDTCR = 0x00;
- MCUSR &= ~(1<<WDRF);
- WDTCR |= (1<<WDCE) | (1<<WDE);
- WDTCR &= ~(1<<WDE);
- #asm("sei") // 开放全局中断
- /*使能INT0中断*/
- GIMSK=0x40;
- MCUCR=0x00;
- GIFR=0x40;
- MCUCR |= (1<<SM1) | (0<<SM0); // 掉电模式
- MCUCR |= (1<<SE); //睡眠使能
- #asm("sleep") //休眠
- PORTB ^= 1<<5; //唤醒后监测
- }
- #asm("WDR") //喂狗
- shangdeng(); //扫描闪灯
- }
- }
复制代码 |
|