/****************************************************************************** 版权所有: 文件名称: i2c.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2008-08-01 功能说明: i2c驱动程序。目前总线频率391KHZ. 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "bspconfig.h" #include "ustimer.h" #include "i2c.h" /*------------------------------- 宏定义 -------------------------------------- */ #define I2C_PM_REG MCF_PMM_PPMCR1 #define I2C_PM_INDEX 4 /*------------------------------ 全局变量 ------------------------------------- */ //总线占用状态 int gh_i2c = 0; /*------------------------------ 外部函数 ------------------------------------- */ /****************************************************************************** 函数名称: i2c_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-06-26 函数说明: i2c初始化。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int i2c_init(void) { #if 0 unsigned char temp; //允许I2C模块时钟 I2C_PM_REG = I2C_PM_INDEX; //管脚配置,假设从默认值开始设置 MCF_PAD_PAR_SSI0H |= 0 | MCF_PAD_PAR_SSI0H_PAR_TXD_SCL2 | MCF_PAD_PAR_SSI0H_PAR_RXD_SDA2; //I2C模块输入时钟125M,将频率设为接近400KHZ(391khz)(分频比320,值0x34). MCF_I2FDR = MCF_I2C_I2FDR_IC(0x34); //允许模块,mcf54418必须打开中断。 MCF_I2CR = 0 | MCF_I2C_I2CR_IEN | MCF_I2C_I2CR_IIEN; //如果总线忙bit设置,发送一个stop信号到slave模块。 if( MCF_I2SR & MCF_I2C_I2SR_IBB) { MCF_I2CR = 0; /* clear control register */ MCF_I2CR = MCF_I2C_I2CR_IEN /* enable module */ | MCF_I2C_I2CR_MSTA; /* send a START condition */ temp = MCF_I2DR; /* dummy read */ MCF_I2SR = 0; /* clear status register */ MCF_I2CR = 0; /* clear control register */ MCF_I2CR = MCF_I2C_I2CR_IEN; /* enable the module again */ } #endif return 0; } /****************************************************************************** 函数名称: i2c_open 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-19 函数说明: 打开一个I2C设备,所有的I2C设备互斥,一次只能打开一个. 注意:此函数在资源竞争问题上,有一定的系统要求,如果要求不满足,用户应 自己处理资源竞争问题.这个要求为:系统中每个任务(一个中断服务程序也算 一个任务)都具有唯一优先级.目前UT800S的系统满足这个条件. 参数说明: i2c_id: 指定需要打开I2C设备的标识符(以I2C_ID_开头)。 返回值: >=0 : 打开设备的句柄 <0 : 打开失败。 修改记录: */ int i2c_open(int i2c_id) { if(i2c_id != I2C_ID_RTC && i2c_id != I2C_ID_E2PROM) { return -1; } //如果QSPI总线空闲,占有它。 if(gh_i2c == 0) { gh_i2c = i2c_id; } else { return -1; } //解决资源竞争问题,如果两个值不相等,说明在竞争中失败,退出。 if(gh_i2c != i2c_id) { return -2; } return i2c_id; } /****************************************************************************** 函数名称: i2c_close 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-21 函数说明: 关闭一个I2C设备。 参数说明: h_i2c:关闭设备的句柄。 返回值: 成功返回0. 修改记录: */ int i2c_close(int h_i2c) { if(h_i2c != gh_i2c) { return -1; } gh_i2c = 0; return 0; } /****************************************************************************** 函数名称: i2c_wait_completion 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-07 函数说明: 等待i2c传输一个字节完成,带0.1秒超时。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int i2c_wait_completion(void) { uint32_t us0,us; //等待中断发生 us0 = ustimer_get_origin(); while(1) { // 得到超时值 us = ustimer_get_duration(us0); // 检查条件 //if((MCF_I2SR & MCF_I2C_I2SR_IIF)) { break; } //超时设定为1秒 if(us > 1*USTIMER_SEC) { //重新初始化I2C模块,否则模块可能再也不能正常工作。 MCF_I2CR = 0; i2c_init(); return -1; } } //MCF_I2SR &= ~MCF_I2C_I2SR_IIF; return 0; } /****************************************************************************** 函数名称: i2c_wait_bus_idle 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-07 函数说明: 等待i2c总线空闲,带0.1秒超时。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int i2c_wait_bus_idle(void) { uint32_t us0,us; //清除arbitration位(IAL),增强程序健壮性。 // MCF_I2SR &= ~MCF_I2C_I2SR_IAL; //等待总线空闲 us0 = ustimer_get_origin(); while(1) { // 得到超时值 us = ustimer_get_duration(us0); // 检查条件 // if((MCF_I2SR & MCF_I2C_I2SR_IBB) == 0) { break; } //超时设定为1秒 if(us > 1*USTIMER_SEC) { //重新初始化I2C模块,否则模块可能再也不能正常工作。 MCF_I2CR = 0; i2c_init(); return -1; } } return 0; } /*------------------------------ 内部函数 ------------------------------------- */ /*------------------------------ 测试函数 ------------------------------------- */