導航:首頁 > 操作系統 > i2c匯流排單片機程序

i2c匯流排單片機程序

發布時間:2023-02-05 22:28:43

Ⅰ 這是一個單片機I2C的程序,麻煩高手幫忙指點下;為什麼有時顯示不行呢,雖然概率很低,要隔很長

1、可能延時時間不夠,器件讀寫速度慢,跟不上。

void delay()
{ ;; } //延遲5毫秒左右;

你用多少的晶振?12M的晶振標准51核,只能延時2個微秒。

2、write_byte(0xaa);
respons();
像這種寫入數據的操作需要時間比較長,你的等待時間可能不夠。查看你器件的datasheet,看它的寫入時間需要多久。

3、拿示波器看一下你IIC匯流排的波形的上升時間和下降時間能不能滿足IIC規范的要求。

4、嵌入式系統從穩定性考慮,最好對每個函數的操作成功與否進行判斷,系統要對錯誤的情況進行處理。比如樓主的respons();函數,比較好的一種處理方式是:如果等待超時,那麼返回錯誤碼,由上層函數決定如何處理錯誤。重發or放棄,等等。 樓主剛剛開始學習不必要深究,可以思考下這方面的問題。

Ⅱ 求:51單片機模擬i2c匯流排程序

//給你一個簡單的可斷電保存的計時程序,用的是24C08
#include <reg52.h> // 包含51單片機寄存器定義的頭文件
#include <intrins.h> //包含_nop_()函數定義的頭文件
#define OP_READ 0xa1 // 器件地址以及讀取操作,0xa1即為1010 0001B
#define OP_WRITE 0xa0 // 器件地址以及寫入操作,0xa1即為1010 0000B
sbit SCL=P3^4; //將串列時鍾匯流排SCL位定義在為P3.4引腳
sbit SDA=P3^5; //將串列數據匯流排SDA位定義在為P3.5引腳
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//定義共陽數碼管顯示字型碼
unsigned char sec=0; //定義計數值,每過1秒,sec加1
unsigned int count; //定時中斷次數
bit write=0; //寫24C08的標志;
sbit shiwei=P2^6; //十位選通定義
sbit gewei=P2^7; //個位選通定義
sbit K5=P3^2; //清0按鍵
/*****************************************************
函數功能:延時1ms
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}

/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函數功能:開始數據傳送
***************************************************/
void start()
// 開始位
{
SDA = 1; //SDA初始化為高電平「1」
SCL = 1; //開始數據傳送時,要求SCL為高電平「1」
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
SDA = 0; //SDA的下降沿被認為是開始信號
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
SCL = 0; //SCL為低電平時,SDA上數據才允許變化(即允許以後的數據傳遞)
}
/***************************************************
函數功能:結束數據傳送
***************************************************/
void stop()// 停止位
{
SDA = 0; //SDA初始化為低電平「0」 _n
SCL = 1; //結束數據傳送時,要求SCL為高電平「1」
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
SDA = 1; //SDA的上升沿被認為是結束信號
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
SDA=0;
SCL=0;
}
/***************************************************
函數功能:檢測應答位
***************************************************/

bit Ask() //檢測應答
{
bit ack_bit; //儲存應答位
SDA = 1; // 發送設備(主機)應在時鍾脈沖的高電平期間(SCL=1)釋放SDA線,
//以讓SDA線轉由接收設備(AT24Cxx)控制
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
SCL = 1; //根據上述規定,SCL應為高電平
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期
ack_bit = SDA; //接受設備(AT24Cxx)向SDA送低電平,表示已經接收到一個位元組
//若送高電平,表示沒有接收到,傳送異常 結束發送
SCL = 0; //SCL為低電平時,SDA上數據才允許變化(即允許以後的數據傳遞)
return ack_bit; // 返回AT24Cxx應答位

}

/***************************************************
函數功能:從AT24Cxx讀取數據
出口參數:x
***************************************************/
unsigned char ReadData()
// 從AT24Cxx移入數據到MCU
{
unsigned char i;
unsigned char x; //儲存從AT24Cxx中讀出的數據
for(i = 0; i < 8; i++)
{
SCL = 1; //SCL置為高電平
x<<=1; //將x中的各二進位向左移一位
x|=(unsigned char)SDA; //將SDA上的數據通過按位「或「運算存入x中
SCL = 0; //在SCL的下降沿讀出數據
}
return(x); //將讀取的數據返回
}
/***************************************************
函數功能:向AT24Cxx的當前地址寫入數據
入口參數:y (儲存待寫入的數據)
***************************************************/
//在調用此數據寫入函數前需首先調用開始函數start(),所以SCL=0
void WriteCurrent(unsigned char y)
{
unsigned char i;
for(i = 0; i < 8; i++) // 循環移入8個位
{
SDA = (bit)(y&0x80); //通過按位「與」運算將最高位數據送到S
//因為傳送時高位在前,低位在後
_nop_(); //等待一個機器周期
SCL = 1; //在SCL的上升沿將數據寫入AT24Cxx
_nop_(); //等待一個機器周期
_nop_(); //等待一個機器周期

SCL = 0; //將SCL重新置為低電平,以在SCL線形成傳送數據所需的8個脈沖
y <<= 1; //將y中的各二進位向左移一位

}
}
/***************************************************
函數功能:向AT24Cxx中的指定地址寫入數據
入口參數:add (儲存指定的地址);dat(儲存待寫入的數據)
***************************************************/
void WriteSet(unsigned char add, unsigned char dat)
// 在指定地址addr處寫入數據WriteCurrent
{
start(); //開始數據傳遞
WriteCurrent(OP_WRITE); //選擇要操作的AT24Cxx晶元,並告知要對其寫入數據
Ask();
WriteCurrent(add); //寫入指定地址
Ask();
WriteCurrent(dat); //向當前地址(上面指定的地址)寫入數據
Ask();
stop(); //停止數據傳遞
delaynms(4); //1個位元組的寫入周期為1ms, 最好延時1ms以上
}
/***************************************************
函數功能:從AT24Cxx中的當前地址讀取數據
出口參數:x (儲存讀出的數據)
***************************************************/
unsigned char ReadCurrent()
{
unsigned char x;
start(); //開始數據傳遞
WriteCurrent(OP_READ); //選擇要操作的AT24Cxx晶元,並告知要讀其數據
Ask();
x=ReadData(); //將讀取的數據存入x
stop(); //停止數據傳遞
return x; //返回讀取的數據
}
/***************************************************
函數功能:從AT24Cxx中的指定地址讀取數據
入口參數:set_addr
出口參數:x
***************************************************/
unsigned char ReadSet(unsigned char set_addr)
// 在指定地址讀取
{
start(); //開始數據傳遞
WriteCurrent(OP_WRITE); //選擇要操作的AT24Cxx晶元,並告知要對其寫入數據
Ask();
WriteCurrent(set_addr); //寫入指定地址
Ask();
return(ReadCurrent()); //從指定地址讀出數據並返回
}
/***********************************************************/
void LEDshow() //LED顯示函數
{

P0=table[sec/10];
shiwei=0;
delaynms(2);
shiwei=1;

P0=table[sec%10];
gewei=0;
delaynms(2);
gewei=1;
}

/***********************************************************/
/***************************************************
函數功能:主函數
***************************************************/

void main(void)
{

TMOD=0x01; //定時器0工作在方式1
ET0=1;
EA=1;
TH0=(65536-50000)/256; //對TH0 TL0賦值
TL0=(65536-50000)%256; //使定時器0.05秒中斷一次
SDA = 1; // SDA=1,SCL=1,使主從設備處於空閑狀態
SCL = 1;
sec=ReadSet(2);//讀出保存的數據賦於sec
TR0=1; //開始計時
while(1)
{
LEDshow();
if(write==1) //判斷計時器是否計時一秒
{
write=0; //清零
WriteSet(2,sec); //在24c08的地址2中寫入數據sec
}

if(K5==0){
delaynms(10);
if(K5==0){
sec=0;
}
}
}
}

/**************************************************************/

