📄 i2c.c
字号:
/*************************************************
File name: I2C.c
Description: I2C 此程序是 I2C 的操作平台的底层的C子程序,
如发送数据,接收数据,应答位的发送,
注意:函数采用软件延时的方法产生scl脉冲。
Others:
Function List:
1.void Stop_I2c();启动总线函数,启动I2C总线
2.void Stop_I2c();结束I2C 总线
3.void SendByte(unsigned char c);字节数据传送函数,将数据c发送出去,可以时地址,也可以时数据
发玩后等待应答,并对此状态位进行操作(不应答或非应答多使ack=false)
发送数据正常,ack=true;
ack=true:被控器无应答或损坏。
4.unsigned char RcvByte();
5.void Ack_I2c(bit a);
6.bit ISendSTR();
7.bit IRcvstr();
History:
1. Date:
Author:
Modification:
2. ...
*************************************************/
#include <C:\KEIL\C51\INC\PHILIPS\reg51f.h>
#include <main.h>
#include <stdlib.h>
#include <intrins.h>
void Stop_I2c();
void Stop_I2c();
void SendByte(unsigned char c);
unsigned char RcvByte();
void Ack_I2c(bit a);
bit ISendSTR();
bit IRcvstr();
/*****************************/
bit data ack; //应答标志位
unsigned char sla; //从器件地址
unsigned char suba; //子地址suba
unsigned char *I2C_buf; // 数据缓冲区指针 (读操作时会被更改)
unsigned char byte_num; // 操作数据个数 (会被更改)
unsigned char idata data_buf[6];
/*************************************************
Function: void Start_I2C()
Description: 启动总线函数,启动I2C总线
Calls:
Called By: ISendSTR()
Input:
Output:
Return:
Others:
*************************************************/
void Start_I2c()
{
SDA=1; //发送起始条件的数据信号
_nop_();
SCL=1;
_nop_(); //起始条件建立时间大于4.8us延时。6us;一个指令周期 2us
_nop_();
_nop_();
SDA=0; //发送起始信号
_nop_();
_nop_();
_nop_(); //起始条件锁定时间大于4us
SCL=0; //钳住I2C总线。准备发送或接收数据
_nop_();
}
/*************************************************
Function: void Stop_I2C()
Description: 结束I2C 总线
Calls:
Called By: ISendSTR() ,IRcvstr()
Input:
Output:
Return:
Others:
*************************************************/
void Stop_I2c()
{
SDA=0; //发送结束条件的数据信号
_nop_(); //发送结束条件的时钟信号
SCL=1; //结束条件建立时间大于4us
_nop_();
_nop_();
_nop_();
SDA=1; //发送I2C结束信号。
_nop_();
_nop_();
_nop_();
}
/*************************************************
Function: void SendByte(uchar)
Description: 字节数据传送函数,将数据c发送出去,可以时地址,也可以时数据
发玩后等待应答,并对此状态位进行操作(不应答或非应答多使ack=false)
发送数据正常,ack=true;
ack=true:被控器无应答或损坏。
Calls:
Called By: ISendSTR() ,IRcvstr()
Input:
Output:
Return:
Others:
*************************************************/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for (BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((c<<BitCnt)&0x80) //判断发送位
{
SDA=1;
}
else
{
SDA=0;
}
_nop_();
SCL=1; //置时钟线为高,通知被控器开始接收数据位
_nop_();
_nop_(); //保证时钟高电平周期大于4us
_nop_();
//_nop_();
SCL=0;
}
_nop_();
//_nop_();
SDA=1; //8位发送完后释放数据线,准备接收应答信号
_nop_();
//_nop_();
SCL=1;
_nop_();
_nop_();
if (SDA==1)
{
ack=false;
}
else
{
ack=true;
}
SCL=0;
_nop_();
}
/*************************************************
Function: void RcvByte()
Description: 字节数据传送函数,用来接收从器件传来的数据,并判断总线错误(不发应答信号)
发玩后请用应答函数。
Calls:
Called By: IRcvstr()
Input:
Output:
Return:
Others:
*************************************************/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_nop_();
_nop_();
SCL=0; //置时钟线为低准备接收数据位
_nop_();
_nop_();
_nop_();//时钟低电平周期大于4.7us
_nop_();
_nop_();
_nop_();
SCL=1; //置时钟线数据为高使数据线上数据有效。
_nop_();
_nop_();
retc=retc<<1;
if (SDA==1)
{
retc=retc+1;//读数据位,接收的数据位放入retc
}
_nop_();
_nop_();
}
SCL=0;
_nop_();
_nop_();
return(retc);
}
/*************************************************
Function: void Ack_I2c(bit a);
Description: 主控器进行应答信号 (可以使应答或非应答信号)
Calls:
Called By:
Input:
Output:
Return:
Others:
*************************************************/
void Ack_I2c(bit a)
{
if(a==0) //在此发送应答或非应答信号。
{
SDA=0;
}
else
{
SDA=1;
}
_nop_();
_nop_();
SCL=1; //时钟高电平周期大于4us,
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0; //清时钟线,钳住I2C总线一边继续接收。
_nop_();
_nop_();
_nop_();
}
/*************************************************
Function: bit ISendSTR()
Description:从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,
子地址suba,发送内容是I2C_buf指向的内容,发送byte_num个字节。
如果返回1表示操作成功,否则操作有误
Calls: Start_I2c(); //启动总线_
Ack_I2c(1);
Stop_I2c();
RcvByte();
Start_I2c();
Called By: key_read();
void Cah_Warp_Save(unsigned char add,unsigned char num)
void Cah_Temp_Save(unsigned char add,unsigned char num)
Input:
Output:
Return:
Others:
*************************************************/
bit ISendSTR()
{
unsigned char i;
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if (ack==false)
{
return(0);
}
SendByte(suba);//发送器件子地址
if (ack==false)
{
return(0);
}
for (i=0;i<byte_num;i++)
{
SendByte(*I2C_buf); //发送数据。
if (ack==false)
{
return(0);
}
I2C_buf++;
}
Stop_I2c();
return(1);
}
/*************************************************
Function: bit IRcvstr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char byte_num)
Description: 向有子地址器件读取多字节函数,从启动总线到发送地址、子地址,读数据,结束总线的全过程
,从器件地址sla,子地址suba,读出的内容放入I2C_buf指向的存储区,读byte_num个字节,如返回1
表示操作成功,否则有误。
Calls: Start_I2c(); //启动总线_
Ack_I2c(1);
Stop_I2c();
RcvByte();
Start_I2c();
void SendByte(unsigned char c);
Called By: void Read_Cah_Warp(unsigned char add,unsigned char num)
void Read_Cah_Temp(unsigned char add,unsigned char num)
void read_setvalue()
Input:
Output:
Return:
Others:
*************************************************/
bit IRcvstr()
{
unsigned char i;
Start_I2c(); //启动总线_
SendByte(sla); //发送器件地址
if (ack==0)
{
return(0);
}
SendByte(suba); //发送器件子地址
if (ack==0)
{
return(0);
}
Start_I2c(); //重新启动总线
SendByte(sla+1); //准备进行读操作W/R置1
if(ack==0)
{
return(0);
}
for (i=0;i<byte_num-1;i++)
{
*I2C_buf=RcvByte(); //发送数据
Ack_I2c(0); //发送就答位
I2C_buf++;
}
*I2C_buf=RcvByte();
Ack_I2c(1); //发送非应位
Stop_I2c();
return(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -