📄 i2c.c
字号:
#include "i2c.h"
void I2C_Initial( void )
{
//将SCL管脚设置为输出管脚
SCLOUT;
I2C_Set_sck_low();
I2C_STOP();
Delay_ms(10);
return;
}
void I2C_Set_sda_high( void )
{
//将SDA设置为输出模式
SDAOUT;
//SDA管脚输出为高电平
SDA1;
NOP();
NOP();
return;
}
void I2C_Set_sda_low ( void )
{
//将SDA设置为输出模式
SDAOUT;
//SDA管脚输出为低电平
SDA0;
NOP();
NOP();
return;
}
void I2C_Set_sck_high( void )
{
//将SCL设置为输出模式
SCLOUT;
//SCL管脚输出为高电平
SCL1;
NOP();
NOP();
return;
}
void I2C_Set_sck_low ( void )
{
//将SCL设置为输出模式
SCLOUT;
//SCL管脚输出为低电平
SCL0;
NOP();
NOP();
return;
}
int I2C_GetACK(void)
{
int nTemp = 0;
int j;
NOP();
NOP();
I2C_Set_sck_low();
for(j = 30;j > 0;j--);
//将SDA设置为输入方向
SDAIN;
I2C_Set_sck_high();
for(j = 30;j > 0;j--);
//获得数据
nTemp = (int)(SDA_STATE); //读入SDA状态
I2C_Set_sck_low();
return (nTemp & LC24_SDA);
}
void I2C_SetACK(void)
{
I2C_Set_sck_low();
I2C_Set_sda_low();
I2C_Set_sck_high();
I2C_Set_sck_low();
return;
}
void I2C_SetNAk(void)
{
I2C_Set_sck_low();
I2C_Set_sda_high();
I2C_Set_sck_high();
I2C_Set_sck_low();
return;
}
void I2C_START(void)
{
int i;
I2C_Set_sda_high();
for(i = 5;i > 0;i--);
I2C_Set_sck_high();
for(i = 5;i > 0;i--);
I2C_Set_sda_low();
for(i = 5;i > 0;i--);
I2C_Set_sck_low();
return;
}
void I2C_STOP(void)
{
int i;
I2C_Set_sda_low();
for(i = 5;i > 0;i--);
I2C_Set_sck_low();
for(i = 5;i > 0;i--);
I2C_Set_sck_high();
for(i = 5;i > 0;i--);
I2C_Set_sda_high();
for(i = 5;i > 0;i--);
I2C_Set_sck_low();
//延迟一点时间
Delay_ms(10);
return;
}
void I2C_TxHToL(int nValue)
{
int i;
int j;
for(i = 0;i < 8;i++)
{
if(nValue & 0x80)
I2C_Set_sda_high();
else
I2C_Set_sda_low();
for(j = 30;j > 0;j--);
I2C_Set_sck_high();
nValue <<= 1;
for(j = 30;j > 0;j--);
I2C_Set_sck_low();
}
return;
}
void I2C_TxLToH(int nValue)
{
int i;
int j;
for(i = 0;i < 8;i++)
{
if(nValue & 0x01)
I2C_Set_sda_high();
else
I2C_Set_sda_low();
for(j = 30;j > 0;j--);
I2C_Set_sck_high();
nValue >>= 1;
for(j = 30;j > 0;j--);
I2C_Set_sck_low();
}
return;
}
/////////////////////////////////////////////
// 接收是从 LSB 到 MSB 的顺序
int I2C_RxByte(void)
{
int nTemp = 0;
int i;
int j;
I2C_Set_sda_high();
//将SDA管脚设置为输入方向
SDAIN;
NOP();
NOP();
NOP();
NOP();
for(i = 0;i < 8;i++)
{
I2C_Set_sck_high();
if(SDA_STATE) //读入SDA状态
{
nTemp |= (0x01 << i);
}
for(j = 30;j > 0;j--);
I2C_Set_sck_low();
}
return nTemp;
}
/////////////////////////////////////////////
// 接收是从 MSB 到 LSB 的顺序
int I2C_RxHToL(void)
{
int nTemp = 0;
int i;
int j;
I2C_Set_sda_high();
//将SDA管脚设置为输入方向
SDAIN;
NOP();
NOP();
NOP();
NOP();
for(i = 0;i < 8;i++)
{
I2C_Set_sck_high();
if(SDA_STATE) //读入SDA状态
{
nTemp |= (0x01 << (7 - i));
}
for(j = 30;j > 0;j--);
I2C_Set_sck_low();
}
return nTemp;
}
void Delay_ms(unsigned long nValue)//毫秒为单位,8MHz为主时钟
{
unsigned long nCount;
int i;
unsigned long j;
nCount = 2667;
for(i = nValue;i > 0;i--)
{
for(j = nCount;j > 0;j--);
}
return;
}
void Delay_us(unsigned long nValue)//微秒为单位,8MHz为主时钟
{
int nCount;
int i;
int j;
nCount = 3;
for(i = nValue;i > 0;i--)
{
for(j = nCount;j > 0;j--);
}
return;
}
//设备码 1010
void readByte24AA64(int addr,unsigned char *reby_p)
{
char hi;
char low;
//高地址
hi = (char)((addr >> 8) & 0xff);
hi &= 0x1F;
//低地址
low = (char)(addr & 0xff);
// 启动数据总线
I2C_START();
// 发送写命令
I2C_TxHToL(0xA0);
// 等待 ACK
I2C_GetACK();
//发送高地址
I2C_TxHToL(hi);
// 等待 ACK
I2C_GetACK();
//发送低地址
I2C_TxHToL(low);
// 等待 ACK
I2C_GetACK();
// 启动数据总线
I2C_START();
// 发送读命令
I2C_TxHToL(0xA1);
// 等待 ACK
I2C_GetACK();
//读一个数据
*reby_p= I2C_RxHToL();
//设置NAK
I2C_SetNAk();
// 停止总线
I2C_STOP();
return;
}
void writeByte24AA64(int addr,unsigned char *wrby_p)
{
char hi;
char low;
//高地址
hi = (char)((addr >> 8) & 0xff);
hi &= 0x1F;
//低地址
low = (char)(addr & 0xff);
// 启动数据总线
I2C_START();
// 发送写命令
I2C_TxHToL(0xA0);
// 等待 ACK
I2C_GetACK();
//发送高地址
I2C_TxHToL(hi);
// 等待 ACK
I2C_GetACK();
//发送低地址
I2C_TxHToL(low);
// 等待 ACK
I2C_GetACK();
//写入数据
I2C_TxHToL(*wrby_p);
// 等待 ACK
I2C_GetACK();
// 停止总线
I2C_STOP();
return;
}
int readPage24AA64(int addr,unsigned char *repa_p,int len)
{
char hi;
char low;
int i;
//高地址
hi = (char)((addr >> 8) & 0xff);
hi &= 0x1F;
//低地址
low = (char)(addr & 0xff);
//高地址
hi = (char)((addr >> 8) & 0xff);
hi &= 0x1F;
//低地址
low = (char)(addr & 0xff);
// 启动数据总线
I2C_START();
// 发送写命令
I2C_TxHToL(0xA0);
// 等待 ACK
I2C_GetACK();
//发送高地址
I2C_TxHToL(hi);
// 等待 ACK
I2C_GetACK();
//发送低地址
I2C_TxHToL(low);
// 等待 ACK
I2C_GetACK();
// 启动数据总线
I2C_START();
// 发送读命令
I2C_TxHToL(0xA1);
// 等待 ACK
I2C_GetACK();
for(i = 0;i < len - 1;i++)
{
//读一个数据
*(repa_p+i) = I2C_RxHToL();
//设置ACK
I2C_SetACK();
}
//最后一个数据
*(repa_p+(len -1))= I2C_RxHToL();
//设置NAK
I2C_SetNAk();
// 停止总线
I2C_STOP();
//读32个数据
return len;
}
void writePage24AA64(int addr,unsigned char *wrpa_p,int len)
{
char hi;
char low;
int i;
//高地址
hi = (char)((addr >> 8) & 0xff);
hi &= 0x1F;
//低地址
low = (char)(addr & 0xff);
//页写最多能写入32个数据
if(len > 32) len = 32;
// 启动数据总线
I2C_START();
// 发送写命令
I2C_TxHToL(0xA0);
// 等待 ACK
I2C_GetACK();
//发送高地址
I2C_TxHToL(hi);
// 等待 ACK
I2C_GetACK();
//发送低地址
I2C_TxHToL(low);
// 等待 ACK
I2C_GetACK();
for(i = 0;i < len;i++)
{
//写入数据
I2C_TxHToL(*(wrpa_p+i));
// 等待 ACK
I2C_GetACK();
}
// 停止总线
I2C_STOP();
return;
}
void I2C_CLR(void) //清24LC子程序;
{
int a,b;
char clrda[8]={0};
for(a=0;a<400;a++)
{
b=a*8;
writePage24AA64(b,clrda,8);
}
}
//******************************************************
//检验两组数据是否正确,如在检验数据中有一组不正确,则退出.
//*Data_REF参考值数组,*Data_CHK被检验数组,n检验数量
//并返回一个成败标志.0为正确,1为错误;
unsigned char data_check(unsigned char *Data_REF, unsigned char *Data_CHK, unsigned char n)
{unsigned char chk ;
while(n)
{
if(Data_REF[n-1]==Data_CHK[n-1]) //进行校对
{ chk =0; //正确
n--; //下一位
}
else
{ chk =1; //校对有错
continue; //马上退出
}
}
return chk ; //返回校对成败标志.
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -