搜索
bottom↓
回复: 6

请教马老师,矩阵按键的问题?吉萨

[复制链接]

出0入0汤圆

发表于 2011-11-11 08:24:18 | 显示全部楼层 |阅读模式
按照马老师书上面介绍的矩阵按键,仿了一个4*2的按键。结果只有2 4 6 8 这4个按键可以。
其他1 3 5 7这4个键没有反应 。请问马老师是啥问题?
我检查了按键也都是完好的。
先把图和程序传下。麻烦马老师指教,我用的芯片是MEGA128L

//按键测试程序
#include "config.h"  //此文件在项目里

#define No_key         255
#define K1_1        1
#define K1_2        2//ok
#define K2_1        3
#define K2_2        4//ok

#define K3_1        5
#define K3_2        6//ok
#define K4_1        7
#define K4_2        8//ok

//4*2 就用到PD0--PD5
#define Key_mask        0x03

unsigned char key_stime_counter=0,key_stime_ok=0;

/*端口初始化*/
void Port_Init(void)
{
         //PORTA = 0xFF;        //PB口配置为输出
         //DDRA = 0xFF;         //PB口初始值为"1"
         
         PORTB = 0xFF;        //PB口配置为输出
         DDRB = 0xFF;         //PB口初始值为"1"

         //DDRA |= (1 << 7);    //流水灯使能脚输出
         //PORTA |= (1 << 7);   //流水灯使能
         
         //DDRA |= (1 << 0);    //流水灯使能脚输出
         //PORTA |= (1 << 0);   //流水灯使能
         //PORTA=0x70;
         //DDRA=0xea;//pa0  IN  0b1110 1010
         
         //DDRA &= ~(1 << PA0) & ~(1 << PA2) & ~(1 << PA3) & ~(1 << PA4) & ~(1 << PA5) & ~(1 << PA6) & ~(1 << PA7) ;//设置为输入,不上拉
         
         //按键引脚
         //PORTD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7);//push
         //DDRD |= (1 << PD2)|(1 << PD3)|(1 << PD4)|(1 << PD5)|(1 << PD6)|(1 << PD7);    //out
         //DDRD &= ~(1 << PD0) & ~(1 << PD1);//in
         PORTD=0xff;
         DDRD=0xfc;
         
         //DDRF &= ~(1 << PF0) & ~(1 << PF2) & ~(1 << PF3) & ~(1 << PF4) & ~(1 << PF5) & ~(1 << PF6) & ~(1 << PF7) ;//
}

/*定时器0初始化*/
//64分频,即ADC时钟是250KHZ
//(255-5)*(1/250000)=250*4us=1000us=1ms
//1ms中断一次
void Timer0_Init(void)    //
{
         TCNT0 = 5;             //给定时器赋初值
         TIMSK |= ( 1<< TOIE0); //使能T0溢出中断
         //SREG = 0x80;           //使能全局中断
         //sei();
         _SEI();//使能全局中断
         //TCCR0 |= (1 << CS01)|(1 << CS00);//64分频,开定时器 mega32,16set
         TCCR0 |= (1 << CS02);//mega128set
}

unsigned char Read_KeyBoard(void)
{       
        static unsigned char key_state = 0, key_value, key_line;
        unsigned char key_return = No_key,i;
       
        switch (key_state)  
        {
                case 0:
                        key_line = 0x04;//0b00000100
                        for (i=1; i<=4; i++)                                        // 扫描键盘
                        {       
                                PORTD = ~key_line;                                // 输出行线电平
                                PORTD = ~key_line;                                // 必须送2次!!!
                                key_value = Key_mask & PIND;                    // 读列电平
                                if (key_value == Key_mask)
                                        key_line <<= 1;                                // 没有按键,继续扫描
                                else
                                {
                                        key_state++;                                // 有按键,停止扫描
                                        break;                                        // 转消抖确认状态
                                }
                        }
                        break;
                case 1:
                        if (key_value == (Key_mask & PIND))                        // 再次读列电平,
                        {
                                switch (key_line | key_value)                        // 与状态0的相同,确认按键
                                {                                                // 键盘编码,返回编码值
                                        case 0x06://0b00000110
                                                key_return = K1_1;
                                                break;
                                        case 0x05://0b00000101
                                                key_return = K1_2;
                                                break;
                                               
                                        case 0x0a://0b00001010
                                                key_return = K2_1;
                                                break;
                                        case 0x09://0b00001001
                                                key_return = K2_2;
                                                break;
                                               
                                        case 0x12://0b00010010
                                                key_return = K3_1;
                                                break;
                                        case 0x11://0b00010001
                                                key_return = K3_2;
                                                break;
                                               
                                        case 0x22://0b00100010
                                                key_return = K4_1;
                                                break;
                                        case 0x21://0b00100001
                                                key_return = K4_2;
                                                break;
                                }
                                key_state++;                                        // 转入等待按键释放状态
                        }
                        else
                                key_state--;                                        // 两次列电平不同返回状态0,(消抖处理)
                        break;                                               
                case 2:                                                                // 等待按键释放状态
                        PORTD = 0x03;                                                // 行线全部输出低电平0b00000011
                        PORTD = 0x03;                                                // 重复送一次
                        if ( (Key_mask & PIND) == Key_mask)
                                key_state=0;                                        // 列线全部为高电平返回状态0
                        break;
        }
        return key_return;
}

//main
void main(void)
{
  unsigned int KeyCode = 0;
  Port_Init();   //初始化IO
  Timer0_Init(); //定时器0初始化

  sys_initial(); //液晶IO初始化
  lcd_initial(); //液晶初始化
  
  Clear_LCM();//
  //Display(0x91,Cursor);//
  Display(0x92,WelcomeToUse);   //开机界面显示欢迎使用
  //WriteString(WelcomeToUse);
  Display(0x8a,Electrical);//
  DelayNms(1000);
  
  Clear_LCM();//
  send_command(0x80);
  send_data('w'); //写data
  send_data('a'); //写data
  send_data('i'); //写data
  send_data('t'); //写data
  
  send_data(' '); //写data
  
  send_data('k'); //写data
  send_data('e'); //写data
  send_data('y'); //写data
  
    while(1)
    {
        if (key_stime_ok)        // 10ms到,键处理
        {
               key_stime_ok = 0;
               KeyCode = Read_KeyBoard();//调用按键扫描程序 10ms一次
        }
        
        if(KeyCode==K1_1)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('1'); //写data  
        }
        if(KeyCode==K1_2)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('2'); //写data  
        }
        
        if(KeyCode==K2_1)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('3'); //写data  
        }
        if(KeyCode==K2_2)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('4'); //写data  
        }
        
        if(KeyCode==K3_1)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('5'); //写data  
        }
        if(KeyCode==K3_2)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('6'); //写data  
        }
        
        if(KeyCode==K4_1)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('7'); //写data  
        }
        if(KeyCode==K4_2)
        {
          Clear_LCM();//
          send_command(0x80);
          send_data('8'); //写data  
        }
    }
}



/*定时器0中断服务程序*/
//1ms中断一次
/*#pragma interrupt_handler Timer0_Ovf:10*/

volatile unsigned int tc0_Cnt = 0,tc0_Cnt_Display = 0;

#pragma vector = TIMER0_OVF_vect//TIMER0 溢出中断入口地址
__interrupt void Timer0_Ovf(void)
{
        TCNT0 = 5;            //给定时器赋初值

        if (++key_stime_counter >=10)
        {
            key_stime_counter = 0;
            key_stime_ok = 1;// 10ms到
            //Voice_ChoiceScanFlag = 1;//声音选择扫描
        }           
}

//图


(原文件名:key4x2.jpg)

开始我怀疑是硬件, 我仔细查了硬件,没有查出啥问题。
大家看看可是软件的问题,如果不是,我继续查硬件,但是郁闷查了,没有新的发现和不对的地方。

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2011-11-11 08:27:54 | 显示全部楼层
这个是我在IAR上面移植的东西。有些改成0X--形式

出0入0汤圆

发表于 2011-11-11 09:35:21 | 显示全部楼层
最好还是把电路图上的按键标号和程序里的定义统一一下,要不然感觉很乱,不知道你的2,4,6,8是键盘上的K2,4,6,8还是程序里定义的2,4,6,8;虽然你在程序里提示了一下OK,也感觉乱

出0入0汤圆

 楼主| 发表于 2011-11-11 10:03:30 | 显示全部楼层
key-cs1 pd0
key-cs2 pd1

key-y1  pd2
key-y2  pd3
key-y3  pd4
key-y4  pd5

按键连接对应起来,这样是否可以。

出0入0汤圆

 楼主| 发表于 2011-11-12 08:44:54 | 显示全部楼层
焦急中---

出0入0汤圆

发表于 2011-11-15 12:44:17 | 显示全部楼层
unsigned char Read_KeyBoard(void)
{
  static unsigned char key_state = 0, key_value, key_line;
  unsigned char key_return = No_key,i;

  switch (key_state)   
  {
    case 0:
      key_line = 0x04;//0b00000100
      for (i=1; i<=4; i++) // 扫描键盘
      {
        PORTD = ~key_line;         // 输出行线电平
        PORTD = ~key_line; // 必须送2次!!!
        key_value = Key_mask & PIND;                    // 读列电平
        if (key_value == Key_mask)
          key_line <<= 1; // 没有按键,继续扫描
        else
        {
          key_state++; // 有按键,停止扫描
          break; // 转消抖确认状态
        }
      }
      break;
    case 1:
      if (key_value == (Key_mask & PIND))         // 再次读列电平,
      {
        switch (key_line | key_value)         // 与状态0的相同,确认按键
        { // 键盘编码,返回编码值  
          case 0x06://0b00000110
            key_return = K1_1;
            break;
          case 0x05://0b00000101
            key_return = K1_2;
            break;
          case 0x0a://0b00001010
            key_return = K2_1;
            break;
          case 0x09://0b00001001
            key_return = K2_2;
            break;
          case 0x12://0b00010010
            key_return = K3_1;
            break;
          case 0x11://0b00010001
            key_return = K3_2;
            break;
          case 0x22://0b00100010
            key_return = K4_1;
            break;
          case 0x21://0b00100001
            key_return = K4_2;
            break;
        }
        key_state++;         // 转入等待按键释放状态
      }
      else
        key_state--;         // 两次列电平不同返回状态0,(消抖处理)
      break;

    case 2:         // 等待按键释放状态
      PORTD = 0x03;                         // 行线全部输出低电平0b00000011
      PORTD = 0x03;                         // 重复送一次
      if ( (Key_mask & PIND) == Key_mask)
        key_state=0;         // 列线全部为高电平返回状态0
      break;
  }
  return key_return;
}

贴上的代码应该整理,让别人容易阅读

代码没有发现问题,可能还是在硬件上。

1.4个电阻可以不要(这个不是原因)
2.读不到的四个键都在一条线上,主要检查这条线:是否连接上了,PD0口是否接通此线;PD0口是否可以读入数据(将PD0接地,如果能读出K1_1,说明PD0口好的,问题在外面的接线上,如果读不到K1_1,可能PD0口坏了,或代码问题,只是代码部分目前没有发现问题)

出0入0汤圆

 楼主| 发表于 2011-11-18 09:36:14 | 显示全部楼层
回复【5楼】machao
-----------------------------------------------------------------------

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

本版积分规则

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

GMT+8, 2024-3-29 08:10

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

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