I2C实验

一、I2C介绍

1.1 I2C简介

I2C使用两条线在主控制器和从机之间进行数据通信,一条串行时钟线(SCL),一条是串行数据线(SDA),这两条线需要接上拉电阻(阻值一般4.7K),总线空闲的时候SCL和SDA都处于高电平。I2C总线标准模式下速度可达100KB/s,快速模式下可达400KB/s

I2C支持多从机,这些不同的I2C从设备有不同的器件地址,I2C控制器可以通过从设备的器件地址访问指定的I2C设备
Linux裸机开发|I2C实验_寄存器
I2C总线工作是按照一定的协议来运行的,下面介绍I2C有关的术语

  • 起始位:SCL为高电平时,SDA出现下降沿表示起始位
    Linux裸机开发|I2C实验_i2c_02
  • 停止位:SCL为高电平时,SDA出现上升沿表示停止位
    Linux裸机开发|I2C实验_imx6ull_03
  • 数据传输:数据传输时要保证SCL高电平期间,SDA上的数据稳定;因此SDA上的数据变化只能发生在SCL低电平期间
    Linux裸机开发|I2C实验_寄存器_04
  • 应答信号:I2C主机发送完8位数据后会将SDA设置为输入状态,等待I2C从机应答;应答信号由从机发出,通过将SDA拉低来发出应答信号,表示通信成功
  • I2C写时序:I2C总线单字节写时序如下图示
    Linux裸机开发|I2C实验_imx6ull_05

– 1. 开始信号
– 2. 发送I2C设备地址
– 3. 读写位,0表示写操作,1表示读操作
– 4. 从机发送的ACK应答信号
– 5. 重新发送开始信号
– 6. 发送要写入数据的寄存器地址
– 7. 从机发送的ACK应答信号
– 8. 发送要写入寄存器的数据
– 9. 从机发送的ACK应答信号
– 10. 停止信号

  • I2C读时序:I2C总线单字节读时序如下图示
    Linux裸机开发|I2C实验_linux_06

– 1. 主机发送起始信号
– 2. 主机发送要读取的I2C从设备地址
– 3. 读写控制位,此时是向从设备发送数据,因此是写信号
– 4. 从机发送的ACK应答信号
– 5. 重新发送开始信号
– 6. 主机发送要读取的寄存器地址
– 7. 从机发送的ACK应答信号
– 8. 重新发送开始信号
– 9. 从新发送要读取的I2C从设备地址
– 10. 读写控制位,此时是从I2C从设备里读取数据,因此是读信号
– 11. 从机发送的ACK应答信号
– 12. 从I2C器件里读取到的数据
– 13. 主机发出NO ACK信号表示读取完成,不需要从机再发ACK信号了
– 14. 主机发出停止信号

1.2 IMX6U I2C介绍

IMX6U提供了4个I2C外设,通过这四个I2C外设即可完成与I2C从器件进行通信。IMX6U的I2C支持两种模式:标准模式(100KB/s)和快速模式(400KB/s)

I2C外设几个重要的寄存器

  • I2Cx_IADR 寄存器:I2C地址寄存器 (x = 1 ~ 4),用来保存从设备地址(bit7:1有效)
    Linux裸机开发|I2C实验_寄存器_07
  • I2Cx_IFDR 寄存器:分频寄存器,用来设置波特率,通过IC位设置波特率
    Linux裸机开发|I2C实验_i2c_08
  • I2Cx_I2CR 寄存器:I2C控制寄存器
    Linux裸机开发|I2C实验_imx6ull_09

– IEN:I2C使能位,为1使能,为0关闭
– IIEN:I2C中断使能位,为1使能,为0关闭
– MSTA:主从模式选择位,为1时工作为主模式,为0时工作在从模式
– MTX:传输方向选择位,为0时接收,为1时发送
– TXAK:传输应答使能,为0发送ACK信号,为1发送NO ACK信号
– RSTA:重复开始信号,为1表示产生一个重新开始信号

  • I2Cx_I2SR 寄存器:I2C状态寄存器
    Linux裸机开发|I2C实验_linux_10

– ICF:数据传输状态位,为0表示数据正在传输,为1表示数据传输完成
– IAAS:为1时表示I2C地址,即I2Cx_IADR寄存器中的地址是从设备地址
– IBB:I2C总线忙标志位,为0表示I2C总线空闲,为1表示总线忙
– IAL:仲裁丢失位,为1时表示发生仲裁丢失
– SRW:从机读写状态位,为0表示主机要向从机写数据,为1表示从从机读取数据
– IIF:I2C中断挂起标志位,为1时表示有中断挂起,此位需要软件清零
– RXAK:应答信号标志位,为0时表示接收到ACK应答信号,为1时表示NO ACK信号

  • I2Cx_I2DR 寄存器:I2C数据寄存器,低8位有效;当要发送数据的时候将要发送的数据写入到此寄存器,当要接收数据的话直接读取此寄存器即可得到接收到的数据
1.3 AP3216C传感器介绍

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

AP3216C常被用于手机、平板、导航设备等,其内置的接近传感器可以用于检测是由有物体接近,也可以使用环境光传感器检测光强度,可以实现自动背光亮度调节。AP3216C结构图如下示
Linux裸机开发|I2C实验_i2c_11AP3216的设备地址为0x1E,AP3216C内部也有一些寄存器,通过这些寄存器可以配置AP3216C的工作模式,并读取相应的数据,AP3216C内部寄存器如下表示:
Linux裸机开发|I2C实验_寄存器_12

综上所述,AP3216C的配置步骤如下:

  1. 初始化相应的IO,设置复用功能,若使用中断还需要设置中断IO
  2. 初始化I2C1,设置波特率
  3. 初始化AP3216C ,读取AP3216C的数据

二、硬件介绍

本例程需要用到的硬件资源:

  • LED0
  • RGB LCD接口
  • UART
  • AP3216C

AP3216C的原理图如下示
Linux裸机开发|I2C实验_寄存器_13

三、程序编写

  • 新建i2c文件夹,在文件夹中创建实时时钟驱动文件bsp_i2c.c和bsp_i2c.h
/* 相关宏定义 */
#define I2C_STATUS_OK				(0)
#define I2C_STATUS_BUSY				(1)
#define I2C_STATUS_IDLE				(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 = 0x0, 		/* 主机向从机写数据 */
    kI2C_Read = 0x1,  		/* 主机从从机读数据 */
} ;
/*
 * 主机传输结构体
 */
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);
/*
 * @description		: 初始化I2C,波特率100KHZ
 * @param - base 	: 要初始化的IIC设置
 * @return 			: 无
 */
void i2c_init(I2C_Type *base)
{
	/* 1、配置I2C */
	base->I2CR &= ~(1 << 7); /* 要访问I2C的寄存器,首先需要先关闭I2C */

    /* 设置波特率为100K
     * I2C的时钟源来源于IPG_CLK_ROOT=66Mhz
 	 * IC2 时钟 = PERCLK_ROOT/dividison(IFDR寄存器)
	 * 设置寄存器IFDR,IFDR寄存器参考IMX6UL参考手册P1260页,表29-3,
	 * 根据表29-3里面的值,挑选出一个还是的分频数,比如本例程我们
	 * 设置I2C的波特率为100K, 因此当分频值=66000000/100000=660.
	 * 在表29-3里面查找,没有660这个值,但是有640,因此就用640,
	 * 即寄存器IFDR的IC位设置为0X15
	 */
	base->IFDR = 0X15 << 0;

	/*
     * 设置寄存器I2CR,开启I2C
     * bit[7] : 1 使能I2C,I2CR寄存器其他位其作用之前,此位必须最先置1
	 */
	base->I2CR |= (1<<7);
}

/*
 * @description			: 发送重新开始信号
 * @param - base 		: 要使用的IIC
 * @param - addrss		: 设备地址
 * @param - direction	: 方向
 * @return 				: 0 正常 其他值 出错
 */
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] : 要发送的数据,这里写入从设备地址
     *            参考资料:IMX6UL参考手册P1249
	 */ 
	base->I2DR = ((unsigned int)address << 1) | ((direction == kI2C_Read)? 1 : 0);
	
	return 0;
}

/*
 * @description			: 发送开始信号
 * @param - base 		: 要使用的IIC
 * @param - addrss		: 设备地址
 * @param - direction	: 方向
 * @return 				: 0 正常 其他值 出错
 */
unsigned char i2c_master_start(I2C_Type *base, unsigned char address,  enum i2c_direction direction)
{
	if(base->I2SR & (1 << 5))			/* I2C忙 */
		return 1;

	/*
     * 设置寄存器I2CR
     * bit[5]: 1 主模式
     * bit[4]: 1 发送
	 */
	base->I2CR |=  (1 << 5) | (1 << 4);

	/*
     * 设置寄存器I2DR
     * bit[7:0] : 要发送的数据,这里写入从设备地址
     *            参考资料:IMX6UL参考手册P1249
	 */ 
	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;		/* 返回NAK(No acknowledge) */
	}
	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中的数据写入到I2DR寄存器 */
		
		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));	/* 接收数据 */
	
	/* 如果只接收一个字节数据的话发送NACK信号 */
	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) & 0X1)){}; 

	/* 如果是读的话,要先发送寄存器地址,所以要先将方向改为写 */
    if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read))
    {
        direction = kI2C_Write;
    }

	ret = i2c_master_start(base, xfer->slaveAddress, direction); /* 发送开始信号 */
    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)); //向I2DR寄存器写入子地址
  
			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); /* 发送重复开始信号和从机地址 */
    		while(!(base->I2SR & (1 << 1))){};/* 等待传输完成 */

            /* 检查是否有错误发生 */
			ret = i2c_check_and_clear_error(base, base->I2SR);
            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文件夹,在文件夹中创建实时时钟驱动文件bsp_ap3216c.c和bsp_ap3216c.h
#define AP3216C_ADDR    	0X1E	/* AP3216C器件地址 */
/* AP3316C寄存器 */
#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);
/*
 * @description	: 初始化AP3216C
 * @param		: 无
 * @return 		: 0 成功,其他值 错误代码
 */
unsigned char ap3216c_init(void)
{
	unsigned char data = 0;

	/* 1、IO初始化,配置I2C IO属性	
     * 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);

	/* 
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 1 默认47K上拉
	 *bit [13]: 1 pull功能
	 *bit [12]: 1 pull/keeper使能 
	 *bit [11]: 0 关闭开路输出
	 *bit [7:6]: 10 速度100Mhz
	 *bit [5:3]: 110 驱动能力为R0/6
	 *bit [0]: 1 高转换率
	 */
	IOMUXC_SetPinConfig(IOMUXC_UART4_TX_DATA_I2C1_SCL, 0x70B0);
	IOMUXC_SetPinConfig(IOMUXC_UART4_RX_DATA_I2C1_SDA, 0X70B0);

	i2c_init(I2C1);		/* 初始化I2C1 */

	/* 2、初始化AP3216C */
	ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0X04);	/* 复位AP3216C 			*/
	delayms(50);													/* AP33216C复位至少10ms */
	ap3216c_writeonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG, 0X03);	/* 开启ALS、PS+IR 		   	*/
	data = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_SYSTEMCONG);	/* 读取刚刚写进去的0X03 */
	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;				/* 地址长度一个字节 			*/
    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;					/* 读取数据长度1个字节			*/
	i2c_master_transfer(I2C1, &masterXfer);

	return val;
}

