📄 i2cio.c
字号:
#include <reg52.h>
#include "I2C.h"
#include "gen.h"
#include <intrins.h>
#define DISABLEINT0 0
bit NoAck = 0;
bit BusFault = 0;
#if I2cBusType==0
// 定义模拟I2c总线的引脚
sbit SDA=P3^4;
sbit SCL=P3^5;
bit Flg_I2c_Ack;
#endif
//#undef DisableInt // 不允许在串行读写中禁止中断
#define DisableInt // 表示在串行读写中禁止中断
#define I2cBusType 0 // 0:采用模拟的IIC总线
// 1:采用MTV212的专用IIC总线
void I2c_Wait(void);
void I2c_Start(void);
void I2c_Stop(void);
void SendByte(unsigned char SendData);
unsigned char RcvByte(void);
void I2c_Ack(bit ack);
void Write_TDA48XX_Reg(unsigned char reg_addr,unsigned char value);
void Write_TDA4886_Reg(unsigned char reg_addr,unsigned char value);
//void Delay20us(void);
void Delayms(int t);
void miscDelay(int t);
#if I2cBusType==1 // 采用MTV212的专用IIC总线接口
/********************************************************************
* 函 数 名: I2c_Wai
* 功能描述: 等待IIC总线的传输,并有限时退出的功能,避免在IIC操作中死锁
* 输 入:
* 返 回:
**********************************************************************/
void I2c_Wait(void)
{
register int i;
for (i=0;i<512;i++) {
if (XFR_IIC_INTFLG&0x01) break;
_nop_();
_nop_();
_nop_();
}
XFR_IIC_INTFLG=0xfe;
}
#endif
void miscDelay(int n)
{
unsigned int i;
while (n--) {
i = 1000/11 ; // one loop below takes about 11 us
while (i--);
}
}
/********************************************************************
* 函 数 名: I2c_Start
* 功能描述: 启动I2c总线
* 输 入: 无
* 返 回:
*********************************************************************/
void I2c_Start(void)
{
#if I2cBusType==0 // 采用模拟的IIC总线
SDA=1; // 发送起始条件的数据信号
_nop_();
SCL=1;
_nop_(); // 起始条件建立时间要大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SDA=0; // 发送起始信号
_nop_(); // 起始条件锁定时间大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0; // 锁住I2C总线,准备发送和接收数据
_nop_();
_nop_();
#elif I2cBusType==1 // 采用MTV212的专用IIC总线接口
XFR_IIC_CTR=0x80;
// Delay20us();
XFR_IIC_CTR=0x81;
I2c_Wait();
#endif
}
/********************************************************************
* 函 数 名: I2c_Stop
* 功能描述: 结束I2c总线
* 输 入: 无
* 返 回: 无
*********************************************************************/
void I2c_Stop(void)
{
#if I2cBusType==0 // 采用模拟的IIC总线
SDA=0; // 发送结束条件的数据信号
_nop_();
SCL=1; // 发送结束条件的时钟信号
_nop_(); // 结束条件建立时间要大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SDA=1; // 发送结束信号
_nop_(); // 起始条件锁定时间大于4.7us
_nop_();
_nop_();
_nop_();
#elif I2cBusType==1 // 采用MTV212的专用IIC总线接口
XFR_IIC_CTR=0x82;
#endif
}
#if I2cBusType==0 // 采用模拟的IIC总线
/********************************************************************
* 函 数 名: SendByte
* 功能描述: 发送单字节数据,该数据既可以是地址也可以是数据。发送完数据要等待应答,
* 并根据是否应答来设置标志为:I2c_Ack
* I2c_Ack=1 :数据发送正常
* I2c_Ack=0 :被控器件无应答
* 输 入:
* 返 回:
**********************************************************************/
void SendByte(unsigned char SendData)
{
register unsigned char i;
for (i=0;i<8;i++) { // 要发送的数据长度为8位
if ((SendData<<i)&0x80) SDA=1;
else SDA=0;
_nop_();
SCL=1; // 置时钟线为高电平,通知被控器件开始接收数据位
_nop_(); // 保证时钟高电平周期大于4us
_nop_();
_nop_();
_nop_();
SCL=0;
}
_nop_();
_nop_();
SDA=1; // 8位数据发送完之后要释放数据线,准备接受应答位
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
if (SDA) Flg_I2c_Ack=0;
else Flg_I2c_Ack=1;
SCL=0;
_nop_();
_nop_();
}
/********************************************************************
* 函 数 名: I2c_Ack
* 功能描述: 主控器发送应答或非应答信号
* 输 入: 应答控制位: 0表示应答;1:表示非应答
* 返 回: 无
**********************************************************************/
/*
void I2c_Ack(bit ack)
{
#if I2cBusType==0 // 采用模拟的IIC总线
if (ack) SDA=1; // 发送非应答信号
else SDA=0; // 发送应答信号
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0; // 清时钟线,钳住I2c总线以便继续接收
_nop_();
_nop_();
#elif I2cBusType==1 // 采用MTV212的专用IIC总线接口
if (ack) XFR_IIC_CTR=0x84;
#endif
}
*/
/********************************************************************
* 功能描述: 从总线上接收一个字节的数据
* 输 入: 无
* 返 回: 从总线上接收的字节
**********************************************************************/
/*
unsigned char RcvByte(void)
{
register unsigned char RcvData,i;
RcvData=0;
SDA=1; // 设置数据线为输入方式
for (i=0;i<8;i++) {
_nop_();
SCL=0; // 设置时钟线为低,准备接收数据位
_nop_(); // 时钟低电平周期大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1; // 设置时钟线为高,使数据线上的数据有效
_nop_();
_nop_();
RcvData=RcvData<<1;
if (SDA) RcvData+=1;
_nop_();
_nop_();
}
SCL=0;
_nop_();
_nop_();
return RcvData;
}*/
#endif
//-------------------------------------------
#if I2cBusType==0
void Write_TDA4886_Reg(unsigned char reg_addr,unsigned char value)
{
#ifdef DisableInt
bit EAbak;
EAbak=EA;
EA=0;
#endif
I2c_Start();
SendByte(0x88);
// if (!I2c_Ack) goto W4886RegEnd;
SendByte(reg_addr);
// if (!I2c_Ack) goto W4886RegEnd;
SendByte(value);
//W4886RegEnd:
I2c_Stop();
#ifdef DisableInt
EA=EAbak;
#endif
}
//------------------------------------------------------------------------
#elif I2cBusType==1 // 采用MTV212的专用IIC总线接口
void Write_TDA4886_Reg(unsigned char reg_addr,unsigned char value)
{
#ifdef DisableInt
bit EAbak;
EAbak=EA;
EA=0;
#endif
XFR_IIC_MBUF=0x88; // 写入TDA4886的器件地址
I2c_Start();
if (XFR_IIC_STUS2&0x80) goto W4886RegEnd;
XFR_IIC_MBUF=reg_addr; // 写入字地址的低8位
I2c_Wait();
if (XFR_IIC_STUS2&0x80) goto W4886RegEnd;
XFR_IIC_MBUF=value; // 写入值
I2c_Wait();
W4886RegEnd:
I2c_Stop();
#ifdef DisableInt
EA=EAbak;
#endif
}
#endif
/*--------------------------- Write_TDA4886_Reg 结束 ------------------------*/
/********************************************************************
* 函 数 名: Write_TDA48XX_Reg
* 功能描述: 写入一个字节的数到TDA48XX(4857/4841/4856)的寄存器当中
* 输 入: reg_addr :寄存器地址
* value :写入到寄存器的值
* 返 回: 无
***********************************************************************/
#if I2cBusType==0 // 采用模拟的IIC总线
void Write_TDA48XX_Reg(unsigned char reg_addr,unsigned char value)
{
#ifdef DisableInt
bit EAbak;
EAbak=EA;
EA=0;
#endif
I2c_Start();
SendByte(0x8c); // 写入TDA48XX的器件地址
// if (!I2c_Ack) goto W48XXRegEnd;
SendByte(reg_addr); // 写入寄存器地址
// if (!I2c_Ack) goto W48XXRegEnd;
SendByte(value); // 写入值
//W48XXRegEnd:
I2c_Stop();
#ifdef DisableInt
EA=EAbak;
#endif
}
//------------------------------------------------------------------------
#elif I2cBusType==1 // 采用MTV212的专用IIC总线接口
void Write_TDA48XX_Reg(unsigned char reg_addr,unsigned char value)
{
#ifdef DisableInt
bit EAbak;
EAbak=EA;
EA=0;
#endif
XFR_IIC_MBUF=0x8c; // 写入TDA48XX的器件地址
I2c_Start();
if (XFR_IIC_STUS2&0x80) goto W48xxRegEnd;
XFR_IIC_MBUF=reg_addr; // 写入字地址的低8位
I2c_Wait();
if (XFR_IIC_STUS2&0x80) goto W48xxRegEnd;
XFR_IIC_MBUF=value; // 写入值
I2c_Wait();
W48xxRegEnd:
I2c_Stop();
#ifdef DisableInt
EA=EAbak;
#endif
}
#endif
#define SCLHigh() { SCL = 1; while(!SCL); }
//#define SCLHigh2() { SCL2 = 1; while(!SCL2); }
/*********************************************
* Send one byte of data to an I2C device *
**********************************************/
void SendI2CByte(unsigned char val)
{
unsigned char bmsk = 0x80;
while (bmsk)
{
SDA = (val & bmsk) ? 0x01 : 0x00;
SCLHigh();
bmsk >>= 1;
SCL = 0;
}
SDA = 1;
SCLHigh();
if (SDA) NoAck = 1;
SCL = 0;
}
/********************************************************
* Grasp the I2C bus, send slave address and command *
*********************************************************/
void GoI2CMaster(unsigned char adr)
{
if (!SCL) SCLHigh();
NoAck = 0;
BusFault = 0;
if (SCL & SDA) {
SDA = 0;
_nop_();
SCL = 0;
_nop_();
SendI2CByte(adr);
}
else
BusFault = 1;
}
/*********************************************
* Receive byte of data from an I2C device *
**********************************************/
unsigned char RcvI2CByte(unsigned char cnt)
{
unsigned char bval = 0, b;
for(b=0; b < 8; b++) {
SCLHigh();
bval <<= 1;
bval |= SDA;
SCL = 0;
}
SDA = (cnt==1) ? 1 : 0;
SCLHigh();
SCL = 0;
SDA = 1; //Clear acknowledge bit.
return bval;
}
/*************************************
* Send I2C STOP, release bus *
**************************************/
void SendI2CStop(void)
{
SDA = 0;
_nop_();
SCLHigh();
_nop_();
SDA = 1;
_nop_();
}
/*********************************************
* Send bytes of data to standard device *
**********************************************/
void eepByteOut(unsigned int index, unsigned char val)//对CPU来说是向EEPROM中发送数据对EEPROM来讲是存
{
unsigned char slv;
#if DISABLEINT0
bit IntFlag;
/* disable interrupt 0 */
IntFlag = EX0;
EX0 = 0;
#endif
PIN_EepWrite_eanable = 0;
slv=0;
slv=slv<<1;
slv=slv|0xA0;
/* I2C Start and send WRITE slave address */
GoI2CMaster(slv);
if(NoAck | BusFault) goto buserror;
/* Send index */
SendI2CByte((unsigned char)index);
if(NoAck) goto buserror;
/* data transmit */
SendI2CByte(val);
//miscDelay(20);
goto endi2c;
buserror:
endi2c:
SendI2CStop();
miscDelay(15);
PIN_EepWrite_eanable = 1;
#if DISABLEINT0
EX0 = IntFlag;
#endif
}
unsigned char eepByteIn(unsigned int index)//对CPU来说是从EEPROM中往出读数据,对EEPROM来讲是取
{
unsigned char bval;
unsigned char slv;
slv=index/256;
slv=slv<<1;
slv=slv|0xA0;
/* I2C Start and send WRITE slave address */
GoI2CMaster(slv);
if(NoAck | BusFault) goto buserror;
/* Send index */
SendI2CByte((unsigned char) index);
if(NoAck) goto buserror;
/* I2C Start and send READ slave address */
GoI2CMaster(slv | 0x01);
if(NoAck) goto buserror;
/* data transmit */
bval = RcvI2CByte(1);
goto endi2c;
buserror:
endi2c:
/* Finish trasmition */
SendI2CStop();
return(bval);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -