哈哈,我的板子可以弹琴了,好高兴好高兴。。。下一步我就让它显示音符给我看哦
#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;//取反,产生方波反
}
阅读(876) | 评论(0) | 转发(0) |