?? i2c.c
字號(hào):
//iic.c
#include <reg51.h>
#include <intrins.h>
#include "I2C.H"
bit gAck;//應(yīng)答標(biāo)志位
//短延時(shí)
void I2C_Delay(long lDly)
{
while ( lDly ) lDly--;
}
void I2C_Init()
{
SCL = 1;
I2C_Delay(10);
SDA = 1;
I2C_Delay(10);
}
/*******************************************************************
起動(dòng)總線函數(shù)
函數(shù)原型: void I2C_Start();
功能: 啟動(dòng)I2C總線,即發(fā)送I2C起始條件
********************************************************************/
void I2C_Start()
{
SDA = 1; //發(fā)送起始條件的數(shù)據(jù)信號(hào)
I2C_Delay(1);
SCL = 1;
I2C_Delay(10); //起始條件建立時(shí)間大于4.7us,延時(shí)
SDA = 0; //發(fā)送起始信號(hào)
I2C_Delay(10); // 起始條件鎖定時(shí)間大于4μs
SCL = 0; //鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
I2C_Delay(2);
}
/*******************************************************************
結(jié)束總線函數(shù)
函數(shù)原型: void Stop_I2c();
功能: 結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
********************************************************************/
void I2C_Stop()
{
SDA = 0; //發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)
I2C_Delay(1); //發(fā)送結(jié)束條件的時(shí)鐘信號(hào)
SCL = 1; //結(jié)束條件建立時(shí)間大于4μs
I2C_Delay(10);
SDA = 1; //發(fā)送I2C總線結(jié)束信號(hào)
I2C_Delay(10);
}
/*******************************************************************
字節(jié)數(shù)據(jù)發(fā)送函數(shù)
函數(shù)原型: void I2C_SendByte(uchar uchData);
功能: 將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對(duì)
此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)
發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無(wú)應(yīng)答或損壞。
********************************************************************/
void I2C_SendByte(unsigned char uchData)
{
unsigned char uchBitCnt;
for(uchBitCnt = 0;uchBitCnt < 8;uchBitCnt ++) /*要傳送的數(shù)據(jù)長(zhǎng)度為8位*/
{
if( (uchData << uchBitCnt) & 0x80)
SDA = 1; //判斷發(fā)送位
else
SDA = 0;
I2C_Delay(1);
SCL = 1; //置時(shí)鐘線為高,通知被控器開(kāi)始接收數(shù)據(jù)
I2C_Delay(10); //保證時(shí)鐘高電平周期大于4μs
SCL = 0;
}
I2C_Delay(2);
SDA = 1; //8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位
I2C_Delay(10); //
SCL = 1;
I2C_Delay(10); //
if(SDA == 1)
gAck=0;
else
gAck=1; //判斷是否接收到應(yīng)答信號(hào)
SCL = 0;
I2C_Delay(5);
}
/*******************************************************************
字節(jié)數(shù)據(jù)接收函數(shù)
函數(shù)原型: unsigned char I2C_RcvByte();
功能: 用來(lái)接收從器件傳來(lái)的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號(hào)),
發(fā)完后請(qǐng)用應(yīng)答函數(shù)應(yīng)答從機(jī)。
********************************************************************/
unsigned char I2C_RcvByte()
{
unsigned char uchRetc;
unsigned char uchBitCnt;
uchRetc = 0;
SDA = 1; //置數(shù)據(jù)線為輸入方式
for(uchBitCnt = 0;uchBitCnt < 8;uchBitCnt ++)
{
I2C_Delay(1);;
SCL = 0; //置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位
I2C_Delay(5); //時(shí)鐘低電平周期大于4.7μs
SCL = 1; //置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效
I2C_Delay(5);
uchRetc = uchRetc << 1;
if(SDA == 1)
uchRetc = uchRetc + 1; //讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中
I2C_Delay(5);
}
SCL = 0;
I2C_Delay(2);
return uchRetc;
}
/********************************************************************
應(yīng)答子函數(shù)
函數(shù)原型: void Ack_I2c(bit a);
功能: 主控器進(jìn)行應(yīng)答信號(hào)(可以是應(yīng)答或非應(yīng)答信號(hào),由位參數(shù)a決定)
********************************************************************/
void I2C_Ack(bit bData)
{
if(bData == 0)
SDA=0; //在此發(fā)出應(yīng)答或非應(yīng)答信號(hào)
else
SDA=1;
I2C_Delay(5);
SCL = 1;
I2C_Delay(5); //時(shí)鐘低電平周期大于4μs
SCL = 0; //清時(shí)鐘線,鉗住I2C總線以便繼續(xù)接收
I2C_Delay(5);
}
/*******************************************************************
向有子地址器件發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
函數(shù)原型: bit I2C_SendStr(unsigned char uchSlaveAddr,unsigned char uchSubAddr,unsigned char uchSize,unsigned char *pBuf);
功能: 從啟動(dòng)總線到發(fā)送地址,子地址,數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件
地址sla,子地址suba,發(fā)送內(nèi)容是s指向的內(nèi)容,發(fā)送no個(gè)字節(jié)。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結(jié)束總線。
********************************************************************/
bit I2C_SendStr(unsigned char uchSlaveAddr,unsigned char uchSubAddr,unsigned char uchSize,unsigned char *pSendBuf)
{
unsigned char i;
I2C_Start(); //啟動(dòng)總線
I2C_SendByte(uchSlaveAddr); //發(fā)送器件地址
if(gAck == 0)
return(0);
I2C_SendByte(uchSubAddr); //發(fā)送器件子地址
if(gAck == 0)
return(0);
for(i = 0;i < uchSize;i++)
{
I2C_SendByte(*pSendBuf); //發(fā)送數(shù)據(jù)
if(gAck == 0)
return(0);
pSendBuf++;
}
I2C_Stop(); //結(jié)束總線
return(1);
}
/*******************************************************************
向有子地址器件讀取多字節(jié)數(shù)據(jù)函數(shù)
函數(shù)原型: bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no);
功能: 從啟動(dòng)總線到發(fā)送地址,子地址,讀數(shù)據(jù),結(jié)束總線的全過(guò)程,從器件
地址sla,子地址suba,讀出的內(nèi)容放入s指向的存儲(chǔ)區(qū),讀no個(gè)字節(jié)。
如果返回1表示操作成功,否則操作有誤。
注意: 使用前必須已結(jié)束總線。
********************************************************************/
bit I2C_RcvStr(unsigned char uchSlaveAddr,unsigned char uchSubAddr,unsigned char uchSize,unsigned char *pRcvBuf)
{
unsigned char i;
I2C_Start(); //啟動(dòng)總線
I2C_SendByte(uchSlaveAddr); //發(fā)送器件地址
if(gAck == 0)
return(0);
I2C_SendByte(uchSubAddr); //發(fā)送器件子地址
if(gAck == 0)
return(0);
I2C_Start(); //重新啟動(dòng)總線
I2C_SendByte(uchSlaveAddr + 1);
if(gAck == 0)
return(0);
for(i = 0;i < uchSize - 1;i++)
{
*pRcvBuf = I2C_RcvByte(); //發(fā)送數(shù)據(jù)
I2C_Ack(0); //發(fā)送數(shù)據(jù)應(yīng)答位
pRcvBuf ++;
}
*pRcvBuf = I2C_RcvByte();
I2C_Ack(1); //發(fā)送非應(yīng)位
I2C_Stop(); //結(jié)束總線
return(1);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -