📄 i2c.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.zyinside.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: I2C.c
** Last modified Date: 2006-01-11
** Last Version: v1.0
** Description: S3C2410的I2C软件包
** 查询控制方式
**------------------------------------------------------------------------------------------------------
** Created By: 黄绍斌
** Created date: 2005-12-31
** Version: v1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#define IN_I2C
#include "config.h"
// I2C总线设置宏定义
#define IICCON_DACK ((1<<7) | (1<<6) | (1<<5) | (0<<0)) /* 使能ACK位,IICCLK=PCLK/512=97656 */
#define IICCON_DNACK ((0<<7) | (1<<6) | (1<<5) | (0<<0)) /* 中断使能(这样才能正确操作I2C) */
/*********************************************************************************************************
** Function name: InitI2C
** Descriptions: 初始化总线 (100KHz总线速率)
** 设FCLK=200MHz,HCLK=100MHz,PCLK=50MHz。
** Input: 无
** Output: 无
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void InitI2C(void)
{
// 设置管脚连接
rGPECON = (rGPECON & 0x0FFFFFFF) | 0xA0000000; // 设置I2C口使能
rGPEUP = rGPEUP | 0xC000; // 禁止内部上拉电阻
// 设置I2C控制寄存器 (使能ACK位时才能接收从机的应答位)
rIICCON = IICCON_DACK;
// 设置I2C为主机模式
rIICSTAT = (3<<6)|(1<<4);
// 从机地址 (作主机时没有用)
rIICADD = 0x10;
}
/*********************************************************************************************************
** Function name: START_I2C
** Descriptions: 启动总线,发送从机地址,并发送从机地址
** Input: sla 从机动地址
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: sla位最低位为读写控制位
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int StartI2C(uint8 sla)
{
uint32 i;
rIICDS = sla; // 设置从机地址
if(sla&0x01)
{
rIICSTAT = (2<<6)|(1<<5)|(1<<4); // 主接收模式,发送使能,启动总线
rIICCON = IICCON_DACK; // 若是重启总线,则需要有此操作
}
else
{
rIICSTAT = (3<<6)|(1<<5)|(1<<4); // 主发送模式,发送使能,启动总线
}
// 等待操作完成
while((rIICCON&0x10) == 0);
// 判断操作是否成功 (总线仲裁和从机应答)
if((rIICSTAT&0x09) == 0)
{
return(TRUE);
}
else
{
// 发送结束信号
if(sla&0x01) rIICSTAT = (2<<6)|(0<<5)|(1<<4);
else rIICSTAT = (3<<6)|(0<<5)|(1<<4);
rIICCON = IICCON_DACK;
for(i=0; i<5000; i++); // 等待结束信号产生完毕
return(FALSE);
} // end of if((rIICSTAT&0x09) == 0)...else...
}
/*********************************************************************************************************
** Function name: I2C_SendByte
** Descriptions: 发送一字节数据,并接收应答位
** Input: dat 要发送的数据
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_SendByte(uint8 dat)
{
uint32 i;
rIICDS = dat; // 将数据写入I2C数据寄存器
rIICCON = IICCON_DACK; // 清除中断标志,允许发送数据操作
// 等待操作完成
while((rIICCON&0x10) == 0);
// 判断操作是否成功 (总线仲裁和从机应答)
if((rIICSTAT&0x09) == 0)
{
return(TRUE);
}
else
{
// 发送结束信号
rIICSTAT = (3<<6)|(0<<5)|(1<<4);
rIICCON = IICCON_DACK;
for(i=0; i<5000; i++); // 等待结束信号产生完毕
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: I2C_RcvByteNA
** Descriptions: 接上I2C总线上一字节数据,并发送非应答位
** Input: dat 用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_RcvByteNA(uint8 *dat)
{
uint32 i;
// 允许接收数据
rIICCON = IICCON_DNACK;
// 等待接收数据操作完成
while((rIICCON&0x10) == 0);
// 判断操作是否成功 (总线仲裁)
if((rIICSTAT&0x08) != 0)
{
// 发送结束信号
rIICSTAT = (2<<6)|(0<<5)|(1<<4);
rIICCON = IICCON_DACK;
for(i=0; i<5000; i++); // 等待结束信号产生完毕
return(FALSE);
}
*dat = rIICDS; // 读取数据
return(TRUE);
}
/*********************************************************************************************************
** Function name: I2C_RcvByteA
** Descriptions: 接上I2C总线上一字节数据,并发送应答位
** Input: dat 用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_RcvByteA(uint8 *dat)
{
uint32 i;
// 允许接收数据
rIICCON = IICCON_DACK;
// 等待接收数据操作完成
while((rIICCON&0x10) == 0);
// 判断操作是否成功 (总线仲裁)
if((rIICSTAT&0x08) != 0)
{
// 发送结束信号
rIICSTAT = (2<<6)|(0<<5)|(1<<4);
rIICCON = IICCON_DACK;
for(i=0; i<5000; i++); // 等待结束信号产生完毕
return(FALSE);
}
*dat = rIICDS; // 读取数据
return(TRUE);
}
/*********************************************************************************************************
** Function name: STOP_I2C
** Descriptions: 结束总线
** Input: send I2C当前模模式。主发送模式时为1,否则为0(主接收模式)
** Output: 无
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void StopI2C(uint8 send)
{
uint32 i;
if(send)
{
rIICSTAT = (3<<6)|(0<<5)|(1<<4);// 发送结束信号
}
else
{
rIICSTAT = (2<<6)|(0<<5)|(1<<4);// 发送结束信号
}
rIICCON = IICCON_DACK;
for(i=0; i<5000; i++); // 等待结束信号产生完毕
}
/*********************************************************************************************************
** Function name: ISendStr
** Descriptions: 使用硬件I2C发送数据。
** Input: sla 从机地址
** suba 器件子地址(第一字节用来表示子地址字节个数)
** s 发送数据缓冲区
** no 发送数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改s、suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int ISendStr(uint8 sla, uint8 *suba, uint8 *s, uint8 no)
{
int bak;
sla = sla & 0xFE;
if(!StartI2C(sla))
{
if(!StartI2C(sla)) return(FALSE); // 启动总线,发送从机地址
}
// 发送器件子地址
bak = *suba++;
for(; bak>0; bak--)
{
if(!I2C_SendByte(*suba++)) return(FALSE);
}
// 发送数据
for(; no>0; no--)
{
if(!I2C_SendByte(*s)) return(FALSE);
s++;
}
StopI2C(1); // 结束总线
return(TRUE);
}
/*********************************************************************************************************
** Function name: IRcvStr
** Descriptions: 使用硬件I2C读取数据。
** Input: sla 从机地址
* suba 器件子地址缓冲区指针(第一字节用来表示子地址字节个数)
* s 接收数据缓冲区
* no 接收数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-01-11
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int IRcvStr(uint8 sla,uint8 *suba,uint8 *s,uint8 no)
{
int bak;
bak = *suba++; // 子地址个数
if(bak > 0)
{
sla = sla & 0xFE;
if(!StartI2C(sla))
{
if(!StartI2C(sla)) return(FALSE); // 启动总线,发送从机地址(写)
}
// 发送器件子地址
for(; bak>0; bak--)
{
if(!I2C_SendByte(*suba++)) return(FALSE);
}
}
// 重启总线
sla = sla | 0x01;
if(!StartI2C(sla)) return(FALSE); // 启动总线,发送从机地址(读)
// 读取数据
for(; no>1; no--)
{
if(!I2C_RcvByteA(s)) return(FALSE); // 发送数据
s++;
}
if(!I2C_RcvByteNA(s)) return(FALSE);
StopI2C(0); // 结束总线
return(TRUE);
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -