打印

第一次写键盘扫描程序,欢迎拍砖!

[复制链接]
3330|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jlgcumt|  楼主 | 2011-12-19 20:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
jlgcumt|  楼主 | 2011-12-19 20:27 | 只看该作者
用中断来执行的,放到定时器中断里就行了,定时器中断1ms!
头文件
#define LEDON(x)  P4 &= ~(0x01<<x)
#define LEDOFF P4 = 0xff

中断程序
void ISR_Timer0() interrupt 1
{
//    TF0 = 0;        //自动清零
          TH0 = T0LoadData.tstLD.TH0Data;                          // 重新装载值
          TL0 = T0LoadData.tstLD.TL0Data;
          KEYScan();
          LEDDisplay();
          
}

使用特权

评论回复
板凳
jlgcumt|  楼主 | 2011-12-19 20:28 | 只看该作者
再发一个写的SPI的程序,用的片子是C8051F120,读写W25X80;

使用特权

评论回复
地板
jlgcumt|  楼主 | 2011-12-19 20:29 | 只看该作者
#include <c8051f120.h>
#include <stdio.h>
#include <stdlib.h>
#include "SPI.h"
#include "Global.h"


extern void Delay();

#define WEnable         0x06
#define WDisable 0x04
#define RStReg   0x05
#define WStReg   0x01
#define RData    0x03
#define FRData   0x0b
#define FRDouOut 0x3b
#define PagePro  0x02
#define BlockErase  0xd8
#define SectorErase 0x20
#define ChipErase   0xc7
#define PWRDown     0xb9
#define DevID       0xab
#define MFID        0x90
#define JEDECID     0x9f

sbit FramCS = P0^7;

typedef struct
{
  unsigned char RBytes;                        // 读字节数
  unsigned char WBytes;                        // 写字节数
  unsigned char WRFlag;          // 0为写 1 为 读
  unsigned char *pWBuf;          // 指向读写的缓冲区,用于写操作或者在读操作中写命令,字节地址等操作
  unsigned char *pRbuf;   // 指向读出数据缓冲区
  unsigned char ST;       // 总线状态 0 为空闲,1为忙
  unsigned char FirstR;          // 用于第1字节的假写
  unsigned char FaultST;  //  0  WCOL  1
}TST_SPI0CB;

TST_SPI0CB tstSPI0CB = {0,0,0,0,0,0,0,0};

unsigned char SPIRData[5] ={0,0,0,0,0};

void SPI0Init()
{
        FramCS = 1;            // 片选初始化为高电平
        SFRPAGE = SPI0_PAGE;       
        SPI0CFG = 0x70;                  //主方式,空闲电平为高,第2边沿采样数据        
        SPI0CKR = (unsigned char)(SYSCLK/2/1000000L-1)        ; //时钟 1000K
        SPI0CN  = 0x01;        // 三线主或从方式 并使能SPI
//        SPIF = 0;       
        EIE1 =0x01;      // 使能SPI0中断
        EA = 1;
}

void SPI0Write(unsigned char *pWBuf,unsigned char WBytes)
{       
        SFRPAGE = SPI0_PAGE;
        while( tstSPI0CB.ST );  // 等待SPI空闲
//        Delay();       
        if(tstSPI0CB.ST == 0)     // 当前总线空闲
          {
            FramCS = 0 ;
                tstSPI0CB.FaultST = 0;
                tstSPI0CB.ST = 1 ;    // 当前设备忙
                tstSPI0CB.pWBuf = pWBuf;
             tstSPI0CB.WRFlag = 0;   // 当前为写
                tstSPI0CB.WBytes = WBytes - 1;
                tstSPI0CB.pRbuf = 0;
                tstSPI0CB.RBytes = 0;                                                     
            SPI0DAT = *tstSPI0CB.pWBuf;           // 发送第一个字节
                while( tstSPI0CB.ST );         //  等待写操作完毕!
          }
}  

void SPI0Read(unsigned char *pWBuf,unsigned char WBytes,unsigned char *pRBuf,unsigned char RBytes)
{
        SFRPAGE = SPI0_PAGE;
        while( tstSPI0CB.ST );              //   等待SPI空闲
//        Delay();       
        if(tstSPI0CB.ST == 0)               //  当前总线空闲
          {
            FramCS = 0 ;
                tstSPI0CB.FaultST = 0;
                tstSPI0CB.ST = 1 ;              //  当前设备忙
                tstSPI0CB.pWBuf = pWBuf;
             tstSPI0CB.WBytes = WBytes - 1;
            tstSPI0CB.WRFlag = 1;           //  当前为读
                tstSPI0CB.pRbuf = pRBuf;
                tstSPI0CB.RBytes = RBytes;
                tstSPI0CB.FirstR = 0;      
               
//                NOP ;         
            SPI0DAT = *tstSPI0CB.pWBuf;         // 启动发送
                while( tstSPI0CB.ST );          // 等待读操作完毕!
          }
}




void ISR_SPI (void) interrupt 6
{
   
   if(WCOL)
           {
                     WCOL = 0;
                  tstSPI0CB.FaultST = 1;
                     return ;
           }
         else if(MODF)
           {
                     MODF = 0;
                  tstSPI0CB.FaultST = 2;
                     return ;
           }   
   
   if(SPIF)
   {          
            SPIF = 0;
         if(tstSPI0CB.WRFlag == 0)           // 当前为写
           {
                    if(tstSPI0CB.WBytes > 0)
                      {
                             tstSPI0CB.WBytes-- ;
                          tstSPI0CB.pWBuf++;
                          SPI0DAT = *tstSPI0CB.pWBuf;
                   }
                 else if(tstSPI0CB.WBytes == 0)
                  {
                             FramCS = 1 ;                           //  CS变为高电平
                          tstSPI0CB.ST = 0;        //  设备为空闲
                          
        //                  return ;                           
                  }                           
           }
             else if(tstSPI0CB.WRFlag == 1)   //  当前为读
           {
                     if(tstSPI0CB.WBytes > 0)
                    {
                          tstSPI0CB.pWBuf++;
                          tstSPI0CB.WBytes--;
                          SPI0DAT = *tstSPI0CB.pWBuf;                          
                        }
                  else                //   命令或地址写完                    
                    {
                           if(tstSPI0CB.FirstR == 0)
                             {
                                    tstSPI0CB.FirstR = 1;
                                    SPI0DAT = 0xff;                            // 假写
                                    return ;
                                 }
                           else
                             {
                                   if(tstSPI0CB.RBytes > 0)
                                     {
                                       *tstSPI0CB.pRbuf = SPI0DAT;
                                       tstSPI0CB.pRbuf++;
                                       tstSPI0CB.RBytes--;
                                       SPI0DAT = 0xff;                          
                                     }
                               else
                                    {
                                      FramCS = 1 ;                           //  CS变为高电平
                                          tstSPI0CB.ST = 0;        //  设备为空闲
                                          tstSPI0CB.FirstR = 0;   
                                  
//                                          return ;                  
                                   }
                                 }              
                        }
           }   
   }

   
}

//************************************Fram******************************************************//


void  FramWEnable()
{
        unsigned char pbuf[1];       
        pbuf[0] =  WEnable ;
        SPI0Write(pbuf,1);
}

void FramWDisable()
{
        unsigned char pbuf[1];        
        pbuf[0] =  WDisable ;
        SPI0Write(pbuf,1);
}

unsigned char FramRSTReg()
{
        unsigned char pbuf[1];
        pbuf[0] = RStReg ;
        SPI0Read(pbuf,1,SPIRData,1);
//        while(tstSPI0CB.ST);
        return SPIRData[0];  
}

void FramWSTReg(unsigned char STData)
{
        unsigned char pbuf[2];
        pbuf[0] = WStReg ;
        pbuf[1] = STData ;
        SPI0Write(pbuf,2);       
}


unsigned char FramWriteBytes(unsigned char *pwbuf,unsigned char nBytes)
{
        unsigned char i;
        unsigned char *pbuf ;
        pbuf = (unsigned char *)malloc(4+nBytes);
       
        if(pbuf == NULL)
          return 0xff;
       
        *pbuf = PagePro;
        for(i=0;i<(nBytes+4);i++)
          {
            *(pbuf+i+1) = *(pwbuf+i);                
            }
        SPI0Write(pbuf,nBytes+4);
        free(pbuf);                        // 释放内存
        return 0x11 ;
}


unsigned char FramReadBytes(unsigned char *pRArr,unsigned char *prbuf,unsigned char nBytes)
{
        unsigned char i;
        unsigned char *pbuf ;

        pbuf = (unsigned char *)malloc(4);       
        if(pbuf == NULL)
          return 0xff;
       
        *pbuf = RData;
        for(i=0;i<3;i++)
          {
            *(pbuf+i+1) = *(pRArr+i);                
            }
        SPI0Read(pbuf,4,prbuf,nBytes);
        free(pbuf);
        return 0x11;

}

void FramSectorErase()
{
        unsigned char erase[4];
        erase[0] = SectorErase;
        erase[1] = 0x01;
        erase[2] = 0;
        erase[3] = 0x34;
        SPI0Write(erase,4);          
}



void FramBlockErase()
{


}


void FramChipErase()
{
    unsigned char pbuf[1];
        pbuf[0] = ChipErase ;       
        SPI0Write(pbuf,1);
}

void ReadDevID()
{
        unsigned char pbuf[4];
        pbuf[0] = DevID ;
        pbuf[1] = 0xff ;
        pbuf[2] = 0xff ;
        pbuf[3] = 0xff ;
        SPI0Read(pbuf,4,SPIRData,1);
}

使用特权

评论回复
5
jlgcumt|  楼主 | 2011-12-19 20:31 | 只看该作者
SPI程序3线操作,片选单独引脚控制,如果做产品的估计得用状态机来写,这个芯片感觉操作太慢了!

使用特权

评论回复
6
jlgcumt|  楼主 | 2011-12-19 20:34 | 只看该作者
重发一个,格式都乱了
#include <c8051f120.h>


#include "Led.h"



/*****************************************
s4(0)中,s4是电路板上的标号,0是人为定义按键对应的键值.

s1(0) |  s2(1) |  s3(2)|    s4(3)|
------/--------/--------/--------/-----key4
s5(4) | s6(5)  |  s7(6)|    s8(7)|
------/--------/--------/---------/----key5
s9(2) | s10(6) |  s11(8)|  s12(8)|
------/--------/--------/---------/----key6
       |        |        |                   |
key0---         |        |                   |
key1------------         |                   |
key2----------------------                   |
key3--------------------------------          
*******************************************/
//

void Deleteonedata();
void Addonedata(unsigned char datatmp);
void Cleardata();

unsigned char code LEDSEG1[]= {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0X89};//0~9,C,H,正
unsigned char code LEDSEG2[]= {0xC0,0xCF,0xA4,0x86,0x8B,0x92,0x90,0xC7,0x80,0x82,0xF0,0X89};//0~9,C,H,倒



struct _Disdata
{
        unsigned char disdata[4];
        unsigned char num;
        unsigned char HeadNO;
}Disdata;

struct _leddata
{
        unsigned char num;
        unsigned char dis[4];
}leddata;




struct _KEYSCANCB
{
        unsigned char RowKey[3][4];
        unsigned char Flag[3][4];

}KEYScanCB;


volatile unsigned char ii = 0;   //用来控制占空比


void LedGPIOInit()
{
        SFRPAGE = CONFIG_PAGE;
        P4MDOUT=0xFF;
    P5MDOUT=0xFF;
}

void KEYInit()
{
        unsigned char i;
        unsigned char j;
        for(i=0;i<3;i++)
          {
              for(j=0;j<4;j++)
                    {
                            KEYScanCB.RowKey[i][j] = 0;
                                KEYScanCB.Flag[i][j] = 0;
                        }                          
          }
}


void KEYScan()
{
        volatile unsigned char P2Tmp;
        unsigned char i;
        unsigned char endata;
        for(i=0;i<3;i++)
          {
                    P2 = ~(0x10<<i);
              P2Tmp = P2&0x0F;
                  if( P2Tmp==0x0F )
                    {
                           KEYScanCB.RowKey[i][0] = 0;        //清零延时计数器
                           KEYScanCB.RowKey[i][1] = 0;
                           KEYScanCB.RowKey[i][2] = 0;
                           KEYScanCB.RowKey[i][3] = 0;
                           KEYScanCB.Flag[i][0] = 0;        //清零入队标志
                           KEYScanCB.Flag[i][1] = 0;
                           KEYScanCB.Flag[i][2] = 0;
                           KEYScanCB.Flag[i][3] = 0;
                           continue ;                       
                        }
                  else
                   {
                      switch(P2Tmp)
                            {
                                    case 0x0E :  // 第一列有按键按下
                                          {
                                             KEYScanCB.RowKey[i][0]++;              // 消抖动 15ms                                                   
                                                 if(KEYScanCB.RowKey[i][0] > 3)
                                                    {
                                                           KEYScanCB.RowKey[i][0] = 3;     // 防止溢出
                                                           if(KEYScanCB.Flag[i][0] == 0)                        // 如果没有入队
                                                             {         
                                                                     KEYScanCB.Flag[i][0] = 0xff;     // 置入队标志
                                                                         endata = i*4;
                                                                     Addonedata(endata);                                                         
                                                                 }
                                                        }                                                  
                                                   break ;
                                          }
                                          
                                        case 0x0D :                   //  第2列
                                          {
                                             KEYScanCB.RowKey[i][1]++;              // 消抖动 15ms                                                   
                                                 if(KEYScanCB.RowKey[i][1] > 3)
                                                    {
                                                           KEYScanCB.RowKey[i][1] = 3;     // 防止溢出
                                                           if((KEYScanCB.Flag[i][1] == 0) && (i<2))                        // 如果没有入队
                                                             {         
                                                                     KEYScanCB.Flag[i][1] = 0xff;     // 置入队标志
                                                                         endata = i*4+1;
                                                                     Addonedata(endata);                                                         
                                                                 }
                                                           else if((KEYScanCB.Flag[i][1] == 0) && (i==2))
                                                             {
                                                                    KEYScanCB.Flag[i][1] = 0xff;
                                                                        Deleteonedata();                                                                                                                                         
                                                                 }
                                                        }                                                  
                                                  break ;                                          
                                          
                                          }
                                       
                                        case 0x0B :
                                          {
                                             KEYScanCB.RowKey[i][2]++;              // 消抖动 15ms                                                   
                                                 if(KEYScanCB.RowKey[i][2] > 3)
                                                    {
                                                           KEYScanCB.RowKey[i][2] = 3;     // 防止溢出
                                                           if((KEYScanCB.Flag[i][2] == 0) && (i<2))                        // 如果没有入队
                                                             {         
                                                                     KEYScanCB.Flag[i][2] = 0xff;     // 置入队标志
                                                                         endata = i*4+2;
                                                                     Addonedata(endata);                                                         
                                                                 }
                                                           else if((KEYScanCB.Flag[i][2] == 0) && (i==2))
                                                             {
                                                                    KEYScanCB.Flag[i][2] = 0xff;
                                                                        Cleardata();                                                                                 
                                                                 }
                                                        }
                                          
                                                    break ;
                                          }
                                          
                                        case 0x07:    //  第4列                               
                                          {
                                             KEYScanCB.RowKey[i][3]++;              // 消抖动 15ms                                                   
                                                 if(KEYScanCB.RowKey[i][3] > 3)
                                                    {
                                                           KEYScanCB.RowKey[i][3] = 3;     // 防止溢出
                                                           if((KEYScanCB.Flag[i][3] == 0) && (i<2))                        // 如果没有入队
                                                             {         
                                                                     KEYScanCB.Flag[i][3] = 0xff;     // 置入队标志
                                                                         endata = i*4+3;
                                                                     Addonedata(endata);                                                         
                                                                 }
                                                           else if((KEYScanCB.Flag[i][3] == 0) && (i==2))
                                                             {
                                                                    KEYScanCB.Flag[i][3] = 0xff;
                                                                        Cleardata();         
                                                                 }
                                                        }
                                          
                                                    break ;
                                          }
                                   //    default:
                               //          break ;                        
                                }
                  
                  
                   }          
          }
}



void DataFormConvert(struct _Disdata *ptst)
{
        unsigned char i;
        unsigned char headno;    //  数组头序号
        headno = (ptst->HeadNO+4-ptst->num)%4;
        leddata.num = ptst->num;
       
        if(leddata.num>0)
        {
                 for(i=0;i<leddata.num;i++)
                {
                         leddata.dis[i] = ptst->disdata[(headno+i)%4];               
                }       
        }
}


void LEDDisplay()
{       
        char SFRPAGE_SAVE = SFRPAGE;
        DataFormConvert(&Disdata);
        SFRPAGE = 0x0f;
        if(leddata.num==0)
                LEDOFF;
        else
        {
                 switch(leddata.num)
                {
                        case 1:
                        {
                               
                                if(ii==0)
                                {
                                        P5 = LEDSEG1[leddata.dis[ii]];
                                        LEDON(ii);                               
                                }
                                else
                                {
                                         LEDOFF;                               
                                }
                                break ;
                        }

                        case 2:
                        {
                                if(ii<2)
                                {
                                        LEDOFF;
                                        P5 = LEDSEG1[leddata.dis[ii]];
                                        LEDON(ii);                               
                                }
                                else
                                {
                                        LEDOFF;                               
                                }                        
                                break;
                        }
                        case 3:
                        {
                            if(ii<3)
                                {
                                        LEDOFF;
                                        P5 = LEDSEG1[leddata.dis[ii]];
                                        LEDON(ii);                               
                                }
                                else
                                {
                                        LEDOFF;                               
                                }
                       
                                break;
                        }

                        case 4:
                        {
                                LEDOFF;
                                P5 = LEDSEG1[leddata.dis[ii]];
                                LEDON(ii);                       
                                break ;
                        }               
                        default:
                        break;       
               
                }       
       
        }
        ii = (ii+1)%4;
    SFRPAGE = SFRPAGE_SAVE;
}


void DisplayInit()
{
        Disdata.num = 0;
        Disdata.HeadNO = 0;
        Disdata.disdata[0] = 0;
        Disdata.disdata[1] = 0;
        Disdata.disdata[2] = 0;
        Disdata.disdata[3] = 0;
}


void Deleteonedata()
{
        if(Disdata.num>0)
          Disdata.num -=1;
}

void Addonedata(unsigned char datatmp)
{               
       
        Disdata.num++;
        if( Disdata.num >= 4 )
         {
            Disdata.num = 4;          
         }

        Disdata.disdata[Disdata.HeadNO] = datatmp;
        Disdata.HeadNO = (Disdata.HeadNO+1) % 4 ;
}


void Cleardata()
{
        Disdata.num = 0;
        Disdata.HeadNO = 0;
        Disdata.disdata[0] = 0;
        Disdata.disdata[1] = 0;
        Disdata.disdata[2] = 0;
        Disdata.disdata[3] = 0;
}

使用特权

评论回复
7
jlgcumt|  楼主 | 2011-12-19 20:36 | 只看该作者
键盘判断长按的只要判断一个计数次数估计就行了

使用特权

评论回复
8
liang7143| | 2011-12-20 08:53 | 只看该作者
:lol 顶
建议LZ发代码的时候,选择 插入代码
格式就 不会 乱了

使用特权

评论回复
9
fliger| | 2011-12-20 09:53 | 只看该作者
太长了。乱。没看。

使用特权

评论回复
10
老鱼探戈| | 2011-12-20 13:01 | 只看该作者
打个包就完了,干吗贴这么长

使用特权

评论回复
11
frlop| | 2011-12-20 15:22 | 只看该作者
楼上,厉害,八行的矩阵键盘,求代码学习,可否?

使用特权

评论回复
12
ljg881130| | 2011-12-20 15:37 | 只看该作者
要勇于创新嘛!

使用特权

评论回复
13
ljg881130| | 2011-12-20 15:39 | 只看该作者
要勇于创新嘛!:P

使用特权

评论回复
14
mage心寒| | 2011-12-20 17:14 | 只看该作者
矩阵键盘反转法:下面贴代码子程序

使用特权

评论回复
15
mage心寒| | 2011-12-20 17:14 | 只看该作者
void keyscan()
{
   P3=0xf0;
   temp=P3;
   temp=temp&0xf0;
   if(temp!=0xf0)
   {
      delay(5);
      if(temp!=0xf0)
      {
         P3=0x0f;
         temp1=P3;
         temp1=temp1&0x0f;
         temp1=temp+temp1;
         switch(temp1)
         {
            case 0x7e:num=1;break;
            case 0xbe:num=2;break;
            case 0xde:num=3;break;
            case 0xee:num=4;break;
         }
         P0=table[num];
      }
   }
}

使用特权

评论回复
16
jlgcumt|  楼主 | 2011-12-20 20:15 | 只看该作者
晕,确实起比较长。
键盘扫描的switch语句里面的每个case:可以一个子程序代替,将扫描结果先给一个编号,入队的时候再增加一个函数解析其结果就行了,就没那么长了。

使用特权

评论回复
17
jlgcumt|  楼主 | 2011-12-20 20:33 | 只看该作者
8行代码?牛人,贴出来让大伙学习学习!

使用特权

评论回复
18
jlgcumt|  楼主 | 2011-12-20 20:35 | 只看该作者
mega寒扫描的是矩阵吗,没看出来

使用特权

评论回复
19
jlgcumt|  楼主 | 2011-12-20 20:36 | 只看该作者
4×4还16个数呢

使用特权

评论回复
20
jlgcumt|  楼主 | 2011-12-20 20:44 | 只看该作者
貌似这个程序不错,网上找的!

#include <reg52.h>//包含头文件
#define uchar unsigned char
#define uint unsigned int
unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
                    0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F,数码管来显示按下键的值。

uchar keyscan(void);            //主要的矩阵键盘扫描函数。
void delay(uint i);
void main()
{
uchar key;
P2=0x00;//1数码管亮 按相应的按键,会显示按键上的字符
while(1)
{
key=keyscan();//调用键盘扫描,
switch(key)
{
case 0x7e:P0=dofly[0];break;//0 按下相应的键显示相对应的码值 原理就是高四位一列低四位一列的组
//合。0111    1110 7e    0表示按键后为0,1表示没有按键按下的。即P3.7与P3.1连接为低电平,为S1键
//其他类推。
case 0x7d:P0=dofly[1];break;//1
case 0x7b:P0=dofly[2];break;//2
case 0x77:P0=dofly[3];break;//3
case 0xbe:P0=dofly[4];break;//4
case 0xbd:P0=dofly[5];break;//5
case 0xbb:P0=dofly[6];break;//6
case 0xb7:P0=dofly[7];break;//7
case 0xde:P0=dofly[8];break;//8
case 0xdd:P0=dofly[9];break;//9
case 0xdb:P0=dofly[10];break;//a
case 0xd7:P0=dofly[11];break;//b
case 0xee:P0=dofly[12];break;//c
case 0xed:P0=dofly[13];break;//d
case 0xeb:P0=dofly[14];break;//e
case 0xe7:P0=dofly[15];break;//f
}
}
}
uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法 比如:行为低电位,列为高四位
{
uchar cord_h,cord_l;//行列值
P3=0x0f;            //行线输出全为0
cord_h=P3&0x0f;     //读入列线值
if(cord_h!=0x0f)    //先检测有无按键按下
{
delay(100);        //去抖
if(cord_h!=0x0f)
{
    cord_h=P3&0x0f; //读入列线值
    P3=cord_h|0xf0; //输出当前列线值
    cord_l=P3&0xf0; //读入行线值
    return(cord_h+cord_l);//键盘最后组合码值
   }
}return(0xff);     //返回该值
}
void delay(uint i)//延时函数
{
while(i--);
}

使用特权

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

本版积分规则

个人签名:善攻者,动于九天之上,善守者,藏于九地之下!

183

主题

733

帖子

4

粉丝