|
/*---------------------------------------------------------------------------------------------------------
** 文件名称 : i2c0.c
** 功能说明 : LPC2000硬件I2C中断方式软件包。
** 使用说明 : 主程序要配置好I2C总线接口(I2C引脚功能和I2C中断,并已使能I2C主模式) ,专用驱动,用于挂FM3130
*********************************************************************************************************
---------------------------------------------------------------------------------------------------------*/
#include "config.h"
//***********************************************************************************************
//本地函数申明 全部加 static
/* 定义I2C0的驱动控制资源 */
volatile static struct I2C_TCB_Source
{
uint8 IIC_FLAG; // I2C标志:0没有使用,1正在使用,2正常结束,3硬件异常结束,4超时结束
uint8 OP_TYPE; // 操作类型:1表示同步读,2表同步写,3表示异步读,4表示异步写
uint8 OP_State; // 操作状态
uint8 *IOData; // 数据缓冲区指针:存放读写数据
uint32 IOData_num; // 要读取/写入的数据个数
uint32 IO_Index; // 读取或写入索引
uint8 Device_sla; // 器件从地址
uint8 OffAddr[3]; // 器件内部偏移地址
uint32 OffAddr_num; // 器件内部偏移地址字节数
}I2C0_TCB;
//***********************************************************************************************
/**********************************************************************************************************
* 名称:
* 功能:查询结束没有,如果结束会将I2C标志清除,有时间超时控制:20-30MS
* 入口参数:无
* 出口参数:1正在使用,2正常结束,3硬件异常结束,4超时结束
**********************************************************************************************************/
uint32 I2C0_IO_End(void)
{
uint32 i;
if(I2C0_TCB.IIC_FLAG > 1)
{
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC|I2CONCLR_I2ENC); // AA SI STA I2EN clr
i = I2C0_TCB.IIC_FLAG;
I2C0_TCB.IIC_FLAG = 0;
return i;
}
else
{
return 1;
}
}
/**********************************************************************************************************
** 函数名称 :I2C0读写操作
** 函数功能 :向有子地址器件写入N字节数据
** 入口参数 :
IO_type : 1表示同步读,2表同步写,3表示异步读,4表示异步写
sla : 器件从地址
offaddr : 器件内部物理地址
offaddr_num : 器件内部物理地址字节数:1-单字节地址 2-双字节地址
IO_dataP : 将要写入或读出的数据的指针
IO_num : 将要写入或读出的数据的个数,操作的数据最大数受I2C0_MAXBUF限制
** 返回参数 :
异步:0失败,1表示操作成功
同步:0失败,2正常结束,3硬件异常结束,4超时结束
**********************************************************************************************************/
uint32 I2C0_IO_Start(uint8 IO_type, uint8 sla, const uint8 *offaddr, uint32 offaddr_num,uint8 *IO_dataP, uint32 IO_num)
{
uint32 i;
if((offaddr_num == 0) || (offaddr_num > 2))
{
return (0);
}
if((IO_num == 0) || (IO_num > I2C0_MAXBUF))
{
return (0);
}
if(I2C0_TCB.IIC_FLAG != 0)
{
return 0;
}
I2C0_TCB.IIC_FLAG = 1;
I2C0_TCB.OP_TYPE = IO_type; // 操作类型
I2C0_TCB.OP_State = 0; // 操作状态
I2C0_TCB.IOData = IO_dataP; // 数据缓冲区指针
I2C0_TCB.IOData_num = IO_num; // 要读取/写入的数据个数
I2C0_TCB.IO_Index = 0; // 读取或写入索引
I2C0_TCB.Device_sla = sla ; // 器件地址
for(i=0;i<offaddr_num;i++)
{
I2C0_TCB.OffAddr = offaddr; // 器件内部偏移地址
}
I2C0_TCB.OffAddr_num = offaddr_num; // 器件内部偏移地址字节数
/* 清除标志 */
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
/* 置位STA,启动I2C总线 */
I20CONSET = (I2CONSET_STA|I2CONSET_I2EN); // STA I2CEN set
/* 等待I2C操作完成 */
OSTimeDly(10);//SET_10MS_SIG(IIC0_10MS_SIG,0);
Uart0Write("wait I2C end\r\n",-1);
if(I2C0_TCB.OP_TYPE <= 2)
{
// 同步
i = I2C0_IO_End();
while(1 == i)
{
i = I2C0_IO_End();
}
return i;
}
else
{
// 异步
return 1;
}
}
/**********************************************************************************************************
** 函数名称 :__irq IRQ_I2C()
** 函数名次 :硬件I2C中断服务程序。
** 入口参数 :无
** 出口参数 :无
** 说明 :注意处理子地址为2字节的情况。
**********************************************************************************************************/
void IRQ_I2C0(void)
{
OS_ENTER_CRITICAL();
if((I2C0_TCB.OP_TYPE%2) == 0) /* 写入操作 */
{
switch (I20STAT & 0xF8)
{
case 0x08: /* 已发送起始条件 */
case 0x10: /* 已发送重复起始条件 */
I20DAT = I2C0_TCB.Device_sla & 0xFE; // 发送SLA+W
I2C0_TCB.OP_State = 1;
I2C0_TCB.IO_Index = 0;
I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC); // 清零SI与STA位
break;
case 0x18: /* 已发送SLA+W,已接收ACK */
case 0x28: /* 已发送I2DAT中的数据,已接收ACK */
if(I2C0_TCB.OP_State == 1)
{
//写入设备内部地址
I20DAT = I2C0_TCB.OffAddr[I2C0_TCB.IO_Index++];
if( (I2C0_TCB.IO_Index >= I2C0_TCB.OffAddr_num) || (I2C0_TCB.IO_Index >= 2) )
{
I2C0_TCB.IO_Index = 0;
I2C0_TCB.OP_State = 2;
}
I20CONCLR = (I2CONCLR_SIC);
}
else if(I2C0_TCB.OP_State == 2)
{
//写入数据
I20DAT = I2C0_TCB.IOData[I2C0_TCB.IO_Index++];
if( (I2C0_TCB.IO_Index >= I2C0_TCB.IOData_num) || (I2C0_TCB.IO_Index >= I2C0_MAXBUF) )
{
I2C0_TCB.IO_Index = 0;
I2C0_TCB.OP_State = 3;
}
I20CONCLR = (I2CONCLR_SIC);
}
else if(I2C0_TCB.OP_State == 3)
{
//写入成功完成
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 2; // 总线已经正常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
}
else
{
//写入异常中断
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 3; // 总线已经正常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
}
break;
case 0x20: /* 已发送SLA+W,已接收非应答 */
case 0x30: /* 已发送I2DAT中的数据,已接收非应答 */
case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */
//写入异常中断
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 3; // 总线已经异常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
break;
default:
//写入异常中断
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 3; // 总线已经异常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
break;
}
}
else /* 读取操作 */
{
switch (I20STAT & 0xF8)
{
//----------------------------------------------------------------------------
case 0x08: /* 已发送起始条件 */
/* 1.发送SLA+W,先写地址 */
I20DAT = I2C0_TCB.Device_sla & 0xFE; // 发送SLA+W
I2C0_TCB.OP_State = 1;
I2C0_TCB.IO_Index = 0;
I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC); // 清零SI与STA位
break;
case 0x18: /* 已发送SLA+W,已接收ACK */
case 0x28: /* 已发送I2DAT中的数据,已接收ACK */
/* 2.写入设备内部地址 */
if(I2C0_TCB.OP_State == 1)
{
I20DAT = I2C0_TCB.OffAddr[I2C0_TCB.IO_Index++];
if( (I2C0_TCB.IO_Index >= I2C0_TCB.OffAddr_num) || (I2C0_TCB.IO_Index >= 2) )
{
I2C0_TCB.OP_State = 2;
}
I20CONCLR = (I2CONCLR_SIC);
}
else //I2C0_TCB.OP_State = 2
{
//I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
/* 置位STA,重新启动总线 */
I20CONSET = (I2CONSET_STA); // STA set
I20CONCLR = (I2CONCLR_SIC); // SI clr
}
break;
//----------------------------------------------------------------------------
case 0x10: /* 已发送重复起始条件 */
/* 3.发送SLA+R */
I20DAT = I2C0_TCB.Device_sla | 0x01; // 发送SLA+R
I2C0_TCB.IO_Index = 0;
I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC); // 清零SI与STA位
break;
case 0x40: /* 已发送SLA+R,已接收ACK */
/* 4.设置应答信号 */
if(I2C0_TCB.IOData_num <= 1)
{
I20CONCLR = I2CONCLR_AAC; // 下次发送非应答信号
}
else
{
I20CONSET = I2CONSET_AA; // 下次发送应答信号
}
I2C0_TCB.IO_Index = 0;
I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC); // 清零SI与STA位
break;
case 0x50: /* 已接收数据字节,已返回ACK */
/* 5.读取数据 */
I2C0_TCB.IOData[I2C0_TCB.IO_Index++] = I20DAT ;
if( (I2C0_TCB.IO_Index >= (I2C0_TCB.IOData_num - 1)) || (I2C0_TCB.IO_Index >= (I2C0_MAXBUF - 1)) )
{
I20CONCLR = I2CONCLR_AAC; // 下次发送非应答信号
}
I20CONCLR = (I2CONCLR_SIC|I2CONCLR_STAC); // 清零SI与STA位
break;
case 0x58: /* 已接收数据字节,已返回非应答 */
/* 6.读取成功完成 */
I2C0_TCB.IOData[I2C0_TCB.IO_Index++] = I20DAT ;
I20CONSET = (I2CONSET_STO); // STO
if(I2C0_TCB.IO_Index == I2C0_TCB.IOData_num)
{
I2C0_TCB.IIC_FLAG = 2; // 总线已经正常停止
}
else
{
I2C0_TCB.IIC_FLAG = 3; // 总线已经正常停止
}
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
break;
case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */
case 0x48: /* 已发送SLA+R,已接收非应答 */
/* 读取异常中断 */
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 3; // 总线已经异常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
break;
default:
/* 读取异常中断 */
I20CONSET = (I2CONSET_STO); // STO
I2C0_TCB.IIC_FLAG = 3; // 总线已经异常停止
I20CONCLR = (I2CONCLR_AAC|I2CONCLR_SIC|I2CONCLR_STAC); // AA SI STA clr
break;
}
}
VICVectAddr = 0x00;
OS_EXIT_CRITICAL();
}
/*************************************************************************************************
** 函数名称:
** 功能描述:
** 输 入: 无
** 输 出: 无
** 返回值: 无
** 全局变量:
** 调用模块:
**--------------------------------------------------------------------------------------------
** 修改记录: bobo 2010/03/30 建立
*************************************************************************************************/
uint32 I2C0_Init(void)
{
//init data
I2C0_TCB.IIC_FLAG = 0;
I2C0_TCB.OP_TYPE = 0;
I2C0_TCB.OP_State = 0;
I2C0_TCB.IOData_num = 0;
I2C0_TCB.IO_Index = 0;
I2C0_TCB.OffAddr_num = 0;
// if(fi2c > 400000)
// {
// fi2c = 400000;
// }
//IIC0_COM0_PINSELr &= IIC0_COM0_PIN_DISvalue;
//IIC0_COM0_PINSELr |= IIC0_COM0_PIN_ENvalue;
PCONP |= (1 << 19);
PINSEL1 &= ~0x03C00000;
PINSEL1 |= 0x01400000; /* set PIO0.27 and PIO0.28 to I2C0 SDA and SCK */
#define I2SCLH_SCLH 0x00000080 /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL 0x00000080 /* I2C SCL Duty Cycle Low Reg */
I20CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
I20SCLH = ((12000000*3) / 400000 + 1)/2;
I20SCLL = ((12000000*3) / 400000)/2;
// I20SCLL = I2SCLL_SCLL;
// I20SCLH = I2SCLH_SCLH;
SetVICIRQ(9, 5, (uint32)IRQ_I2C0); // 注册I2C0中断
return (TRUE);
}
/*****************************************************************************
** Function name: I2CEngine
**
** Descriptions: The routine to complete a I2C transaction
** from start to stop. All the intermitten
** steps are handled in the interrupt handler.
** Before this routine is called, the read
** length, write length, I2C master buffer,
** and I2C command fields need to be filled.
** see i2cmst.c for more details.
**
** parameters: None
** Returned value: true or false, return false only if the
** start condition can never be generated and
** timed out.
**
*****************************************************************************/
//DWORD I2CEngine( void )
//{
// I2CMasterState = I2C_IDLE;
// RdIndex = 0;
// WrIndex = 0;
// if ( I2CStart() != TRUE )
// {
// I2CStop();
// return ( FALSE );
// }
//
// while ( 1 )
// {
// if ( I2CMasterState == DATA_NACK )
// {
// I2CStop();
// break;
// }
// }
// return ( TRUE );
//}
===============================================================================================================================
/****************************************Copyright (c)******************************************
*
* http://www.aoretech.cn/main.asp Copyright(C) 2010, YMHX ,All rights reserved.
*
*-------------------------------------文件信息--------------------------------------------
* 文件名:
* 功能描述:Header file for
* 创建 人: bobo
*
* 修改历史:
* 2010/01/13 v1.00 bobo
* 范围性质:全局性头文件,半全局头性文件,私有性头文件
************************************************************************************************/
#ifndef __I2C0_H__
#define __I2C0_H__
/* 以下是变量和函数声明 */
// uint32 I2C0_Init(uint32 fi2c);
uint32 I2C0_IO_End(void);
#define I2C0_MAXBUF (512)
#define I2C0_SYN_READ (1)
#define I2C0_SYN_WRITE (2)
#define I2C0_ASYN_READ (3)
#define I2C0_ASYN_WRITE (4)
/* I2C Control Set Register */
#define I2CONSET_I2EN 0x00000040
#define I2CONSET_AA 0x00000004
#define I2CONSET_SI 0x00000008
#define I2CONSET_STO 0x00000010
#define I2CONSET_STA 0x00000020
/* I2C Control clear Register */
#define I2CONCLR_AAC 0x00000004
#define I2CONCLR_SIC 0x00000008
#define I2CONCLR_STAC 0x00000020
#define I2CONCLR_I2ENC 0x00000040
uint32 I2C0_Init(void);
uint32 I2C0_IO_Start(uint8 IO_type, uint8 sla, const uint8 *offaddr, uint32 offaddr_num,uint8 *IO_dataP, uint32 IO_num);
typedef struct
{
unsigned char year ;
unsigned char month ;
unsigned char day ;
unsigned char hour ;
unsigned char minute;
unsigned char second;
} RTC_DT;
extern RTC_DT rtc;
#endif /* __I2C0_H__ */
//************************************************************************************************
// END FILE
//************************************************************************************************ |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|