基于I2C協(xié)議的單片機(jī)記錄單片機(jī)開機(jī)次數(shù)
在之前我講過(guò)I2C協(xié)議,也給出了簡(jiǎn)單例子,這次利用I2C協(xié)議,我們可以做一個(gè)小實(shí)驗(yàn),讓單片機(jī)記錄單片機(jī)開機(jī)次數(shù),也就是機(jī)器使用次數(shù)。
// 內(nèi)容:每次開機(jī)都將次數(shù)加1 并存儲(chǔ)到EEPROM。這樣就能直觀的看到機(jī)器的使用 //
// 次數(shù)用P1口LED做為顯示,次數(shù)大于256是將溢出,按復(fù)位模擬開機(jī) //
// 或者直接通過(guò)開關(guān)開機(jī) //
#include
#include
#define AddWr 0xae //寫數(shù)據(jù)地址,需要參考24c02芯片文檔
#define AddRd 0xaf //讀數(shù)據(jù)地址
sbit Sda=P1^2; //定義總線連接端口
sbit Scl=P1^1;
sbit WP=P1^0; //寫保護(hù),這里不使用
/*------------------------------------------------
延時(shí)程序
------------------------------------------------*/
void mDelay(unsigned char j)
{
unsigned int i;
for(;j>0;j--)
{
for(i=0;i<125;i++)
{;}
}
}
/*------------------------------------------------
啟動(dòng)IIC總線
------------------------------------------------*/
void Start(void)
{
Sda=1;
_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
Sda=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
Scl=0;
}
/*------------------------------------------------
停止IIC總線
------------------------------------------------*/
void Stop(void)
{
Sda=0;
_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
Sda=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
Scl=0;
}
/*------------------------------------------------
應(yīng)答IIC總線
------------------------------------------------*/
void Ack(void)
{
Sda=0;
_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
Scl=0;
_nop_();_nop_();
}
/*------------------------------------------------
非應(yīng)答IIC總線
------------------------------------------------*/
void NoAck(void)
{
Sda=1;
_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
Scl=0;
_nop_();_nop_();
}
/*------------------------------------------------
發(fā)送一個(gè)字節(jié)
------------------------------------------------*/
void Send(unsigned char Data)
{
unsigned char BitCounter=8;
unsigned char temp;
do
{
temp=Data;
Scl=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
if((temp&0x80)==0x80)
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1;
Data=temp;
BitCounter--;
}
while(BitCounter);
Scl=0;
}
/*------------------------------------------------
讀入一個(gè)字節(jié)并返回
------------------------------------------------*/
unsigned char Read(void)
{
unsigned char temp=0;
unsigned char temp1=0;
unsigned char BitCounter=8;
Sda=1;
do
{
Scl=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
if(Sda)
temp=temp|0x01;
else
temp=temp&0xfe;
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}
while(BitCounter);
return(temp);
}
/*------------------------------------------------
寫入數(shù)據(jù)
------------------------------------------------*/
void WrToROM(unsigned char Data[],unsigned char Address,unsigned char Num)
{
unsigned char i;
unsigned char *PData;
PData=Data;
for(i=0;i
{
Start();
Send(AddWr); //寫入芯片地址
Ack();
Send(Address+i);//寫入存儲(chǔ)地址
Ack();
Send(*(PData+i));//寫數(shù)據(jù)
Ack();
Stop();
mDelay(20);
}
}
/*------------------------------------------------
讀出數(shù)據(jù)
------------------------------------------------*/
void RdFromROM(unsigned char Data[],unsigned char Address,unsigned char Num)
{
unsigned char i;
unsigned char *PData;
PData=Data;
for(i=0;i
{
Start(); //寫入芯片地址
Send(AddWr);
Ack();
Send(Address+i);//寫入存儲(chǔ)地址
Ack();
Start();
Send(AddRd); //讀入地址
Ack();
*(PData+i)=Read();//讀數(shù)據(jù)
Scl=0;
NoAck();
Stop();
}
}
//以上程序是EEPROM24C02程序部分,IIC協(xié)議Scl=0;
/*------------------------------------------------
主程序
------------------------------------------------*/
//下載程序后,記錄下LED2~LED9的狀態(tài),然后按下復(fù)位鍵(相當(dāng)于開機(jī)),觀察LED2~LED9的狀態(tài)改變
void main()
{
unsigned char Number[1];
unsigned char i;
WP=0;//寫保護(hù)關(guān)掉
RdFromROM(Number,0,1);//調(diào)用存儲(chǔ)數(shù)據(jù) 從地址0開始寫一個(gè)數(shù)據(jù)
Number[0]++;
WrToROM(Number,0,1);//寫入24c02
P1 = ~ Number[0];//在P1口上顯示 反向顯示 LED亮代表1
while(1)
{
}
}
//用戶可以自己把程序移植到數(shù)碼管顯示或者液晶顯示 ,可以直觀的看到數(shù)字 ,也可以定義int類型 用于計(jì)數(shù)萬(wàn)次以上