/*
 * @description	: 读取AP3216C的数据,读取原始数据,包括ALS,PS和IR, 注意!
 *				: 如果同时打开ALS,IR+PS的话两次数据读取的时间间隔要大于112.5ms
 * @param - ir	: ir数据
 * @param - ps 	: ps数据
 * @param - ps 	: 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++)	
    {
        buf[i] = ap3216c_readonebyte(AP3216C_ADDR, AP3216C_IRDATALOW + i);	
    }
	
    if(buf[0] & 0X80) 	/* IR_OF位为1,则数据无效 */
		*ir = 0;					
	else 				/* 读取IR传感器的数据   		*/
		*ir = ((unsigned short)buf[1] << 2) | (buf[0] & 0X03); 			
	
	*als = ((unsigned short)buf[3] << 8) | buf[2];	/* 读取ALS传感器的数据 			 */  
	
    if(buf[4] & 0x40)	/* IR_OF位为1,则数据无效 			*/
		*ps = 0;    													
	else 				/* 读取PS传感器的数据    */
		*ps = ((unsigned short)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F); 	
}

  • 主函数main.c中编写测试程序
int main(void)
{
	unsigned short ir, als, ps;
	unsigned char state = OFF;

	int_init(); 				/* 初始化中断(一定要最先调用!) */
	imx6u_clkinit();			/* 初始化系统时钟 			*/
	delay_init();				/* 初始化延时 			*/
	clk_enable();				/* 使能所有的时钟 			*/
	led_init();					/* 初始化led 			*/
	beep_init();				/* 初始化beep	 		*/
	uart_init();				/* 初始化串口,波特率115200 */
	lcd_init();					/* 初始化LCD 			*/

	tftlcd_dev.forecolor = LCD_RED;	
	lcd_show_string(30, 50, 200, 16, 16, (char*)"ALPHA-IMX6U IIC TEST");  
	lcd_show_string(30, 70, 200, 16, 16, (char*)"AP3216C TEST");  
	lcd_show_string(30, 90, 200, 16, 16, (char*)"ATOM@ALIENTEK");  
	lcd_show_string(30, 110, 200, 16, 16, (char*)"2019/3/26");  
	
	while(ap3216c_init())		/* 检测不到AP3216C */
	{
		lcd_show_string(30, 130, 200, 16, 16, (char*)"AP3216C Check Failed!");
		delayms(500);
		lcd_show_string(30, 130, 200, 16, 16, (char*)"Please Check!        ");
		delayms(500);
	}	
	
	lcd_show_string(30, 130, 200, 16, 16, (char*)"AP3216C Ready!");  
    lcd_show_string(30, 160, 200, 16, 16, (char*)" IR:");	 
	lcd_show_string(30, 180, 200, 16, 16, (char*)" PS:");	
	lcd_show_string(30, 200, 200, 16, 16, (char*)"ALS:");	
	tftlcd_dev.forecolor = LCD_BLUE;	
	while(1)					
	{
		ap3216c_readdata(&ir, &ps, &als);		/* 读取数据		  	*/
		lcd_shownum(30 + 32, 160, ir, 5, 16);	/* 显示IR数据 		*/
        lcd_shownum(30 + 32, 180, ps, 5, 16);	/* 显示PS数据 		*/
        lcd_shownum(30 + 32, 200, als, 5, 16);	/* 显示ALS数据 	*/ 
		delayms(120);
		state = !state;
		led_switch(LED0,state);	
	}
	return 0;
}

四、下载验证

  • 修改Makefile文件:修改TARGET为ap3216c,追加“bsp/ap3216c”和“bsp/i2c”文件夹
  • 使用imxdownload软件将bin文件下载到SD卡中
  • 烧写成功后,插入SD卡,复位开发板后,LCD屏幕上会显示环境光强度(ALS)、接近距离(PS)和红外强度(IR)的数值