I2C總線在傳送數(shù)據(jù)過程中共有三種類型信號(hào), 它們分別是:開始信號(hào)、結(jié)束信號(hào)和應(yīng)答信號(hào).
開始信號(hào):SCL為高電平時(shí),SDA由高電平向低電平跳變,開始傳送數(shù)據(jù).
結(jié)束信號(hào):SCL為低電平時(shí),SDA由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù).
應(yīng)答信號(hào):接收數(shù)據(jù)的IC在接收到8bit數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的IC發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù).CPU向受控單元發(fā)出一個(gè)信號(hào)后,等待受控單元發(fā)出一個(gè)應(yīng)答信號(hào),CPU接收到應(yīng)答信號(hào)后,根據(jù)實(shí)際情況作出是否繼續(xù)傳遞信號(hào)的判斷.若未收到應(yīng)答信號(hào),由判斷為受控單元出現(xiàn)故障.
目前有很多半導(dǎo)體集成電路上都集成了I2C接口.*/
/*
***************************************************************************
*
* (C) Copyright 2007,單片機(jī)初學(xué)者園地
* All Rights reserved.
*
*項(xiàng)目名稱: 51單片機(jī)學(xué)習(xí)開發(fā)系統(tǒng)
*
*本文件名稱:IIC.c
* 完成作者 : 單片機(jī)初學(xué)者
* 當(dāng)前版本 : V1.0
* 完成日期 :
* 描 述 : 本程序結(jié)構(gòu)簡單、合理,有幫助于初學(xué)者養(yǎng)成良好的編
* 程風(fēng)格.主要實(shí)現(xiàn)IIC總線的讀寫.
****************************************************************************
*/
#include
#include < .h>
#define uchar unsigned char
#define uint unsigned int
#define IIC_READ 0XA1 //定義讀指令
#define IIC_WRITE 0XA0 //定義寫指令
#define NOP _nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_()
//==============================
sbit SDA=P0^6;
sbit SCL=P0^7;
//===============================
//define a bit_operation byte to use in shift operation
//use this mode can achieve high operation speed
uchar bdata bbyte;//定義位操作用數(shù)組,采用此方法可提高位操作速度
sbit a0=bbyte^0;
sbit a1=bbyte^1;
sbit a2=bbyte^2;
sbit a3=bbyte^3;
sbit a4=bbyte^4;
sbit a5=bbyte^5;
sbit a6=bbyte^6;
sbit a7=bbyte^7;
//=============定義位標(biāo)志===========================
bit IFACK; //record the SDA state to confirn if ACK has happened
bit NO_ACK; //no ack flag
bit BUS_FAULT; //bus fault flag
//=============IIC開始時(shí)序==========================
//FUNCTION:ROUTES TO PROVIDE A START SIGNAL
void start(void)
{
SCL=0;SDA=1; NOP;SCL=1;SDA=0;NOP;SCL=0;
}
//==============IIC停止時(shí)序=========================
//FUNCTION:ROUTES TO PROVIDE A STOP SIGNAL
void stop(void)
{
SCL=0;SDA=0;NOP;SCL=1;SDA=1;NOP;SCL=0;
}
//=====================================
//FUNCTION:ROUTES TO PROVIDE ACK SINGAL
void ack(void)
{
SCL=0;SDA=0;NOP;SCL=1;NOP;SCL=0;
}
//=====================================
//FUNCTION:ROUTES TO RELEASE THE SDA TO RECEIVE A ACK SIGNAL
// OR TO PROVIDE A NO_ACK SIGNAL
//type=1等待應(yīng)答信號(hào)
//type=0 產(chǎn)生無應(yīng)答信號(hào)
void nack(uchar type)
{
SCL=0;SDA=1;NOP;SCL=1;IFACK=SDA; NOP;SCL=0;
if(type)
{
if(IFACK) //如果無應(yīng)答信號(hào),則置標(biāo)志位NO_ACK,程序中止
{
NO_ACK=1; //用戶可以加入自己的異常處理程序
//while(1);
}
else NO_ACK=0;
}
}
//=======================================================
//FUNCTION:THE IIC DEVICE SHIFT OUT A BYTE TO THE MASTER
uchar inbyte(void)
{ //從IIC器件中讀出數(shù)據(jù)
SDA=1;
SCL=1;a7=SDA;NOP;SCL=0;
SCL=1;a6=SDA;NOP;SCL=0;
SCL=1;a5=SDA;NOP;SCL=0;
SCL=1;a4=SDA;NOP;SCL=0;
SCL=1;a3=SDA;NOP;SCL=0;
SCL=1;a2=SDA;NOP;SCL=0;
SCL=1;a1=SDA;NOP;SCL=0;
SCL=1;a0=SDA;NOP;SCL=0;
return(bbyte);
}
//=======================================================
//FUNCTION:THE IIC DEVICE SHIFT IN A BYTE FROM THE MASTER
void outbyte(uchar outdata)
{ //將數(shù)據(jù)寫放IIC器件
bbyte=outdata;
SDA=a7;SCL=1;NOP;SCL=0;
SDA=a6;SCL=1;NOP;SCL=0;
SDA=a5;SCL=1;NOP;SCL=0;
SDA=a4;SCL=1;NOP;SCL=0;
SDA=a3;SCL=1;NOP;SCL=0;
SDA=a2;SCL=1;NOP;SCL=0;
SDA=a1;SCL=1;NOP;SCL=0;
SDA=a0;SCL=1;NOP;SCL=0;
}
/**********************寫函數(shù)****************************************
** 函數(shù)名稱: 寫數(shù)據(jù)
** 入口參數(shù):add為讀起始地址,ptr數(shù)據(jù)保存指針,writelen為寫出數(shù)據(jù)長度
********************************************************************/
void writebyteseq(unsigned char page_addr, unsigned char byte_address,uchar *ptr,uchar writelen)
{
uchar temph;
uchar i;
unsigned char x;
x = (page_addr<<1);
temph = (x | IIC_WRITE);
start();
// outbyte(IIC_WRITE);
// nack(1);
outbyte(temph);
nack(1);
outbyte(byte_address);
nack(1);
for(i=0;i {
outbyte(*(ptr+i));
nack(1);
}
stop();
}
/**********************讀函數(shù)***************************************
** 函數(shù)名稱: 連續(xù)讀數(shù)據(jù)
** 入口參數(shù):add為讀起始地址,ptr數(shù)據(jù)保存指針,readlen為讀出數(shù)據(jù)長度
********************************************************************/
void readbyteseq(unsigned char page_addr, unsigned char byte_address,uchar *ptr,uchar readlen)
{
uchar temph;
uchar i;
unsigned char x;
x = (page_addr<<1); // 2 address bytes.
temph = (x | IIC_WRITE);
start();
// outbyte(IIC_WRITE);
// nack(1);
outbyte(temph);
nack(1);
outbyte(byte_address);
nack(1);
start();
outbyte(IIC_READ);
nack(1);
for(i=0;i {
*(ptr+i)=inbyte();
ack();
}
*(ptr+readlen-1)=inbyte();
nack(0);
stop();
}
/*版主注:因?yàn)槟阋郧霸啻紊嫦右约夹g(shù)為名做廣告,因此不得不采取一些措施.否則是對(duì)其他網(wǎng)友的不公平,也是對(duì)版內(nèi)原則的踐踏.希望您能理解并對(duì)單片機(jī)的技術(shù)發(fā)起和參與討論.*/