void t0(void) interrupt 1 using 0 //定時中斷服務函數
{
TH0=(65536-50000)/256; //對TH0 TL0賦值
TL0=(65536-50000)%256; //重裝計數初值
count++; //每過50ms tcnt加一
if(count==20) //計滿20次(1秒)時
{
count=0; //重新再計
sec++;
write=1; //1秒寫一次24C08
if(sec==100) //定時100秒,在從零開始計時
{sec=0;}
}
}

Ⅲ 用I2C實現兩單片機聯機,接收程序怎麼寫

發送和接收差不多,

這里是個例子,有問題歡迎一起討論
/*****************************************************
/* 文件名 : I2C.h
/* 描述 : I2C.c的頭文件
/* 編寫環境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 學校 : 廣東XX大學
/* Email : [email protected]
/* 版本 : V1.0
/* 編寫日期 : 2008-3-30
/* 僅供學習參考
/* 晶元 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模擬I2C匯流排的介面程序庫,主機的程序
/* 應用 : 發送n個位元組: 起始位->發送控制位元組(類型標識符4位->
片選3位->讀寫位最後1位)->應答位->數據->應答...........應答->終止位
高位先到達,低位後到達
/****************************************************/
#include "reg51.h" /*根據不同主控晶元型號改寫該套入*/
#include "intrins.h"
sbit SCL = P1^6; /*定義SCL線所在口,根據實踐需要改寫該定義*/
sbit SDA = P1^7; /*定義SDA線所在口,根據實踐需要改寫該定義*/
unsigned char idata error; /*錯誤提示,全局變數*/

extern void Start_I2C(void);
extern void Stop_I2C(void);
extern void Ack_I2C(void);
extern void Send_Ack(void);
extern void Send_Not_Ack(void);
extern void Send_I2C(unsigned char send_byte);
extern unsigned char Receive_I2C(void);

/*****************************************************/
/* 文件名 : I2C.c
/* 描述 : I2C通信程序
/* 編寫環境 : Keil uVision 3 V3.51
/* 作者 : XX
/* 學校 : 廣東XX大學
/* Email : [email protected]
/* 版本 : V1.0
/* 編寫日期 : 2008-3-30
/* 僅供學習參考
/* 晶元 : MCS-51 AT89S52
/* 晶振 : 11.0592MHz
/* 功能描述 : 模擬I2C匯流排的介面程序庫,為主機的程序
/*****************************************************/
#include "I2C.h"

/**************************************************
調用方式 : void Start_I2C(void)
函數說明: 啟動I2C匯流排
**************************************************/
void Start_I2C(void)
{
EA = 0; /*關總中斷*/
SDA = 1; /*發送啟動匯流排的數據信號*/
SCL = 1; /*發送啟動匯流排的時鍾信號*/
_nop_(); /*保持數據線高,延時*/
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; /*發送起始信號*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0; /*時鍾線高低跳變一次,I2C通信開始*/
}

/**************************************************
調用方式 : void Stop_I2C(void)
函數說明: 關閉I2C匯流排
**************************************************/

void Stop_I2C(void)
{
SCL = 0; /*發送關閉匯流排的時鍾信號*/
SDA = 0; /*發送關閉匯流排的數據信號*/
_nop_();
_nop_();
_nop_(); /*保持數據線低,延時*/
_nop_();
_nop_();
SCL = 1; /*時鍾線一次低高跳變,I2C通信停止*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; /*發送I2C匯流排停止數據信號*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
EA = 1; /*開總中斷*/
}

/**************************************************
調用方式 : void Ask_I2C(void)
函數說明: 主控程序等待從器件接收方式應答
**************************************************/

void Ack_I2C(void)
{
unsigned char errtimes = 0xFF;
SDA = 1;
SCL = 1;
error = 0x10;
while(SDA)
{
errtimes--;
if(!errtimes)
{
Stop_I2C();
error = 0x11;
return;
}
}
SCL = 0;
}

/**************************************************
調用方式 : void Send_Ask(void)
函數說明: 主控程序為接收方,從器件為發送方時,從
器件等待主器件應答
**************************************************/
void Send_Ack(void)
{
SDA = 0; /*保持數據線低,時鍾線發生一次高低跳變 發送一個應答信號*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*時鍾線保持低電平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}

/**************************************************
調用方式 : void Send_Not_Ask(void)
函數說明: 主控程序為接收方,從器件為發送方時,非應答信號
**************************************************/

void Send_Not_Ack(void)
{
SDA = 1; /*保持數據線高,時鍾線發生一次高低跳變 沒有應答*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1; /*時鍾線保持高電平*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}

/**************************************************
調用方式 : void Send_I2C(unsigned char send_byte)
函數說明: 匯流排發送一個位元組
**************************************************/

void Send_I2C(unsigned char send_byte)
{
unsigned char send_bit;
for(send_bit = 8;send_bit <= 0;send_bit--)
{
SCL = 0;
_nop_();
SDA = (send_byte & 0x80);
send_byte<<=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
SCL = 0;
}

/**************************************************
調用方式 : unsigned char Receive_I2C(void)
函數說明: 從I2C匯流排上接收一個位元組
**************************************************/
unsigned char Receive_I2C(void)
{
unsigned char receive_bit , receive_byte = 0;
for(receive_bit = 8;receive_bit <= 0;receive_bit--)
{
SCL = 0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
receive_byte <<=1;
receive_byte |= SDA;
}
SCL = 0;
return receive_byte;
}

Ⅳ 高分跪求PIC 單片機I2C匯流排的常式

這是pic16f873單片機的i2c匯流排的例子,先把數據寫到at24c02上,然後再讀回來,給數碼管顯示

#include<pic.h>
#define uchar unsigned char
#define uint unsigned int
#define add 0xaa
__CONFIG(0x3B31);
const uchar ee_data[]={1,2,3,4,5,6};
uchar read_data[6];
const uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay(uint x);
void init();
void didi(uchar num);
void disp(uchar num1,uchar num2,uchar num3,uchar num4,uchar num5,uchar num6);
void write();
void read();
void main()
{
init();
write();
delay(100);
read();
while(1)
{
disp(read_data[0],read_data[1],read_data[2],read_data[3],read_data[4],read_data[5]);
}
}
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=110;b>0;b--);
}
void init()
{
TRISD=0;
TRISA=0;
TRISE0=0;
// ADCON1=0x07;
RE0=0;
PORTD=0;
PORTA=0;
TRISC=0xff;
SSPSTAT=0x80;
SSPCON=0x38;
SSPCON2=0;
SSPADD=0x09;
}
void write()
{
uchar i;
SSPIF=0;
SEN=1;
while(!SSPIF);
SSPIF=0;
SSPBUF=0xA0;
while(!SSPIF);
SSPIF=0;
SSPBUF=add;
while(!SSPIF);
SSPIF=0;
for(i=0;i<6;i++)
{
SSPBUF=ee_data[i];
while(!SSPIF);
SSPIF=0;
}
PEN=1;
while(!SSPIF);
SSPIF=0;
}
void read()
{
uchar i;
SSPIF=0;
SEN=1;
while(!SSPIF);
SSPIF=0;
SSPBUF=0xA0;
while(!SSPIF);
SSPIF=0;
SSPBUF=add;
while(!SSPIF);
SSPIF=0;
SSPIF=0;
RSEN=1;
while(!SSPIF);
SSPIF=0;
SSPBUF=0xA1;
while(!SSPIF);
SSPIF=0;
for(i=0;i<6;i++)
{
RCEN=1;
while(!SSPIF);
read_data[i]=SSPBUF;
while(!SSPIF);
SSPIF=0;
if(i>=5)
{
ACKDT=1;
}
else
{
ACKDT=0;
}
ACKEN=1;
while(!SSPIF);
SSPIF=0;
}
PEN=1;
while(!SSPIF);
SSPIF=0;
}
void didi(uchar num)
{
uchar di_num;
for(di_num=num;di_num>0;di_num--)
{
RE0=1;
delay(50);
RE0=0;
delay(20);
}
}

void disp(uchar num1,uchar num2,uchar num3,uchar num4,uchar num5,uchar num6)
{
PORTD=table[num1];//顯示第一個數碼管
PORTA=0x20;//0010 0000
delay(2);
PORTD=table[num2];//顯示第二個數碼管
PORTA=0x10;//0001 0000
delay(2);
PORTD=table[num3];//顯示第三個數碼管
PORTA=0x08;//0000 1000
delay(2);
PORTD=table[num4];//顯示第四個數碼管
PORTA=0x04;//0000 0100
delay(2);
PORTD=table[num5];//顯示第五個數碼管
PORTA=0x02;//0000 0010
delay(2);
PORTD=table[num6];//顯示第六個數碼管
PORTA=0x01;//0000 0001
delay(2);
}

Ⅳ 51單片機如何模擬I2C匯流排中從機接收ID,發送數據的程序

希望能給你解答:
1、時鍾信號都是主機產生的,從機只有一種情況下才能控制時鍾線,即在忙的時候,主機還在發送數據,從機會主動把時鍾拉低,表示我正在忙,不能收數據。
2、兩個主機的話,在發送的時候一定會有一個從屬關系,這個需要自己設置。
3、響應:i2c上每傳輸一個位元組,都必須要有響應,方向是從機到主機。

Ⅵ 一個關於I2C匯流排傳輸的單片機程序

沒有KEIL51的安裝 運行不了 粗略看了一下 發現 你的你的中斷寄存器IE -》ET 沒有設置 你把他設置一下在看看 要是不行下午在問吧 吃飯了

Ⅶ 單片機中I2C匯流排程序中的return(1)在該程序中怎麼運行的

如果通信正常 前面2個if(ack==0),就不會執行,直到運行retrun(1); 返回1,告訴調用程序,通信成功了;若返回0,表示通信錯誤;

Ⅷ 單片機iic程序不懂給分析下啊

貼個程序給你看看,,,單片機沒有I2C匯流排介面,只能靠軟體模擬
/*程序的I2C從器件地址為1010,片選地址為000*/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SDA=P1^7;
sbit SCL=P1^6;

void Delay(uint us)
{
for(us;us>0;us--);
}

void start_iic() // 啟動I2C匯流排
{
SDA=1; // 發送起始條件數據信號,啟動時,
SCL=1; // 必需使數據線、時鍾信號線處於高電平(空閑態)
Delay(10); // 使用I2C匯流排必需考慮保持時間和建立時間,故延時
SDA=0; //產生下降沿,發送起始信號
Delay(10);
SCL=0;
}

void stop_iic()
{
SDA=0; //為產生上跳沿做准備
SCL=1; //打開時鍾線
Delay(10);
SDA=1; //產生停止信號(上跳沿有效)
Delay(10);
SCL=0; //時鍾線恢復無效態//
}

void ack_iic()
{
SDA=0; // 接受器件發送應答信號
SCL=1;
Delay(10);
SCL=0;
SDA=1; //應答信號低電平有效,故需將其重新置高電平
}

void nack_iic()
{
SDA=1; //主器件發非應答信號,通知AT24C08不再發送數據
SCL=1;
Delay(10);
SCL=0;
SDA=0; //非應答信號高電平有效,故需將其重新置低電平
}

Write_byte(uchar c)
{
uchar i;
for(i=0;i<8;i++)
{
if(c&0x80)SDA=1;
else SDA=0;
SCL=1;
Delay(10);
SCL=0; //因為當時鍾線有效是,數據線必須保持穩定的電平,
c=c<<1; //要改變SDA電平,應先將SCL拉低
}
SDA=1; //釋放I2C匯流排,准備接受應答信號
SCL=1;
Delay(10);
if(SDA==1)F0=0; //沒有接到應答位
else F0=1;
SCL=0;
}

uchar Read_byte()
{
uchar i;
uchar r=0;
SDA=1; //置數據線為輸入方式
for(i=0;i<8;i++)
{
r=r<<1;
SCL=1;
Delay(10); //保證一定的電平保持時間
if(SDA==1)r++; //從高位開始,一位一位的讀
SCL=0;
}
return r;
}

main()
{
uchar slave=0xa0; //I2C匯流排從器件地址(注意:硬體電路的接法要是片選地址為0,否則不能工作)
uchar Rslave=slave+1; //主器件發送讀控制字位元組
uchar addre=0x20; // 指定的寫數據地址
uchar wbuf=0x23; //將要寫進addre的數據
uchar rbuf; //存放讀出的數據的臨時變數
start_iic(); //產生起始信號
Write_byte(slave); //發送從器件地址
if(F0==0)return 0; //檢查應答位
Write_byte(addre); //發送目的地址
if(F0==0)return 0;
Write_byte(wbuf); //發送8為數據
if(F0==0)return 0;
stop_iic(); //停止信號

/*8位的數據發送完畢*/

Delay(1000);
start_iic();
Write_byte(slave);
if(F0==0)return 0;
Write_byte(addre);
if(F0==0)return 0;

start_iic(); //再次產生起始信號,不能少
Write_byte(Rslave); //送讀控制字
if(F0==0)return 0;
rbuf=Read_byte(); //讀出指定單元的內容
nack_iic(); //非應答信號
stop_iic();

/*8位的數據讀取完畢*/

TMOD=0x20; //串口調試
TL1=0xfd;
TH1=0xfd;
SCON=0x40;
PCON=0x00;
TR1=1;
while(1)
{
SBUF=rbuf; //放入緩沖
while(TI==0);
TI=0;
Delay(10000);
}

}

Ⅸ 單片機模擬i2c匯流排通信

#ifndef _iic_h_
#define _iic_h_
#define uchar unsigned char
#define uint unsigned int
#define Byte unsigned char
#define Word unsigned int
#define bool bit
#define true 1
#define false 0
extern void I2CStart(void);
extern void I2CStop(void);
extern bool WaitAck(void);
extern void SendAck(void);
extern void I2CSendByte(Byte ch);
extern Byte I2CReceiveByte(void);
extern void SomeNOP(void);
sbit SDA=P0^0;
sbit SCL=P0^1;
void SomeNOP(void)
{ _nop_();_nop_();_nop_();_nop_();
}
/**------------------------------------------------------------------------------
調用方式:void I2CStart(void) ﹫2001/07/04 函數說明:私有函數,I2C專用
---------------------------------------------------------------------------------*/
void I2CStart(void)
{
EA=0;

SDA=1; SCL=1; SomeNOP();//INI
SDA=0; SomeNOP(); //START
SCL=0;
}

/**-------------------------------------------------------------------------------
調用方式:void I2CStop(void) ﹫2001/07/04
函數說明:私有函數,I2C專用
---------------------------------------------------------------------------------*/
void I2CStop(void)
{
SCL=0; SDA=0; SomeNOP(); //INI
SCL=1; SomeNOP(); SDA=1; //STOP
EA=1;
} /**-------------------------------------------------------------------------------
調用方式:bit I2CAck(void) ﹫2001/07/04
函數說明:私有函數,I2C專用,等待從器件接收方的應答
---------------------------------------------------------------------------------*/
bool WaitAck(void)
{
uchar errtime=255;//因故障接收方無ACK,超時值為255。
SDA=1;SomeNOP();
SCL=1;SomeNOP();

while(SDA) {errtime--; if (!errtime) {I2CStop();SystemError=0x11;return false;}}
SCL=0;
return true;
}
/*
調用方式:void SendAck(void) ﹫2001/07/04
函數說明:私有函數,I2C專用,主器件為接收方,從器件為發送方時,應答信號。
---------------------------------------------------------------------------------*/
void SendAck(void)

{
SDA=0; SomeNOP();
SCL=1; SomeNOP();
SCL=0;
}

/**-------------------------------------------------------------------------------
調用方式:void SendAck(void) ﹫2001/07/04
函數說明:私有函數,I2C專用,主器件為接收方,從器件為發送方時,非應答信號。
}**-------------------------------------------------------------------------------
void SendNotAck(void)
{
SDA=1; SomeNOP();
SCL=1; SomeNOP();
SCL=0;
} /**-------------------------------------------------------------------------------
調用方式:void I2CSend(uchar ch) ﹫2001/07/05
函數說明:私有函數,I2C專用

---------------------------------------------------------------------------------*/
void I2CSendByte(Byte ch)
{
uchar i=8;
while (i--)
{
SCL=0;_nop_();
SDA=(bit)(ch&0x80); ch<<=1; SomeNOP();
SCL=1; SomeNOP();
}
SCL=0;
} /**-------------------------------------------------------------------------------
調用方式:uchar I2CReceive(void) ﹫2001/07/05
函數說明:私有函數,I2C專用
---------------------------------------------------------------------------------*/
Byte I2CReceiveByte(void)
{
uchar i=8;
Byte ddata=0;
SDA=1;
while (i--)
{
ddata<<=1;
SCL=0;SomeNOP();
SCL=1;SomeNOP();
ddata|=SDA;
}
SCL=0;

return ddata;
}
#endif

Ⅹ 51單片機如何模擬I2C匯流排中從機接收ID,發送數據的程序

#include /*頭文件的包含*/
#include
#define uchar unsigned char /*宏定義*/
#define uint unsigned int

/*埠位定義*/
sbit BELL_OUT=P3^5;
sbit SCL="P1"^3;/*模擬I2C數據傳送位*/
sbit SDA="P1"^4;/*模擬I2C時鍾控制位*/

bit ack; /*應答標志位*/

/*********************************************************************
起動匯流排函數
函數原型: void Start_I2c();
功能:啟動I2C匯流排,即發送I2C起始條件
********************************************************************/
void Start_I2c()
{
SDA="1"; /*發送起始條件的數據信號*/
_nop_();
SCL="1"; /*起始條件建立時間大於4.7us,延時*/
_nop_();
SDA="0"; /*發送起始信號*/
_nop_(); /* 起始條件鎖定時間大於4μs*/
SCL="0"; /*鉗住I2C匯流排,准備發送或接收數據 */
_nop_();
}

/***********************************************
結束匯流排函數
函數原型: void Stop_I2c();
功能:結束I2C匯流排,即發送I2C結束條件
***********************************************/
void Stop_I2c()
{

SDA="0"; /*發送結束條件的數據信號*/
_nop_(); /*發送結束條件的時鍾信號*/
SCL="1"; /*結束條件建立時間大於4μs*/
_nop_();
SDA="1"; /*發送I2C匯流排結束信號*/
_nop_();
}

/*******************************************************************
位元組數據傳送函數
函數原型: void SendByte(uchar c);
功能:將數據c發送出去,可以是地址,也可以是數據,發完後等待應答,並對此狀
態位進行操作(不應答或非應答都使ack=0 假) 。發送數據正常,ack=1;
ack=0表示被控器無應答或損壞。
********************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++) /*要傳送的數據長度為8位*/
{
SCL="0";
if((c<
else SDA="0";
SCL="1"; /*置時鍾線為高,通知被控器開始接收數據位*/
_nop_(); /*保證時鍾高電平周期大於4μs*/
}

//從機應答,可以用應答和非應答信號代替
_nop_();
SCL="0";
_nop_();
SDA="1"; //
_nop_();
SCL="1";
_nop_();

if(SDA==1){ack=0;} /*判斷是否接收到應答信號*/
else ack="1";

SCL="0";
_nop_();

}

/*******************************************************************
位元組數據傳送函數
函數原型: uchar RcvByte();
功能:用來接收從器件傳來的數據,並判斷匯流排錯誤(不發應答信號),
發完後請用應答函數。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;

retc="0";

for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL="1"; /*置時鍾線為高使數據線上數據有效*/
_nop_();
retc="retc"<<1;
if(SDA==1) retc="retc"+1; /*讀數據位,接收的數據位放入retc中 */
SCL="0";
}
return(retc);
}

/********************************************************************
應答子函數
原型: void Ack_I2c();
功能:主控器進行應答信號
********************************************************************/
void Ack_I2c()
{
SDA="0"; /*在此發出應答信號 */
_nop_();
SCL="0";
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清時鍾線,鉗住I2C匯流排以便繼續接收*/
_nop_();
SDA="1";
_nop_();
}

/********************************************************************
非應答子函數
原型: void NoAck_I2c();
功能:主控器進行非應答信號
********************************************************************/
void NoAck_I2c()
{
SDA="1"; /*在此發出非應答信號 */
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清時鍾線,鉗住I2C匯流排以便繼續接收*/
}

/*******************************************************************
向無子地址器件發送位元組數據函數
函數原型: bit ISendByte(uchar sla,ucahr c);
功能:從啟動匯流排到發送地址,數據,結束匯流排的全過程,從器件地址sla。如果
返回1表示操作成功,否則操作有誤。
********************************************************************/
bit ISendByte(uchar sla,uchar c)
{
Start_I2c(); /*啟動匯流排*/
SendByte(sla); /*發送器件地址*/
if(ack==0)return(0);

SendByte(c); /*發送數據*/
if(ack==0)return(0);

Stop_I2c(); /*結束匯流排*/
return(1);
}

/*******************************************************************
向有子地址器件發送多位元組數據函數
函數原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:從啟動匯流排到發送地址,子地址,數據,結束匯流排的全過程,從器件地址sla,
子地址suba,發送內容是s指向的內容,發送no個位元組。如果返回1表示
操作成功,否則操作有誤。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;

Start_I2c(); /*啟動匯流排*/
SendByte(sla); /*發送器件地址*/
if(ack==0)return(0);

