📄 i2c_hard.c
字号:
//-----头文件-----//
#include <reg922.h>
//#include <stdio.h>
//#include <intrins.h>
//SI I2C中断标志。 当进入25种可能的I2C状态中的任何一个后,该位置位。
// 当EA, EI2C(IEN1.0)以及SI置位时,产生一个中断请求。SI必须通过软件清零。
#define uchar unsigned char
#define GENERATE_STOP 0x54 // 置位 STO, 复位 STA 、SI
#define RELEASE_BUS_ACK 0x44 // 复位 STO,STA,SI 并置位 AA (ack)
#define RELEASE_BUS_NOACK 0x40 // 复位 STO,STA,SI 并置位 AA (noack)
#define RELEASE_BUS_STA 0x64 // 起动总线/重新起动总线, 置位 STA
bit GetBus(void);
bit AckBus(void) reentrant;
//bit SendByte(uchar data);
//bit ISendStr(uchar sla, uchar suba, uchar *str, uchar str_len);
//bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no);
bit ISendStr(uchar SLA, uchar *SUBA, uchar *DATA_I2C, uchar *DATA_LEN);
bit Write_EEPROM(uchar data_add,uchar *EEPROM,uchar data_len);
bit Read_EEPROM (uchar data_add,uchar *EEPROM,uchar data_len);
extern uchar idata SUBA[2],DATA_I2C[11],DATA_LEN[2],EEPROM[6];//SLA,
//-----申请总线-----//
//功能:进行I2C总线的初始化--包括时钟选择,I2C使能,发送起始信号
// 等等。I2EN为1,设置为主机;CRSEL位为0,使用内部SCL发生器。
bit GetBus(void)
{
I2SCLH = 15; // 设置SCL高电平的PCLK周期数
I2SCLL = 15; // 设置SCL低电平的PCLK周期数,6MHz时为100Kbit/S
I2CON = RELEASE_BUS_STA; // 申请成为主机,起动总线。使用内部SCL发生器,I2EN和AA置位。
//while( SI==0 ); // 等待起始位的发送
return(AckBus());
}
//-----应答函数-----//
bit AckBus(void) reentrant
{
uchar TimeOut;
TimeOut = 0xFF;
while(SI==0)
{
TimeOut--;
if( TimeOut==0x00 ) //100uS无响应,超时退出
{
I2CON = GENERATE_STOP;
return(0);
}
}
return(1);
}
//-----发送数据函数-----//
//功能:用于向总线发送数据
//入口参数:ACC 待发送的数据
bit SendByte(uchar ACC)
{
I2DAT = ACC;
I2CON = RELEASE_BUS_ACK; // 清除SI位等等
//while( SI==0 ); // 等待数据的发送
return(AckBus());
}
//-----向有子地址器件发送多字节数据函数-----//
// 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程
// 入口参数: SLA 从器件地址
// *SUBA 子地址
// *DATA_I2C 发送内容的指针
// *DATA_LEN 发送字节数
// 出口参数: 返回1表示操作成功,否则操作有误。
bit ISendStr(uchar SLA,uchar *SUBA, uchar *DATA_I2C, uchar *DATA_LEN) //
{
uchar i;
if( GetBus()==0 ) return(0); // 启动总线
if(SendByte(SLA)==0) return(0); // 发送器件地址
if( I2STAT!=0X18 )
{
I2CON = GENERATE_STOP;
return(0);
}
for(i=0; i<(*DATA_LEN); i++)
{
if(SendByte(*SUBA)==0) return(0); // 发送器件子地址
if( I2STAT!=0X28 )
{ I2CON = GENERATE_STOP;
return(0);
}
SUBA++;
}
DATA_LEN++;
for(i=0; i<(*DATA_LEN); i++)
{
if(SendByte(*DATA_I2C)==0) return(0); //发送数据
if( I2STAT!=0X28 )
{ I2CON = GENERATE_STOP;
return(0);
}
DATA_I2C++;
}
I2CON = GENERATE_STOP; // 结束总线
return(1);
}
//-----向有子地址器件读取多字节数据函数-----//
//功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程
//入口参数:SLA 从器件地址
// *SUBA 子地址
// *DATA_I2C 读出的内容存储区的指针
// *DATA_LEN 读*DATA_LEN个字节。
//出口参数:函数返回1表示操作成功,否则操作有误。
bit IRcvStr(uchar *SUBA,uchar *DATA_I2C,uchar *DATA_LEN ) //uchar SLA,
{
uchar i;
uchar CheckSum=0;
if(GetBus()==0) return(0); // 启动总线
if(SendByte(0xA0)==0) return(0); // 发送器件地址
if( I2STAT!=0X18)
{
I2CON = GENERATE_STOP;
return(0);
}
for(i=0; i<(*DATA_LEN); i++)
{
if(SendByte(*SUBA)==0) return(0); // 发送器件子地址
if( I2STAT!=0X28 )
{
I2CON = GENERATE_STOP;
return(0);
}
SUBA++;
}
DATA_LEN++;
I2CON = RELEASE_BUS_STA; // 重新启动总线
//while( SI==0 );
if(AckBus()==0) return(0);
if(SendByte(0xA1)==0) return(0); // 发送器件读地址
if( I2STAT!=0X40 )
{
I2CON = GENERATE_STOP;
return(0);
}
for(i=0; i<*DATA_LEN-1; i++)
{
I2CON = RELEASE_BUS_ACK; // 接收一字节数据并发送应答位
//while( SI==0 ); // 等待接收数据
if(AckBus()==0) return(0);
if( I2STAT!=0X50 )
{
I2CON = GENERATE_STOP;
return(0);
}
*DATA_I2C = I2DAT; // 读取数据
CheckSum+=*DATA_I2C; //算出校验码
DATA_I2C++;
}
I2CON = RELEASE_BUS_NOACK; // 接收最后一字节数据并发送非应答位
//while( SI==0 );
if(AckBus()==0) return(0);
*DATA_I2C = I2DAT; //接收最后一字节数据
//CheckSum+=*DATA_I2C; //已经是校验码不能加了
I2CON = GENERATE_STOP; // 结束总线
if(*DATA_I2C==CheckSum) return(1); //验证校验码
else return(0);
}
bit Write_EEPROM(uchar data_add,uchar *EEPROM,uchar data_len)
{
//uchar SLA;
//SLA=0xA0;
SUBA[0]=data_add;
//SUBA[1]=data_add;
DATA_LEN[0]=1;
DATA_LEN[1]=data_len;
if(ISendStr(0xA0,SUBA, EEPROM, DATA_LEN)) return (1);
else return (0);
}
bit Read_EEPROM(uchar data_add, uchar *EEPROM,uchar data_len)
{
//uchar SLA;
//SLA=0xA0;
SUBA[0]=data_add;
DATA_LEN[0]=1;
DATA_LEN[1]=data_len;
if(IRcvStr(SUBA, EEPROM, DATA_LEN)) return (1); //0xA0,
else return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -