赞
踩
iic主机驱动,(一旦编写完成就不需要再做修改)其他的 I2C 设备直接调用主机驱动提供的API函数完成读写操作即可
上面可以看到主机驱动已经留够了坑(主机可以连接不同的设备)
bsp_i2c.h文件
#ifndef _BSP_I2C_H #define _BSP_I2C_H #include "imx6ul.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); #endif
bsp_i2c.c
bsp_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 */ /* 设置波特率为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; }
#ifndef _BSP_AP3216C_H #define _BSP_AP3216C_H #include "imx6ul.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); #endif
#include "bsp_ap3216c.h" #include "bsp_i2c.h" #include "bsp_delay.h" #include "cc.h" #include "stdio.h" /* * @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); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。