📄 i2c.c
字号:
#include<p18f452.h>
#include"delays.h"
/*****************************************************************************
******函 数 名 称 : i2c_idle()
******函 数 功 能 : 判读i2c是否空闲
******输 入 :
******输 出 :
******注 意 :
******************************************************************************/
void i2c_idle(void)
{
while( SSPSTATbits.R_W);
}
/*****************************************************************************
******函 数 名 称 : initial_i2c()
******函 数 功 能 : 初始化i2c
******输 入 : 无
******输 出 : 无
******************************************************************************/
void initial_i2c(void)
{
TRISCbits.TRISC3=1; //定义SCL(RC3)输入
TRISCbits.TRISC4=1; //定义SDA(RC4)输入
SSPCON1=0x28; //SSPEN=1 同步串口使能 and SSPM3:SSPM0=1000 主动模式 时钟=Fosa/(4*(SSPADD+1))
SSPADD= 0x28; //传输速率100k
}
/*****************************************************************************
******函 数 名 称 : start_i2c()
******函 数 功 能 : i2c开始条件产生
******输 入 : 无
******输 出 : 无
******************************************************************************/
void start_i2c( void )
{
SSPCON2bits.SEN = 1; // 在SDA和SCL启动启动条件 由硬件自动清零
while(!PIR1bits.SSPIF); //判断 i2c传输(接收、发送)中断位
PIR1bits.SSPIF=0;
}
/*****************************************************************************
******函 数 名 称 : restart_i2c()
******函 数 功 能 : i2c重起条件产生
******输 入 : 无
******输 出 : 无
******************************************************************************/
void restart_i2c( void )
{
SSPCON2bits.RSEN = 1; //在SDA和SCL启动重复启动条件 由硬件自动清零
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF=0;
}
/*****************************************************************************
******函 数 名 称 : stop_i2c()
******函 数 功 能 : i2c停止条件产生
******输 入 : 无
******输 出 : 无
******************************************************************************/
void stop_i2c( void )
{
SSPCON2bits.PEN = 1; // 在SDA和SCL启动停止条件 由硬件自动清零
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF=0;
}
/*****************************************************************************
******函 数 名 称 : write_i2c()
******函 数 功 能 : i2c写条件产生
******输 入 : 无
******输 出 : 无
******************************************************************************/
void write_i2c( char date )
{
SSPBUF = date;
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF=0;
}
/*****************************************************************************
******函 数 名 称 : write_i2c_data()
******函 数 功 能 : 通过硬件IIC向器件写入数据
******输 入 : addr(从器件地址), child_addr(从器件内部寄存器的子地址),date( 要写入的数据)
******输 出 : 无
******注 意 : 地址的最低位总是0
******************************************************************************/
void write_i2c_data( char addr, char child_addr, char date)
{
i2c_idle(); //等待i2c处于空闲
start_i2c(); // 启动开始
write_i2c(addr&0xFE); // 写入从器件地址
while(SSPCON2bits.ACKSTAT); //接受来自从器件的应答
write_i2c(child_addr); // 从器件内部寄存器的子地址
while(SSPCON2bits.ACKSTAT);
write_i2c(date); // 写入信息
while(SSPCON2bits.ACKSTAT);
stop_i2c(); // 停止
delays(100,150);
}
/*****************************************************************************
******函 数 名 称 : write_i2c_pagedate()
******函 数 功 能 : 通过硬件IIC向器件写入多组数据
******输 入 : addr(从器件地址), child_addr(从器件内部寄存器的子地址),*dptr( 要写入的数据的首地址);unsigned char length(写入的数据长度)
******输 出 :
******注 意 :
******************************************************************************/
void write_i2c_pagedate( char addr,char child_addr,char length, char *dptr)
{
while(length!=0)
{
write_i2c_data( addr, child_addr, *dptr++);
child_addr++;
length--;
}
}
/*****************************************************************************
******函 数 名 称 : read_i2c_date()
******函 数 功 能 : 通过硬件IIC从从器件读数据
******输 入 : addr(从器件地址), child_addr(从器件内部将被读的寄存器的子地址)
******输 出 : 读到的数据
******注 意 : 地址的最低位总是0
******************************************************************************/
unsigned char read_i2c_date( char addr, char child_addr)
{
char f;
i2c_idle(); ///等待i2c处于空闲
start_i2c(); // 启动开始
write_i2c(addr&0xFE); //写入从器件地址
while(SSPCON2bits.ACKSTAT); //接受来自从器件的应答
write_i2c(child_addr); //从器件内部寄存器的子地址
while(SSPCON2bits.ACKSTAT);
restart_i2c();
write_i2c(addr|0x01); // 从器件内部寄存器的子地址并使能读操作
while(SSPCON2bits.ACKSTAT);
SSPCON2bits.RCEN=1; // 使能接受
while(!PIR1bits.SSPIF);
f=SSPBUF;
PIR1bits.SSPIF=0;
SSPCON2bits.ACKDT=1; // 应答数据为 1=不应答 0=应答
SSPCON2bits.ACKEN=1; //启动SCL SDA应答序列 发送ACKDTS数据位
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF=0;
stop_i2c(); // 停止I2C工作
delays(100,150);
return (f); // 返回 SSPBUF值
}
/*****************************************************************************
******函 数 名 称 : read_i2c_pagedate()
******函 数 功 能 : 通过硬件IIC从从器件读出多组数据
******输 入 : addr(从器件地址), child_addr(从器件内部寄存器的子地址),*dptr( 要读出的数据的首地址);unsigned char length(读出的数据长度)
******输 出 :
******注 意 :
******************************************************************************/
void read_i2c_pagedate( char addr, char child_addr, char length, char *dptr)
{
while(length!=0)
{
*dptr++=read_i2c_date( addr,child_addr++);
length--;
}
// 停止I2C工作
}
/*****************************************************************************
******函 数 名 称 : float stof()
******函 数 功 能 : 从eeprom中读取小数
******输 入 :
******输 出 :
******注 意 :
******************************************************************************/
float stof( char addr, char child_addr)
{
char i;
union {
char c[4];
float f;
}temp;
temp.f=0;
for(i=0;i<4;i++)
{
temp.c[i]=read_i2c_date(addr, child_addr+i);
}
return temp.f;
}
/*****************************************************************************
******函 数 名 称 : float ftos()
******函 数 功 能 : 往eeprom中写入小数
******输 入 :
******输 出 :
******注 意 :
******************************************************************************/
void ftos(float a, char addr, char child_addr)
{
char dat;
char i;
union {
char c[4];
float f;
}temp;
temp.f=a;
for(i=0;i<4;i++)
{
dat=temp.c[i];
write_i2c_data( addr, child_addr+i, dat);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -