完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
回复本帖可获得 1 分积分奖励! 每人限 2 次 |
单片机新手,想实现一个按键的双击功能,从网上参考了一个大神的程序,用ICCAVR编写,使用AVR STUDIO调试时发现主函数运行时无法调用前面写的子函数,这是为什么呢?求教!!!
//ICC-AVR application builder : 2017/5/22 20:28:35 // Target : M8 // Crystal: 11.059Mhz #include #include #define key_input PIND3 // 按键输入口 #define LED1() (PORTC=0B00000001) #define LED2() (PORTC=0B00000010) #define LED3() (PORTC=0B00000100) #define N_key 0 //无键 #define S_key 1 //单键 #define D_key 2 //双键 #define L_key 3 //长键 #define key_state_0 0 #define key_state_1 1 #define key_state_2 2 #define key_state_3 3 int time_10ms_ok ; void port_init(void) { PORTB = 0x00; DDRB = 0x00; PORTC = 0x0F; //m103 output only DDRC = 0x0F; PORTD = 0x18; DDRD = 0x00; } //TIMER0 initialize - prescale:1024 // desired value: 10mSec // actual value: 9.908mSec (0.9%) void timer0_init(void) { TCCR0 = 0x00; //stop TCNT0 = 0xD9; //set count TCCR0 = 0x05; //start timer } #pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF void timer0_ovf_isr(void) { TCNT0 = 0xD9; //reload counter value time_10ms_ok = 1; } unsigned char key_driver(void) { static unsigned char key_state = key_state_0, key_time = 0; unsigned char key_press, key_return = N_key; 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_time = 0; // key_state = key_state_2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件 } else key_state = key_state_0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。 break; case key_state_2: if(key_press) { key_return = S_key; // 此时按键释放,说明是产生一次短操作,回送S_key key_state = key_state_0; // 转换到按键初始态 } else if (++key_time >= 100) // 继续按下,计时加10ms(10ms为本函数循环执行间隔) { key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件 key_state = key_state_3; // 转换到等待按键释放状态 } break; case key_state_3: // 等待按键释放状态,此状态只返回无按键事件 if (key_press) key_state = key_state_0; //按键已释放,转换到按键初始态 break; } return key_return; } unsigned char key_read(void) { static unsigned char key_m = key_state_0, key_time_1 = 0; unsigned char key_return = N_key,key_temp; key_temp = key_driver(); switch(key_m) { case key_state_0: if (key_temp == S_key ) { key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击 key_m = key_state_1; } else key_return = key_temp; // 对于无键、长键,返回原事件 break; case key_state_1: if (key_temp == S_key) // 又一次单击(间隔肯定<500ms) { key_return = D_key; // 返回双击键事件,回初始状态 key_m = key_state_0; } else { // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键 if(++key_time_1 >= 50) { key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件 key_m = key_state_0; // 返回初始状态 } } break; } return key_return; } // //call this routine to initialize all peripherals void init_devices(void) { //stop errant interrupts until set up CLI(); //disable all interrupts port_init(); timer0_init(); MCUCR = 0x00; GICR = 0x00; TIMSK = 0x01; //timer interrupt sources SEI(); //re-enable interrupts //all peripherals are now initialized } unsigned char key; void main(void) { init_devices(); while (1) { if (time_10ms_ok) //每10ms执行一次, { time_10ms_ok =0; key = key_read(); //《====== 10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常 if (key == L_key) LED1(); //点亮A_LED,关闭B_LED和C_LED else if(key == D_key) LED2(); //点亮B_LED,关闭A_LED和C_LED else if(key == S_key) LED3(); //点亮C_LED,关闭A_LED和B_LED } } //insert your functional code here... } |
|
相关推荐 |
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1569 浏览 0 评论
【每周推荐】采用11代Intel CPU,基于youyeetoo X1开发板搭建少儿AI智能STEAM积木平台
972 浏览 0 评论
3000 浏览 2 评论
【youyeetoo X1 windows 开发板体验】+ 影音处理和AI模型移植
2631 浏览 5 评论
I.MX6ULL-飞凌 ElfBoard ELF1板卡- 移植zbar的方法
1775 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
6365 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-5-8 00:35 , Processed in 0.536489 second(s), Total 74, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号