打印

cortex M0扫描按键 大侠拍砖

[复制链接]
8940|56
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sunshitao|  楼主 | 2011-8-13 09:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
今年大二 开学大三  玩M0有一年了 暑假无事 小弟M0写的按键扫描的 请匠人、菜农各位大侠拍砖,M0搞了一个调度器,暑假不出去游玩的话 ,应该可以完成,到时上传源码,请高手指点:D

main.c

#include "LPC11xx.h"                                                   /* LPC11xx 外设寄存器定义        */
#include "gpio.h"
#include "uart.h"
#include "key.h"
#include "systick.h"
uint8_t  TMR20MS;
uint8_t  TMR40MS;
uint32_t key =0 ;
void TimeEvent(void);
void DelayMS(uint32_t dly)
{
  uint32_t i;
  while (dly-- > 0) {
     for(i = SystemFrequency / 1000; i > 0; i--);                       /* 延时1ms                      */
  }
}
int main (void)
{
uint8_t datatest[] = "sunshitao" ;
  
SystemInit();                                                     /* 系统初始化                   */
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6);                     
KeyPin_init();
UARTInit(115200);  
SysTick_Config( 200000 );  //系统定时时间4mS
UARTSend(datatest, 10);
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 16);
KeyQueue.out = 0;
KeyQueue.in  = 0;
while (1) {     
  TimeEvent();
}
}
void TimeEvent(void)
{
uint8_t KeyValue;
if(TMRInt4ms标志寄存器){
  TMRInt4ms标志寄存器 = 0;
  if(++TMR20MS > 5){
    TMR20MS = 0;
    KeyFSM();
  }
  if(++TMR40MS > 10){
   TMR40MS = 0;
   KeyValue = KeyRead();
   if(KeyValue != 0xff){
    UARTSend(&KeyValue,1);
   }
  }
}
}
/********************************************************************************************************
**  End Of File
********************************************************************************************************/
key.h


#ifndef KEY_H_
#define KEY_H_

#define P0KEYMASKEDIN          0x8FE
#define P2KEYMASKEDOUT     0xFF



#define X0           ( 0xFE )
#define X1          ( 0xFD )
#define X2          ( 0xFB )
#define X3          ( 0xF7 )
#define X4          ( 0xEF )
#define X5    ( 0xDF )
#define X6    ( 0xBF )
#define X7    ( 0x7F )

#define Y0          (0x8FC)
#define Y1          (0x8FA)
#define Y2          (0x8F6)
#define Y3          (0x8EE)
#define Y4          (0x8DE)
#define Y5           (0x8BE)
#define Y6    (0x87E)
#define Y7    (0x0FE)

#define UNVALID 0xFF



#define PULL_DOWNBIT    ( 1 << 3 )
#define KeyQLEN 8
typedef struct         {
                                        uint8_t KeyBuffer[KeyQLEN];
                                        uint8_t out;
                                        uint8_t in;                               
                                } KeyQ;
extern KeyQ KeyQueue;


extern void KeyPin_init(void);
extern uint32_t  Key_scan(void);

extern uint8_t KeyFSM(void );
extern uint8_t KeyRead(void);
#endif
key.c


#include "LPC11xx.h"
#include "uart.h"
#include "gpio.h"
#include "key.h"


#define LED1          (1 << 0)
#define LED1INIT()   LPC_IOCON->PIO3_0 &= ~0x07;LPC_GPIO3->DIR |= LED1
#define LED1OFF()    LPC_GPIO3->MASKED_ACCESS[LED1] = LED1
#define LED1ON()     LPC_GPIO3->MASKED_ACCESS[LED1] = 0

enum KeyFSM_Enum //按键状态有限状态机
{
    _Key_Idle=0,   
    _Key1_down,   
    _Key1_press,   
    _Key1_up,   
    _Key_confirm,   
};

KeyQ KeyQueue;
void KeyPin_init(void)
{
    //PIO0_1--PIO0_7保留chip默认设置;PIO0_11设置为IO口
    //PIO2_0--PIO22_7保留chip默认设置
        LPC_IOCON->PIO0_1 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_2 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_3 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_4 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_5 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_6 |= PULL_DOWNBIT;
        LPC_IOCON->PIO0_7 |= PULL_DOWNBIT;
        LPC_IOCON->R_PIO0_11 |= 0x01;//PIO0_11默认不是IO口,配置为IO口
        LPC_IOCON->R_PIO0_11 |= PULL_DOWNBIT;

        LPC_GPIO0->DIR &= 0x0701 ;         //PIO0_1--PIO0_7、PIO0_11设置为输入       
        LPC_GPIO2->DIR |=  0xFF;         //PIO2_0--PIO2_7 设置为输出
        LPC_GPIO2->MASKED_ACCESS[0xFF] = 0xFF;
       
        LED1INIT();
}
uint32_t  Key_scan(void)
{       
        uint32_t Key_coordinate;
        uint32_t Y_coordinate = 0x0;
                         Key_coordinate = UNVALID ;
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X0;        //p2.0输出低电平 扫描X0
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN ) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x00;
                                break;
                        case Y1        :  Key_coordinate = 0x01;
                                break;
                        case Y2        :  Key_coordinate = 0x02;
                                break;
                        case Y3        :  Key_coordinate = 0x03;
                                break;
                        case Y4 :  Key_coordinate = 0x04;
                                break;
                        case Y5 :  Key_coordinate = 0x05;
                                break;
                        case Y6 :  Key_coordinate = 0x06;
                                break;
                        case Y7 :  Key_coordinate = 0x07;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);          
        }

       
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X1 ;    //p2.1输出低电平         扫描X1
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN) != P0KEYMASKEDIN  ){       
                        switch ( Y_coordinate ) {                 
                        case Y0 :  Key_coordinate = 0x10;
                                break;
                        case Y1        :  Key_coordinate = 0x11;
                                break;
                        case Y2        :  Key_coordinate = 0x12;
                                break;
                        case Y3        :  Key_coordinate = 0x13;
                                break;
                        case Y4 :  Key_coordinate = 0x14;
                                break;
                        case Y5 :  Key_coordinate = 0x15;
                                break;
                        case Y6 :  Key_coordinate = 0x16;
                                break;
                        case Y7 :  Key_coordinate = 0x17;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }

        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X2 ;        //p2.2输出低电平 扫描X2
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x20;
                                break;
                        case Y1        :  Key_coordinate = 0x21;
                                break;
                        case Y2        :  Key_coordinate = 0x22;
                                break;
                        case Y3        :  Key_coordinate = 0x23;
                                break;
                        case Y4 :  Key_coordinate = 0x24;
                                break;
                        case Y5 :  Key_coordinate = 0x25;
                                break;
                        case Y6 :  Key_coordinate = 0x26;
                                break;
                        case Y7 :  Key_coordinate = 0x27;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }

        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X3 ;     //p2.3输出低电平         扫描X3
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x30;
                                break;
                        case Y1        :  Key_coordinate = 0x31;
                                break;
                        case Y2        :  Key_coordinate = 0x32;
                                break;
                        case Y3        :  Key_coordinate = 0x33;
                                break;
                        case Y4 :  Key_coordinate = 0x34;
                                break;
                        case Y5 :  Key_coordinate = 0x35;
                                break;
                        case Y6 :  Key_coordinate = 0x36;
                                break;
                        case Y7 :  Key_coordinate = 0x37;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X4 ;    //p2.4输出低电平 扫描X4
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN ) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x40;
                                break;
                        case Y1        :  Key_coordinate = 0x41;
                                break;
                        case Y2        :  Key_coordinate = 0x42;
                                break;
                        case Y3        :  Key_coordinate = 0x43;
                                break;
                        case Y4 :  Key_coordinate = 0x44;
                                break;
                        case Y5 :  Key_coordinate = 0x45;
                                break;
                        case Y6 :  Key_coordinate = 0x46;
                                break;
                        case Y7 :  Key_coordinate = 0x47;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X5 ;    //p2.4输出低电平 扫描X4
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN ) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x50;
                                break;
                        case Y1        :  Key_coordinate = 0x51;
                                break;
                        case Y2        :  Key_coordinate = 0x52;
                                break;
                        case Y3        :  Key_coordinate = 0x53;
                                break;
                        case Y4 :  Key_coordinate = 0x54;
                                break;
                        case Y5 :  Key_coordinate = 0x55;  
                                break;
                        case Y6 :  Key_coordinate = 0x56;  
                                break;
                        case Y7 :  Key_coordinate = 0x57;  
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X6 ;    //p2.4输出低电平 扫描X4
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN ) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x60;
                                break;
                        case Y1        :  Key_coordinate = 0x61;
                                break;
                        case Y2        :  Key_coordinate = 0x62;
                                break;
                        case Y3        :  Key_coordinate = 0x63;
                                break;
                        case Y4 :  Key_coordinate = 0x64;
                                break;
                        case Y5 :  Key_coordinate = 0x65;  
                                break;
                        case Y6 :  Key_coordinate = 0x66;
                                break;
                        case Y7 :  Key_coordinate = 0x67;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }
        LPC_GPIO2->MASKED_ACCESS[P2KEYMASKEDOUT] = X7 ;    //p2.4输出低电平 扫描X4
        Y_coordinate = LPC_GPIO0->MASKED_ACCESS[P0KEYMASKEDIN];
        if( (Y_coordinate & P0KEYMASKEDIN ) != P0KEYMASKEDIN  ){
                switch ( Y_coordinate ) {
                        case Y0 :  Key_coordinate = 0x70;
                                break;
                        case Y1        :  Key_coordinate = 0x71;
                                break;
                        case Y2        :  Key_coordinate = 0x72;
                                break;
                        case Y3        :  Key_coordinate = 0x73;
                                break;
                        case Y4 :  Key_coordinate = 0x74;
                                break;
                        case Y5 :  Key_coordinate = 0x75;
                                break;
                        case Y6 :  Key_coordinate = 0x76;
                                break;
                        case Y7 :  Key_coordinate = 0x77;
                                break;
                          default :          ;
                                   break;
                }
                return (Key_coordinate);
        }
        return ( Key_coordinate );
}
uint8_t  KeyFSM(void)
{       
        static uint32_t KeyTemp = UNVALID;
                   uint32_t NewKey = UNVALID;
        static uint8_t  KeyState = 0;
        NewKey = Key_scan();       
        if((NewKey == UNVALID)&&(KeyState != _Key1_press)&&(KeyState != _Key1_up)){
                return 0;
        }
        switch(KeyState) {//状态机
        case _Key_Idle:{//空闲
            KeyTemp = NewKey;//保存键值
            KeyState = _Key1_down;//单键按下消抖
            break;
        }
        case _Key1_down:{//单键按下消抖
                        if(NewKey == KeyTemp){//键值不变
                                KeyState = _Key1_press;
                        } else {//单键按下
                                KeyState = _Key_Idle;//空闲
                        }
            break;
        }
        case _Key1_press:{//单键按下
            if(NewKey != KeyTemp)//键值改变
                KeyState = _Key1_up;//单键抬起消抖
            break;
        }
        case _Key1_up:{//单键抬起消抖
            if(NewKey == KeyTemp){//键值不变
                KeyState = _Key1_press;//单键按下
                        } else {
                KeyState = _Key_confirm;//按键确认成功
                        }
            break;      
        }  
                default:{
            KeyState = _Key_Idle;//空闲
            break;
        }
    }
        if(KeyState == _Key_confirm){//按键确认成功
                KeyState = _Key_Idle;//空闲
                //放入键值缓冲区中
                if(KeyTemp != UNVALID){//如果键值有效,则放入缓冲区中
                    KeyQueue.KeyBuffer[KeyQueue.in++] = KeyTemp;
                    if(KeyQueue.in >= KeyQLEN){//如果"写"跑到了队列尾部,则重新跳回原点
                        KeyQueue.in=0;
                    }
                        return 1;
                }
                return 0;
        }
        return 0;               
}
uint8_t KeyRead(void)
{
    uint8_t Value;                                 
    if(KeyQueue.out != KeyQueue.in){
        Value=KeyQueue.KeyBuffer[KeyQueue.out ;
        if(KeyQueue.out >= KeyQLEN) {
            KeyQueue.out=0;
        }
    } else {
        Value=UNVALID  
  }
    return(Value);
}

systick.h
#ifndef SYSTICK_H_
#define SYSTICK_H_

extern volatile uint32_t TimeTick;
extern volatile uint32_t TMRInt4ms标志寄存器 ;
#endif

systick.c
#include "LPC11xx.h"
#include "systick.h"
#include "uart.h"
volatile uint32_t TimeTick = 0;
volatile uint32_t TMRInt4ms标志寄存器 = 0;
void SysTick_Handler(void)
{
    TimeTick++;
        TMRInt4ms标志寄存器 = 1;
}

相关帖子

沙发
sunshitao|  楼主 | 2011-8-13 09:54 | 只看该作者
自己先顶一下 欢迎高手指点 共同进步

使用特权

评论回复
板凳
yuyi21ic| | 2011-8-13 11:49 | 只看该作者
太罗嗦了

使用特权

评论回复
地板
刘前辈| | 2011-8-13 12:14 | 只看该作者
敬佩!谁能把一个程序缩短一半,就是创新。
最后缩短到一条也不能减了,就叫软件了。可以给人看了。

使用特权

评论回复
5
sunshitao|  楼主 | 2011-8-13 13:43 | 只看该作者
3# yuyi21ic
呃。。。该怎么改?8x8 64按键 感觉扫描时也只能这样了 该怎么改?指点一下子?

使用特权

评论回复
6
sunshitao|  楼主 | 2011-8-13 13:45 | 只看该作者
4# 刘前辈
给指点一下?不是很明白你的话的意思?

使用特权

评论回复
7
Cortex-M0| | 2011-8-13 13:50 | 只看该作者
4# 刘前辈  
给指点一下?不是很明白你的话的意思?
sunshitao 发表于 2011-8-13 13:45



刘前辈的意思------这叫垃圾。
谁能把一个程序缩短一半,就是创新。----- 免强能看
最后缩短到一条也不能减了,就叫软件了。可以给人看了。

使用特权

评论回复
8
Cortex-M0| | 2011-8-13 13:54 | 只看该作者
不过,俺挺佩服LZ的,一个大二学生,能写出如此长篇程序,俺预计,下一个OO就是您!

请别告诉俺,您不知道OO是谁?

使用特权

评论回复
9
sunshitao|  楼主 | 2011-8-13 13:57 | 只看该作者
4# 刘前辈
请高手指点一二吧 。。。。。

使用特权

评论回复
10
sunshitao|  楼主 | 2011-8-13 13:59 | 只看该作者
7# Cortex-M0
兄弟是?? 这程序确实繁琐。。。 有时间再改改。。我想不用按键芯片。。扫描也没什么好的办法。。

使用特权

评论回复
11
sunshitao|  楼主 | 2011-8-13 14:00 | 只看该作者
8# Cortex-M0
OO听过。。写了本书玩转USB吧。。

使用特权

评论回复
12
刘前辈| | 2011-8-13 14:27 | 只看该作者
本帖最后由 刘前辈 于 2011-8-13 14:30 编辑

看看别人怎么写的,才知道自己差在哪。C标准程序可以说都是用箩筐装的,根本不用自己写,需要的时候知道在哪个箩筐里找到拿来用就行了。——这就是C模块的意义,写出来不仅是给自己用,还要别人能看的懂,能重复采用,减少重复劳动。
    也许我一生都想不出、写不出这么精彩的键盘扫描程序。但是我只要看的懂别人的精彩,能利用别人的精彩模块为自己节省时间,随时知道需要的时候在什么地方找到这样的精彩模块,就是了不起的事。有时间做点创新的事,别人没做过的事。

/*  Key arrangement is:   ---------
                          1  2  3
                          4  5  6
                          7  8  9
                          *  0  #
                         ---------

   Supports two function keys ('*' and '#').
*/
/*------------------------------------------------------------------*-

  KEYPAD_Scan()

  This function is called from scheduled keypad function.

  Must be edited as required to match your key labels.

  Includes two 'function keys' which may be used simultaneously
  with keys from any other column.  

  Adapt as required!

-*------------------------------------------------------------------*/
bit KEYPAD_Scan(char* const pKey, char* const pFuncKey)
   {
   static data char Old_Key;

   char Key = KEYPAD_NO_NEW_DATA;
   char Fn_key = (char) 0x00;

   C1 = 0; // Scanning column 1
      if (R1 == 0) Key = '1';
      if (R2 == 0) Key = '4';
      if (R3 == 0) Key = '7';
      if (R4 == 0) Fn_key = '*';
   C1 = 1;

   C2 = 0; // Scanning column 2
      if (R1 == 0) Key = '2';
      if (R2 == 0) Key = '5';
      if (R3 == 0) Key = '8';
      if (R4 == 0) Key = '0';
   C2 = 1;

   C3 = 0; // Scanning column 3
      if (R1 == 0) Key = '3';
      if (R2 == 0) Key = '6';
      if (R3 == 0) Key = '9';
      if (R4 == 0) Fn_key = '#';
   C3 = 1;

   if (Key == KEYPAD_NO_NEW_DATA)
      {
      // No key pressed (or just a function key)
      Old_Key = KEYPAD_NO_NEW_DATA;
      Last_valid_key_G = KEYPAD_NO_NEW_DATA;

      return 0;  // No new data
      }
   
   // A key has been pressed: debounce by checking twice
   if (Key == Old_Key)
      {
      // A valid (debounced) key press has been detected
      
      // Must be a new key to be valid - no 'auto repeat'
      if (Key != Last_valid_key_G)
         {
         // New key!
         *pKey = Key;
         Last_valid_key_G = Key;

         // Is the function key pressed too?
         if (Fn_key)
            {
            // Function key *is* pressed with another key
            *pFuncKey = Fn_key;
            }
         else
            {
            *pFuncKey = (char) 0x00;
            }

         return 1;
         }
      }

   // No new data
   Old_Key = Key;
   return 0;
   }

/*------------------------------------------------------------------*-
  ---- END OF FILE -------------------------------------------------
-*------------------------------------------------------------------*/

使用特权

评论回复
13
刘前辈| | 2011-8-13 14:32 | 只看该作者
#define KEYPAD_PORT   P1

sbit C1 = KEYPAD_PORT^0;
sbit C2 = KEYPAD_PORT^1;
sbit C3 = KEYPAD_PORT^2;

sbit R1 = KEYPAD_PORT^6;
sbit R2 = KEYPAD_PORT^5;
sbit R3 = KEYPAD_PORT^4;
sbit R4 = KEYPAD_PORT^3;

使用特权

评论回复
14
sunshitao|  楼主 | 2011-8-13 15:09 | 只看该作者
12# 刘前辈
首先 谢谢前辈指点,受教了。。。这个程序的宏定义的名字非常清晰,让人一目了然,有效的区分了程序的硬件,驱动层。。应用层。。按键的抬起判断也很精妙 。。。程序收录了  再次表示受教了,,这次写完程序慌张上传   代码没有规范:D

使用特权

评论回复
15
sunshitao|  楼主 | 2011-8-13 15:13 | 只看该作者
13# 刘前辈
顺便说一下  也许你不会一辈子都写不出来这样的程序:D

使用特权

评论回复
16
Cortex-M0| | 2011-8-13 15:14 | 只看该作者
恭喜LZ,  能得到刘前辈的指点,技术又上层楼~~~

继续努力,下一个OO,  就是您~~~

使用特权

评论回复
17
sunshitao|  楼主 | 2011-8-13 15:15 | 只看该作者
16# Cortex-M0
赶上OO是不太可能了。。呵呵。。。。。

使用特权

评论回复
18
Cortex-M0| | 2011-8-13 15:31 | 只看该作者
OO是二姨家的一面旗子,你的奋斗目标!

刚毕业就混个副总工玩玩,再过几年,升为总工不是梦。

他的老板发话,什么时候OO不想玩技术了,想单干,他老板投资几千万,让他随便玩。

做人做到这个份,应该是您追求奋斗的目标吧~~~

使用特权

评论回复
19
baiyunfei.k.f| | 2011-8-13 15:33 | 只看该作者
学习了

使用特权

评论回复
20
sunshitao|  楼主 | 2011-8-13 15:39 | 只看该作者
18# Cortex-M0
呃。。。确实牛X(我说的是技术)。。。我吃饱 穿暖。。有的住。。就行了,,可惜GCD不给老百姓住的地方。。。我毕业估计也做不了技术。。。毕业就从军了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

111

帖子

1

粉丝