EFR32BG22 I2C通讯学习笔记

项目中需要用到Silicon Labs的ERF32BG22系列的芯片,接收从机的I2C数据并且通过蓝牙BLE发送到手机端。

一.引脚配置

1.首先通过SSV5的pintool工具配置芯片引脚,例如将PC0配置为SCL,PC1配置为SDA。

2.需要先在SOFEWARE COMPONENTS中开启I2C相关外设和驱动

3.接着给引脚添加Software Component功能

4.I2C的基本设置,例如使用EFR32BG22的I2C0,速度设置为100kbit/s

完成配置后在sl_driver_init(void)中,SSV5会自动生成I2C初始化函数

void sl_driver_init(void)
{
  sl_i2cspm_init_instances();
}

二.I2C接收和发送函数

//发送函数
static sl_status_t user_i2c_send_data(sl_i2cspm_t *i2cspm, uint8_t addr, uint8_t *command,
                                          uint8_t command_len)
{
  I2C_TransferSeq_TypeDef    seq;
  I2C_TransferReturn_TypeDef ret;
  uint8_t                    i2c_write_data[8];
  uint8_t i;

  seq.addr  = addr<<1;
  seq.flags = I2C_FLAG_WRITE;
  /* Select command to issue */
  for(i=0;i<command_len;i++)
    {
      i2c_write_data[i] = command[i];
    }
  seq.buf[0].data   = i2c_write_data;
  seq.buf[0].len    = command_len;


  ret = I2CSPM_Transfer(i2cspm, &seq);
  return SL_STATUS_OK;
}

//接收函数
static sl_status_t user_i2c_read_data(sl_i2cspm_t *i2cspm, uint8_t addr, uint8_t *data,uint8_t data_len)
{
  I2C_TransferSeq_TypeDef    seq;
  I2C_TransferReturn_TypeDef ret;
  uint8_t                    i2c_read_data[8];
  uint8_t i;
  seq.addr  = addr<<1;
  seq.flags = I2C_FLAG_READ;
  /* Select command to issue */
  seq.buf[0].data = i2c_read_data;
  seq.buf[0].len  = data_len;


  ret = I2CSPM_Transfer(i2cspm, &seq);

  for(i=0;i<I2C_BUFFER_SIZE;i++)
    {
      data[i] = i2c_read_data[i];
    }


  return SL_STATUS_OK;
}

发送和接收主要通过对I2C_TransferSeq_TypeDef这个结构体进行相应操作

typedef struct {
  /**
   * @brief
   *   Address to use after (repeated) start.
   * @details
   *   Layout details, A = Address bit, X = don't care bit (set to 0):
   *   @li 7 bit address - Use format AAAA AAAX
   *   @li 10 bit address - Use format XXXX XAAX AAAA AAAA
   */
  uint16_t addr;//I2C从机地址

  /** Flags defining sequence type and details, see I2C_FLAG_ defines. */

  uint16_t flags;//需要I2C进行的操作

  /**
   * Buffers used to hold data to send from or receive into, depending
   * on sequence type.
   */
  struct {
    /** Buffer used for data to transmit/receive, must be @p len long. */
    uint8_t  *data;//发送或者接收的数据

    /**
     * Number of bytes in @p data to send or receive. Notice that when
     * receiving data to this buffer, at least 1 byte must be received.
     * Setting @p len to 0 in the receive case is considered a usage fault.
     * Transmitting 0 bytes is legal, in which case only the address
     * is transmitted after the start condition.
     */
    uint16_t len;//数据长度
  } buf[2];
} I2C_TransferSeq_TypeDef;

其中flags可以设置为以下几种状态

#define I2C_FLAG_WRITE          0x0001//I2C进行写数据操作

/**
 * @brief
 *   Indicate plain read sequence: S+ADDR(R)+DATA0+P.
 * @details
 *   @li S - Start
 *   @li ADDR(R) - Address with W/R bit set
 *   @li DATA0 - Data read into buffer with index 0
 *   @li P - Stop
 */