SendByte(suba); /*發送器件子地址*/
if(ack==0)return(0);

for(i=0;i
{
SendByte(*s); /*發送數據*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*結束匯流排*/
//delayMs(1); //
return(1);
}

/*******************************************************************
向無子地址器件讀位元組數據函數
函數原型: bit IRcvByte(uchar sla,ucahr *c);
功能:從啟動匯流排到發送地址,讀數據,結束匯流排的全過程,從器件地址sla,返
回值在c。如果返回1表示操作成功,否則操作有誤。
********************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{
Start_I2c(); /*啟動匯流排*/
SendByte(sla+1); /*發送器件地址*/
if(ack==0)return(0);

*c=RcvByte(); /*讀取數據*/
NoAck_I2c(); /*發送非就答位*/
Stop_I2c(); /*結束匯流排*/
return(1);
}

/**********************************************************************
向有子地址器件讀取多位元組數據函數
函數原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:從啟動匯流排到發送地址,子地址,讀數據,結束匯流排的全過程,從器件地址sla,
子地址suba,讀出的內容放入s指向的存儲區,讀no個位元組。如果返回1
表示操作成功,否則操作有誤。
**********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
Start_I2c(); /*啟動匯流排*/
SendByte(sla); /*發送器件地址*/
if(ack==0)return(0);

SendByte(suba); /*發送器件子地址*/
if(ack==0)return(0);

Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);

while(no!=1)
{
*s=RcvByte();/*發送數據*/
Ack_I2c(); /*發送就答位*/
s++;
no--;
}
*s=RcvByte();
NoAck_I2c(); /*發送非應位*/
Stop_I2c(); /*結束匯流排*/
return(1);
}

閱讀全文

與i2c匯流排單片機程序相關的資料

熱點內容
午夜電影在線觀看網頁 瀏覽:220
美國男同電影 瀏覽:558
主角穿越電影強化性能力 瀏覽:837
主角林楓穿越到異界 瀏覽:469
小說下載書包網txt在線下載 瀏覽:969
肉很多很欲的高質量現言 瀏覽:428
電影愛情來得不準時塞爾維亞 瀏覽:748
有關監獄的恐怖片 瀏覽:242
穿越僵屍世界收女系統 瀏覽:899
java關鍵字保留字 瀏覽:244
linux系統運維下載 瀏覽:48
同程的簡便演算法 瀏覽:649
linux命令行管理主機 瀏覽:300
騰訊雲20元的伺服器 瀏覽:215
plsql編程入門 瀏覽:12
《fog》txt下載 瀏覽:494
怎樣用氣泡紙解壓 瀏覽:120
香港李時珍的經典電影 瀏覽:319
母親和房子電影 瀏覽:141
收盡天下女明星的超級主播 瀏覽:469