Chinaunix首页 | 论坛 | 博客
  • 博客访问: 470768
  • 博文数量: 164
  • 博客积分: 4024
  • 博客等级: 上校
  • 技术积分: 1580
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-10 16:27
文章分类

全部博文(164)

文章存档

2011年(1)

2010年(108)

2009年(55)

我的朋友

分类: 嵌入式

2009-11-02 21:42:06

哈哈,我的板子可以弹琴了,好高兴好高兴。。。下一步我就让它显示音符给我看哦
 
#include "msp430x44x.h"
#include "string.h"
//定义键值
//*****************************
#define   cKB_1    0x12   //1
#define   cKB_2    0x13   //2
#define   cKB_3    0x14   //3
#define   cKB_4    0x15   //4
#define   cKB_5    0x16   //5
#define   cKB_6    0x17   //6
#define   cKB_7    0x18   //7
#define   cKB_8    0x21   //8
#define   cKB_9    0x22   //9

//延时函数,这个随便写个循环就成,DelayTime即为延时的时间
void Delay(unsigned int DelayTime)        
{
  unsigned int i;
  for (i = 0;i < DelayTime;i++);
}
//根据cScanVal的值获取按键的列号,cScanVal为ScanKeyboard()后获得的值
char LocateKeyRow(unsigned int cScanVal)
{
  char RowCode;
 
  switch (cScanVal)    //键盘为5*8哦
  {
    case 0x7F:                     //0111 1111第一个为低,说明此行第一列的键被按下,以下雷同
    {
      RowCode = 0x01;              //row1
      break;
    }
    case 0xBF:                     //1011 1111
    {
      RowCode = 0x02;             //row2
      break;
    } 
    case 0xDF:
    {
      RowCode = 0x03;            //row3
      break;
    }
    case 0xEF:
    {
      RowCode = 0x04;           //row4
      break;
    }    
    case 0xF7:
    {
      RowCode = 0x05;          //row5
      break;
    }
    case 0xFB:
    {
      RowCode = 0x06;         //row6
      break;
    } 
    case 0xFD:
    {
      RowCode = 0x07;        //row7
      break;
    }
    case 0xFE:
    {
      RowCode = 0x08;        //row8
      break;
    }
    case 0xFF:               //没有键按下
    {
      RowCode = 0;
      break;
    }
    default:                //多健同时按下
    {
      RowCode = 0xFF; 
      break;
    }
  }
  
  return RowCode;     //返回列号
}
 
//扫描行 ,因为键盘为5*8,所以扫描5行,pLineArray存储扫描到的行信息
void ScanKeyboard(char *pLineArray)
{
 
  //设置扫描键盘所需的硬件端口状态
  P5DIR = 0;                                    //P5端口设置为输入状态
  P3DIR |= 0xe0;                                //设置P3.5、P3.6、P3.7设置为输出状态
  P2DIR |= 0x02;                                //P2.1为键盘所用的245的Enable端(由于P2.1仅用于此目的,所以不需要考虑恢复状态)
 
  P2OUT &= ~0x02; //使能总线驱动245
 
  P3OUT = 0x60;                //向HC138输出011使之在Y3上输出低电平
  *pLineArray++ = P5IN;
  P3OUT = 0x80;                //向HC138输出100使之在Y4上输出低电平
  *pLineArray++ = P5IN;
  P3OUT = 0xa0;                //向HC138输出101使之在Y5上输出低电平
  *pLineArray++ = P5IN;
  P3OUT = 0xc0;                //向HC138输出110使之在Y6上输出低电平
  *pLineArray++ = P5IN;
  P3OUT = 0xe0;               //向HC138输出111使之在Y7上输出低电平
  *pLineArray++ = P5IN;
 
  P2OUT |= 0x02;   //关闭245 key  总线驱动
 
}

//根据ScanKeyboard和LocateKeyRow获得的行列值,组合成 cFirstKey;高四位为行值,低四位为列值;并返回
char ReadKeyboard()
{
  char cTemp,cFirstKey;
  char cLineStatus[5];    //记录五行值 
 
  cFirstKey = 0;
 
  while(1)
  {
    memset(cLineStatus,0,5);
    ScanKeyboard(cLineStatus);//扫描后,cLineStatus中记录了每一行的按键信息
   
    cLineStatus[0] = LocateKeyRow(cLineStatus[0]);//扫描每一行,看所在行是否有键按下,并获得列值
    cLineStatus[1] = LocateKeyRow(cLineStatus[1]);//同上
    cLineStatus[2] = LocateKeyRow(cLineStatus[2]);
    cLineStatus[3] = LocateKeyRow(cLineStatus[3]);
    cLineStatus[4] = LocateKeyRow(cLineStatus[4]); 
  
   
    for (cTemp = 0;cTemp < 5;cTemp++)//因为是5行,所以...
    {
      //从LocateKeyRow中可知只有一行中有多个键被同时按下才会返回0xff
      if (cLineStatus[cTemp] == 0xff)
        continue;
       
      if (cLineStatus[cTemp] != 0)
      {
        if (cFirstKey == 0)
        cFirstKey = ((cTemp + 1) << 4) | cLineStatus[cTemp];
       }
    }
              
    return cFirstKey;
   }
}   
   
   
 
 
//根据行列获得自定义键值
char SwitchKeyValue(void)
{
  char NewKey, RetKeyVal;
  NewKey = ReadKeyboard();  //  得到行列值,高四位为行值,低四位为列值
 
  switch(NewKey)
  {
  
    case 0x47:
             {
                RetKeyVal = cKB_1;         //1
                break;
             }
    case 0x42:
             {
                RetKeyVal = cKB_2;         //2
                break;
             }
    case 0x46:
             {
                RetKeyVal = cKB_3;         //3
                break;
             }
    case 0x37:
             {
                RetKeyVal = cKB_4;         //4 
                break;
             }
    case 0x32:
             {
                RetKeyVal = cKB_5;         //5
                break;
             }
    case 0x36:
             {
                RetKeyVal = cKB_6;         //6
                break;
             }
    case 0x27:
             {
                RetKeyVal = cKB_7;         //7
                break;
             }
    case 0x22:
             {
                RetKeyVal = cKB_8;         //8
                break;
             }
    case 0x26:
             {
                RetKeyVal = cKB_9;         //9
                break;
             }
  
 
    default:  RetKeyVal = 0xFF; break;
  }
  return RetKeyVal;
}
 
 

void main(void)
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  P3DIR |= 0xE0;          // p3.5 p3.6 p3.7   3-8 DECODER
  P3OUT |= 0xE0;
 
  P2DIR |= 0x0E;          //关总线驱动器
  P2OUT |= 0x0E;
 
  P1DIR |= BIT1;  //设置p1.2为输出,接蜂鸣器
  TACCTL0 |= CCIE;//使能比较中断
  TACTL|=TASSEL0+MC_1;//选择时钟源ACLK(32768HZ)
  _EINT();
 
  while(1)
  {
  switch(SwitchKeyValue())
  { 
  case cKB_1: P1DIR|=BIT1;TACCR0=31;break; //dao
  case cKB_2: P1DIR|=BIT1;TACCR0=28;break; //re
  case cKB_3: P1DIR|=BIT1;TACCR0=25;break; //mi
  case cKB_4: P1DIR|=BIT1;TACCR0=23;break; //fa
  case cKB_5: P1DIR|=BIT1;TACCR0=21;break; //sao
  case cKB_6: P1DIR|=BIT1;TACCR0=19;break; //la
  case cKB_7: P1DIR|=BIT1;TACCR0=17;break; //xi
  case cKB_8: P1DIR|=BIT1;TACCR0=16;break; //gao dao
  default:  P1DIR &= ~BIT1; break;
  }
  }
}
 
//定时器A中断服务程序
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
  P1OUT^=BIT1;//取反,产生方波反
}
阅读(837) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~