📄 i2c.c
字号:
/***********************************************Copyright (c)*********************************************
** Guangzou ZLG-MCU Development Co.,LTD.
**
** http://www.zlgmcu.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name: IIC.c
** Last modified Date: 2007-10-15
** Last Version: 1.0
** Descriptions: I2C函数实现,采用设备描述符来操作
**
**--------------------------------------------------------------------------------------------------------
** Created by: lixiaocheng
** Created date: 2007-10-15
** Version: 1.0
** Descriptions: 无
**
**--------------------------------------------------------------------------------------------------------
** Modified by: lixiaocheng
** Modified Date: 2007-10-26
** Version: 1.1
** Descriptions: 增加了I2C对UCOSII操作系统的兼容
**
*********************************************************************************************************/
#include "Config.h"
#include "I2cPrivate.h"
#include "I2c.h"
#include "I2cHook.h"
#include "CmdStr.h"
#include "DeviceConfig.h"
/*********************************************************************************************************
定义操作I2C器件的结构体,有多个器件就需要声明多个结构体
*********************************************************************************************************/
static __I2C_INFO __I2C0Data;
static __I2C_INFO __I2C1Data;
static __I2C_INFO __I2C2Data;
/*********************************************************************************************************
是操作系统就申明信号量
*********************************************************************************************************/
#if __UCOSII_EN > 0
OS_EVENT *GposeI2c0Sem;
OS_EVENT *GposeI2c1Sem;
OS_EVENT *GposeI2c2Sem;
OS_EVENT **GpposeI2cTable[__IIC_MAX_NUM] = {&GposeI2c0Sem, &GposeI2c1Sem, &GposeI2c2Sem};
#endif
/*********************************************************************************************************
下面使用指针数组来保存结构体指针,方便对该驱动的扩展
*********************************************************************************************************/
const __PI2C_INFO __GpiinfoDateTab[__IIC_MAX_NUM] = {&__I2C0Data, &__I2C1Data, &__I2C2Data};
/*********************************************************************************************************
下面定义了I2C0基地址值,如果有多个I2C器件可以在该位置添加相应的基地址即可
*********************************************************************************************************/
const uint32 __GuiI2cBaseAddrTab[__IIC_MAX_NUM] = {I2C0_BASE_ADDR, I2C1_BASE_ADDR, I2C2_BASE_ADDR};
/*********************************************************************************************************
** Function name: endBus
** Descriptions: 总线错误结束总线,改函数被__i2cISR调用
** Input parameters: Parm--I2C设备描述符结构体指针
** Output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
static void __endBus (__PI2C_INFO Parm)
{
uint32 uiOffBase;
volatile uint8 *pucAddrBase;
pucAddrBase = Parm->pucAddrBase;
uiOffBase = Parm->uiOffBase;
pucAddrBase[__B_IIC_SET << uiOffBase] = 1 << 4; /* 总线出错,结束总线.STO */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x2C; /* 总线出错,清零STA,SI,AA */
Parm->ucIICflag = I2C_ERR;
__I2C_UNLOCK(*GpposeI2cTable[Parm->uiID]); /* 释放信号量 */
}
/*********************************************************************************************************
** Function name: AddrWrite
** Descriptions: 写入从机地址,改函数被__i2cISR调用
** Input parameters: Parm--I2C设备描述符结构体指针
** Output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
static void __AddrWrite (__PI2C_INFO Parm)
{
uint32 uiOffBase;
volatile uint8 *pucAddrBase;
pucAddrBase = Parm->pucAddrBase;
uiOffBase = Parm->uiOffBase;
if (Parm->ucI2CSubAddrCtl == 1) { /* 指定子地址读时,先写入地址 */
pucAddrBase[__B_IIC_DAT << uiOffBase] = (uint8)((Parm->ucSLAddr)&0xFE);
} else { /* 否则直接发送从机地址 */
pucAddrBase[__B_IIC_DAT << uiOffBase] = (Parm->ucSLAddr);
}
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28; /* 清除中断标志 */
}
/*********************************************************************************************************
** Function name: dateWrite
** Descriptions: 写入数据,改函数被__subAddrWrite调用
** Input parameters: Parm--I2C设备描述符结构体指针
** Output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
static void __dateWrite (__PI2C_INFO Parm)
{
uint32 uiOffBase;
volatile uint8 *pucAddrBase;
pucAddrBase = Parm->pucAddrBase;
uiOffBase = Parm->uiOffBase;
if (Parm->usDataNum > 0) {
pucAddrBase[__B_IIC_DAT << uiOffBase] = *Parm->pucDataBuf++;
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28; /* 清零SI,STA */
Parm->usDataNum--;
} else {
pucAddrBase[__B_IIC_SET << uiOffBase] = 0x10; /* 无数据发送结束总线 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucIICflag = I2C_WRITE_END; /* 设置总线结束标志 */
__I2C_UNLOCK(*GpposeI2cTable[Parm->uiID]); /* 释放信号量 */
}
}
/*********************************************************************************************************
** Function name: dateRead
** Descriptions: 读取数据,改函数被__i2cISR调用
** Input parameters: Parm--I2C设备描述符结构体指针
** Output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
static void __dateRead (__PI2C_INFO Parm)
{
uint32 uiOffBase;
volatile uint8 *pucAddrBase;
pucAddrBase = Parm->pucAddrBase;
uiOffBase = Parm->uiOffBase;
*(Parm->pucDataBuf++) = pucAddrBase[__B_IIC_DAT << uiOffBase];
Parm->usDataNum--;
switch ( Parm->usDataNum ) {
case 0:
pucAddrBase[__B_IIC_SET << uiOffBase] = 0x10; /* 结束总线 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucIICflag = I2C_READ_END; /* 返回读取成功 */
__I2C_UNLOCK(*GpposeI2cTable[Parm->uiID]); /* 释放信号量 */
break;
case 1: /* 接收最后一个字节 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x2C; /* 再接收到数据返回非应答位 */
break;
default:
pucAddrBase[__B_IIC_SET << uiOffBase] = 0x04; /* 接收到数据,返回ACK */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
break;
}
}
/*********************************************************************************************************
** Function name: subAddrWrite
** Descriptions: 写入从机子地址地址,改函数被__i2cISR调用
** Input parameters: Parm--I2C设备描述符结构体指针
** Output parameters: NONE
** Returned value: NONE
*********************************************************************************************************/
static void __subAddrWrite (__PI2C_INFO Parm)
{
uint32 uiOffBase;
volatile uint8 *pucAddrBase;
pucAddrBase = Parm->pucAddrBase;
uiOffBase = Parm->uiOffBase;
if (Parm->ucI2CSubAddrCtl == __IIC_SUB_NONE) { /* 无子地址或子地址已处理 */
__dateWrite( Parm ); /* 直接发送数据 */
} else if (Parm->ucI2CSubAddrCtl == __IIC_SUB_R) { /* 读操作发送子地址 */
if(Parm->ucSubAddrNum == 2) {
pucAddrBase[__B_IIC_DAT << uiOffBase] = (uint8)((Parm->usSubAddr >> 8) & 0xff);
/* 多于一个字节从机子地址 */
/* 先发送高字节地址 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucSubAddrNum--;
} else if (Parm->ucSubAddrNum == 1) {
pucAddrBase[__B_IIC_DAT << uiOffBase] = (uint8)((Parm->usSubAddr) & 0xff);
/* 发送低字节地址或单字节地址 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucSubAddrNum--;
} else if (Parm->ucSubAddrNum == 0) { /* 发送完子地址,重起总线 */
pucAddrBase[__B_IIC_SET << uiOffBase] = 0x20;
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x18;
Parm->ucI2CSubAddrCtl = __IIC_SUB_NONE;
}
} else if (Parm->ucI2CSubAddrCtl == __IIC_SUB_W) { /* 写操作发送子地址 */
if(Parm->ucSubAddrNum == 2) {
pucAddrBase[__B_IIC_DAT << uiOffBase] = (uint8)((Parm->usSubAddr >> 8) & 0xff);
/* 多于一个字节从机子地址 */
/* 先发送高字节地址 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucSubAddrNum--;
} else if ( Parm->ucSubAddrNum == 1 ) {
pucAddrBase[__B_IIC_DAT << uiOffBase] = (uint8)(Parm->usSubAddr & 0xff);
/* 发送低字节地址或单字节地址 */
pucAddrBase[__B_IIC_CLR << uiOffBase] = 0x28;
Parm->ucI2CSubAddrCtl = __IIC_SUB_NONE; /* 子地址已处理 */
Parm->ucSubAddrNum--;
} else if (Parm->ucSubAddrNum == 0) { /* 写数据无子地址 */
__dateWrite( Parm ); /* 直接发送数据 */
Parm->ucI2CSubAddrCtl = __IIC_SUB_NONE; /* 子地址已处理 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -