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

全部博文(164)

文章存档

2011年(1)

2010年(108)

2009年(55)

我的朋友

分类: 嵌入式

2009-11-06 22:55:07

#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

 char  table[]={
 0x00,0xf8,0x48,0x48,0x48,0x48,0xff,0x48,
 0x48,0x48,0x48,0xfc,0x08,0x00,0x00,0x00,
 0x00,0x07,0x02,0x02,0x02,0x02,0x3f,0x42,
 0x42,0x42,0x42,0x47,0x40,0x70,0x00,0x00};
char  table1[]={
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 0x42,0x42,0x42,0x47,0x40,0x70,0x00,0x00,
 0x00,0xf8,0x48,0x48,0x48,0x48,0xff,0x48,
 0x48,0x48,0x48,0xfc,0x08,0x00,0x00,0x00
};
static char page, col;
/////////////////////////////////////////////////////////////////////////////////////////
//本函数用于向LCD写一个字节数据
//    依赖性:无
//    前提条件:1。LCD有3片列驱动,由CS来选择,0≤ROW≤63时CS=1; 64≤Row≤127时CS=2; 128≤Row≤191时CS=3
//              2。LCD工作正常,能正确返回状态信息,否则程序会挂死
//    参数:CS为列驱动片选;DAT为待写入的数据
//    返回值:无
void WDAT (unsigned int cs,unsigned int dat)
{
   char chip,RState;
   switch(cs)
   {
     case 1:{
              chip = 0x00|(P6OUT & 0xfc);
              break;
            }
     case 2:{
              chip = 0x01|(P6OUT & 0xfc);
              break;
            }
     case 3:{
              chip = 0x02|(P6OUT & 0xfc);
              break;
            }
   }
   RState = 0xFF;
   P1OUT &= ~0x80;             //E=0
   P1OUT &= ~0x40;             //RS=0
   P6OUT = chip;
   P2OUT |= 0x01;              //R/W=1
   P2OUT &=~0x04;              //245 enable
   P1OUT &= ~0x04;             //DIR=0
   P5DIR &= ~0xFF;
   while((0x80 & RState)==0x80)
   {
     P1OUT |= 0x80;           //E=1
     RState = P5IN;
     P1OUT &= ~0x80;         //E=0
   }
   P1OUT |= 0x40;            //RS=1
   P2OUT &= ~0x01;           //R/W=0
   P1OUT |= 0x80;            //E=1
   P5OUT = dat;
   P5DIR |= 0xFF;
   P1OUT |= 0x04;           //DIR=1
   P1OUT &= ~0x80;          //E=0
   P6OUT |= 0x03;            //no CS
   P1OUT |= 0x80;           //E=1
  
}
/////////////////////////////////////////////////////////////////////////////////////////
//本函数用于向LCD写一个命令字
//    依赖性:无
//    前提条件:1。LCD有3片列驱动,由CS来选择,0≤ROW≤63时CS=1; 64≤Row≤127时CS=2; 128≤Row≤191时CS=3
//              2。LCD工作正常,能正确返回状态信息,否则程序会挂死
//    参数:CS为列驱动片选;COM为待写入的命令字
//    返回值:无
void WCOM(unsigned int CS,unsigned int COM)

   char RState;
   char chip;
   switch(CS)
   {
     case 1:{
              chip = 0x00|(P6OUT & 0xfc);//1111 1100 第一片
              break;
            }
     case 2:{
              chip = 0x01|(P6OUT & 0xfc);//1111 1110 第三片
              break;
            }
     case 3:{
              chip = 0x02|(P6OUT & 0xfc);//1111 1101第二片
              break;
            }
   }
   RState = 0xFF;
   P1OUT &= ~0x80;             //E=0
   P1OUT &= ~0x40;          //RS=0
   P6OUT = chip;            //CS
   P2OUT |= 0x01;           //R/W=1  READ
   P2OUT &=~0x04;           //245 enable
   P1OUT &= ~0x04;          //DIR=0  B__A  INPUT
   P5DIR &= ~0xFF;
    
   while((0x80 & RState)==0x80)
   {
     P1OUT |= 0x80;         //E=1
     RState = P5IN;
     P1OUT &= ~0x80;      //E=0
   }
   P2OUT &= ~0x01;        //R/W=0  WRITE
   P1OUT |= 0x80;         //E=1
   P5OUT = COM;
   P5DIR |= 0xFF;
   P1OUT |= 0x04;        //DIR=1  A__B OUTPUT
   P1OUT &= ~0x80;       //E=0
   P6OUT |= 0x03;        // no CS
   P1OUT |= 0x80;        //E=1
  
  
}
 

//延时函数,这个随便写个循环就成,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 Display(char *word)
{
  WCOM(1,page);
  WCOM(1,col);
 
  for(int i=0;i<32;i++)
  {
     WDAT(1,table[i]); 
     if(i==15)
    {
     page++;
      WCOM(1,page);
      WCOM(1,col);    
    }
  
   
  }
 page--;
 col=col+16;
 if((col-0x40)%64==0) {col = 0x40; page=page+2;}
 
}
void InitLCD ()
{
   P5OUT |= 0xFF;
   P5DIR |= 0xFF;                //DB0_DB7   P5为LCD的输入端
  
   P1OUT |= 0x04;
   P1DIR |= 0x04;               //P1.2__245DIR=1   A__B  OUTPUT
  
   P1OUT &= ~0x40;
   P1DIR |= 0x40;               //P1.6__RS=0  instruction code
 
   P1OUT |= 0x80;
   P1DIR |= 0x80;               //P1.7__E=1   unable
 
   P2OUT &= ~0x01;
   P2DIR |= 0x01;               //P2.0__R/W=0  write
  
   P2OUT &= ~0x04;                
   P2DIR |= 0x04;               //P2.2__245 OE=0  enable
  
   P6OUT &= ~0x00;
   P6DIR |= 0x03;               //作为片选,11为没有CS,disable any block of LCD
  
   WCOM(1,0xC0);               //0xC0 设置列起始位置
   WCOM(2,0xC0);
   WCOM(3,0xC0);
  
   WCOM(1,0x3F);              //设置起始页  参见上一篇说明书哦 
   WCOM(2,0x3F);
   WCOM(3,0x3F);
  
 
  P2OUT |= 0x0E;                 //display 245 unable
}

void ClearScreen(void)
{
 page=0xb8;
 col=0x40; 
 for(int i=0;i<8;i++)
 {
   for(int j=0;j<192;j++)
   {    
     if(j<64)
     {
       if(j==0)
       {
         WCOM(1,page);
         WCOM(1,col);
       }
     WDAT(1,0x00);
     }
    else if(j<128)
    {
      if(j==64)
      {
        WCOM(3,page);
         WCOM(3,col);
      }
     WDAT(3,0x00);
    }
   else
    {
      if(j==128)
      {
        WCOM(2,page);
        WCOM(2,col);
      }
     WDAT(2,0x00);
    }
  }
  page++;
  col=0x40;
 }
}
void main(void)
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
 
  P2OUT |= 0x0E;                  //P2.1 245key  ;P2.2 245DIS; P2.3 245PRN
  P2DIR |= 0x0E;                  // three 245 unable
 
  //本函数用于初始化LCD
  InitLCD();
  P3DIR |= 0xE0;          // p3.5 p3.6 p3.7   3-8 DECODER
  P3OUT |= 0xE0;
 
 
 
  P1DIR |= BIT1;  //设置p1.2为输出,接蜂鸣器
  TACCTL0 |= CCIE;//使能比较中断
  TACTL|=TASSEL0+MC_1;//选择时钟源ACLK(32768HZ)
  _EINT();
 
  ClearScreen();
  page = 0xb8;
  col = 0x40;
 
  while(1)
  {
  switch(SwitchKeyValue())
  { 
  case cKB_1: P1DIR|=BIT1;TACCR0=31;Display(table);Delay(30000);break; //dao
  case cKB_2: P1DIR|=BIT1;TACCR0=28;Display(table);Delay(30000);break; //re
  case cKB_3: P1DIR|=BIT1;TACCR0=25;Display(table);Delay(30000);break; //mi
  case cKB_4: P1DIR|=BIT1;TACCR0=23;Display(table);Delay(30000);break; //fa
  case cKB_5: P1DIR|=BIT1;TACCR0=21;Display(table);Delay(30000);break; //sao
  case cKB_6: P1DIR|=BIT1;TACCR0=19;Display(table);Delay(30000);break; //la
  case cKB_7: P1DIR|=BIT1;TACCR0=17;Display(table);Delay(30000);break; //xi
  case cKB_8: P1DIR|=BIT1;TACCR0=16;Display(table);Delay(30000);break; //gao dao
  default:  P1DIR &= ~BIT1; break;
  }
  }
}
 
//定时器A中断服务程序
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A(void)
{
  P1OUT^=BIT1;//取反,产生方波反
}
阅读(1044) | 评论(0) | 转发(0) |
0

上一篇:终于可以显示了

下一篇:MSP430 指令集

给主人留下些什么吧!~~