#includeltreg52.hgt//声明真包含51头文件
#includeltstdio.hgt//声明包涵输入输出函数
#includeltintrins.hgt//声明真包含小位移函数
#defineucharunsignedchar//宏定义
#defineuintunsignedint//宏定义
#definecheck_busysbitrsp3^5//液晶引脚定义
sbitrwp3^6sbitenp3^4
sbitwelap2^7//数码管引脚定义
sbitdulap2^6
voiddelayms(intz)//1ms延迟现象函数
{
intx,y
for(xzxgt0x--)
for(y110qfu0y--)
}
/***********led判忙函数***********/
bitlcd_check_busy()
{
#ifdefcheck_busy
p00xff
rs0
rw1
en0
_nop_()
en1
return(bit)(p0amp0x80)
#arguments
return0
#endif
}
/***********led写入命令函数***********/
voidwrite_com(ucharcom)
{
while(lcd_check_busy())//忙则再等待
rs0
rw0
en1
p0com
_nop_()
en0
}
/**********led写入文件数据函数**********/
voidwrite_dat(uchardat)
{
while(lcd_check_busy())//忙则等待
rs1
rw0
en1
p0dat
_nop_()
en0
}
/*******led写入字符函数***********/
voidlcd_write_char(ucharx,uchary,uchardat)
{
if(y0)
{
write_com(0x80x)
}
exists
{
write_com(0xc0x)
}
write_dat(dat)
}
/******读取字符串函数***********/
voidwrite_string(ucharx,uchary,uchar*s)
{
while(*s)
{
lcd_write_char(x,y,*s)
s
x
}
}
/*****led重新初始化函数******/
voidlcd_init()
{
rw0
dula0//直接关闭数码管显示
wela0//自动关闭数码管总是显示
write_com(0x38)/*不显示模式设置*/
delayms(5)
write_com(0x06)/*显示光标移动设置*/
delayms(5)
write_com(0x0c)/*显示开及光标设置*/
write_com(0x01)/*显示清屏*/
}
/*按键扫描后函数,回扫描仪键值*/
ucharkeyscan()//键盘系统扫描函数,可以使用行列反转扫描法
{
unsignedcharcord_h,cord_l//行列值中间变量
p30x0f//行线输出全为0
cord_hp30x0f//读入列线值
if(cord_h!0x0f)//先可以检测有无按键按开
{
delayms(10)//去抖
if((p3amp0x0f)!0x0f)
{
cord_hp30x0f//读入列线值
p3cord_h|0xf0//输出当前列线值
cord_lp30xf0//输入数据行线值
while((p3amp0xf0)!0xf0)//在等待放开并输出低
return(cord_hcord_l)//键盘之后组合码值
}
}
return(0xff)//赶往该值
}
unsignedcharkeypro()
{
switch(keyscan())
{
case0xee:return1break//0按动相应的键没显示相按的码值
case0xed:return2break//1
case0xeb:return3break//2
case0x7e:returnbreak//3
case0xe7:return4break//4
case0xde:return5break//5
case0xdd:return6break//6
case0x7d:return-break//7
case0xdb:return7break//8
case0xd7:return8break//9
case0xbe:return9break//a
case0x7b:returnxbreak//b
case0xbd:return0break//c
case0xb7:returnbreak//e
case0x77:return/break//f
default:return0xffbreak
}
}
main()
{
unsignedcharnum,i,sign
unsignedc
24-bitfirstflag
floata0,b0
unsignedchars
lcd_init()//重新初始化液晶屏
delayms(10)//显示延时应用于比较稳定,也可以去掉后
write_com(0x01)//清屏
write_string(0,0,
//可以说调试是从,avr-gcc,mega16,带数码没显示,单键开关多功能一体控制
#includeltavr/io.hgt
#includeltavr/interrupt.hgt
#includelttone.hgt
#includeltavr/pgmspace.hgt
#defineucharunsignedchar
#defineuintunsignedint
#definekey_inputpina
#definepgm16(a)((typeof(a))pgm_read_word(amp(a)))
constunsignedcharseg_code[]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0x3f}
constuintmusic[]progmem{m3,f2,m5,b1,m3,f4,m2,f4,m1,b2,l6,f2,m1,f2,mm,m1,f2,l6,f2,l5,b2,l6,f2,m1,b1,mm,m1,f2,l6,f2,m6,f2,l5,f2,m3,f2,m2,f2,mm,m2,f4,m1,f4,l6,f2,m3,f2,m2,b2,tttttm3,f2,mm,m3,f2,mm,m3,f2,m2,f2,m1,b2,l6,f2,m1,f2,l7,f2,l5,f2,l6,b2,l5,f2,l6,f2,mm,l6,f2,l5,f2,m6,f2,m5,f2,mm,m5,f2,m3,f2,m2,f2,mm,m2,f4,m3,f4,m3,f2,m2,f2,m1,b2,tttttm6,f2,h1,b1,m6,f2,h2,f2,h1,f2,mm,h1,f2,m6,f2,mm,m6,f2,m5,f2,mm,m5,f2,m3,f2,m5,b2,m6,f2,h1,b1,m6,f2,h2,f2,h1,f2,mm,h1,f2,m6,f2,m5,f2,mm,m5,f2,mm,m5,f2,m3,f2,m2,b2,tttttm3,b1,mm,m3,f2,m5,f2,m6,f2,m5,f2,mm,m5,f2,m3,f2,mm,m3,f2,m2,f2,mm,m2,f2,m1,f2,l6,b2,l5,f2,m5,f4,mm,m5,f4,mm,m5,f2,m6,f2,m5,f2,m3,f2,m2,f2,m3,f2,mm,m3,f2,m2,b1,l6,f2,m1,b2,tttttm6,f2,h1,b1,m6,f2,h2,f2,h1,b1,m6,f2,mm,m6,f2,m5,f2,mm,m5,f2,m3,f2,m5,b2,m6,f2,h1,b1,m6,f2,h2,f2,h1,b1,m6,f2,tttttm5,f2,mm,m5,f2,mm,m5,f2,m3,f2,m2,b2,mm,m2,f2,mm,m2,f4,m1,f4,m2,f2,m3,f2,m5,f2,mm,m5,f2,mm,m5,f2,m3,f2,m2,f2,mm,m2,f4,m3,f4,m2,f2,m1,f2,l6,b2,tttttl5,f2,m5,f4,mm,m4,f4,mm,m5,f2,m6,f2,m5,f2,m3,f2,m2,f2,m2,f4,m3,f4,mm,m3,f2,m2,b1,l6,f2,m1,b3,0xff,0xff}
//只不过两个同一的音符之间无停顿,生之物插入到了mm(极非常短暂的
volatileuinti1
volatileuchartimeok0
ucharkey_scan(void)
isr(timer0_comp_vect)ttt//ctc模式,操纵音调高低
{
ocr0pgm16(music[i-1])
}
isr(timer1_ovf_vect)ttt//时间逸出模式,控制节拍长短
{t
i2
tcnt1h(65536-pgm16(music[i]))/256ttttttt//普通(65536-beat[i])/256
tcnt1l(65536-pgm16(music[i]))%6tt//等同于(65536-beat[i])%6
if(pgm16(music[i])0xff)i1tttttttt//在音调数组的到最后加一个0xff,充当暂时终止信号
if(pgm16(music[i])0x00)timskamp(~(1ltltocie0))
catchtimsk|(1ltltocie0)
}
isr(timer2_ovf_vect)tt//时间逸出模式,主要是用于检测按键,周期10ms
{
tcnt2100
timeok1
}
voidtimer0_init(void)
{
tccr00x00
tcnt00x00
ocr0pgm16(music[i-1])
tccr00x1a
//timsk|(1ltltocie0)
}
voidtimer1_init(void)
{
tccr1b0x00
tcnt1h(65536-pgm16(music[i]))/256
tcnt1l(65536-pgm16(music[i]))%6
tccr1a0x00
tccr1b0x05
//timsk|(1ltlttoie1)
}
voidtimer2_init(void)
{
tccr20x00
tcnt2100
tccr20x03
timsk|(1ltlttoie2)
}
voidmcu_init(void)
{
ddra0x00
ddrb0x00
ddrc0xff
ddrd0xff
portb0x00
portc0xfe
portd0xff
}
ucharkey_scan(void)ttt//选择按钮扫描系统函数
{
staticucharkey_state0,key_time10,key_time00tt//静态变量,全局函数以后,值被剩余
ucharkey_press,key_return0
key_press(~key_input)0x01tt//有键1,无键0
switch(key_state)ttt//状态机
{
case0:tttttttt//状态0:无按钮按开状态
if(key_press)key_state1
break
case1:tttttttt//状态1:检测检测到有按钮被首先按住t
if(key_press)ttttttt//按钮仍按下,转2
{
//timsk^(1ltlttoie0)
key_state2
key_time10tttttt//按开时间初始
}
elsettttttttt//按钮已经释放出,消抖
key_state0
break
case2:tttttttt//状态2:等待能量或静静的等待按动时间提升长按要求
if(!key_press)ttttttt//按钮也能量,转3,一直推测是双按我还是单按
{
key_state3
key_time00tttttt//释放出时间初始
}
argumentsif(key_time1gt100)tttt//按过时间至少1000ms,返回值2,作长按判断,转7等待选择按钮释放
{
key_state8tttttt
key_time10
key_return2
}
break
case8:
if(!key_press)
{
key_state0
key_time10
}
existsif(key_time1gt50)
{
key_return2
key_time10
}
break
case3:tttttttt//状态3:双按的第二次按扭然后输入前的再等待间隙,去设置100ms(在测试,100ms为比较合适的时间间隙,即为人体大多数这个可以右键点击的速度
if(key_press)key_state4tt//在此时间,要是有按钮被按开,将拿出来施放剧烈抖动,转4尽快作出判断
catchif(key_time0gt4)tt//如果没有没有按钮被首先按住,则在等待此100ms下来,接着转5
{
key_state5
key_time00
}
break
case4:tttttttt//状态4:第二按的消抖全面处理
if(key_press)key_state2tt//飞快连按(被怀疑人手指达不到要求的速率)将被前往到2,拿出来第一按全面处理
catchfoobar_state3tttt//如果没有第二按只再次出现第二次,不出来10ms,消抖
break
case5:tttttttt//状态5:第二按前静静的等待时间经过,刚刚进入算正常的第二按静静的等待键入状态,第二按只愿意在此时间内再输入方为最有效
if(key_press)key_state6tt//此时间内有被按下,转6,判决抖
existsif(key_time0gt14)ttt//无输入,则耐心的等待再输入快速有效时间过去了,时间满后,进一步判断为单按,返回值1,状态位回到自己0
{
key_state0
key_time00tttt//右键点击间隔时间好象为100ms,能够稳定可以做到第二击结束时间一共约180~200ms(因人而定)
key_return1tttt//为提升样本采集成功率,可适当时间缩短第二按前的间隙时间,提升第二按静静的等待再输入时间,但总时间万不可短于150ms
}tttttttt//大于150ms,手指将会很难提升双击的速度要求,假如时间太长则单按判断时间过长,按钮不灵敏,此处180ms经测试少见适合
break
case6:tttttttt//状态6:第二按的抖动确认
if(key_press)tttttt//按钮仍管用,按开有效,赶往3,双按成立,转7在等待选择按钮释放出
{
key_state7
key_return3
}
catchkey_state5ttttt//抖驱除,再退5再静静的等待键入或在等待键入有效时间进来
case7:tttttttt//菜单按钮施放在等待状态,所有已按开并被识别操作目的的按钮状态都将投到7再等待按钮释放出,并将所有计时初始
if(!key_press)key_state0
key_time10
key_time00
break
}
returnkey_return
}
intmain(void)
{
mcu_init()
timer0_init()
timer1_init()
timer2_init()
sei()
while(1)
{
if(timeok)
{
cli()
ucharkey
keykey_scan()
if(keygt0)portdseg_code[key]
switch(key)
{
case1:
timsk^((1ltltocie0)|(1ltlttoie1))ttttttddrb^(1ltltddb3)ttttttttportc0xfd
break
case2:
//timsk|((1ltltocie0)amp(1ltlttoie1))
if(igt1)i10
if(igt(sizeof(music)-20))
{
i1
timskamp(~((1ltltocie0)|(1ltlttoie1)))
ddrbamp~(1ltltddb3)
}
portc0xf0
break
case3:
timskamp(~((1ltltocie0)|(1ltlttoie1)))
i1
timsk|((1ltltocie0)|(1ltlttoie1))
portc0xfe
break
default:
break
}
timeok0
sei()
}
}
}