IMX6UL-I2C

使用开发板:正点原子-阿尔法开发板

简介

I2C是一种常用总线协议,由NXP公司设计,主从模式,由主机发起通信。I2C使用两条线进行数据传输,一条是SCL(串行时钟线),另外一条是SDA(数据线),这两条数据线需要接上拉电阻。

I2C总线特点

  1. I2C是由数据线(SDA)时钟线(SCL)构成的串行总线,数据线用来传输数据,时钟线用来同步数据收发。
  2. 总线上的每个器件都有一个唯一的地址识别。
  3. SDA和SCL都是双向线路,通过一个电流源或上拉电阻连接到正电压,所以总线空闲时,SDA和SCL都是高电平。
  4. 总线上数据传输速率,标准模式下100kbit/s,快速模式下400kbit/s,高速模式下3.4Mbit/s。
  5. 总线支持设备连接,支持多个主机多个从机,连接到总线上的接口数量有总线电容400pF的限制决定。
    总线空闲时,SDA和SCL为高电平。如下图所示:I2C物理链接图

起始位

起始信号,就是开始I2C通信的开始信号,该信号由主机发送,从机接收。功能是告诉从机从现在“我”要开始通信I2C通信了。
开始信号:SCL为高电平,SDA出现下降沿(即SDA由高电平变为低电平)。信号变化如图所示:
起始位

停止位

停止位就是停止I2C通信的信号,在SCL为高电平的时候,SDA出现上升沿(即SDA由低电平变为高电平)。停止信号

数据传输

I2C总线在传输数据时,必须保证在SCL为高电平期间,SDA上的电平稳定,因此,SDA数据的变化只能在SCL为低电平期间(如果在SCL为高电平期间,SDA上的电平发生变化,会被认为是起始或停止信号)。
数据传输

应答信号

当I2C主机发送完8位数据后,需要将SDA设置为输入状态,等待从机的应答,也就是等待I2C从机告诉主机它接收到数据了。应答信号是从机发送的,主机需要提供应答信号所需的时钟。主机发送完8位数据后紧跟着的一个时钟信号就是给应答信号使用的。
从机通过将SDA信号拉低来表示发出应答信号。主机接收到应答信号表示通信成功,否则表示通信失败。

I2C时序

主机通过I2C总线与从机通讯,主要就是两个操作:读和写

I2C写时序

I2C单字节写时序如图:
I2C写时序
时序图中数字含义:

  1. 发送开始信号
  2. 发送I2C设备地址,设备地址是一个7位的数据,和‘3’共构成一个字节。
  3. I2C器件地址湖面跟着的读写位。0:写操作,1:读操作。
  4. 从机发送应答信号。
  5. 重新发送起始信号。
  6. 要发送的数据的寄存器地址。
  7. 从机应答信号。
  8. 发送要写入的数据。
  9. 从机发送应答信号。
  10. 停止信号。

I2C读时序

读单个字节
I2C单字节的读要比写复杂些,读时序大约分为4个步骤,

  1. 发送设备地址
  2. 发送要读取的寄存器地址
  3. 发送设备地址
  4. I2C从器件输出要读取的寄存器地址

具体步骤如下:

  1. 主机发送开始信号
  2. 主机发送要读取的设备地址
  3. 读写控制位,因为是向主机发送设备地址,所以此位应该是0(写信号)
  4. 从机发送ACK应答信号
  5. 重新发送START信号
  6. 主机发送要读取的寄存器地址
  7. 从机发送ACK应答信号
  8. 重新发送START信号
  9. 重新发送要读取的I2C从设备地址
  10. 读写控制位,这里是读信号(1),表示接下来要从I2C里面读取数据
  11. 从机发送的ACK应答信号
  12. 从I2C器件里面读取到色数据
  13. 主机发送NO ACK信号,表示读取完成,不需要从机在发送ACK信号
  14. 主机发送STOP信号,停止I2C通信

I2C读写多个字节

读写多个字节和单字节基本一致,只是在读写数据的时候可以连续发送多个字节的数据,其他的控制时序是和单字节一样的。

I.MX6UL I2C简介

I.MX6UL提供了4个I2C外设,支持标准模式和快速模式,特征如下:

  1. 与标准I2C兼容
  2. 多主机运行
  3. 软件可编程的64种不同的串行时钟序列
  4. 软件可选择的应答位
  5. 开始/结束信号生成和检测
  6. 重复开始信号生成
  7. 确认位生成
  8. 总线忙检测

主要寄存器

(x=1~4)

  • I2Cx_IADR
    I2C地址寄存器,只有ADR[7:1]位有效,用来保存设备地址数据,当要访问某个I2C从设备的时候,就需要将其设备地址写入到ADR里面。
    I2C_IADR寄存器
功能
IEN[7]I2C使能位,1:使能I2C,0:关闭I2C
IIEN[6]I2C中断使能位, 1:使能中断,0:关闭中断
MSTA[5]主从模式选择位,1:主模式, 0:从模式
MTX[4]传输方向选择位,1:发送,0:接收
TXAK[3]传输应答使能,1:发送NO ACK,0:发送ACK
RSTA[2]重复开始信号,1:产生一个重新开始信号
  • I2Cx_IFDR
    I2C分频寄存器,IC[5:0]有效,用来设置I2C的波特率,I2C的时钟源可以选择IPG_CLK_ROOT=66MHz,通过设置IC可以得到想要的波特率。I2C可选分频如下图:
    I2C_IFDR寄存器
    寄存器I2Cx_IFR也只有IC(bit5:0)这个位,用来设置I2C的波特率。
    IC设置

  • I2Cx_I2CR
    I2C控制寄存器
    I2CR寄存器

功能
IEN(bit7)I2C使能位,1:使能I2C, 0:关闭I2C
IIEN(bit6)I2C中断使能位,1:使能I2C中断, 0:I2C关闭中断
MSTA(bit5)主从模式选择位,1:主模式,0:从模式
MTX(bit4)传输方向选择位,0:接收, 1:发送
TXAK(bit3)传输应答使能位,0:发送ACK信号,1:NO ACK信号
RSTA(bit2)重复开始信号,1:产生一个重新开始信号
  • I2Cx_I2SR
    I2C状态寄存器
    I2C_I2SR寄存器
功能
ICF(bit7)数据传输状态位,0:数据正在传输,1:数据传输完成
IAAS(bit6)
IBB(bit5)I2C总线忙标志位,0:I2C总线空闲,1:总线忙
IAL(bit4)仲裁丢失位,1:仲裁丢失
SRW(bit2)从机读写状态位,0:主机向从机写数据,1:主机要从从机读取数据
IIF(bit1)I2C中断挂起标志位
RXAK(bit0)应答信号标志位
  • I2Cx_I2DR
    I2C数据寄存器

AP3216C简介

三合一环境传感器,支持环境光强度(ALS),接近距离(PS)和红外强度(IR)。该芯片可以通过IIC接口与主控制相连,并且支持中断,AP3216C的特点如下:

  1. I2C接口,快速模式下波特率可以达到400Kbit/S
  2. 多种工作模式选择:ALS、PS+IR、ALS+PS+IR、PD等等
  3. 内建温度补偿电路
  4. 宽工作温度范围(-30°~+80°C)
  5. 超小封装
  6. 环境光传感器具有16位分辨率
  7. 接近传感器和红外传感器具有10位分辨率
寄存器地址 寄存器功能 描述
0X00 2:0 系统模式 000:掉电模式(默认)
001:使能ALS
010:使能PS+IR
011:使能ALS+PS+IR
100:软复位
101:ALS单次模式
110:PS+IR单次模式
111:ALS+PS+IR 单次模式
0X0A 7 IR低位数据 0:IR&PS数据有效位 1:无效
1:0 IR最低两位数据
0X0B 7:0 IR高位数据 IR高8位数据
0X0C 7:0 ALS低位数据 ALS低8位数据
0X0D 7:0 ALS高位数据 ALS高8位数据
0X0E 7 PS低位数据 0:物体在远离,1:物体在接近
6 0:IR&PS数据有效,1:IR&PS数据无效
3:0 PS最低4位数据
0X0F 7 PS高位数据 0:物体在远离,1:物体在接近
6 0:IR&PS数据有效,1:IR&PS数据无效
5:0 PS高6位数据

程序编写

I2C驱动

I2C驱动包括:

  • I2C初始化(I2C频率设置)
  • I2C开始信号、重新开始信号和停止信号(数据传输时的时序,开始信号、重新开始信号函数都有从设备地址)
  • I2C检测和清除错误(传输过程中的状态检测)
  • I2C主机读、写(主机发送或接收数据)
  • I2C数据传输(对读写函数的进一步封装)

最终的对外接口有两个,一个是I2C初始化,一个是I2C数据传输。

I2C的 .h文件,为正点原子例程中代码

#ifndef BSP_I2C_H
#define BSP_I2C_H

#include "imx6ul.h"

/* 定义相关宏 为i2c总线的状态 */
#define I2C_STATUS_OK               (0)		/* 传输完成 */
#define I2C_STATUS_BUSY             (1)		/* 总线忙 */
#define I2C_STATUS_LDLE             (2)		/*  */
#define I2C_STATUS_NAK              (3)		/* 无应答着 */
#define I2C_STATUS_ARBITRATIONLOST  (4)		/* 仲裁错误 */
#define I2C_STATUS_TIMEOUT          (5)		/* 传输超时 */
#define I2C_STATUS_ADDRNAK          (6)		/*  */


/* 
 *  I2C方向枚举类型
 *  传输方向
 */
enum i2c_direction
{
    kI2C_Write = 0, 	/* 主机向从机写数据 */
    kI2C_Read = 1,      /* 主机从从机读数据 */
};


/* 主机传输结构体 */
struct i2c_transfer
{
    unsigned char slaveAddress;         /* 7位从机地址 */
    enum i2c_direction direction;       /* 传输方向 */
    unsigned int subaddress;            /* 寄存器地址 */
    unsigned char subaddressSize;       /* 寄存器长度 */
    unsigned char *volatile data;       /* 数据缓冲区 */
    volatile unsigned int dataSize;     /* 数据缓冲区长度 */
};


/* 函数声明 */
void i2c_init(I2C_Type *base);
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_master_repeated_start(I2C_Type *base, unsigned char address, enum i2c_direction direction);
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status);
unsigned char i2c_master_stop(I2C_Type *base);
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size);
void i2c_master_read(I2C_Type *base, unsigned char *buf, unsigned int size);
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer);


#endif

I2C的 .c文件,为正点原子例程中代码

#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "stdio.h"

/* 
 * @description     : 初始化I2C,波特率100kHZ
 * @param - base    : 要初始化的IIC
 * @return          : 无    
 */
void i2c_init(I2C_Type *base)
{
    /* 1、配置 I2C */
    base->I2CR &= ~(1 << 7);    /* 要访问I2C的寄存器,首先需要关闭I2C */
    
    /* 设置波特率 100khz*/
    base->IFDR = 0X15 << 0;		/* 640分频,时钟选择66Mhz*/

    /* 设置寄存器 I2CR,开启I2C */
    base->I2CR |= (1 << 7);
}

/* 
 * @description         : 发送重新开始信号
 * @param - base        : 要使用的IIC
 * @param - addrss      : 设备地址
 * @param - direction   :方向
 * @return              : 无    
 */
unsigned char i2c_master_repeated_start(I2C_Type *base,  unsigned char address,enum i2c_direction direction)
{
    /* I2C 忙 并且工作在从模式, 跳出。 从模式不用发送重新开始信号 */
    if(base->I2SR & (1 << 5) && (((base->I2CR) & (1 << 5)) == 0))
        return 1;
    /* 
     * 设置寄存器I2CR
     * bit[4]: 1 发送
     * bit[2]: 1 产生重新开始信号
     */
    base->I2CR |= (1 << 4) | (1 << 2);
    
    /* 设置寄存器 I2DR,bit[7:0] :要发送的数据,这里写入从设备地址 */
    base->I2DR = ( (unsigned int) address << 1 ) | ( (direction == kI2C_Read) ? 1 : 0 );
    return 0;
}

/* 
 * @description         : 发送开始信号
 * @param - base        : 要使用的IIC
 * @param - addrss      : 设备地址
 * @param - direction   :方向
 * @return              : 无    
 */
unsigned char i2c_master_start(I2C_Type *base, unsigned char address, enum i2c_direction direction)
{
    if(base->I2SR & (1 << 5))  /* 忙 跳出*/
        return 1;
    /*
     * 设置寄存器I2C
     * bit[5]: 1 主模式
     * bit[4]: 1 发送
     */
    base->I2CR |= (1 << 5) | (1 << 4);
    
    /*
     * 设置寄存器I2DR,bit[7:0]: 要发送的数据,这里写入从设备地址
     */
    base->I2DR = ( (unsigned int)address << 1) | ( (direction == kI2C_Read)? 1 : 0);

    return 0;
}

/*
 * @description         : 检查并清除错误
 * @param - base        : 要使用的IIC
 * @param - status      : 状态
 * @return              : 状态结果 
 */
unsigned char i2c_check_and_clear_error(I2C_Type *base, unsigned int status)
{
    if(status & (1 << 4))       /* 检查是否发生仲裁丢失错误 */
    {
        base->I2SR &= ~(1 << 4);    /* 清除仲裁丢失错误位 */
        base->I2CR &= ~(1 << 7);    /* 先关闭I2C */
        base->I2CR |= (1 << 7);     /* 重新打开 I2C */
        return I2C_STATUS_ARBITRATIONLOST;
    }
    else if(status & (1 << 0)){     /* 没有接收到从机的应答信号 */
        return I2C_STATUS_NAK;
    }
    return I2C_STATUS_OK;
}

/*
 * @description         : 停止信号
 * @param - base        : 要使用的IIC
 * @param               : 无
 * @return              : 状态结果 
 */
unsigned char i2c_master_stop(I2C_Type *base)
{
    unsigned short timeout = 0xFFFF;
    /* 清除I2CR的bit[5:3]这三位 */
    base->I2CR &= ~((1 << 5) | (1 << 4) | (1 << 3));
    while ((base->I2SR & (1 << 5)))     /* 等待忙结束 */
    {
        timeout --;
        if(timeout == 0)        /* 超时跳出 */
        {
            return I2C_STATUS_TIMEOUT; 
        }   
    }
    return I2C_STATUS_OK;
}

/*
 * @description         : 发送数据
 * @param - base        : 要使用的IIC
 * @param - buf         : 要发送的数据
 * @param - size        : 要发送的数据大小
 * @param - flags       : 标志
 * @return              : 无
 */
void i2c_master_write(I2C_Type *base, const unsigned char *buf, unsigned int size)
{
    while(!(base->I2SR & (1 << 7)));        /* 等待数据发送完成 */
    base->I2SR &= ~(1 << 1);                /* 清除标志位 */
    base->I2CR |= 1 << 4;                   /* 发送数据 */
    while(size--)
    {
        base->I2DR = *buf++;                /* 将数据写入buf */
        while(!(base->I2SR & (1 << 1)));    /* 等待发送完成,注意和上面的等待发送判断的不是同一标志位 */
        base->I2SR &= ~(1 << 1);            /* 清除标志位 */

        /* 检查ACK信号 */
        if(i2c_check_and_clear_error(base, base->I2SR))
            break;
    }
    base->I2SR &= ~(1 << 1);
    i2c_master_stop(base);  /* 发送停止位 */
}

/*
 * @description         : 读取数据
 * @param - base        : 要使用的IIC
 * @param - buf         : 读取到的数据
 * @param - size        : 要读取的数据大小
 * @return              : 无 
 */
void i2c_master_read(I2C_Type *base, unsigned char *buf,unsigned int size)
{
    volatile uint8_t dummy = 0;

    dummy ++;  /* 防止编译报错 */
    while(! (base->I2SR & (1 << 7)));       /* 等待传输完成 */
    base->I2SR &= ~(1 << 1);                /* 清除中断挂起位 */
    base->I2CR &= ~((1 << 4) | (1 << 3));   /* 接收数据 */
    /* 如果只接收一个字节的数据发送应答信号 */
    if(size == 1)
    {
        base->I2CR |= (1 << 3);
    }
    dummy = base->I2DR;		/* 假读 */
    while(size--)
    {
        while(!((base->I2SR) & (1 << 1)));  /* 等待传输完成 */
        base->I2SR &= ~(1 << 1);            /* 清除标志位 */

        if(size == 0)
            i2c_master_stop(base);          /* 发送停止信号 */
        if(size == 1)
            base->I2CR |= (1 << 3);    /* 发送停止应答信号  */ 
        *buf++ = base->I2DR;
    }
}

/*
 * @description         : I2C数据传输
 * @param - base        : 要使用的IIC
 * @param - xfer        : 传输结构体
 * @return              : 传输结果 , 0 成功, 其他值 失败
 */
unsigned char i2c_master_transfer(I2C_Type *base, struct i2c_transfer *xfer)
{
    unsigned char ret = 0;
    enum i2c_direction direction = xfer->direction;

    base->I2SR &= ~((1 << 1) | (1 << 4));       /* 清除标志位 */
    while(!((base->I2SR >> 7) & 0x01)){};         /* 等待传输完成 */

    /* 如果是读的话,要先发送寄存器地址,所以要先将方向改为写 */
    if((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
    {   
        direction = kI2C_Write;
    } 
    ret = i2c_master_start(base,xfer->slaveAddress,direction);
    //printf("ret = %d\n",ret);
    if(ret)
    {
        return ret;
    }
    
    while(!(base->I2SR & (1 << 1))){};
    ret = i2c_check_and_clear_error(base,base->I2SR);
    if(ret)
    {
        i2c_master_stop(base);
        return ret;
    }

    /* 发送寄存器地址 */
    if(xfer->subaddressSize)
    {
    	/* 寄存器地址为多个字节 */
        do
        {
           base->I2SR &= ~(1 << 1);
           xfer->subaddressSize--;
           base->I2DR = ((xfer->subaddress) >> (8 * xfer->subaddressSize));	/* 先发送高字节 */
           while(!(base->I2SR & (1 << 1)));
           ret = i2c_check_and_clear_error(base, base->I2SR);
           if(ret)
           {
                i2c_master_stop(base);
                return ret;
           }
        } while ((xfer->subaddressSize > 0) && (ret == I2C_STATUS_OK));
        
        /* 读从机数据需要发送重新开始信号 */
        if(xfer->direction == kI2C_Read)
        {
            base->I2SR &= ~(1 << 1);
            i2c_master_repeated_start(base, xfer->slaveAddress, kI2C_Read);
            //printf("send restart \n");
            while(!(base->I2SR & (1 << 1))){};
            
            ret = i2c_check_and_clear_error(base, base->I2SR);
            //printf("read ret = %d\n",ret);
            if(ret)
            {
                ret = I2C_STATUS_ADDRNAK;
                i2c_master_stop(base);
                return ret;
            }
        }
    }
        
    /* 发送数据 */
    if((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
        i2c_master_write(base,xfer->data, xfer->dataSize);

    /* 读取数据 */
    if((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
        i2c_master_read(base, xfer->data, xfer->dataSize);
    
    return 0;
}

AP3216C应用程序

获取AP3216C的ALS、PS、IR三个参数值,采用I2C通信。AP3216C应用程序中主要包括:

  • AP3216C初始化(引脚配置)
  • 读写AP3216C中的寄存器数据
  • 获取ALS、PS、IR值

AP3216C的 .h文件,为正点原子例程中代码

#ifndef __BSP_AP3216C_H
#define __BSP_AP3216C_H

#include "imx6ul.h"

#define AP3216C_ADDR        0x1E    /* AP3216C器件地址 */

/* AP3216C寄存器地址 */
#define AP3216C_SYSTEMCONG   0x00   /* 配置寄存器 */
#define AP3216C_INTSTATUS    0x01   /* 中断状态寄存器 */
#define AP3216C_INTCLEAR     0x02   /* 中断清除寄存器*/
#define AP3216C_IRDATALOW    0x0A   /* IR数据低字节 */
#define AP3216C_IRDATAHIGH   0x0B   /* IR数据高字节 */
#define AP3216C_ALSDATALOW   0x0C   /* ALS数据低字节 */   
#define AP3216C_ALSDATAHIGH  0x0D   /* ALS数据高字节 */
#define AP3216C_PSDATALOW    0x0E   /* PS数据低字节 */
#define AP3216C_PSDATAHIGH   0x0F   /* PS数据高字节 */

/* 函数声明 */
unsigned char ap3216c_init(void);
unsigned char ap3216c_readonebyte(unsigned char addr, unsigned char reg);
unsigned char ap3216c_writeonebyte(unsigned char addr, unsigned char reg,unsigned char data);
void ap3216c_readdata(unsigned short *ir, unsigned short *ps, unsigned short *als);
#endif

AP3216C的 .c文件,为正点原子例程中代码

#include "bsp_ap3216c.h"
#include "bsp_i2c.h"
#include "bsp_delay.h"
#include "cc.h"
#include  "stdio.h"
#include "bsp_uart.h"

/*
 * @description    : 初始化AP3216C
 * @param          : 无
 * @return         : 0 成功, 其他值 错误代码
 */
unsigned char ap3216c_init(void)
{
    unsigned char data = 0;

    /* 
     * 1、IO初始化,配置IO属性  使用I2C1,
     * I2C1_SCL -> UART4_TXD
     * I2C1_SDA -> UART4_RXD
     */
    IOMUXC_SetPinMux(IOMUXC_UART4_TX_DATA_I2C1_SCL,1);
    IOMUXC_SetPinMux(IOMUXC_UART4_RX_DATA_I2C1_SDA,1);
    IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL, 0x70B0);
    IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA, 0x70B0);
	
	/* 2、初始化I2C1 */
    i2c_init(I2C1);
	
	/* 
	 * 3、初始化AP3216C
	 *  复位AP3216C
	 */
    ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0x04);
    delayms(50); /* AP3216C复位至少10ms,*/

	/* 开启 ALS、PS+IR模式 */
    ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0x03);

	/* 读取刚刚写进去的 0X03 */
    data = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG);
    //printf("data = %x\n", data);
    if(data == 0x03)
        return 0;	/* AP3216C 正常 */
    else
        return 1;	/* AP3216C 失败 */
}


/*
 * @description    : 向AP3216C写数据
 * @param - addr   : 设备地址
 * @param - reg    : 要写入的寄存器
 * @param - data   : 要写入的数据
 * @return         : 操作结果
 */
unsigned char ap3216c_writeonebyte(unsigned char addr,
                                   unsigned char reg,
                                   unsigned char data)
{
    unsigned char status = 0;
    unsigned char writedata = data;
    struct i2c_transfer masterXfer;

    /* 配置I2C xfer结构体 */
    masterXfer.slaveAddress = addr;     /* 设备地址 */
    masterXfer.direction = kI2C_Write;  /* 写入数据 */
    masterXfer.subaddress = reg;        /* 要写入数据的寄存器地址 */
    masterXfer.subaddressSize = 1;      /* 地址长度 1个字节 */
    masterXfer.data = &writedata;       /* 要写入的数据 */
    masterXfer.dataSize = 1;            /* 数据长度 1个字节 */

    if(i2c_master_transfer(I2C1,&masterXfer))
        status = 1;

    return status;
}   

/*
 * @description    : 向AP3216C读数据
 * @param - addr   : 设备地址
 * @param - reg    : 要读取的寄存器
 * @return         : 读到的数据
 */
unsigned char ap3216c_readonebyte(unsigned char addr,
                                  unsigned char reg)
{
    unsigned char val = 0;

    struct i2c_transfer masterXfer;
    masterXfer.slaveAddress = addr;
    masterXfer.direction = kI2C_Read;
    masterXfer.subaddress = reg;
    masterXfer.subaddressSize = 1;
    masterXfer.data = &val;
    masterXfer.dataSize = 1;
    i2c_master_transfer(I2C1,&masterXfer);

    return val;
}    

/*
 * @description    : 读取AP3216C的原始数据,包括ALS,PS,IR,
 *                 : 同时打开ALS,IR+PS,两次数据读取的时间间隔需要大于112.5ms
 * @param - ir     : ir数据
 * @param - ps     : 数据
 * @param - als    : als数据
 * @return         : 无
 */
void ap3216c_readdata(unsigned short *ir,
                      unsigned short *ps,
                      unsigned short *als)
{
    unsigned char buf[6];
    unsigned char i;

    /* 循环读取数据 */
    for(i=0; i<6; i++)
    {
    	/* 读取0X0A~0X0F的数据*/
        buf[i] = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_IRDATALOW + i);	/* +i 是地址偏移,*/
    }

    if(buf[0] & 0x08)   /* IR_OF位为1,则数据无效 */
        *ir = 0;
    else
        *ir = ((unsigned short)buf[1] << 2 | (buf[0] & 0x03));
    
    *als = ((unsigned short)buf[3] << 8) | buf[2];

    if(buf[4] & 0x40)
        *ps = 0;
    else
        *ps = ((unsigned short)(buf[5] & 0x3F) << 4) | (buf[4] & 0x0F);
}                      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值