📄 csmii2c.cpp
字号:
#include "class.h"
/****************************************Copyright (c)**************************************************
** 终端产品
**
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名: CSMII2C.cpp
**创 建 人: 杨虎岳
**最后修改日期: 2006年6月7日
**描 述: 模拟II2C总线
**说 明:
**--------------历史版本信息----------------------------------------------------------------------------
** 创建人: 杨虎岳
** 版 本: v1.0
** 日 期: 2006年6月7日
** 描 述: 原始版本
**
**--------------当前版本修订------------------------------------------------------------------------------
**创 建 人: 杨虎岳
**日 期: 2006年3月4日
** 描 述:
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
CFGPIO_OUT SCL(I2C_SCL,0);
CFGPIO_OUT WP(I2C_WP,1);
CFGPIO_OUT SDA(I2C_SDA,1);
//写EEPROM需要5MS的延时,写一页和一个字节 的时间是一样的。
/*void CSMII2C::Delay_EEProm_5ms()
{
INT32U i;
for(i=0;i<150000;i++);
}
void CSMII2C:: Delay5us(void)
{
INT8U i;
for(i=0;i<0xff;i++);
}*/
void CSMII2C::WaitRcv(void)
{
CFGPIO_IN SDA(I2C_SDA);
}
void CSMII2C::WaitSend(void)
{
CFGPIO_OUT SDA(I2C_SDA,1);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 起动总线函数
//函数原型: void I2c_Start();
//功能: 启动I2C总线,即发送I2C起始条件.
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void CSMII2C::I2cStart()
{
WaitSend();
SDA.set(); //发送起始条件的数据信号
SCL.set();
Xus(5); //起始条件建立时间大于4.7us,延时
SDA.clr(); //发送起始信号//
Xus(5); // 起始条件锁定时间大于4μs
SCL.clr(); ///钳住I2C总线,准备发送或接收数据
Xus(5);
WaitRcv();
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 结束总线函数
//函数原型: void I2c_Stop();
//功能: 结束I2C总线,即发送I2C结束条件.
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void CSMII2C::I2cStop()
{
WaitSend();
SDA.clr(); //发送结束条件的数据信号
SCL.set();//结束条件建立时间大于4μs
Xus(5);
SDA.set(); //发送I2C总线结束信号
WaitRcv();
//SCL.clr();
}
/*INT8U CSMII2C:: CheckAck(void)
{
INT8U ack;
SDA.set(); //释放数据线,准备接收应答位,调试时可以在SDA=1和SCL=1之间加延时
SCL.set();
Xus(5);//时钟低电平周期大于4μs
ack=SDA.value();
Xus(5);
SCL.clr();//清时钟线,钳住I2C总线以便继续接收
Xus(5);
if(ack==1)
return FALSE;
return TRUE;
}
*/
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 字节数据传送函数
//函数原型: void SendByte(INT8U c);
////功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
// 此状态位进行操作.(不应答或非应答都使ack=0 假)
// 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C::I2cSendByte(INT8U data)
{
INT8U BitCnt;
WaitSend();
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位//
{
if((data<<BitCnt)&0x80)
{
SDA.set();
SDA.set();//防止线路延时
} //判断发送位//
else
{
SDA.clr();
SDA.clr();
}
SCL.set(); //置时钟线为高,通知被控器开始接收数据位//
Xus(5); //保证时钟高电平周期大于4μs//
SCL.clr();
Xus(5);
}
//SDA.set();
WaitRcv(); //8位发送完后释放数据线,准备接收应答位//
SCL.set();
Xus(5);
BitCnt=SDA.out_value();
SCL.clr();
Xus(5);
if(BitCnt) return(FALSE);
else return(TRUE); //判断是否接收到应答信号//
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 字节数据传送函数
//函数原型: INT8U I2c_RcvByte();
//功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
// 发完后请用应答函数。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C:: I2cRcvByte()
{
INT8U retc=0;
INT8U BitCnt;
//SDA.set(); //置数据线为输入方式,因为默认是输入,所以不用变
//WaitRcv();
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL.clr(); //置时钟线为低,准备接收数据位
Xus(5);//时钟低电平周期大于4.7μs
SCL.set(); //置时钟线为高使数据线上数据有效
Xus(5); //时钟低电平周期大于4.7μs
retc=retc<<1;
if(SDA.out_value()==1) retc=retc|0x01; //读数据位,接收的数据位放入retc中
}
SCL.clr();
Xus(5);
//WaitSend();
return(retc);
}
void CSMII2C::WriteEnable(void)
{
WP.clr();
}
void CSMII2C::WriteDisable(void)
{
WP.set();
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 应答子函数
//原型: void I2c_Ack(bit a);
//功能:主控器进行应答信号,(可以是应答或非应答信号)
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
void CSMII2C::I2cAck(INT8U Ack)
{
WaitSend();
if(Ack==0)SDA.clr(); //在此发出应答或非应答信号
else SDA.set();
Xus(5); //时钟低电平周期大于4μs
SCL.set();
Xus(5); //时钟低电平周期大于4μs
SCL.clr();
Xus(5); //清时钟线,钳住I2C总线以便继续接收
WaitRcv();//一定要在SCL为低时变为输入方式,如果在高时变为输入,则成了停止位
}
/*
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 向无子地址器件发送字节数据函数
//函数原型: bit ISendByte(INT8U sla,ucahr c);
//功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
// 如果返回1表示操作成功,否则操作有误。
//注意: 使用前必须已结束总线。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C::ISendByte(INT8U sla,INT16U addr,INT8U c)
{
INT8U ack;
INT8U temp;
I2cStart(); //启动总线//
WP.clr();
ack=I2cSendByte(sla);
if(ack==FALSE) return(FALSE);
ack=I2cSendByte(0x00);
if(ack==FALSE) return(FALSE);
ack=I2cSendByte(addr); //发送数据//
if(ack==FALSE) return(FALSE);
I2cSendByte(c); //发送数据//
I2cStop(); //结束总线//
Delay_EEProm_5ms();
WP.set();
return(TRUE);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 向有子地址器件发送多字节数据函数
//函数原型: bit ISendStr(INT8U sla,INT8U suba,ucahr /s,INT8U no);
//功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
// 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
// 如果返回1表示操作成功,否则操作有误。
//注意: 使用前必须已结束总线。
///如果《32字节,最好从页的起始地址开始,如果》32字节,必须,从页的中间开始差+32
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C::ISendStr(INT8U sla,INT16U suba,INT8U *s,INT8U no)
{
INT8U i;
WP.clr();
I2cStart(); //启动总线
ack=I2cSendByte(sla); ///发送器件地址
if(ack==FALSE) return(FALSE);
ack=I2cSendByte(FALSE);
if(ack==FALSE) return(FALSE);
ack=I2cSendByte(suba); //发送器件子地址
if(ack==FALSE) return(FALSE);
for(i=0;i<no;i++)
{
ack=I2cSendByte(*s); //发送数据
if(ack==FALSE) return(FALSE);
s++;
}
I2cStop(); //结束总线
Delay_EEProm_5ms();
WP.set();
return(TRUE);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 向无子地址器件读字节数据函数
//函数原型: bit II2c_RcvByte(INT8U sla,ucahr /c);
//功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地
// 址sla,返回值在c.
// 如果返回1表示操作成功,否则操作有误。
//注意: 使用前必须已结束总线。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C:: IRcvByte(INT8U sla,INT16U addr,INT8U *outdata)
{
INT8U ack;
I2cStart(); //启动总线//
ack=I2cSendByte(sla&0xfe); //发送器件地址//
if(ack==FALSE)return(FALSE);
ack=I2cSendByte(0x00);
if(ack==FALSE) return(FALSE);
ack=I2cSendByte(addr);
I2cStart();
ack=I2cSendByte(sla);
if(ack==FALSE) return(FALSE);
*outdata=I2cRcvByte(); //读取数据//
I2cAck(1); //发送非就答位//
I2cStop(); //结束总线//
return(1);
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// 向有子地址器件读取多字节数据函数
//函数原型: bit ISendStr(INT8U sla,INT8U suba,ucahr /s,INT8U no);
//功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
// 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
// 如果返回1表示操作成功,否则操作有误。
//注意: 使用前必须已结束总线。
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
INT8U CSMII2C::IRcvStr(INT8U sla,INT16U suba,INT8U *s,INT8U no)
{
INT8U i;
INT8U ack;
I2cStart(); //启动总线//
ack=I2cSendByte(sla&0xfe); //发送器件地址//
if(ack==0)return(0);
ack= I2cSendByte(0x00);
ack=I2cSendByte(suba); //发送器件子地址//
if(ack==0)return(0);
I2cStart();
ack=I2cSendByte(sla);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=I2cRcvByte(); //发送数据//
I2cAck(0); //发送就答位//
s++;
}
*s=I2cRcvByte();
I2cAck(1); //发送非应位//
I2cStop(); //结束总线//
return(1);
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -