搜索
bottom↓
回复: 4

按键操纵问题

[复制链接]

出0入0汤圆

发表于 2015-6-11 09:52:49 | 显示全部楼层 |阅读模式
程序如下。请教给问题,按键操作。我原本想就是每次按加键数值+1,按减键数值-1,但是我把我写的程序下载到板子上却是从0一下子到30,按减键从30一下子变为0,请教这是为什么。

#include <stc12c5a.h>

#include "Config.h"
#include "intrins.h"


#define  NOP() _nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_() /* ????? */

#define Upkeytimer    80     //up键延迟消抖
#define Downkeytimer  80     //down键延迟消抖
#define Setkeytimer   80     //设置键延迟消抖

unsigned char i = 0;

unsigned char code LedChar[] = { //共阴字形码
                                ~0xC0, ~0xF9, ~0xA4, ~0xB0, ~0x99,
//                                 0      1      2     3       4   
                                ~0x92, ~0x82, ~0xF8, ~0x80, ~0x90,
//                                 5      6      7     8       9
                                 0x77,  0x7c,  0x39,  0x5e,  0x79, 0x71,0x3e
//                                 A      B      C     D       E     F   V
};

unsigned char ucKeySec = 0; //被触发的按键编号
unsigned char ucWd=1; //本程序的核心变量,窗口显示变量,类似一级菜单的变量,代表不太的显示窗口

unsigned char Sensor_Address = 15;   //传感器地址参数
unsigned char Sensor_Type    = 0;   //传感器类型参数
unsigned int  Sensor_Bias    = 0;   //传感器偏差参数
unsigned int  Sensor_Alarm   = 0;   //传感器报警值参数

unsigned char ucDigShow3;       //第3位数码管显示的内容
unsigned char ucDigShow2;       //第2位数码管显示的内容
unsigned char ucDigShow1;       //第1位数码管显示的内容

unsigned int ucTemp3 = 0;       //中间过度变量
unsigned int ucTemp2 = 0;       //中间过度变量
unsigned int ucTemp1 = 0;       //中间过度变量
   
unsigned int KeyUpTime  = 0;       //延迟去抖延迟计数器
unsigned char KeyUpLock = 0;       //"+"键触发后自锁的变量标志

unsigned int KeyDownTime  = 0;     //延迟去抖延迟计数器
unsigned char KeyDownLock = 0;     //"-"键触发后自锁的变量标志
   
unsigned int KeySetTime  = 0;      //延迟去抖延迟计数器
unsigned char KeySetLock = 0;      //"Set"键触发后自锁的变量标志

unsigned char ucDigDot;       //数码管第二位是否有小数点
   

unsigned char ucDisplayUpdata = 1;   //更新显示标志
unsigned int ucDigShowTemp = 0;     //临时中间变量


void Intial_myself();
void Delay_long(unsigned int ms);
void Intial_peripheral();
void Key_service();
void Display_service();
void KeyScan();
void display_drive();
void SMG_Display();
void Delay2ms();

void HC595SendData(unsigned char SendVal);


void main()
{
    Intial_myself();
    Delay_long(100);
    Intial_peripheral();
   
    while(1)
    {
        Key_service();            //按键服务的应用程序
        Display_service();          //显示窗口菜单服务程序
    }
   
}

/*初始化函数*/
void Intial_myself()
{
    ADDR0 = 1;   //第0位数码管   0:亮  1:灭
    ADDR1 = 1;   //第1位数码管
    ADDR2 = 1;   //第2位数码管
   
    LED_R = 1;   //D1--红灯   
    LED_G = 1;   //D2--绿灯
    LED_B = 1;   //D3--蓝灯
   
    KEY_UP   = 1;             //独立键盘扫描 “+” 输入引脚
    KEY_DOWN = 1;             //独立键盘扫描 “-” 输入引脚
    KEY_SET  = 1;             //独立键盘扫描 “设置”输入引脚
   
    HC595SendData(0X00);

    TMOD = 0x01;
    TH0 = 0xf8;
    TL0 = 0xcd;        
}

void Intial_peripheral()
{        
    EA=1;
   
    ET0=1;
   
    TR0=1;   
}

void Delay_long(unsigned int ms)
{
    unsigned int i;
    unsigned int j;
    for(i=0;i<ms;i++)
    {
        for(j=0;j<500;j++)
        {;}
    }
}
void KeyScan()
{
    if(KEY_UP == 1)  //高电平,没有按键按下,这时及时清标志位
    {
        KeyUpTime = 0;  //按键自锁标志清0
        KeyUpLock = 0;  //按键去抖动计数器清0        
    }
    else if(KEY_UP == 0) //说明有键按下,而且是第一次
    {
        KeyUpTime++;     //累加定时中断加1      
        if(KeyUpTime > Upkeytimer)
        {
            KeyUpTime = 0;
            KeyUpLock = 1;//自锁键置位,避免一直触发
            ucKeySec  = 1; //触发"+"号键
        }                    
    }
    if(KEY_DOWN == 1)  //高电平,没有按键按下,这时及时清标志位
    {
        KeyDownTime = 0;  //按键自锁标志清0
        KeyDownLock = 0;  //按键去抖动计数器清0        
    }
    else if(KEY_DOWN == 0) //说明有键按下,而且是第一次
    {
        KeyDownTime++;     //累加定时中断加1      
        if(KeyDownTime > Downkeytimer)
        {
            KeyDownTime = 0;
            KeyDownLock = 1;//自锁键置位,避免一直触发
            ucKeySec  = 2; //触发"-"号键
        }                    
    }
    if(KEY_SET == 1)  //高电平,没有按键按下,这时及时清标志位
    {
        KeySetTime = 0;  //按键自锁标志清0
        KeySetLock = 0;  //按键去抖动计数器清0        
    }
    else if(KEY_SET == 0) //说明有键按下,而且是第一次
    {
        KeySetTime++;     //累加定时中断加1      
        if(KeySetTime > Downkeytimer)
        {
            KeySetTime = 0;
            KeySetLock = 1;//自锁键置位,避免一直触发
            ucKeySec  = 3; //触发"设置"键
        }                    
    }   
}
//按键服务的应用程序
void Key_service()
{
    switch(ucKeySec)     //按键服务状态切换
    {
        case 1:          //"+"按键
             switch(ucWd)  //在不同的窗口下,设置不同的参数
             {
                 case 1: Sensor_Address++;if(Sensor_Address > 30);{Sensor_Address =0;}break;
                 case 2: Sensor_Type++;   if(Sensor_Type    > 4); {Sensor_Type    =0;}break;
                 case 3: Sensor_Bias++;   if(Sensor_Bias    > 60);{Sensor_Bias    =0;}break;
                 case 4: Sensor_Alarm++;  if(Sensor_Alarm   > 60);{Sensor_Alarm   =0;}break;
                 default:break;
             }

             ucDisplayUpdata = 1;  //显示更新内容
             ucKeySec = 0;         //相应按键服务程序后,按键编号清0,避免一次触发
             break;
            
        case 2:         //"-"按键
             switch(ucWd)  //在不同的窗口下,设置不同的参数
             {
                 case 1: Sensor_Address--;if(Sensor_Address <0);Sensor_Address =30;break;
                 case 2: Sensor_Type--;   if(Sensor_Type    <0);Sensor_Type    =4; break;
                 case 3: Sensor_Bias--;   if(Sensor_Bias    <0);Sensor_Bias    =60;break;
                 case 4: Sensor_Alarm--;  if(Sensor_Alarm   <0);Sensor_Alarm   =60;break;
                 default:break;
             }

             ucDisplayUpdata = 1;  //显示更新内容
             ucKeySec = 0;         //相应按键服务程序后,按键编号清0,避免一次触发
             break;
            
        case 3:      //切换窗口键
             ucWd++;
             if(ucWd>4)
             {
                ucWd = 1;
             }   
             ucDisplayUpdata = 1;  //显示更新内容
             ucKeySec = 0;         //相应按键服务程序后,按键编号清0,避免一次触发
             break;        
    }        
}

//显示窗口菜单服务程序
void Display_service()         
{
    if(ucDisplayUpdata == 1)   //有数据要更新
    {
        ucDisplayUpdata = 0;
        switch(ucWd)
        {
            case 1:   //显示压力传感器地址参数设置页面 d x x
                   ucDigShow3 = 13;      //第1位显示d
            
                   ucTemp2 = Sensor_Address / 10;   //第二位显示十位数
                   ucTemp1 = Sensor_Address % 10;   //第三位显示个位数
            
                   ucDigShow2 = ucTemp2;            //十位数送到缓冲区
                   ucDigShow1 = ucTemp1;            //个位数送到缓冲区
                  
                    LED_R = 1;
                    LED_G = 1;
                    LED_B = 1;
            // SMG_Display();
                   break;                     
            case 2:   //显示压力传感器类型参数设置页面 A x x
                    ucDigShow3 = 10;            //第1位显示 A  
                    ucDigShow2 = 0;             //第二位显示0
                    
                    ucTemp1    = Sensor_Type % 10; //获得个位数
            
                    ucDigShow1 =ucTemp1;          //个位数送到缓冲区
                    
                    LED_R = 1;
                    LED_G = 1;
                    LED_B = 1;
                    //SMG_Display();
                    break;
            case 3:   //显示压力传感器偏差参数设置页面 xx.x
                    ucTemp3 = Sensor_Bias / 100;        //获得百位数
                    ucTemp2 = Sensor_Bias / 10%10;      //获得十位数
                    ucTemp1 = Sensor_Bias % 10;         //获得个位数
            
                    ucDigShow3 =ucTemp3;                //百位数送到缓冲区
                    ucDigShow2 =ucTemp2;                //十位数送到缓冲区
                    ucDigShow1 =ucTemp1;                //个位数送到缓冲区
            
                    LED_R = 0;
                    LED_G = 1;
                    LED_B = 1;
                    //SMG_Display();
                    break;
            case 4:   //显示压力传感器报警值参数设置页面 xx.x
                    ucTemp3 = Sensor_Alarm / 100;        //获得百位数
                    ucTemp2 = Sensor_Alarm / 10%10;      //获得十位数
                    ucTemp1 = Sensor_Alarm % 10;         //获得个位数
            
                    ucDigShow3 =ucTemp3;                 //百位数送到缓冲区
                    ucDigShow2 =ucTemp2;                 //十位数送到缓冲区
                    ucDigShow1 =ucTemp1;                 //个位数送到缓冲区
                    
                    LED_R = 1;
                    LED_G = 0;
                    LED_B = 1;
                    
                    break;
            default:break;
        }           
    }
}
void SMG_Display()
{   
    ADDR2 = 0; ADDR1 = 1; ADDR0 = 1;HC595SendData(LedChar[ucDigShow3]);Delay2ms();HC595SendData(0);
    ADDR2 = 1; ADDR1 = 0; ADDR0 = 1;HC595SendData(LedChar[ucDigShow2]);Delay2ms();HC595SendData(0);
    ADDR2 = 1; ADDR1 = 1; ADDR0 = 0;HC595SendData(LedChar[ucDigShow1]);Delay2ms();HC595SendData(0);   
}


//void display_drive()
//{
//        
//    switch(i)
//    {
//        case 0: ucDigShowTemp = LedChar[9];
//                ADDR2 = 0; ADDR1 = 0; ADDR0 = 0;  
//                HC595SendData(ucDigShowTemp);
//        
//        case 1: ucDigShowTemp = LedChar[12];
//                ADDR2 = 0; ADDR1 = 0; ADDR0 = 0;
//                if(ucDigDot == 1)
//                {
//                    ucDigShowTemp=ucDigShowTemp|0x80;
//                }
//               HC595SendData(ucDigShowTemp);
//               
//        case 2:ucDigShowTemp = LedChar[11];
//               ADDR2 = 0; ADDR1 = 0; ADDR0 = 0;
//               HC595SendData(ucDigShowTemp);
//        default:break;
//    }
//   
//}
/*********************************************************************************************************
** 函数名称: HC595SendData
** 功能描述: 向SPI总线发送数据
*********************************************************************************************************/
void HC595SendData(unsigned char SendVal)
{  
    unsigned char i;
               
    for(i=0;i<8;i++)
    {
        if((SendVal<<i)&0x80) MOSIO=1; //set dataline high  0X80  最高位与SendVal左移的最高位 进行逻辑运算
        else MOSIO=0;                                   // 如果为真 MOSIO = 1  

        S_CLK=0;  
        NOP();         //短暂延时产生一定宽度的脉冲信号
        NOP();         //短暂延时
        S_CLK=1;
    }
    R_CLK=0; //set dataline low
    NOP();  //短暂延时
    NOP();  //短暂延时
    R_CLK=1;         //
}
/*定时中断函数*/
void T0_Time() interrupt 1
{
    static unsigned char tmr10ms = 0;

    TH0 = 0xf8;
    TL0 = 0xcd;
   
    KeyScan();
    tmr10ms++;
    if (tmr10ms >= 5)
    {
        tmr10ms = 0;
        SMG_Display();  //调用秒表计数函数
    }
   
//   display_drive();
   
}

void Delay2ms()                //@11.0592MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 22;
        j = 128;
        do
        {
                while (--j);
        } while (--i);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2015-6-11 22:06:37 | 显示全部楼层
看不懂c代码
想问下楼主:你的按键代码里有消抖动延时吗?

出0入0汤圆

发表于 2015-6-12 08:46:44 | 显示全部楼层
所有KEYLOCK没用上啊,有置有清,但没有判断的地方
不能只靠改ucKeySec为0来实现重复触发,没用的

出0入0汤圆

发表于 2015-6-12 11:18:04 | 显示全部楼层
没看程序。就问一句,程序跑一编就加减1,你按钮的速度要和程序跑的速度比了。除非设置了上下沿检测,确定是按了一次按钮。程序应该就设计单次按按钮。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-7-23 08:30

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

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