#define I2C_FLAG_READ           0x0002//I2C进行读数据操作

/**
 * @brief
 *   Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P.
 * @details
 *   @li S - Start
 *   @li Sr - Repeated start
 *   @li ADDR(W) - Address with W/R bit cleared
 *   @li ADDR(R) - Address with W/R bit set
 *   @li DATAn - Data written from/read into buffer with index n
 *   @li P - Stop
 */
#define I2C_FLAG_WRITE_READ     0x0004

//I2C进行写数据操作之后读取数据,I2C_TransferSeq_TypeDef中有两个buf,例如可以将buf[0]中的data作为需要写入的数据,将buf[1]中的data设置为接收的数据

/**
 * @brief
 *   Indicate write sequence using two buffers: S+ADDR(W)+DATA0+DATA1+P.
 * @details
 *   @li S - Start
 *   @li ADDR(W) - Address with W/R bit cleared
 *   @li DATAn - Data written from buffer with index n
 *   @li P - Stop
 */
#define I2C_FLAG_WRITE_WRITE    0x0008

/** Use 10 bit address. */
#define I2C_FLAG_10BIT_ADDR     0x0010

设置完成后通过自带的I2CSPM_Transfer函数启动I2C发送或者接收。

三.与从机通讯验证

使用上述函数发送0xAC,0x78,0x01,0x52命令使从机开始发送数据并接受从机发回的数据,从机地址为0x7D,发送命令之后成功接收到从机发回的{1,2,3,6,6,6,0,0}.

四.蓝牙GATT Configuratior

新建自己的Services,新建自己的Characteristics  Data用于显示接收到的I2C数据

Data中的ID一定要勾选并且取名之后可以在gatt_db.h文件中找到自己新建Characteristics,例如我这里自动生成的#define gattdb_Sensor_data                    21

五.蓝牙事件代码

static void i2c_char_config_changed_cb(sl_bt_evt_gatt_server_characteristic_status_t *data)
{
  bool enable = sl_bt_gatt_disable != data->client_config_flags;
  i2c_connection = data->connection;

  // update notification status
  switch (data->characteristic) {
    case gattdb_Sensor_data:
      i2c__notification = enable;
      break;
    default:
      //app_assert(false, "Unexpected characteristic\n");
      break;
  }
}

有了上面的ID,当触发相关事件时,才能将数据正常传入到我们需要的Characteristics中。

static void i2c_notify(void)//接收I2C数据,并且将其链接到Sensor_data中
{
  sl_status_t sc;
  uint8_t i;
  for(i=0;i<I2C_BUFFER_SIZE;i++)
    {
      i2c_buf[i] = i2c_Buffer[i];
    }

  sc = sl_bt_gatt_server_send_notification(
      i2c_connection,
      gattdb_Sensor_data,
    sizeof(i2c_buf),
    (uint8_t*)i2c_buf);
}

void sl_gatt_service_i2c_step(void)//gatt服务
{
  if (i2c__notification)
  {
      i2c_notify();
  }
}

在void sl_bt_on_event(sl_bt_msg_t *evt)中添加事件相应代码

case sl_bt_evt_gatt_server_characteristic_status_id:
       if ((sl_bt_gatt_server_client_config ==                 
    (sl_bt_gatt_server_characteristic_status_flag_t)evt->data.evt_gatt_server_characteristic_status.status_flags)
              && (gattdb_Sensor_data == evt->data.evt_gatt_server_user_read_request.characteristic))
          {
            // client characteristic configuration changed by remote GATT client
              i2c_char_config_changed_cb(&evt->data.evt_gatt_server_characteristic_status);
          }
 break;

将sl_gatt_service_i2c_step()放入sl_internal_app_process_action中使得在触发相应时间后能执行相应操作

void sl_internal_app_process_action(void)
{
  sl_gatt_service_i2c_step();
}

当手机端的notify被打开始,将会显示I2C接收到的数据

初值显示为Data

打开notify之后显示I2C接收到的数据

  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值