STM8/STM32硬件I2C读取APDS9930程序代码

   STM的硬件I2C一直被各种吐槽,实际上只是用起来比较复杂而已,难点主要是在作为Master时的数据接收上,作为Slave时的数据发送没难度,正常用。重点是要真正掌握它里面设计的那个Data shift register和Data register,后者是前者的数据存储,

    作为Master时的数据接收,I2C发送的ACK与STOP按接收长度不同要导致多种处理方式,稍不留神就会被绕晕。分为:3字节以上,2字节,1字节,这三种状态的处理方式是不同的,因为Data shift register会先被装上,然后存到Data register中,如果总线数据太快来不及处理,这时如果Data shift register又被装满了,就要触发BTF中断了。

    而作为2字节时非常难弄,因为必须在卡在Data register和Data shift register被装满之前,所以手册上特殊说明了:

For 2-byte reception:
• Wait until ADDR = 1 (SCL stretched low until the ADDR flag is cleared)
• Set ACK low, set POS high
• Clear ADDR flag
• Wait until BTF = 1 (Data 1 in DR, Data2 in shift register, SCL stretched low until a data
1 is read)
• Set STOP high
• Read data 1 and 2

按手册的说法要在ADDR之后立即关闭ACK并且打开POS(就是使本次设置的ACK在下一字节接收时有效),而最奇葩的是,ST设计的这个硬件,不能等ADDR中断来了处理,因为中断的处理速度跟不上!!只能用While(1)轮循。

C代码:

/**
  ******************************************************************************
  读取APDS9930 I2C 文件
  APDS9930包括读写两个操作,写又包括两种:写寄存器、写动作(即写操作直接触发动作)
  下文中CMD表示COMMAND寄存器,实际是一个命令值,用于不同的操作,具体含义详见手册。
  写寄存器的顺序是:S addr W A CMD(0x80)|reg A DataL (DataH) A P
  写动作的顺序是: S addr W A CMD(0b111xxxxx) 其中x代表不同的清除中断动作,详见手册
  读的操作顺序:S addr W A CMD(0xA0)|reg A Sr addr R A DataL (DataH) NA P
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "main.h"
#include "stm8s_eval.h"
#include "app_i2c.h"

static __IO I2CDataTyp i2cTXData, i2cRXData;
static uint8_t Rx_Idx, Tx_Idx;
static __IO uint8_t txBuf[I2CTXBUFSIZE];
static __IO uint8_t rxBuf[I2CRXBUFSIZE];
static __IO I2CWRState I2C_RW;
static __IO I2CLenType Rx_SafeLen;
static __IO bool isI2C_Busy;
static __IO bool isReadFinish;
static __IO bool isWriteFinish;

void I2C_APP_Init(void)
{
  i2cTXData.buf = txBuf;
  i2cRXData.buf = rxBuf;
  I2C_RW = I2C_RW_NULL;
  isI2C_Busy = FALSE;
  isReadFinish = FALSE;
  isWriteFinish = FALSE;
  /* I2C Initialize */
  I2C_DeInit();
  I2C_Init(I2C_SPEED, 0xA0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);
  /* Enable Buffer and Event Interrupt*/
  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT /*| I2C_IT_BUF*/) , ENABLE);
  //enableInterrupts();
}

ErrorStatus I2C_WriteRegData(APDS9930RegAddr reg, uint8_t *data, uint8_t len)
{ 
  uint8_t cnt = 0;
  ErrorStatus err = ERROR; 
  isWriteFinish = FALSE;
  while (isI2C_Busy == TRUE)  {
    Delay(0x7FF);
    cnt++;
    if (cnt >= I2C_RW_BLOCK_CNT){
      break;
    }
  }; /*阻塞式等待*/
  if (cnt < I2C_RW_BLOCK_CNT){
    i2cTXData.len = len;
    i2cTXData.reg= 0x80|reg;  /*0x80:Repeated Byte protocol transaction*/
    DEBUG_I2C("i2cTXData.buf:" );
    for (uint8_t i=0; i<len; i++){
      i2cTXData.buf[i] = data[i];
      DEBUG_I2C(" 0x%x,", i2cTXData.buf[i]);
    }
    DEBUG_I2C(" \n" );
    I2C_RW = I2C_WRITE;
    isI2C_Busy = TRUE;  /*做阻塞标记*/
    //I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);
    I2C_GenerateSTART(ENABLE);
    cnt = 0;
    while (isWriteFinish == FALSE){
      Delay(0x7FF);
      cnt++;
      if (cnt >= I2C_RW_BLOCK_CNT){
        break;
      }
    }
    if (cnt < I2C_RW_BLOCK_CNT){  /*写成功*/
      err = SUCCESS;
    }
    else{
      err = ERROR;
      DEBUG_I2C("I2C_WriteReg 0x%x Over time: Write over time!\n", reg);
    }
  }
  else{
    err = ERROR;
    DEBUG_I2C("I2C_WriteReg 0x%x Over time: I2C bus busy!\n", reg);
  }
  return err;
}

ErrorStatus I2C_ReadRegData(APDS9930RegAddr reg, uint8_t *data, uint8_t len) 
{ 
  uint8_t cnt = 0;
  ErrorStatus err = ERROR;
  isReadFinish = FALSE;
  while (isI2C_Busy == TRUE)  {WAIT_FOR_OVERTIME;} /*阻塞式等待*/
  if (cnt < I2C_RW_BLOCK_CNT){
    if ((len>0) && (len<=I2CRXBUFSIZE)) {
      I2C_AcknowledgeConfig(I2C_ACK_CURR);
      if (len > 2) {
        Rx_SafeLen = I2C_LEN_3X;
      }
      else if (len == 2){
        Rx_SafeLen = I2C_LEN_2;
      }
      else {    /*len == 1*/
        Rx_SafeLen = I2C_LEN_1;
        /* Disable Acknowledgement */
        I2C_AcknowledgeConfig(I2C_ACK_NONE);
      }
      i2cRXData.len = len;
      i2cRXData.reg= 0xA0|reg; /*0xA0:Auto-Increment protocol transaction*/
      I2C_RW = I2C_READ_W;
      isReadFinish = FALSE;
      if (Rx_SafeLen == I2C_LEN_2){
        err = I2C_HandleRead2Bytes();
      }
      else{  /* LEN3X, LEN1 */
        I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT) , ENABLE);
        I2C_GenerateSTART(ENABLE);
        cnt = 0;
        while (isReadFinish == FALSE){WAIT_FOR_OVERTIME;}
        if (cnt < I2C_RW_BLOCK_CNT){  /*读成功*/
          err = SUCCESS;
        }
      }

      if (err == SUCCESS){  /*读成功*/
        for (uint8_t i=0; i<len; i++){
          data[i] = i2cRXData.buf[i];
        }
      }
      else{         /* err == ERROR*/
        DEBUG_I2C("I2C_ReadReg 0x%x Over time: Read over time!\n", reg);
      }
    }
    else {
      err = ERROR;
      if (len == 0){
        DEBUG_I2C("I2C_ReadReg 0x%x len=0 error!\n", reg);
      }
      else {
        DEBUG_I2C("I2C_ReadReg 0x%x len overlength error!\n", reg);
      }
    }
  }
  else{
    err = ERROR;
    DEBUG_I2C("I2C_ReadReg 0x%x Over time: I2C bus busy!\n", reg);
  }
  return err;
}

ErrorStatus I2C_ReadWord(APDS9930RegAddr reg, uint16_t* data)
{
  ErrorStatus err = ERROR;
  uint8_t barr[I2CRXBUFSIZE];
  err = I2C_ReadRegData(reg, barr, I2CRXBUFSIZE);
  if (err == SUCCESS){
    *data = ((uint16_t)barr[1])<<8 | (uint16_t)barr[0];
  }
  return err;
}

ErrorStatus I2C_HandleRead2Bytes(void)
{
  ErrorStatus err = ERROR;
  uint8_t cnt;
  Rx_Idx = 0;
  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);
  DEBUG_I2C("Begin to Read! \n");
  I2C_GenerateSTART(ENABLE);
  /*等待LEN2写寄存器结束*/
  cnt = 0;
  while (I2C_RW != I2C_READ_R){WAIT_FOR_OVERTIME;}    
  if (cnt < I2C_RW_BLOCK_CNT){
    I2C_GenerateSTART(ENABLE); /*Sr*/
    DEBUG_I2C("I2C_Generate ReSTART:Read \n");
    /* Test on EV5 and clear it */
    cnt = 0;
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)){WAIT_FOR_OVERTIME;}
    if (cnt < I2C_RW_BLOCK_CNT){
      DEBUG_I2C("Send slave address: 0x%x\n",SLAVE_ADDRESS);
      I2C_AcknowledgeConfig(I2C_ACK_NEXT);
      I2C_Send7bitAddress(SLAVE_ADDRESS, I2C_DIRECTION_RX);
      cnt = 0;
      while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){WAIT_FOR_OVERTIME;}
      if (cnt < I2C_RW_BLOCK_CNT){
        I2C_AcknowledgeConfig(I2C_ACK_NONE);
        DEBUG_I2C("Enter Receiver Mode!\n");
        /*立即进入接收轮循*/
        cnt = 0;
        while ((I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET)){WAIT_FOR_OVERTIME;} /* Poll on RxNE */
        if (cnt < I2C_RW_BLOCK_CNT){
          /*1个字节已经收到*/
          I2C_AcknowledgeConfig(I2C_ACK_NONE);  /*立即关闭ACK*/
          I2C_GenerateSTOP(ENABLE);  /*立即发送停止信号,本字节接收完自动停止*/
          i2cRXData.buf[Rx_Idx++] = I2C_ReceiveData(); /*读第1字节*/
          cnt = 0;
          while ((I2C_GetFlagStatus(I2C_FLAG_RXNOTEMPTY) == RESET)){WAIT_FOR_OVERTIME;} /* Poll on RxNE */
          if (cnt < I2C_RW_BLOCK_CNT){
            i2cRXData.buf[Rx_Idx++] = I2C_ReceiveData(); /*读第2字节*/ 
            cnt = 0;
            while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)){WAIT_FOR_OVERTIME;}
            if (cnt < I2C_RW_BLOCK_CNT){
              isI2C_Busy = FALSE;
              isReadFinish = TRUE;
              I2C_RW = I2C_RW_NULL;
              err = SUCCESS;
            }
          }
        }
      }
    }
  }
  return err ;
}

void I2C_APP_Interrupt(void)
{
  I2C_Direction_TypeDef rw;
  I2C_Event_TypeDef event = I2C_GetLastEvent();
  DEBUG_I2C("interrupt event: 0x%x, ", event);
  DEBUG_I2C("SR2= 0x%x => ", I2C->SR2);
  switch (event)
  {
    case I2C_EVENT_MASTER_MODE_SELECT_RESTART: //(0x0300)
      DEBUG_I2C("I2C_EVENT_MASTER_MODE_SELECT_RESTART \n");
      break;
      /* EV5 */
    case I2C_EVENT_MASTER_MODE_SELECT :   //SB (ITEVTEN)     
      if (I2C_RW != I2C_RW_NULL) {
        DEBUG_I2C("I2C_EVENT_MASTER_MODE_SELECT \n");
        if (I2C_RW != I2C_READ_R){  /*发送和接收第一阶段*/
          rw = I2C_DIRECTION_TX;
          //I2C_ITConfig(I2C_IT_BUF, ENABLE);
        }
        else {   /*接收第二阶段,只会处理LEN3X,LEN1*/
          rw = I2C_DIRECTION_RX;
          I2C_RW = I2C_RW_NULL;
        }
      /* Send slave Address for write */
        DEBUG_I2C("RW=%d (0:tx, 1:rx)\n",rw);
        I2C_Send7bitAddress(SLAVE_ADDRESS, rw);
      }
      else {
        DEBUG_I2C("I2C_EVENT_MASTER_MODE_SELECT error:I2C_RW=%d \n",I2C_RW);
      }
      break;

      /* EV6 TRA, BUSY, MSL, TXE and ADDR  flags*/
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:  //0x0782 (TXE(ITBUFEN) ADDR) (ITEVTEN)
      DEBUG_I2C("I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED \n");
      switch (I2C_RW)
      {
        case I2C_WRITE:
          /* Send the first Data */
          DEBUG_I2C("I2C_WRITE=>i2cTXData.reg:0x%x",i2cTXData.reg);
          DEBUG_I2C("(%d) \n",i2cTXData.reg);
          Tx_Idx = 0;
          I2C_SendData(i2cTXData.reg);
          break; /*next: I2C_EVENT_MASTER_BYTE_TRANSMITTED*/
        case I2C_READ_W:
          /* Send the first Data */
          DEBUG_I2C("I2C_READ_W=>i2cRXData.reg:0x%x",i2cRXData.reg);
          DEBUG_I2C("(%d) \n",i2cRXData.reg);
          I2C_SendData(i2cRXData.reg);
          break; /*next: I2C_EVENT_MASTER_BYTE_TRANSMITTED*/
        default:
          DEBUG_I2C("TRANSMITTER_MODE_SELECTED error:I2C_RW=%d \n",I2C_RW);
          break;
      }
      break;
      
    case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: //RX:ADDR; 0x0302 TRA=0, BUSY MSL (ADDR) (ITEVTEN)
      //DEBUG_I2C("I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED \n");
      Rx_Idx = 0;
#if 0      /*STM8S存储空间不足,1字节处理方案忍痛砍掉*/
      switch (Rx_SafeLen)
      {     
        case I2C_LEN_1:
          /* Disable Acknowledgement */
          I2C_AcknowledgeConfig(I2C_ACK_NONE);
          I2C_ITConfig(I2C_IT_BUF, ENABLE);
           /* Send STOP Condition */
          I2C_GenerateSTOP(ENABLE);
          break;
        default:
          break;
      }
#endif      
      break;
      /* EV7 */
#if 0   /*STM8S存储空间不足,3字节处理方案忍痛砍掉*/
    case I2C_EVENT_MASTER_BYTE_RECEIVED_FULL: /*RX:RXNE&BTF; 0x0344, RXNE(ITBUFEN) BTF(ITEVTEN) */
      DEBUG_I2C("I2C_EVENT_MASTER_BYTE_RECEIVED_FULL, Rx_Idx:%d\n",Rx_Idx);
      switch (Rx_SafeLen)
      {
        case I2C_LEN_3X:
          if (Rx_Idx == (i2cRXData.len-3)){
            /* Disable Acknowledgement */
            I2C_AcknowledgeConfig(I2C_ACK_NONE);
            i2cRXData.buf[Rx_Idx++] = I2C_ReceiveData(); /*Read DataN-2 in DR*/
            DEBUG_I2C("N=3xN-2 RXData:0x%x\n",i2cRXData.buf[Rx_Idx-1]);
            //I2C_ITConfig(I2C_IT_BUF, ENABLE);
            /* Send STOP Condition */
            I2C_GenerateSTOP(ENABLE);
            i2cRXData.buf[Rx_Idx++] = I2C_ReceiveData(); /*Read DataN-1*/
            DEBUG_I2C("N=3xN-1 RXData:0x%x\n",i2cRXData.buf[Rx_Idx-1]);
            /*开启RXNE中断,准备接收最后一个字节*/
            I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_BUF) , ENABLE);
          }
          else {
            i2cRXData.buf[Rx_Idx++] = I2C_ReceiveData();
            DEBUG_I2C("N<3x RXData:0x%x\n",i2cRXData.buf[Rx_Idx-1]);
          }
          break;         
        case I2C_LEN_2:  /*LEN2的NACK来不及进入中断处理,只能采用while方式*/
          break;
        case I2C_LEN_1:
          break;
        default:
          break;          
      }
      break;
#endif 
    
    case I2C_EVENT_MASTER_BYTE_RECEIVED: /*RX:RXNE; 0x0340 !< BUSY, MSL and RXNE flags*/ 
    case I2C_EVENT_MASTER_BYTE_RECEIVE_FINISHED: /*0x44*/
    case I2C_EVENT_MASTER_BYTE_RECEIVE_RXNE:  /*0x40 RX:RXNE*/
      DEBUG_I2C("I2C_EVENT_MASTER_BYTE_RECEIVE_RXNE, Rx_Idx:%d\n",Rx_Idx);    
      if (Rx_SafeLen != I2C_LEN_2){
        i2cRXData.buf[Rx_Idx] = I2C_ReceiveData(); /*Read DataN*/  
        I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_BUF) , DISABLE);
        isI2C_Busy = FALSE;  /*读操作结束,清除阻塞标记*/
        isReadFinish = TRUE;
      }
      else {
        /*LEN2时来不及进入RXNE中断,只能使用while等待模式*/
        DEBUG_I2C("error: I2C_LEN_2 enter RXNE!!");
      }
      break;
       
      /* EV8 */
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:  //(TXE(ITBUFEN)  ) (ITEVTEN)
      DEBUG_I2C("I2C_EVENT_MASTER_BYTE_TRANSMITTING \n");
      break;
      /* EV8_2 */
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //(TXE(ITBUFEN) BTF) (ITEVTEN)
      DEBUG_I2C("I2C_EVENT_MASTER_BYTE_TRANSMITTED \n");
      switch (I2C_RW)
      {
        case I2C_WRITE:
          if (i2cTXData.len != 0)
          {
            /* Send the first Data */
            DEBUG_I2C("Send TxBuffer[%d]:",Tx_Idx);
            DEBUG_I2C("0x%x",i2cTXData.buf[Tx_Idx]);
            DEBUG_I2C("(%d) \n",i2cTXData.buf[Tx_Idx]);
            I2C_SendData(i2cTXData.buf[Tx_Idx]);
            Tx_Idx++;
            /* Decrement number of bytes */
            i2cTXData.len--;
          }
          else
          {
            /* Send STOP condition */
            I2C_GenerateSTOP(ENABLE);
            DEBUG_I2C("i2cTXData.buf:" );
            for (uint8_t i=0; i<10; i++){
              DEBUG_I2C(" 0x%x,", i2cTXData.buf[i]);
            }
            DEBUG_I2C(" \n" );
            //I2C_ITConfig(I2C_IT_EVT, DISABLE);
            isI2C_Busy = FALSE;  /*写操作结束,清除阻塞标记*/
            isWriteFinish = TRUE;
            I2C_RW = I2C_RW_NULL;
          }
          break;
        case I2C_READ_W:
          I2C_RW = I2C_READ_R; /*切换到读第二阶段*/
          if (Rx_SafeLen == I2C_LEN_2) {  /*LEN2结束中断之旅,回归while方式*/
            I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , DISABLE);
          }        
          else {
            I2C_GenerateSTART(ENABLE); /*Sr*/
          }
          break;
        default:
          DEBUG_I2C("I2C_RW err: 0x%x\n",I2C_RW);
          break; 
      }
      break;    
    case I2C_EVENT_SLAVE_ACK_FAILURE:
      DEBUG_I2C("I2C_EVENT_SLAVE_ACK_FAILURE\n");
      DEBUG_I2C("IIC Disabled \n");
      I2C_Cmd(DISABLE);
      //I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF) , DISABLE);
      I2C_SoftwareResetCmd(ENABLE);
      I2C_APP_Init();
      DEBUG_I2C("IIC restart\n");
      //I2C_GenerateSTART(ENABLE);
      break;      
    default:
      DEBUG_I2C("非法 event: %x, ", event);
      DEBUG_I2C("SR2= %x\n", I2C->SR2);
      I2C->SR2 = 0;
      I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF) , DISABLE);
      break;
  }
}

ErrorStatus APDS9930_Init(void)
{
  ErrorStatus err = SUCCESS;
  APDS_RegVal key, Atime, Ptime, Wtime, Ppluse;
  key = 0x0;
  Atime = 0xff; // 2.7 ms – minimum ALS integration time
  Wtime = 0xff; // 2.7 ms – minimum Wait time
  Ptime = 0xff; // 2.7 ms – minimum Prox integration time
  Ppluse = 8; // Minimum prox pulse count
  err &= I2C_WriteRegData(APDS_ENABLE_REG, &key, sizeof(key));
  err &= I2C_WriteRegData(APDS_ATIME_REG, &Atime, sizeof(Atime));
  err &= I2C_WriteRegData(APDS_PTIME_REG, &Ptime, sizeof(Ptime));
  err &= I2C_WriteRegData(APDS_WTIME_REG, &Wtime, sizeof(Wtime));
  err &= I2C_WriteRegData(APDS_PPULSE_REG, &Ppluse, sizeof(Ppluse));
  /*APDS_CONTROL_REG*/
  APDS_RegVal CtrlVal;
  CtrlVal = CTRLVAL;
  err &= I2C_WriteRegData(APDS_CONTROL_REG, &CtrlVal, sizeof(CtrlVal));
  /*APDS_ENABLE_REG*/
  APDS_RegVal power;
  power = POWER;
  err &= I2C_WriteRegData(APDS_ENABLE_REG, &power, sizeof(power));
  
  if (err == SUCCESS){
    Delay(0x5FF);  /*wait for stable*/
  }
  return err;
}
/**
  * @}
  */

/**
  * @}
  */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

头文件:

/**
 app_i2c.h
 2016.07.01 
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __I2C_H
#define __I2C_H


/* definition of fast or default standard mode (bus speed up to 400 or 100 kHz) */
//#define FAST_I2C_MODE


#ifdef FAST_I2C_MODE
#define I2C_SPEED 400000
#else
#define I2C_SPEED 100000
#endif


/* definition of 10-bit or default 7-bit slave address */
/* #define TEN_BITS_ADDRESS */


#ifdef TEN_BITS_ADDRESS
#define SLAVE_ADDRESS  0x330
#else
#define SLAVE_ADDRESS  (0x39<<1)
#endif


/* This define is used in master receiver */
/* Uncomment the line below if you want to use the safe procedure */
#define SAFE_PROCEDURE
/*定义数据长度*/
#define I2CTXBUFSIZE 2
#define I2CRXBUFSIZE 2
#define I2C_RW_BLOCK_CNT 10


#define I2C_EVENT_MASTER_BYTE_RECEIVED_FULL      (I2C_EVENT_MASTER_BYTE_RECEIVED|(uint16_t)0x04)
#define I2C_EVENT_MASTER_MODE_SELECT_RESTART     ((uint16_t)0x0300)
#define I2C_EVENT_MASTER_BYTE_RECEIVE_RXNE       ((uint16_t)0x0040)
#define I2C_EVENT_MASTER_BYTE_RECEIVE_FINISHED   ((uint16_t)0x0044) 




typedef uint8_t APDS_RegVal;


typedef struct
{
  __IO uint8_t len;
  __IO uint8_t reg;
  __IO uint8_t* buf;
}I2CDataTyp;


typedef enum 
{
  I2C_WRITE = (uint8_t)0,
  I2C_READ_W  = (uint8_t)1,
  I2C_READ_R = (uint8_t)2,
  I2C_RW_NULL = (uint8_t)0xFF
}I2CWRState;


typedef enum 
{
  I2C_LEN_0 = (uint8_t)0,
  I2C_LEN_1 = (uint8_t)1,
  I2C_LEN_2 = (uint8_t)2,
  I2C_LEN_3X = (uint8_t)3,
}I2CLenType;


/*APDS9930寄存器地址*/
typedef enum
{
  APDS_ENABLE_REG = (uint8_t)0x00 ,
  APDS_ATIME_REG  = (uint8_t)0x01 ,
  APDS_PTIME_REG  = (uint8_t)0x02 ,
  APDS_WTIME_REG  = (uint8_t)0x03 ,
  APDS_AILTL_REG  = (uint8_t)0x04 ,
  APDS_AILTH_REG  = (uint8_t)0x05 ,
  APDS_AIHTL_REG  = (uint8_t)0x06 ,
  APDS_AIHTH_REG  = (uint8_t)0x07 ,
  APDS_PILTL_REG  = (uint8_t)0x08 ,
  APDS_PILTH_REG  = (uint8_t)0x09 ,
  APDS_PIHTL_REG  = (uint8_t)0x0A ,
  APDS_PIHTH_REG  = (uint8_t)0x0B ,
  APDS_PERS_REG = (uint8_t)0x0C ,
  APDS_CONFIG_REG = (uint8_t)0x0D ,
  APDS_PPULSE_REG = (uint8_t)0x0E ,
  APDS_CONTROL_REG  = (uint8_t)0x0F ,
  APDS_ID_REG = (uint8_t)0x12 ,
  APDS_STATUS_REG = (uint8_t)0x13 ,
  APDS_Ch0DATAL_REG = (uint8_t)0x14 ,
  APDS_Ch0DATAH_REG = (uint8_t)0x15 ,
  APDS_Ch1DATAL_REG = (uint8_t)0x16 ,
  APDS_Ch1DATAH_REG = (uint8_t)0x17 ,
  APDS_PDATAL_REG = (uint8_t)0x18 ,
  APDS_PDATAH_REG = (uint8_t)0x19 ,
  APDS_POFFSET_REG  = (uint8_t)0x1E 
}APDS9930RegAddr;


/*APDS9930寄存器位*/
/*0x0 :APDS_ENABLE_REG*/
#define  WEN  3
#define  PEN  2
#define  AEN  1
#define  PON  0
#define  POWER  (BV(WEN) | BV(PEN) | BV(AEN) | BV(PON))






/*0x0F: APDS_CONTROL_REG*/
#define  PDRIVE  0      /*100 mA of LED Power*/
#define  PDIODE  BV(5)  /*Proximity uses the Ch1 diode*/
#define  PGAIN   0      /*1x Prox gain*/
#define  AGAIN   0      /*1x ALS gain*/
#define  CTRLVAL (PDRIVE | PDIODE | PGAIN | AGAIN)


#define WAIT_FOR_OVERTIME  do{cnt++; Delay(0x7FFF);if (cnt>=I2C_RW_BLOCK_CNT)break;}while(0)




void I2C_APP_Init(void);
ErrorStatus I2C_WriteRegData(APDS9930RegAddr reg, uint8_t *data, uint8_t len);
ErrorStatus I2C_ReadRegData(APDS9930RegAddr reg, uint8_t *data, uint8_t len) ;
ErrorStatus I2C_ReadWord(APDS9930RegAddr reg, uint16_t* data);
ErrorStatus I2C_HandleRead2Bytes(void);
void I2C_APP_Interrupt(void);
ErrorStatus APDS9930_Init(void);




#endif /* __I2C_H */




/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
 

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
你好,以下是 STM32 驱动 APDS996 的代码: #include "stm32f10x.h" #include "i2c.h" #include "apds996.h" void APDS996_Init(void) { I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ENABLE, x00); // 关闭所有功能 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ATIME, DEFAULT_ATIME); // 设置 ADC 的采样时间 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_WTIME, DEFAULT_WTIME); // 设置等待时间 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_PPULSE, DEFAULT_PROX_PPULSE); // 设置近距离探测器的脉冲数 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_POFFSET_UR, DEFAULT_POFFSET_UR); // 设置近距离探测器的偏移量 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_POFFSET_DL, DEFAULT_POFFSET_DL); I2C_WriteByte(APDS996_I2C_ADDR, APDS996_CONFIG1, DEFAULT_CONFIG1); // 设置配置寄存器 1 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_PPULSE, DEFAULT_PPULSE); // 设置脉冲数 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_CONTROL, DEFAULT_CONTROL); // 设置控制寄存器 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_CONFIG2, DEFAULT_CONFIG2); // 设置配置寄存器 2 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ID, DEFAULT_ID); // 设置 ID 寄存器 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ENABLE, DEFAULT_ENABLE); // 开启所有功能 } uint8_t APDS996_ReadID(void) { return I2C_ReadByte(APDS996_I2C_ADDR, APDS996_ID); } void APDS996_EnableGestureSensor(void) { uint8_t val; I2C_WriteByte(APDS996_I2C_ADDR, APDS996_WTIME, xFF); // 设置等待时间 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_PPULSE, DEFAULT_GESTURE_PPULSE); // 设置脉冲数 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF1, x60); // 设置手势识别的配置寄存器 1 APDS996_SetGestureGain(DEFAULT_GESTURE_GAIN); // 设置手势识别的增益 APDS996_SetGestureLEDDrive(DEFAULT_GESTURE_LED_DRIVE); // 设置手势识别的 LED 驱动电流 APDS996_SetGestureWaitTime(DEFAULT_GESTURE_WAIT_TIME); // 设置手势识别的等待时间 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF2, DEFAULT_GESTURE_GCONF2); // 设置手势识别的配置寄存器 2 val = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GCONF4); val &= ~(APDS996_GFIFO_CLR | APDS996_GMODE); val |= APDS996_GMODE_CONTINUOUS; I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF4, val); // 设置手势识别的配置寄存器 4 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ENABLE, (APDS996_ENABLE_GEN | APDS996_ENABLE_PIEN | APDS996_ENABLE_AIEN | APDS996_ENABLE_WEN | APDS996_ENABLE_PEN)); // 开启手势识别、接近检测、环境光感应、等待、近距离探测器 } void APDS996_DisableGestureSensor(void) { uint8_t val; val = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GCONF4); val &= ~(APDS996_GFIFO_CLR | APDS996_GMODE); val |= APDS996_GMODE_SINGLE; I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF4, val); // 设置手势识别的配置寄存器 4 I2C_WriteByte(APDS996_I2C_ADDR, APDS996_ENABLE, (APDS996_ENABLE_PIEN | APDS996_ENABLE_AIEN | APDS996_ENABLE_WEN | APDS996_ENABLE_PEN)); // 关闭手势识别,开启接近检测、环境光感应、等待、近距离探测器 } void APDS996_SetGestureGain(uint8_t gain) { uint8_t val; val = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GCONF2); val &= ~APDS996_GGAIN_2X; val |= (gain & x01) << 5; I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF2, val); // 设置手势识别的增益 } void APDS996_SetGestureLEDDrive(uint8_t drive) { uint8_t val; val = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GCONF2); val &= ~APDS996_GLDRIVE; val |= (drive & x03) << 3; I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GCONF2, val); // 设置手势识别的 LED 驱动电流 } void APDS996_SetGestureWaitTime(uint8_t time) { I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GWTIME, time); // 设置手势识别的等待时间 } uint8_t APDS996_ReadGesture(void) { uint8_t fifo_level, fifo_data[128], i; uint8_t gstatus; uint8_t motion; uint8_t l, r, u, d; uint8_t count; uint8_t valid_gesture = ; if (!(I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GSTATUS) & APDS996_GVALID)) { return APDS996_DIR_NONE; } fifo_level = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GFLVL); if (fifo_level == ) { return APDS996_DIR_NONE; } else if (fifo_level > 32) { fifo_level = 32; } I2C_ReadBytes(APDS996_I2C_ADDR, APDS996_GFIFO_U, fifo_data, fifo_level * 4); for (i = ; i < fifo_level; i++) { l = fifo_data[i * 4 + ]; r = fifo_data[i * 4 + 1]; u = fifo_data[i * 4 + 2]; d = fifo_data[i * 4 + 3]; if (l > APDS996_GESTURE_THRESHOLD_OUT && r > APDS996_GESTURE_THRESHOLD_OUT && u > APDS996_GESTURE_THRESHOLD_OUT && d > APDS996_GESTURE_THRESHOLD_OUT) { motion = APDS996_DIR_NEAR; } else if (l > APDS996_GESTURE_THRESHOLD_IN && r > APDS996_GESTURE_THRESHOLD_IN && u > APDS996_GESTURE_THRESHOLD_OUT && d > APDS996_GESTURE_THRESHOLD_OUT) { motion = APDS996_DIR_FAR; } else if (l > APDS996_GESTURE_THRESHOLD_OUT && r > APDS996_GESTURE_THRESHOLD_OUT && u > APDS996_GESTURE_THRESHOLD_IN && d > APDS996_GESTURE_THRESHOLD_IN) { motion = APDS996_DIR_LEFT; } else if (l > APDS996_GESTURE_THRESHOLD_IN && r > APDS996_GESTURE_THRESHOLD_IN && u > APDS996_GESTURE_THRESHOLD_OUT && d > APDS996_GESTURE_THRESHOLD_OUT) { motion = APDS996_DIR_RIGHT; } else if (l > APDS996_GESTURE_THRESHOLD_OUT && r > APDS996_GESTURE_THRESHOLD_OUT && u > APDS996_GESTURE_THRESHOLD_OUT && d > APDS996_GESTURE_THRESHOLD_IN) { motion = APDS996_DIR_UP; } else if (l > APDS996_GESTURE_THRESHOLD_OUT && r > APDS996_GESTURE_THRESHOLD_OUT && u > APDS996_GESTURE_THRESHOLD_IN && d > APDS996_GESTURE_THRESHOLD_OUT) { motion = APDS996_DIR_DOWN; } else { motion = APDS996_DIR_NONE; } if (motion != APDS996_DIR_NONE) { valid_gesture = 1; } if (valid_gesture) { break; } } if (!valid_gesture) { return APDS996_DIR_NONE; } count = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GCOUNT); if (count == ) { return APDS996_DIR_NONE; } gstatus = I2C_ReadByte(APDS996_I2C_ADDR, APDS996_GSTATUS); if (gstatus & APDS996_GSINT) { I2C_WriteByte(APDS996_I2C_ADDR, APDS996_GINTP, x01); } return motion; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值