?? 模擬i2c總線.txt
字號(hào):
在單片機(jī)應(yīng)用中,I2C(I方C)總線一種簡(jiǎn)單,雙向的二線制同步串行總線,它只需要兩根串行線,脈沖線,就可以在總線與連接的器件之間傳送信息, 它不外乎有以下幾個(gè)特點(diǎn):
a.每個(gè)連接到總線上的器件都可以進(jìn)行唯一的尋址,還可建立起簡(jiǎn)單的主從關(guān)系,主器件既可作為發(fā)送器,也可作為接收器.
b.它帶競(jìng)爭(zhēng)電路和仲裁電路,可以接收多個(gè)主器件發(fā)送的數(shù)據(jù),而這些數(shù)據(jù)不會(huì)產(chǎn)混亂.
c.同步脈沖可以允許器件可以通過總線以不同的波特率進(jìn)行通信.
d.因?yàn)橹挥袃筛€,連接簡(jiǎn)單,方便.
對(duì)于MCS51系列來(lái)講,內(nèi)部并沒I2C總線接口,在這種情況下,可以采用軟件模擬的方法來(lái)寫出I2C總線的操作,下面我的程序就在開始處定義哪個(gè)引腳作為數(shù)據(jù)線SDA,哪個(gè)引腳作為脈沖線,請(qǐng)看我的程序(C51寫的,總共有8個(gè)函數(shù)來(lái)模擬I2C總線):
Common.h File
#pragma LA DB SB OE CD OT(SPEED,6)
//LA indicate LARGE Compling Mode-All local and global variables are located in external-ram.
//DB indicate DEBUG
//SB indicate SYMBOL
//OE indicate OBJECTEXTEND
//CD indicate CODE //Generate ASM Code
//OT indicate OPTIMIZATION
#include <stdio.h>
#include <reg51.h>
#include <intrins.h>
#include <stdlib.h>
#pragma REGPARMS
#pragma SAVE
#define BOOL bit
#define BYTE unsigned char
#define UINT unsigned int
#define ULONG unsigned long
#define HIGH 1
#define LOW 0
#define TRUE 1
#define FALSE 0
#define MAXLONGS 2147483647
#define MINLONGS -2147483648
#define MAXINTS 32767
#define MININTS -32768
#define MAXLONGU 4294967295
#define MAXINTU 65535
#define BLOCKLOW 0x0000 //The start-address in AT24C64 is 0x0000
#define BLOCKSIZE 0x20 //Each block is 32 bytes
#define BLOCKNUM 0xC8 //At best 200,Only Save the newest 200 records.
#define BLOCKHIGH 0x18FF//The end-address in AT24C64 is 0x18FF
#define OSC 24000000 //Osillcator Frequency
#define BAUDRATE 9600
#define OTV 256-OSC/12/BAUDRATE/32 //character O represents Obtain,character T represents Timer,character V represents Value
//IMPORTANT ANNOUNCEMENT:I use a word 0x1FFC,0x1FFD to save the next block's address and 0x1FFE,0x1FFF to save the block's no.
sbit GUN=0x85;//PIN P05
sbit SCL=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit SDA=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit SHKL=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit SHKH=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH0=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH1=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
sbit KH2=0xFF; //Undefined bit-address,which will be defined in function:DEFI2C
extern void DEFI2C(char *name) //To define which pin is SDA and which pin is SCL
extern void I2CInit() //Initialization For I2C Bus
extern void I2CStart() //Start I2C Bus
extern void I2CStop(); //Stop I2C Bus
extern bit I2CClock(); //return SDA while SCL is HIGH
extern void I2CDelay(); //Delay
extern void I2CAck(); //Answer
extern bit I2CSend(BYTE I2CData);//Send data with I2C Bus
extern BYTE I2CReceive(); //Receive data
Common.c
void DEFI2C(char *name)
{
//Todo:add your codes here....
//Announcement:If you question me why use the function DEFI2C?
//Well,the function will be used to define which PIN is SCL and which PIN is SDA,especially there are more than 1 I2C
//equipment in your circuit.In this sitiuation,we write a function for defining I2C Bus named DEFI2C....
}
void I2CStart()
{
SCL=HIGH;
I2CDelay();
SDA=LOW;
I2CDelay();
SCL=LOW;
I2CDelay();
}
void I2CStop()
{
SDA=LOW;
I2CDelay();
SCL=HIGH;
I2CDelay();
SDA=HIGH;
I2CDelay();
SCL=LOW;
I2CDelay();
}
void I2CInit()
{
SCL=LOW;
I2CStop();
}
bit I2CClock() //return SDA while SCL is HIGH
{
bit sample;
SCL=HIGH;
I2CDelay();
sample=SDA;
SCL=LOW;
I2CDelay();
return sample;
}
bit I2CSend(BYTE I2CData)
{
BYTE i;
for(i=0;i<8;i++)
{
SDA=(bit)(((I2CData) & 0x80) / 0x80) ;
I2CData=I2CData << 1;
I2CClock();
}
SDA=HIGH;
return (~I2CClock());
}
void I2CAck()
{
SDA=LOW;
I2CClock();
SDA=HIGH;
}
void I2CDelay()
{
BYTE ll;
for(ll=0;ll<100;ll++)
{
;
}
}
BYTE I2CReceive()
{
BYTE I2CData=0;
BYTE kk;
for(kk=0;kk<8;kk++)
{
I2CData*=2;
if(I2CClock())
{
I2CData++;
}
}
return I2CData;
}
單片機(jī)模擬I2C總線及24C02(I2C EEPROM)讀寫實(shí)例(源代碼)
[ 作者:StephenZhu 轉(zhuǎn)貼自:xnovo 點(diǎn)擊數(shù):393 更新時(shí)間:2005-6-19 文章錄入:白樺 ]
減小字體 增大字體
/* 51系列單片機(jī)在使用時(shí),有時(shí)需要模擬I2C總線, */
/* 這里舉出一個(gè)實(shí)例(讀寫串行EEPROM芯片at2402) */
/************************************************************************/
/* Name:AT24C02存儲(chǔ)器的讀寫程序,用到I2C總線,含相對(duì)獨(dú)立的I2C總線讀寫函數(shù) */
/* Language: C51單片機(jī)編程語(yǔ)言 */
/* Platform: Win98,Intel Celeron 433 Processor,偉福仿真器,仿真8751 */
/* Author: StephenZhu javasdk@163.com */
/* Date: 2003年5月21日,5月22日,5月29日 */
/* Version: 1.1.1 */
/* Others: None */
/************************************************************************/
#include<string.h>
#include<reg52.h>
#include<intrins.h>
#define DELAY_TIME 60 /*經(jīng)實(shí)驗(yàn),不要小于50!否則可能造成時(shí)序混亂*/
#define TRUE 1
#define FALSE 0
sbit SCL=P1^7;/*假設(shè)由P1.7和P1.6控制*/
sbit SDA=P1^6;
/********** Function Definition 函數(shù)定義 ************/
void DELAY(unsigned int t) /*延時(shí)函數(shù)*/
{
while(t!=0)
t--;
}
void I2C_Start(void)
{
/*啟動(dòng)I2C總線的函數(shù),當(dāng)SCL為高電平時(shí)使SDA產(chǎn)生一個(gè)負(fù)跳變*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SDA=0;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void I2C_Stop(void)
{
/*終止I2C總線,當(dāng)SCL為高電平時(shí)使SDA產(chǎn)生一個(gè)正跳變*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SDA=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_0(void) /* SEND ACK */
{
/*發(fā)送0,在SCL為高電平時(shí)使SDA信號(hào)為低*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_1(void)
{
/*發(fā)送1,在SCL為高電平時(shí)使SDA信號(hào)為高*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
bit Check_Acknowledge(void)
{
/*發(fā)送完一個(gè)字節(jié)后檢驗(yàn)設(shè)備的應(yīng)答信號(hào)*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME/2);
F0=SDA;
DELAY(DELAY_TIME/2);
SCL=0;
DELAY(DELAY_TIME);
if(F0==1)
return FALSE;
return TRUE;
}
void WriteI2CByte(char b)reentrant
{
/*向I2C總線寫一個(gè)字節(jié)*/
char i;
for(i=0;i<8;i++)
if((b<<i)&0x80)
SEND_1();
else
SEND_0();
}
char ReadI2CByte(void)reentrant
{
/*從I2C總線讀一個(gè)字節(jié)*/
char b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*釋放總線*/
SCL=1; /*接受數(shù)據(jù)*/
DELAY(10);
F0=SDA;
DELAY(10);
SCL=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
/**********以下為讀寫24c02的函數(shù)**********/
void Write_One_Byte(char addr,char thedata)
{
bit acktemp=1;
/*write a byte to mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
WriteI2CByte(thedata);/*thedata*/
acktemp=Check_Acknowledge();
I2C_Stop();
}
void Write_A_Page(char *buffer,char addr)
{
bit acktemp=1;
bit wrtmp;
int i;
/*write a page to at24c02*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
for(i=0;i<7;i++)
{
WriteI2CByte(buffer[i]);
if(!Check_Acknowledge())
{
I2C_Stop();
}
}
I2C_Stop();
}
char Read_One_Byte(char addr)
{ bit acktemp=1;
char mydata;
/*read a byte from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
mydata=ReadI2CByte();
acktemp=Check_Acknowledge();
return mydata;
I2C_Stop();
}
void Read_N_Bytes(char *buffer,char n,char addr)
{
bit acktemp=1;
int i=0;
/*read 8 bytes from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
for(i=0;i<n;i++)
{
buffer[i]=ReadI2CByte();
if(i!=n-1)
SEND_0(); /*發(fā)送應(yīng)答*/
else
SEND_1(); /*發(fā)送非應(yīng)答*/
}
I2C_Stop();
}
void main()
{
int i;
char mybyte;
char myarray[8];
char myarray2[8];
char rdarray[16];
for(i=0;i<8;i++)
{
myarray[i]=i;
myarray2[i]=i+0x08;
}
Write_One_Byte(0x20,0x28);
Write_A_Page(myarray,0x10);
Write_A_Page(myarray2,0x18);
mybyte=Read_One_Byte(0x20);
Read_N_Bytes(rdarray,16,0x10);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -