打印

IIC接口键盘控制器芯片IIC驱动源代码

[复制链接]
2908|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
FVsteven|  楼主 | 2013-1-27 12:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*
FV2816-KA是一款键盘控制器专用芯片,内置时钟振荡电路,同时可以进行210个按键扫描,并支持复合键操作。KA版本同时支持UART接口和IIC接口通讯,并提供按键按下中断信号,KA提供2种工作模式:1.UART主动发送键值并提供外部中断,2.有按键中断脚拉低,等待CPU读取键值。(键值为4字节的键码)1.  工作电压:2.7V ~ 5.5V2.  提供按键中断(低电平有效)3.  与主控器提供2种接口可选。2线串行接口:400Khz时钟速度,兼容2线IIC总线,节约引脚串行UART接口:(默认115200N,8,1寄存器0: 保留 IIC的地址。1-4:键值寄存器KEYVALUEREG5:中断控制寄存器KEYINTREG6:  按键去抖时间寄存器KEYTIMEREG IIC通讯方式:读键值寄存器操作:1 控制字节(器件地址)写:  0x902.  地址字节(KEYVALUEREG寄存器) 0x013.  控制字节(器件地址)读:  0x914.返回4个字节即 当前按键键值 配置中断控制寄存器操作:1 控制字节(器件地址)写:  0x902.  地址字节(中断控制寄存器) 0x053.  数据字节(寄存器数据KEYINTREG)写:   0x00(默认值)   KEYINTREG:
   0x00:
当有按键按下动作产生后,/INT中断脚拉低(低电平)直到KEYVALUE寄存器被读取后/INT中断脚拉高(高电平)   0x01: 当有按键按下,/INT中断脚为低电平; 当有按键松开或无按键,/INT中断脚为高电平。   0x02: 当有按键按下动作产生后,/INT中断脚为低电平;当KEYVALUE寄存器被读取后,或按键松开、无按键等情况下,/INT中断脚为高电平。 配置按键去抖时间寄存器操作:1 控制字节(器件地址)写:  0x902.  地址字节(按键去抖时间寄存器) 0x063.  数据字节(寄存器数据KEYTIMEREG)写:   0x32(默认值50   KEYTIMEREG:  (1-200)


*/

#include<intrins.h>   

#define FV2816DDR  0x90

sbit b_SCL_IIC =P0^6;                                                  //0,0
sbit b_SDA_IIC =P0^7;                                                  //0,0

#define  Set_IIC_SCL                 (b_SCL_IIC=1)         //SCL
#define  Reset_IIC_SCL                 (b_SCL_IIC=0)
//
#define  Set_IIC_SDA                 (b_SDA_IIC=1)         //SCL
#define  Reset_IIC_SDA                 (b_SDA_IIC=0)
#define  SDA_IIC                        (b_SDA_IIC)

bit ack;                 /*应答标志位*/

//////////////////////////////////
union UNCHAR2SHORT             //37
{ unsigned char ucpStr[2];                                                         //1
  unsigned short usData;              //0x55                  1
};


void  IIC_Delay(unsigned char i)
{
unsigned char k;
for(k=0;k<i;)
{k++;
}
}

/*******************************************************************
                     起动总线函数               
函数原型: void  Start_I2c();  
功能:       启动I2C总线,即发送I2C起始条件.

********************************************************************/
void Start_I2c(void)
{
  Set_IIC_SDA;   /*发送起始条件的数据信号*/
  IIC_Delay(1);
  Set_IIC_SCL;
  IIC_Delay(2);   
  Reset_IIC_SDA;   /*发送起始信号*/
  IIC_Delay(2);      
  Reset_IIC_SCL;   /*钳住I2C总线,准备发送或接收数据 */
  IIC_Delay(1);
}




/*******************************************************************
                      结束总线函数               
函数原型: void  Stop_I2c();  
功能:       结束I2C总线,即发送I2C结束条件.

********************************************************************/
void Stop_I2c(void)
{
  Reset_IIC_SDA;  /*发送结束条件的数据信号*/
  IIC_Delay(1);  /*发送结束条件的时钟信号*/
  Set_IIC_SCL;  /*结束条件建立时间大于4μs*/
  IIC_Delay(2);
  Set_IIC_SDA;  /*发送I2C总线结束信号*/
  IIC_Delay(2);
}




/*******************************************************************
                 字节数据传送函数               
函数原型: void  I2C_SendByte(unsigned char c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)     
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  I2C_SendByte(unsigned char c)
{
unsigned char BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
     if((c<<BitCnt)&0x80)Set_IIC_SDA;   /*判断发送位*/
       else  Reset_IIC_SDA;               
      IIC_Delay(1);
     Set_IIC_SCL;               /*置时钟线为高,通知被控器开始接收数据位*/
      IIC_Delay(3);           /*保证时钟高电平周期大于4μs*/
     Reset_IIC_SCL;
    }

     IIC_Delay(1);
    Set_IIC_SDA;               /*8位发送完后释放数据线,准备接收应答位*/
     IIC_Delay(1);  
    Set_IIC_SCL;
     IIC_Delay(2);
    if(SDA_IIC)ack=0;     
       else ack=1;        /*判断是否接收到应答信号*/
    Reset_IIC_SCL;
     IIC_Delay(1);
}






/*******************************************************************
                 字节数据传送函数               
函数原型: unsigned char  I2C_RecvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。  
********************************************************************/       
unsigned char  I2C_RecvByte(void)
{
  unsigned char retc;
  unsigned char BitCnt;

  retc=0;
  Set_IIC_SDA;             /*置数据线为输入方式*/
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        IIC_Delay(1);         
        Reset_IIC_SCL;       /*置时钟线为低,准备接收数据位*/
        IIC_Delay(3);        /*时钟低电平周期大于4.7μs*/
        Set_IIC_SCL;       /*置时钟线为高使数据线上数据有效*/
        IIC_Delay(1);
        retc=retc<<1;
        if(SDA_IIC)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
        IIC_Delay(1);
      }
  Reset_IIC_SCL;   
  IIC_Delay(1);
  return(retc);
}




/********************************************************************
                     应答子函数
原型:  void Ack_I2c(bit a);

功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(unsigned char a)
{

  if(a==0)
  Reset_IIC_SDA;     /*在此发出应答或非应答信号 */
  else Set_IIC_SDA;
   IIC_Delay(2);     
  Set_IIC_SCL;
    IIC_Delay(3);           /*时钟低电平周期大于4μs*/
  Reset_IIC_SCL;                /*清时钟线,钳住I2C总线以便继续接收*/
    IIC_Delay(1);
}

/*******************************************************************
                    向有子地址器件发送多字节数据函数               
函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
          地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
/*         
unsigned char cI2C_8SendStr(unsigned char ucMainAddr,unsigned char ucSubAddr,unsigned char *s,unsigned char no)
{
   unsigned char i;

   Start_I2c();            
   I2C_SendByte(ucMainAddr);            
     if(ack==0)return(0);
   I2C_SendByte(ucSubAddr);            
     if(ack==0)return(0);

   for(i=0;i<no;i++)
    {   
     I2C_SendByte(*s);               
       if(ack==0)return(0);
     s++;
    }
Stop_I2c();               
  return(1);
}          */
/**/




/*******************************************************************
                    向有子地址器件读取多字节数据函数               
函数原型: bit  ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);  
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
          地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
/*          
unsigned char cI2C_8RecvStr(unsigned char ucMainAddr,unsigned char ucSubAddr,unsigned char *s,unsigned char no)
{
   unsigned char i;

   Start_I2c();              
   I2C_SendByte(ucMainAddr);            
     if(ack==0)return(0);
   I2C_SendByte(ucSubAddr);            
     if(ack==0)return(0);

   Start_I2c();
   I2C_SendByte(ucMainAddr+1);
      if(ack==0)return(0);

   for(i=0;i<no-1;i++)
    {   
     *s=I2C_RecvByte();               
      Ack_I2c(0);                 
     s++;
    }
   *s=I2C_RecvByte();
    Ack_I2c(1);                  
Stop_I2c();                    
  return(1);
} */
/* */


//////////////////////////////////////////////////////////////////////////////////////
union UNLONG2CHAR{ unsigned char ucpChar[4]; unsigned long ulData;};
unsigned long lReadFv2816_Keyvalue_I2c()
{

union UNLONG2CHAR  g_unKey;
if(cI2C_8RecvStr(0x90,0x01,g_unKey.ucpChar,4)==1)
{
ucWaitKey=1;
return(g_unKey.ulData);
}
return(0);
}


相关帖子

沙发
FVsteven|  楼主 | 2013-1-27 12:15 | 只看该作者
void  IIC_Delay(unsigned char i)
{
unsigned char k;
unsigned long m;
for(k=0;k<i; k++)
{
for(m=0;m<2000;)
{m++;
}
}
}

使用特权

评论回复
板凳
FVsteven|  楼主 | 2013-1-27 12:17 | 只看该作者
void Set_KeyReg()
{
unsigned char c;
c=0x00;
  cI2C_8SendStr(0x90,0x05,&c,1);//KEYINTREG
c=10;
cI2C_8SendStr(0x90,0x06,&c,1);//KEYTIMEREG
}

使用特权

评论回复
地板
huangxz| | 2013-1-27 12:28 | 只看该作者
怎么像周立功的杰作啊:lol

使用特权

评论回复
5
FVsteven|  楼主 | 2013-1-27 20:40 | 只看该作者
英雄所见略同:lol

使用特权

评论回复
6
FVsteven|  楼主 | 2013-1-27 22:46 | 只看该作者
FV2816-KA 有21个键盘IO线,最多可控制210个按键,按键挺多的;IIC 接口不错,方便。

使用特权

评论回复
7
FVsteven|  楼主 | 2013-1-29 10:05 | 只看该作者
8
FVsteven|  楼主 | 2013-1-29 11:37 | 只看该作者
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

39

帖子

0

粉丝