新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > I2c程序 51系列及 AVR系列

I2c程序 51系列及 AVR系列

作者: 時間:2016-11-11 來源:網絡 收藏
keil c編譯 51

#define uchar unsigned char
#define uint unsigned int
#include "reg51.h"
#include "intrins.h"

本文引用地址:http://m.butianyuan.cn/article/201611/316772.htm

sbit Scl=P3^3; //串行時鐘
sbit Sda=P3^4; //串行數據

/*發(fā)送起始條件*/
void Start(void) /*起始條件*/
{
Sda=1;
Scl=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Sda=0;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
}
void Stop(void) /*停止條件*/
{
Sda=0;
Scl=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Sda=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
}
void Ack(void) /*應答位*/
{
Sda=0;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Scl=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Scl=0;
}
void NoAck(void) /*反向應答位*/
{
Sda=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Scl=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Scl=0;
}
void Send(uchar Data) /*發(fā)送數據子程序,Data為要求發(fā)送的數據*/
{
uchar BitCounter=8; /*位數控制*/
uchar temp; /*中間變量控制*/
do
{
temp=Data;
Scl=0;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
if((temp&0x80)==0x80)/* 如果最高位是1*/
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1; /*RLC*/
Data=temp;
BitCounter--;
}while(BitCounter);
Scl=0;
}
uchar Read(void) /*讀一個字節(jié)的數據,并返回該字節(jié)值*/
{
uchar temp=0;
uchar temp1=0;
uchar BitCounter=8;
Sda=1;
do{
Scl=0;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
Scl=1;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
if(Sda) /*如果Sda=1;*/
temp=temp|0x01; /*temp的最低位置1*/
else
temp=temp&0xfe; /*否則temp的最低位清0*/
if(BitCounter-1)
{ temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}while(BitCounter);
return(temp);
}
////////////////////////////////////////////////
void WrToROM(uchar Data[],uchar Address,uchar Num)
{
uchar i=0;
uchar *PData;
PData=Data;
Start();
Send(0xa0);
Ack();
Send(Address);
Ack();
for(i=0;i {
Send(*(PData+i));
Ack();
}
Stop();
}
void RdFromROM(uchar Data[],uchar Address,uchar Num)
{
uchar i=0;
uchar *PData;
PData=Data;
for(i=0;i {
Start();
Send(0xa0);
Ack();
Send(Address+i);
Ack();
Start();
Send(0xa1);
Ack();
*(PData+i)=Read();
Scl=0;
NoAck();
Stop();
}
}

/////////////////////////////////END of IIC/////////////////////////////////
////////////////////start of DS1621/////////////////////////////////
void delay_ms(unsigned char temp)
{
while(temp--);
}
void temp_config(unsigned char temp)
{

Start();
Send(0x90);
Ack();
Send(0xac);
Ack();
Send(temp);
Ack();
Stop();
delay_ms(110);
}


void init_temp()
{
Scl=1; //串行時鐘
Sda=1;
Start();
Send(0x90);
Ack();
Send(0xee);
Ack();
Stop();
temp_config(8);
}


void read_temp() ////// Returns degrees F (0-255)
{
unsigned char datah,datal;

////溫度數據讀入開始
Start(); //
Send(0x90);
Ack();
Send(0xaa);
Ack();
Start();
Send(0x91);
Ack();
datah=Read();
Ack();
datal=Read();
Stop();
///溫度數據讀入結束
if((datah&0x80)!=0)
{
word1[3]=-;
datah=datah-1;
datah=~datah;
word1[4]=datah/100+48;
word1[5]=((datah/10)%10)+48;
word1[6]=datah%10+48;
word1[7]=C;

}
else
{
word1[3]=+;
word1[4]=datah/100+48;
word1[5]=((datah/10)%10)+48;
word1[6]=datah%10+48;
word1[7]=C;

}

}


AVR

void Start() //I2C總線的開始條件
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100); //等待時鐘信號變高
Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(0); // SCL=0;
}

void Stop() //I2C總線結束條件
{Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(1); //SCL=1;
delay(100); //等待時鐘信號變低
Set_SDA(1); //SDA=1;
delay(100);
Set_SCL(0); //SCL=0;
}

void Ack() //I2C總線應答
{Set_SDA(0); //SDA=0;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(1); //SDA=1;
}

void Nack() //I2C總線應答非
{Set_SDA(1); //SDA=1;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(0); //SDA=0;
}

void Check_Ack() //I2C總線應答檢查
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
Ack_Flag=0; //清除應答標志;
DDRA&=0xbf; //設置SDA為輸入
if(!((PINA & 0x40)>>6))
{delay(50);
Set_SCL(0); //SCL=0;
delay(100);}
else
{Ack_Flag=1; //收到應答;
delay(50);
Set_SCL(0); //SCL=0;
delay(100);}
DDRA |=0xff; //重新設置SDA為輸出
}

void Write_Bit0() //寫1bit數據:0
{Set_SDA(0); //SDA=0;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
}

void Write_Bit1() //寫1bit數據:1
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
Set_SDA(0); //SDA=0;
}

void Write_Byte(uchar Data) //寫一字節(jié)數據Data
{uchar i;
for(i=0;i<8;i++)
{if(Data & 0x80) Write_Bit1(); //傳輸位從高位到低位,先傳最高位
else Write_Bit0();
Data <<=1;} //數據左移
}

uchar Read_Byte() //讀一字節(jié)數據:返回值即讀的數據
{uchar Read_Data=0xff; // Read_Data為讀入的數據,初始值為0xff
uchar j;
for (j=0;j<8;j++)
{Set_SDA(1);
Set_SCL(1);
DDRA &=0xbf;
if((PINA & 0x40)==0)
{Read_Data <<=1;
Read_Data=(Read_Data & 0xfe);
Set_SCL(0);}
else
{Read_Data <<=1;
Read_Data =( Read_Data | 0x01);
Set_SCL(0);}}
DDRA |=0x40;
return(Read_Data);
}

//***************************寫一字節(jié)數據****************************//
//向從地址為Slave的IIC器件的Address地址寫一字節(jié)數據Data
void Write_1byte(uchar Slave,uchar Address,uchar Data)
{Start(); //開始
Write_Byte(Slave); //寫I2C器件地址
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Write_Byte(Address); //送寄存器地址
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Write_Byte(Data); //寫入一字節(jié)數據
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Stop(); //停止
}

//***************************寫兩字節(jié)數據****************************//
//向從地址為Slave的IIC器件的Address地址開始寫兩字節(jié)數據Data0,Data1
void Write_2byte(uchar Slave,uchar Address,uchar Data0,uchar Data1)
{Start(); //開始
Write_Byte(Slave); //寫I2C器件地址
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Write_Byte(Address); //送寄存器地址
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Write_Byte(Data0);
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Write_Byte(Data1);
do Check_Ack(); //檢查應答位
while(Ack_Flag==1);
Stop(); //停止信號
}

//***************************讀一字節(jié)數據****************************//
//從從地址為Slave的IIC器件的Address地址處讀一字節(jié)數據
uchar Read_1byte(uchar Slave,uchar Address)
{uchar data0,x;
do{
Start(); //開始信號
Write_Byte(Slave); //寫I2C器件地址
Check_Ack(); //檢查應答位
}while(Ack_Flag);
do{
Write_Byte(Address); //寫寄存器地址
Check_Ack(); //檢查應答位
}while(Ack_Flag);
do{
Start(); //開始
Write_Byte(Slave+1); //寫I2C器件地址(+1表示為讀操作)
Check_Ack(); //檢查應答位
}while(Ack_Flag);
data0=Read_Byte(); //讀1字節(jié)
Nack(); //讀完發(fā)送一個Not Ack應答
Stop(); //停止
return data0; //返回讀取數據
}



評論


技術專區(qū)

關閉