📄 i2c.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.zyinside.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: I2C.c
** Last modified Date: 2006-09-20
** Last Version: v1.0
** Description: PXA270的I2C软件包
** 查询控制方式
**------------------------------------------------------------------------------------------------------
** Created By: 黄绍斌
** Created date: 2006-09-20
** Version: v1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#define IN_I2C
#include "config.h"
// I2C总线设置宏定义
#define BPS_100K (0<<15) /* 即ICR_FM位 */
#define BPS_400K (1<<15)
#define WAIT_MAX 900000 /* 等待最长时间 */
/*********************************************************************************************************
** Function name: InitI2C
** Descriptions: 初始化总线,设置为100KHz总线速率。此函数只需调用一次。
** (PXA270的I2C支持100KHz和400KHz两种,由ICR的FM位控制)
** Input: 无
** Output: 无
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void InitI2C(void)
{
uint32 i;
// 使能I2C单元的时钟源
CKEN = CKEN | (1<<14);
for(i=0; i<3000; i++);
// 设置管脚连接GP117(SCL)、GP118(SDA)
GPSR3 = (0x03 << (117-96));
GPDR3 = GPDR3 | (0x03<<(117-96));
GAFR3_U = (GAFR3_U & (~(0x0F<<10))) |
(0x05<<10);
// I2C寄存器设置
ISAR = 0x18; // 设置从方式时的从机地址(没有特定意义的值)
ICR = ICR_UR | BPS_100K; // ICR_UR=1,复位I2C单元。I2C总线速度设置为100KHz。同时清0其它位
ISR = 0x7FF; // 清0所有状态标志位(写1时清0)
ICR = ICR & (~ICR_UR); // ICR_UR=0 (所有I2C中断被禁止)
ICR = ICR | ICR_GCD | ICR_SCLE; // 允许SCL时钟输出 (禁止全局传呼)
ICR = ICR | ICR_IUE; // 使能I2C单元 (仅使用ICR的STOP位发送I2C结束信号)
for(i=0; i<500; i++);
}
/*********************************************************************************************************
** Function name: StartI2C
** Descriptions: 启动总线,发送从机地址,并发送从机地址
** Input: sla 从机动地址
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: sla位最低位为读写控制位
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int StartI2C(uint8 sla)
{
uint32 i;
ISR = ISR | ISR_ALD | ISR_ITE; // 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败)
IDBR = sla; // 设置从机地址
ICR = ICR | ICR_START | ICR_TB; // ICR_START=1,ICR_TB=1,启动总线并发送从机地址
// 等待操作完成 (有超时退出功能)
i = 0;
while((ISR & ISR_ITE) == 0)
{
if((++i) > WAIT_MAX)
{
ICR = ICR & (~ICR_START); // ICR_START=0
return(FALSE);
}
}
ICR = ICR & (~ICR_START); // ICR_START=0
// 判断操作是否成功 (从机应答/总线仲载)
if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: I2C_SendByte
** Descriptions: 发送一字节数据,并接收应答位
** Input: dat 要发送的数据
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_SendByte(uint8 dat)
{
uint32 i;
ISR = ISR | ISR_ALD | ISR_ITE; // 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败)
IDBR = dat; // 将数据写入I2C数据寄存器
ICR = ICR | ICR_TB; // ICR_TB=1,允许发送数据操作
// 等待操作完成
i = 0;
while((ISR & ISR_ITE) == 0)
{
if((++i) > WAIT_MAX)
{
return(FALSE);
}
}
// 判断操作是否成功 (从机应答/总线仲载)
if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: I2C_SendByte_Stop
** Descriptions: 发送一字节数据,并接收应答位,然后产生结束总线信号
** Input: dat 要发送的数据
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_SendByte_Stop(uint8 dat)
{
uint32 i;
ISR = ISR | ISR_ALD | ISR_ITE; // 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败)
IDBR = dat; // 将数据写入I2C数据寄存器
ICR = ICR | ICR_TB | ICR_STOP; // ICR_STOP=1,发送完最后一字节数据后发送结束总线信号
// 等待操作完成
i = 0;
while((ISR & ISR_ITE) == 0)
{
if((++i) > WAIT_MAX)
{
ICR = ICR & (~ICR_STOP); // ICR_STOP=0
return(FALSE);
}
}
ICR = ICR & (~ICR_STOP); // ICR_STOP=0
// 判断操作是否成功 (从机应答/总线仲载)
if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
{
return(TRUE);
}
else
{
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: I2C_RcvByteNA_Stop
** Descriptions: 接上I2C总线上一字节数据,并发送非应答位,然后产生结束总线信号
** Input: dat 用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_RcvByteNA_Stop(uint8 *dat)
{
uint32 i;
ISR = ISR | ISR_ALD | ISR_IRF; // 清0标志位ISR_IRF和ISR_ALD(总线仲裁失败)
// 允许接收数据
ICR = ICR | ICR_ACKNAK | ICR_STOP; // ICR_STOP=1,接收完最后一字节数据后发送结束总线信号
ICR = ICR | ICR_TB;
// 等待接收数据操作完成
i = 0;
while((ISR & ISR_IRF) == 0)
{
if((++i) > WAIT_MAX)
{
ICR = ICR & (~ICR_STOP); // ICR_STOP=0
return(FALSE);
}
}
ICR = ICR & (~ICR_STOP); // ICR_STOP=0
// 判断操作是否成功 (总线仲裁)
if((ISR & ISR_ALD) == 0)
{
*dat = IDBR; // 读取数据
return(TRUE);
}
else
{
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: I2C_RcvByteA
** Descriptions: 接上I2C总线上一字节数据,并发送应答位
** Input: dat 用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int I2C_RcvByteA(uint8 *dat)
{
uint32 i;
ISR = ISR | ISR_ALD | ISR_IRF; // 清0标志位ISR_IRF和ISR_ALD(总线仲裁失败)
// 允许接收数据
ICR = ICR & (~ICR_ACKNAK);
ICR = ICR | ICR_TB;
// 等待接收数据操作完成
i = 0;
while((ISR & ISR_IRF) == 0)
{
if((++i) > WAIT_MAX)
{
return(FALSE);
}
}
// 判断操作是否成功 (总线仲裁)
if((ISR & ISR_ALD) == 0)
{
*dat = IDBR; // 读取数据
return(TRUE);
}
else
{
return(FALSE);
}
}
/*********************************************************************************************************
** Function name: ISendStr
** Descriptions: 使用硬件I2C发送数据。
** Input: sla 从机地址
** suba 器件子地址(第一字节用来表示子地址字节个数)
** s 发送数据缓冲区
** no 发送数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改s、suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** 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>1; no--)
{
if(!I2C_SendByte(*s)) return(FALSE);
s++;
}
if(!I2C_SendByte_Stop(*s)) return(FALSE); // 结束总线
return(TRUE);
}
/*********************************************************************************************************
** Function name: IRcvStr
** Descriptions: 使用硬件I2C读取数据。
** Input: sla 从机地址
* suba 器件子地址缓冲区指针(第一字节用来表示子地址字节个数)
* s 接收数据缓冲区
* no 接收数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** 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_Stop(s)) return(FALSE); // 结束总线
return(TRUE);
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -