📄 i2c.c
字号:
/*I2C总线操作函数*/
#include "I2C.H"
#include <reg52.H>
sbit I2C_scl=P1^2; //I2C时钟信号
sbit I2C_sda=P1^3; //I2C数据信号
void I2C_Delay(unsigned int item); //I2C总线延时
void I2C_Init(); //I2C总线初始化
void I2C_Start(); //I2C总线启动
void I2C_WriteByte(unsigned char x); //I2C总线写入1字节数据
unsigned char I2C_ReadByte(); //I2C总线读取1字节数据
bit I2C_SlaveAck(); //I2C总线从机应答
void I2C_MasterAck(bit ack); //I2C总线主机应答
void I2C_Stop(); //I2C总线停止
bit I2C_Puts(unsigned char slave_addr,unsigned int sub_addr,unsigned char sub_mode, char* dat,unsigned char size);
//I2C总线连续发送字节,slave_addr为从机地址,sub_addr为从机内部寄存器地址,sub_mode为寄存器地址类型,"0"表示无地址,
//"1"表示单字节地址,"2"表示双字节地址,dat为发送字节指针,size为字节数
bit I2C_Gets(unsigned char slave_addr,unsigned int sub_addr,unsigned char sub_mode, char* dat,unsigned char size);
//I2C总线连续接收字节,slave_addr为从机地址,sub_addr为从机内部寄存器地址,sub_mode为寄存器地址类型,"0"表示无地址,
//"1"表示单字节地址,"2"表示双字节地址,dat为发送字节指针,size为字节数
/* I2C总线延时*/
void I2C_Delay(unsigned int item)
{
while(item--);
}
/* I2C初始化子程序 */
void I2C_Init()
{
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_sda=1;
I2C_Delay(I2C_DELAY_VALUE);
}
/* I2C总线启动子程序,时钟线高电平时,数据线下降沿启动总线*/
void I2C_Start()
{
I2C_sda=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_sda=0;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=0;
I2C_Delay(I2C_DELAY_VALUE);
}
/* I2C总线字节写入子程序*/
void I2C_WriteByte(unsigned char x)
{
unsigned char i;
for(i=8;i>0;i--)
{
I2C_sda=(bit)(x&(0x80));
x=x<<1;
I2C_scl=1; //时钟线高时写入
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=0;
I2C_Delay(I2C_DELAY_VALUE);
}
}
/* I2C总线字节读取子程序*/
unsigned char I2C_ReadByte()
{
unsigned char x,i; //函数返回字节
I2C_sda=1; //数据线先置高
x=0;
for(i=8;i>0;i--)
{
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
x=x<<1;
if(I2C_sda){x=x|(0x01);} //数据线为1
I2C_scl=0;
I2C_Delay(I2C_DELAY_VALUE);
}
return(x); //字节返回
}
/* I2C总线从机应答,返回值为1时终止传输,为0时表明从机接收完一字节数据*/
bit I2C_SlaveAck()
{
bit ack;
I2C_sda=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
ack=I2C_sda;
I2C_scl=0;
I2C_Delay(I2C_DELAY_VALUE);
return ack; //返回状态位
}
/* I2C总线主机应答,"ack"为"1"时终止传输,为"0"时表明接收完一字节数据*/
void I2C_MasterAck(bit ack)
{
I2C_sda=ack;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=0;
I2C_Delay(I2C_DELAY_VALUE);
}
/* I2C总线停止*/
void I2C_Stop()
{
unsigned int delay=I2C_STOP_VALUE;
I2C_sda=0;
I2C_Delay(I2C_DELAY_VALUE);
I2C_scl=1;
I2C_Delay(I2C_DELAY_VALUE);
I2C_sda=1;
I2C_Delay(I2C_DELAY_VALUE); //上升沿终止I2C总线传输
while(delay--);
//{delay--;} //延时一段时间
}
/* I2C接口器件内部数据写入子程序*/
bit I2C_Puts(unsigned char slave_addr,unsigned int sub_addr,unsigned char sub_mode, char* dat,unsigned char size)
{
unsigned char i;
unsigned char num[3];
bit ack=0;
if(size==0) {return 0;} //字节长度为0,返回
num[0]=slave_addr; //数组首字节存储从机I2C地址,末位"0"表示写入,"1"表示读出
//ZLG7290地址定义为0x70H,默认时为写操作
if(sub_mode>2) {sub_mode=2;} //检查内部字节储存方式
switch(sub_mode) //存储内部地址
{
case 0:
{break;}
case 1:
{num[1]=(char)(sub_addr);
break;}
case 2:
{num[1]=(char)(sub_addr>>8);
num[2]=(char)(sub_addr&(0x00ff));
break;}
default:
break;
}
sub_mode++; //配合后面for循环操作
I2C_Start(); //启动I2C总线
for(i=0;i<sub_mode;i++)
{
I2C_WriteByte(num[i]); //写入从机I2C地址
ack=I2C_SlaveAck();
if(ack==1)
{
I2C_Stop(); //终止I2C总线传输
return 1;
}
}
for(i=0;i<size;i++)
{
I2C_WriteByte(*dat);
ack=I2C_SlaveAck();
if(ack==1){break;} //跳出for循环
dat++; //指针加1
}
I2C_Stop(); //传输停止
if(ack==0) //数据传输正确,返回值"0"。
{return 0;}
else
{return 1;}
}
/* I2C接口器件内部数据读出子程序,只能读取单一地址单元内数据*/
bit I2C_Gets(unsigned char slave_addr,unsigned int sub_addr,unsigned char sub_mode, char* dat,unsigned char size)
{
bit bdata ack;
unsigned char i;
unsigned char num[3];
// unsigned char content;
if(size==0){return 0;}
num[0]=slave_addr; //首先将地址写入(写操作)
if(sub_mode>2){sub_mode=2;}
if(sub_mode!=0) //有内部地址
{
switch(sub_mode)
{
case 0:
{break;}
case 1:
{num[1]=(char)(sub_addr);
break;}
case 2:
{num[1]=(char)(sub_addr>>8);
num[2]=(char)(sub_addr&(0x00ff));
break;}
default:
break;
}
}
sub_mode++;
I2C_Start(); //启动I2C总线
for(i=0;i<sub_mode;i++)
{
I2C_WriteByte(num[i]); //写入从机I2C地址
ack=I2C_SlaveAck();
if(ack==1)
{
I2C_Stop(); //终止I2C总线传输
return 1;
}
}
//开始读操作
I2C_Start(); //启动I2C总线
num[0]=num[0]|(0x01); //末位置高,读操作
I2C_WriteByte(num[0]); //写入读操作地址
ack=I2C_SlaveAck();
if(ack==1)
{
I2C_Stop(); //终止I2C总线传输
return (0x01);
}
while(1)
{
*dat=I2C_ReadByte();
dat++;
size--; //长度减1
if(size==0)
{
I2C_MasterAck(1); //接收完毕,终止I2C传输
break;
}
I2C_MasterAck(0); //继续传输
}
I2C_Stop();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -