搜索
bottom↓
楼主: machao

题目:多功能按键设计。利用一个I/O口,接一个按键,实现3功能操作:单击 + 双击 + 长按。

  [复制链接]

出0入0汤圆

发表于 2011-10-9 22:20:56 | 显示全部楼层
mark!!!以后看!!!!谢谢楼主分享!!!!

出0入0汤圆

发表于 2011-10-9 22:59:58 | 显示全部楼层
马克了再细看

出0入0汤圆

发表于 2011-10-9 23:01:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-10 00:17:33 | 显示全部楼层
手机马克

出0入0汤圆

发表于 2011-10-23 00:27:16 | 显示全部楼层
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4747117&bbs_page_no=1&search_mode=3&search_text=BG4RFF&bbs_id=9999
原来我是罪魁祸首

出0入0汤圆

发表于 2011-10-23 00:40:58 | 显示全部楼层
mark

出0入131汤圆

发表于 2011-10-29 09:51:35 | 显示全部楼层
好东西很好用

出0入0汤圆

发表于 2011-10-30 21:28:08 | 显示全部楼层
很受教育,看来做什么都不能浮躁啊

出0入10汤圆

发表于 2011-10-30 22:05:18 | 显示全部楼层
马老师又开讲了,顶

出0入0汤圆

发表于 2011-10-31 00:19:39 | 显示全部楼层
用过类似的思路写按键处理

出0入0汤圆

发表于 2011-10-31 07:23:28 | 显示全部楼层
思路写按键处理

出0入0汤圆

发表于 2011-10-31 08:18:13 | 显示全部楼层
小知识有学问,MARK

出0入0汤圆

发表于 2011-10-31 09:34:29 | 显示全部楼层
这个要几号一下,发现状态机很好用哈~

出0入0汤圆

发表于 2011-11-3 08:16:12 | 显示全部楼层
不知道有没有人用这个做多个按键,单击+长按+组合键写,我最近写了一个,感觉效果不是很好,按键多按几次有时会失效(只加入了单击+长按),实时效不好,还有一个问题,就是当返回按键的时候你的按键值取值的位置应该放在哪里比较好,当你返回长短按键时按键是释放的,我做的也是每10ms扫描一次,还有一个就是感觉代码比较繁琐!

出0入0汤圆

发表于 2011-11-3 08:52:01 | 显示全部楼层
谢谢马老师!学习了

出0入0汤圆

发表于 2011-11-3 09:15:51 | 显示全部楼层
谢谢。

出0入0汤圆

发表于 2011-11-4 11:05:53 | 显示全部楼层
这个帖子还在火?

出0入0汤圆

发表于 2011-11-4 12:53:50 | 显示全部楼层
Mark~

出0入0汤圆

发表于 2011-11-4 13:05:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-4 15:45:25 | 显示全部楼层
很好很强大

出0入0汤圆

发表于 2011-11-13 14:27:36 | 显示全部楼层
挺实用的,先mark

出0入0汤圆

发表于 2011-11-22 23:33:12 | 显示全部楼层
经典,谢谢马潮老师

出0入0汤圆

发表于 2011-11-23 08:54:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-29 14:02:10 | 显示全部楼层
mark。不仅内容很精彩,格式也是相当标准,学习。

出0入0汤圆

发表于 2011-11-29 15:05:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-4 11:20:51 | 显示全部楼层
新手,学习了

出0入0汤圆

发表于 2011-12-11 15:57:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-11 18:33:32 | 显示全部楼层
技术外的观点也很有见地

出0入0汤圆

发表于 2011-12-13 11:12:50 | 显示全部楼层
马老师的书最近在看,这个很不错!留下脚印

出0入0汤圆

发表于 2011-12-16 16:52:21 | 显示全部楼层
回复【楼主位】machao
-----------------------------------------------------------------------

最近正在学习按键使用和去抖动方面的知识,老师的资料很好,很有参考和学习价值谢谢老师。

出0入0汤圆

发表于 2011-12-20 18:23:49 | 显示全部楼层
很精彩!

出0入0汤圆

发表于 2011-12-24 13:34:57 | 显示全部楼层
回复【楼主位】machao
-----------------------------------------------------------------------

MArk
头像被屏蔽

出0入0汤圆

发表于 2011-12-25 10:50:59 | 显示全部楼层
太经典了,真是好东西,简介 稳定!

出0入0汤圆

发表于 2011-12-28 15:06:19 | 显示全部楼层
好好看看,谢谢马老师!

出0入0汤圆

发表于 2011-12-28 22:58:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-1 18:43:48 | 显示全部楼层
好好看看,谢谢马老师!

出0入0汤圆

发表于 2012-1-4 22:05:24 | 显示全部楼层
获取按键输入,有多种状态,马克

出0入0汤圆

发表于 2012-1-5 07:05:59 | 显示全部楼层
不错,标记一下

出0入0汤圆

发表于 2012-1-17 00:54:09 | 显示全部楼层
思考、实践,转换成自己的东西! 加油

出0入0汤圆

发表于 2012-1-17 11:01:47 | 显示全部楼层
多功能按键设计 MARK

出0入0汤圆

发表于 2012-1-24 21:47:55 | 显示全部楼层
马克

出0入0汤圆

发表于 2012-1-28 15:07:30 | 显示全部楼层
俺是初学者,很想知道马老师楼主位的程序是适合GCC还是ICC?

说来惭愧,俺改了一下,无论用ICC还是GCC运行,报错好多。

出0入0汤圆

发表于 2012-1-29 16:58:18 | 显示全部楼层
AVR编译软件还真多,就是不通用,CodeVisionAVR,勤翻书有好处,第九章。

出0入0汤圆

发表于 2012-1-29 17:27:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-17 11:29:21 | 显示全部楼层
不错,收益了!

出0入0汤圆

发表于 2012-2-17 12:07:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-17 13:27:35 | 显示全部楼层
mm

出0入0汤圆

发表于 2012-2-21 16:38:21 | 显示全部楼层
在这边看马潮的帖子 半年来真的学到好多东西

出0入0汤圆

发表于 2012-2-22 10:19:19 | 显示全部楼层
很好用!

出0入0汤圆

发表于 2012-2-22 12:54:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-26 12:47:58 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2012-3-26 13:28:34 | 显示全部楼层
mark。不错的帖子
头像被屏蔽

出0入0汤圆

发表于 2012-3-27 16:41:33 | 显示全部楼层
mark  mark mark mark

出0入0汤圆

发表于 2012-3-28 14:25:57 | 显示全部楼层

很好用!mark

出0入0汤圆

发表于 2012-3-28 14:31:34 | 显示全部楼层
mark,,,,,,,,

出0入0汤圆

发表于 2012-4-1 13:58:57 | 显示全部楼层
学习一下

出0入36汤圆

发表于 2012-4-6 08:23:34 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2012-4-6 09:35:22 | 显示全部楼层
http://www.ourdev.cn/forum.php?m ... =%E6%8C%89%E9%94%AE
这个似乎比马老师的更经典,更有技巧

出0入0汤圆

发表于 2012-4-6 15:30:12 | 显示全部楼层
受教了,同LS。

出0入0汤圆

发表于 2012-4-6 17:05:35 | 显示全部楼层
还好我一般都是需要短按与长按的事件,双击是一个需要取舍的事情。

出0入0汤圆

发表于 2012-4-13 14:05:32 | 显示全部楼层
看了帖子觉得很惭愧,原来自己最简单的东西都没做好

出0入0汤圆

发表于 2012-4-17 13:54:06 | 显示全部楼层
有时间看看!

出0入0汤圆

发表于 2012-4-17 14:59:22 | 显示全部楼层
嗯,谢谢老师

出0入0汤圆

发表于 2012-5-1 17:39:30 | 显示全部楼层
先Mark一下,稍后学习了

出0入0汤圆

发表于 2012-5-3 12:20:50 | 显示全部楼层
在某个空间看到了这篇文章,觉得写得很复杂,变量定义得太长不好理解,所以用STC89C52做了测试,可正常工作,和要求一样。
每10MS扫描一次用到了定时器2的16位自动重装方式。一共有4个状态。P2口接LED作为显示用
#include<reg52.h>
unsigned char delay=0;
sbit key=P3^5;
void init();
main()
{
unsigned char lp=0,time=0,num=0,flag=0,value=0;
init();
while(1){
if(delay){
delay=0;
switch(lp)
{
case 0:if(!key)lp++;else if(flag){if(++time>50){value=1;time=0,flag=0;}}break;
case 1:if(!key)lp++;else lp=0;break;
case 2:if(key){lp++;if(flag){value=2;flag=0;}else flag=1;}else if(++num>100){flag=0;value=4;lp++;}break;
case 3:if(key){lp=0;num=0;time=0;}break;
}
}
P2=~value;
}
}

void init()
{
EA=1;
RCAP2H=55536/256;  
RCAP2L=55536%256;  
TH2=RCAP2H;  
TL2=RCAP2L;
ET2=1;  //开启定时器2中断
TR2=1;  //启动定时器

}
void timer()interrupt 5
{
TF2=0;
delay=1;
}

如果要实现和手机英文输入一致,则把4个状态改成如下:
case 0:if(!key)lp++;else if(flag){if(++time>50){time=0,flag=0;}}break;
case 1:if(!key)lp++;else lp=0;break;
case 2:if(key){lp++;if(flag)value=(value)%4+1; else {value=1;flag=1;}}else if(++num>100){flag=0;value=4;lp++;}break;
case 3:if(key){lp=0;num=0;time=0;}break;

出0入0汤圆

发表于 2012-5-25 22:46:09 | 显示全部楼层
马老师  看了你的多功能按键设计。利用一个I/O口,接一个按键,实现3功能操作:单击 + 双击 + 长按。 我个人感觉程序写得有点庞大。而且在通用应用中双击用得不多。单击和长按道是用得很频繁。下面示出我常用的一段精点按键函数供大家探讨一下。关于此按键的算法的出处也是从一个网站博客中看到的,具体地址不太清楚了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-25 23:06:22 | 显示全部楼层
程序如下:
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Chip type           : ATmega8L
*****************************************************/
#include <mega8.h>

#define KEY_MODE 0x08    // 模式按键  PB3
#define KEY_ADD 0x10      // 加   PB4
#define KEY_SUB 0x20       // 减   PB5
unsigned char Trg=0;
unsigned char Cont=0;
//按键扫描处理程序
void KeyProcess(void)
{
//PORTC=0x07;在主程序初始化段设置PC口低三位上拉电阻有效 DDRC=0x00;设置PC口输入模式
unsigned char ReadData=~PINC;       //读PC口并将数据取反
Trg=ReadData&(ReadData^Cont);     //判断是否点动即单击
Cont=ReadData;                             //判断是否长按

  if(Trg&KEY_ADD)                           //加键单击时  Dis_Vale加1
  {
     if(Dis_Vale<=65535)
     Dis_Vale++;
    }

   if(Trg&KEY_SUB)                          //减键单击时  Dis_Vale减1
   {
     if(Dis_Vale>=1)
     Dis_Vale--;
     }                                            
   
}
以上只举例说明了单击的情况,其实长按键程序依据上面按键的工作原理分析也很容易得出。
此程序的优势在于实时性很好,程序没有延迟的地方。

出0入0汤圆

发表于 2012-5-25 23:09:53 | 显示全部楼层
下面是我用一个MEGA8+AD420做的一个信号发生器的程序,里面也有用到按键函数部份。
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
Project :
Version :
Date    : 2011-6-12
Author  :
Company :
Comments:
Chip type           : ATmega8L
Program type        : Application
Clock frequency     : 4.000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/
#include <mega8.h>
#include <delay.h>
#include <lcd.h>
#include <spi.h>
#asm
.equ __lcd_port=0x12 ; PORTD数据寄存器地址
#endasm

#define KEY_MODE 0x08    // 模式按键  PB3
#define KEY_ADD 0x10     // 加   PB4
#define KEY_SUB 0x20     // 减   PB5

unsigned char Trg=0;
unsigned char Cont=0;
char str[10]={'0','1','2','3','4','5','6','7','8','9'};  
int dis_buff[6]={0,0,0,0,0,0};
int dis_buff2[6]={0,0,0,0,0,0};
int dis_buff3[6]={0,0,0,0,0,0};
int dis_bufft[3]={0,0,0};
unsigned int Dis_Vale=800;
unsigned char T_vale=0;
unsigned char T_valeb=0;
bit KEY_MODE_ST=1;
unsigned char Dis_outmv_Date=1;

unsigned long BuffDate=0;
unsigned long BuffDate1=0;    //N次采样数累加暂存地址空间  
bit ZhuanHuanOKBZ=0;          //N次采样OK标志值
unsigned char ADC_BZ=0;       //ADC转换状态标志
int ZhuanHuanCS=0;            //具体采样的次数
unsigned int OKdata=0;          //转换OK的输入信号值
unsigned int OKdata1=0;          //转换OK的输入信号值
int DateLV=2937;              //ADC量程系数5V等于5000  FLUCK表实测Vref 2.937 V
int DateXZ=0;

//手动给定数值显示
void PrintLCD_int(unsigned int adc)               
{
  char i,ii;
  for (i=0;i<=5;i++)
  {
  dis_buff[i]=adc % 10;
  adc /= 10;
  }
//换成字符形式方便于LCD显示
  for (ii=0;ii<=4;ii++)
  {
  lcd_gotoxy(ii+10,0);     //去LCD第二行第0列显示百位数
  lcd_putchar(str[dis_buff[4-ii]]);
      
  }
}

//手动给定值显示函数
void PrintLCD_short(unsigned char ad)
{
  char i1;
   for (i1=0;i1<=1;i1++)
  {
  dis_bufft[i1]=ad % 10;
  ad /= 10;
  }
//换成字符形式方便于LCD显示
  lcd_gotoxy(2,0);     
  lcd_putchar(str[dis_bufft[1]]);
  lcd_putchar('.');
  lcd_putchar(str[dis_bufft[0]]);  
}

//ADC 转换中断服务程序
interrupt[ADC_INT]void adc_m8(void)
{
    unsigned int adc_data;
    adc_data=ADCW;                               //读取ADC置换结果  
    BuffDate1=(unsigned long)adc_data+BuffDate1; //第一步 将过采样数据进行累加
    ++ZhuanHuanCS;   
    if(ZhuanHuanCS>=255)                         //判断N次的采样
    {
     ZhuanHuanCS=0;
     BuffDate=BuffDate1;  
     BuffDate1=0;
     ZhuanHuanOKBZ=1;
     ADC_BZ++;   
    }
}

//第一路输出电流AD采样数据显示
void PrintLCD_intAD0(unsigned int adc)               
{
char i;
adc=(unsigned int)(20000/2000)*adc;    //2V对应20mA转换函数
for (i=0;i<=4;i++)                          
  {
  dis_buff2[i]=adc % 10;
  adc/= 10;
  }
  //换成字符形式方便于LCD显示
  lcd_gotoxy(9,1);     //去LCD第二行第0列显示百位数
  lcd_putchar(str[dis_buff2[4]]);
  lcd_putchar(str[dis_buff2[3]]);
  lcd_putchar('.');
  lcd_putchar(str[dis_buff2[2]]);
  lcd_putchar(str[dis_buff2[1]]);
  lcd_putchar(str[dis_buff2[0]]);   
}
//第二路输出电压AD采样数据显示
void PrintLCD_intAD1(unsigned int adc)               
{
char i;
adc=adc*2;           //将采样的数据放大2倍。因为硬件上通过放大器将采样信号衰减2倍
for (i=0;i<=3;i++)
  {
  dis_buff3[i]=adc % 10;
  adc /= 10;
  }
//换成字符形式方便于LCD显示
  lcd_gotoxy(2,1);     //去LCD第二行第0列显示百位数
  lcd_putchar(str[dis_buff3[3]]);
  lcd_putchar('.');
  lcd_putchar(str[dis_buff3[2]]);
  lcd_putchar(str[dis_buff3[1]]);
  lcd_putchar(str[dis_buff3[0]]);   
}

//按键扫描处理程序
void KeyProcess(void)
{
//PORTC=0x07;在主程序初始化段设置PC口低三位上拉电阻有效 DDRC=0x00;设置PC口输入模式
unsigned char ReadData=~PINC; //读PC口并将数据取反
Trg=ReadData&(ReadData^Cont); //判断是否点动
Cont=ReadData;                //判断是否长按
  if(Trg&KEY_MODE)
  {
   KEY_MODE_ST=~KEY_MODE_ST;
   lcd_gotoxy(15,0);     //去LCD第二行第0列显示百位数
   if(KEY_MODE_ST)
   lcd_putchar('+');
   else
   lcd_putchar('-');
  }
  if(Trg&KEY_ADD)
  {
   if(KEY_MODE_ST)
    {
     if(Dis_Vale<=64223)
     {
     Dis_Vale=Dis_Vale+1305;
     Dis_outmv_Date++ ;
     }
    }
    else
    {
     if(Dis_Vale>=1312)
     {
     Dis_Vale=Dis_Vale-1305;
     Dis_outmv_Date--;
     }
    }
  }   
   if(Trg&KEY_SUB)
   {
     if(KEY_MODE_ST)
    {
     if(Dis_Vale<=65534)
     Dis_Vale=Dis_Vale+2;
     }
    else
    {
     if(Dis_Vale>=2)
     Dis_Vale=Dis_Vale-2;
     }
    }   
}

//SPI主机初始化函数
void SPI_MasterInitY(void)
{
DDRB=0x2C;   //SPI接口SCK PB7设置成输出,SPI接口MOSI PB5设置成输出,SPI接口SS PB4设置成输出。其它设置成输入                       
PORTB=0x00;   
SPCR=0b01010001; //SPI控制寄存器SPCR的第6位SPE设置成1 第4位MAST主从选择设置成1为主方式 第0位为1表示SCK分频系数为什16
}                                 
//SPI主机发送数据函数
void SPI_MasterTransmitY(unsigned char T_Data)
{
SPDR=T_Data;         // 向SPI数据寄存器SPDR赋需要传送的值
while(!(SPSR&0x80))  //判断SPI发送数据有没有结束如果结束SPSR状态寄存器的第7位SPIF则为1否则则等待
  {};
}

void SPI_TransmitY(unsigned int TrData)
{
unsigned char a,b;
a=TrData/256;
b=TrData%256;
PORTB&=0xFB;            //将SPI接口SS PB4置0完成16位数据传
SPI_MasterTransmitY(a); //先传输高8位
SPI_MasterTransmitY(b); //再传输低8位从而组成AD420所需的16位数据
PORTB|=0x04;  
}  
                 
void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
PORTB=0x43; //设置PB6,PB1,PB0上拉电阻有效 且为输入模式
DDRB=0x00;
PORTC=0xFC;
DDRC=0x00;
PORTD=0x00;
DDRD=0xFF;   //设置PD口为液晶显示器输出接口
// Timer/Counter 0 initialization
TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// Analog Comparator initialization
ADMUX=0b00000000;
ADCSRA=0b11101110;

ACSR=0x80;
SFIOR=0x00;
lcd_init(16);       //LCD显示器的初始化
SPI_MasterInitY();  //SPI通讯初始化
lcd_gotoxy(15,0);
if(KEY_MODE_ST)
lcd_putchar('+');
else
lcd_putchar('-');
#asm("sei") //开中断
while (1)
      {
      lcd_gotoxy(0,0);
      lcd_putsf("U:"); // display the message
      lcd_gotoxy(5,0);
      lcd_putsf("00V");
      lcd_gotoxy(0,1);
      lcd_putsf("o:");
      lcd_gotoxy(7,1);
      lcd_putsf("V");
      lcd_gotoxy(14,1);
      lcd_putsf("mA");                  
      if(T_valeb>=20)
      {
       KeyProcess();
       PrintLCD_int(Dis_Vale);
       PrintLCD_short(Dis_outmv_Date);
       SPI_TransmitY(Dis_Vale);
       }
      if(T_vale>=25)
      {
      T_vale=0;
      DDRD=DDRD|0b00001000;
      PORTD.3=~PORTD.3;
      }
       T_vale++;
        T_valeb++;
        
      if(ZhuanHuanOKBZ)
       {
        #asm("cli") //开中断
       ADCSRA=ADCSRA&0b01111111;       //停ADC转换
       ZhuanHuanOKBZ=0;                //清除标志位
       BuffDate=BuffDate/16;           //第二步将N次采样的累积数据右移4位
       BuffDate=BuffDate*DateLV/16384; //第三步还原14位数据精度的输入值
       if(ADC_BZ==1)
       {
         //AD转换非线性修正
         if(BuffDate>=10)
         DateXZ=4;
         else DateXZ=0;
         if(BuffDate>=150)
         DateXZ=5;
         if(BuffDate>=300)
         DateXZ=6;
         if(BuffDate>=600)
         DateXZ=7;
         if(BuffDate>=750)
         DateXZ=8;
         if(BuffDate>=2100)
         DateXZ=9;
         if(BuffDate>=2250)
         DateXZ=10;
         if(BuffDate>=2350)
         DateXZ=11;
         BuffDate=BuffDate+DateXZ;
         OKdata=(unsigned int)BuffDate;  
         PrintLCD_intAD0(OKdata);      //调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示
         ADMUX=0b00000001;  //采样ADC1
         
         
        }
        if(ADC_BZ==3)
        {
         //AD转换非线性修正
         if(BuffDate>=10)
         DateXZ=3;
         else DateXZ=0;
         if(BuffDate>=60)
         DateXZ=4;
         if(BuffDate>=250)
         DateXZ=6;
         if(BuffDate>=700)
         DateXZ=7;
         if(BuffDate>=1150)
         DateXZ=8;
         if(BuffDate>=1750)
         DateXZ=9;
         if(BuffDate>=2150)
         DateXZ=10;
         if(BuffDate>=2350)
         DateXZ=11;
          BuffDate=BuffDate+DateXZ;
         OKdata1=(unsigned int)BuffDate;  
         PrintLCD_intAD1(OKdata1);    //调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示//调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示
         ADMUX=0b00000000;  //采样ADC0
        
      
        }
        if(ADC_BZ>=4)
        ADC_BZ=0;
        
        ADCSRA=0b11101110;      //启动ADC转换
         #asm("sei") //开中断
         
        }
         
           
      };
}

出0入0汤圆

发表于 2012-5-25 23:11:41 | 显示全部楼层
写得不好的地方还请高手多多指正。

出0入0汤圆

发表于 2012-6-1 17:41:34 | 显示全部楼层
厉害,楼上的思路很不错,学习消化下

出0入0汤圆

发表于 2012-6-4 19:25:31 | 显示全部楼层
试了一下蛮OK的,可惜只有一个按键,不知咋样改成多个按键的?

出0入0汤圆

发表于 2012-6-4 20:57:27 | 显示全部楼层
原来我以前编写的按键检测方法叫做状态机啊

出0入0汤圆

发表于 2012-6-4 23:22:25 来自手机 | 显示全部楼层
回头去实验一下…

出70入0汤圆

发表于 2012-6-5 11:21:40 | 显示全部楼层
实际上,现在的全国大学生电子设计大赛也变成是一个浮躁的产物,学校和学生都指望它能贴金,对于真正培养和锻炼人的目的和作用,实际上只是挂在前面遮羞布了。
----------------------------------------------------------------------------------------------------------------------------------
马潮老师这话说得很实在。我们学校的电子大赛就全部是老师做的,和老师关系好的学生去挂一个名。太让人心寒了!

出0入0汤圆

发表于 2012-6-13 00:15:35 | 显示全部楼层
MARK !

出0入0汤圆

发表于 2012-6-13 06:18:10 | 显示全部楼层
mark, thanks a lot.

出0入0汤圆

发表于 2012-6-14 16:19:57 | 显示全部楼层
向马老师看起!学习思想,消化成自己的,哈哈   真心感谢!

出0入0汤圆

发表于 2012-6-14 17:54:13 | 显示全部楼层
学习啊学习了

出0入0汤圆

发表于 2012-6-15 20:14:33 | 显示全部楼层
貌似程序有同类的两个错误吧,长按和双击都有问题。。

出0入0汤圆

发表于 2012-6-20 14:39:29 | 显示全部楼层
mark 模仿了

出0入0汤圆

发表于 2012-6-20 16:18:19 | 显示全部楼层
这种才是真正能运用到产品上的程序
以前按照其它51教材上按键处理办法
结果在产品上体验不好 一直怀疑是按键质量不好
现在想想真是惭愧 怪自己没认真研究和学习
感谢马老师的分享和指导!

出0入0汤圆

发表于 2012-6-20 21:37:06 | 显示全部楼层
差距太大了

出0入0汤圆

发表于 2012-6-24 16:13:53 | 显示全部楼层
学习了,一个按键有这么大学问,佩服

出0入0汤圆

发表于 2012-6-29 08:49:58 | 显示全部楼层
mark~~~~~~~~~~~

出0入0汤圆

发表于 2012-6-29 14:36:29 | 显示全部楼层
嗯,马老师分析的很好,学习了啊

出0入0汤圆

发表于 2012-7-4 22:53:04 | 显示全部楼层
绝对好贴mark

出0入0汤圆

发表于 2012-7-16 10:43:07 | 显示全部楼层
哪位大侠帮我看看这个程序啊,根据马老师书里的状态机按键程序写的,要求按键控制LED亮灭,编译没错误,就是运行不出来
#include<reg52.h>

sbit LED = P2^0;         //定义LED在P2.0脚上
char g_bSystemTime1Ms = 0 ;              
bit time_ok=0;          // 10MS系统时标

#define key_input P0^0// 按键输入口
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2

char read_key(void)
{
static char key_state=0 ;
char key_press, key_return = 0;
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_return = 1; // 按键仍按下,按键确认输出为“1”
            key_state = key_state_2;  //状态转换到键释放态
           }
         else
            key_state = key_state_0;  //按键已抬起,是抖动,转换到按键初始态
            break;
   case key_state_2:                                  //等待释放状态
        if (key_press) key_state = key_state_0; //按键已释放,转换到按键初始态
        break;
}
  return key_return;
}
void main()
{
  TMOD &= 0xf0 ;
  TMOD |= 0x01 ;      //定时器0工作方式1
  TH0  =  0xfc ;     //定时器初始值
  TL0  =  0x66 ;
  TR0  = 1 ;
  ET0  = 1 ;
  EA = 1 ;
  while(1)
  {
   if(time_ok==1)
    {
          time_ok=0;
          if(read_key()==1)  LED = ~LED;             
     
    }       
  }
}
void Time0Isr(void) interrupt 1
{
     TH0  =  0xfc ;      //定时器重新置始值
     TL0  =  0x66 ;
         if(++g_bSystemTime1Ms>=10)  //1MS转换10MS
          {
                   g_bSystemTime1Ms=0;
                time_ok =1;                  // 10MS系统时标
      }   
}

出0入0汤圆

发表于 2012-7-18 14:57:39 | 显示全部楼层
key_time 为局部变量,好像不对吧,哈哈

出0入0汤圆

发表于 2012-7-21 16:10:10 | 显示全部楼层
如果是多个独立按键呢,程序怎么写啊

出0入0汤圆

发表于 2012-7-21 23:53:01 | 显示全部楼层
不错 很有帮助

出0入0汤圆

发表于 2012-9-13 09:19:41 | 显示全部楼层
记号一下,很实用.

出0入0汤圆

发表于 2012-9-13 14:12:41 | 显示全部楼层
必须顶,绝对好东东

出0入0汤圆

发表于 2012-9-13 23:25:47 | 显示全部楼层
非常好

出0入0汤圆

发表于 2012-9-15 08:43:11 | 显示全部楼层
来学习了   很不错

出0入0汤圆

发表于 2012-9-15 09:32:16 来自手机 | 显示全部楼层
不错学习学习

出0入0汤圆

发表于 2012-9-17 08:59:10 | 显示全部楼层
不错,好好学习学习

出0入0汤圆

发表于 2012-10-15 11:11:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-10-15 13:59:36 | 显示全部楼层
受教了。

出0入20汤圆

发表于 2012-10-15 14:04:28 | 显示全部楼层
支持一下

出0入21汤圆

发表于 2012-10-15 14:19:47 | 显示全部楼层
谢谢马老师!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 02:49

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表