欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
利用AT24C02來保存,精華都在程序中。。。。。
[打印本頁]
作者:
xiao_yp2014
時間:
2015-1-10 23:57
標題:
利用AT24C02來保存,精華都在程序中。。。。。
本帖最后由 xiao_yp2014 于 2016-1-21 14:33 編輯
功能需求:
開機后兩位數碼管顯示0到99之間的某一個數值,用一個按鍵可以不斷的遞增,用另外一個按鍵可以不斷的遞減。斷電后此數據可保存,下次通電 開機的時候還是從那個保存的數據開始顯示。
程序如下:
main.c
/*EEPROM篇--利用AT24C02存儲數據
功能需求:
開機后兩位數碼管顯示0到99之間的某一個數值,用一個按鍵可以不斷的遞增,
用另外一個按鍵可以不斷的遞減。斷電后此數據可保存,下次通電開機的時候
還是從那個保存的數據開始顯示。
*/
#include<reg52.h> //頭文件
#include"AT24C02.h" //IIC自定義頭文件
#include"Key_Scan.h" //按鍵自定義頭文件
#include"display.h" //數碼管顯示自定義頭文件
sbit beep_dr = P3^6; //蜂鳴器
unsigned int uiVoiceCnt = 0; //蜂鳴器時間變量
unsigned char ucSetNumber = 0; //設定值變量
void Init_All(); //初始化全部程序
void Timer_T0(); //TO定時器中斷
void main()
{
Init_All(); //初始化全部
while(1)
{
display(); //調用數碼管顯示函數
Key_Service(); //調用按鍵服務函數,放在主函數里
}
}
void Init_All()
{
TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f
TL0=0x2f;
EA = 1;
ET0 = 1;
TR0=1; //開中斷
ucSetNumber = read_eeprom(128); //上電開機讀取EEPROM數據,128是一個我任意選的一個存儲地址
if(ucSetNumber > 99)
{
write_eeprom(128,0); //往一個地址存入一個字節數據,128是一個我任意選的一個存儲地址
}
}
void Timer_T0() interrupt 1
{
TF0=0; //清除中斷標志
TR0=0; //關中斷
Key_Scan(); //按鍵掃描放在中斷里
if(uiVoiceCnt!=0) //蜂鳴器
{
uiVoiceCnt--; //每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫
beep_dr = 0; //蜂鳴器是PNP三極管控制,低電平就開始鳴叫
}
else
{
beep_dr = 1; //蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
}
TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f
TL0=0x2f;
TR0=1; //開中斷
}
復制代碼
AT24C02.c
#include<intrins.h>
#include"AT24C02.h"
sbit eeprom_scl_dr = P3^4; //時鐘線
sbit eeprom_sda_dr = P3^5; //數據輸出線
//AT24C02驅動程序
void start24() //開始位
{
eeprom_sda_dr=1;
eeprom_scl_dr=1;
Delay_time(15);
eeprom_sda_dr=0;
Delay_time(15);
eeprom_scl_dr=0;
}
void ack24() //確認位
{
eeprom_scl_dr=1;
Delay_time(15);
eeprom_scl_dr=0;
Delay_time(15);
}
void stop24() //停止位
{
eeprom_sda_dr=0;
eeprom_scl_dr=1;
Delay_time(15);
eeprom_sda_dr=1;
}
unsigned char read24() //讀取一個字節的時序
{
unsigned char outdata,tempdata;
outdata=0;
_nop_(); //空指令,相當于一個機器周期
_nop_(); //空指令,相當于一個機器周期
for(tempdata=0;tempdata<8;tempdata++)
{
eeprom_scl_dr=0;
_nop_(); //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
eeprom_scl_dr=1;
_nop_() ; //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
outdata<<=1;
if(eeprom_sda_dr==1)
{
outdata++;
}
_nop_() ; //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
}
return(outdata);
}
void write24(unsigned char dd) //發送一個字節的時序
{
unsigned char tempdata;
for(tempdata=0;tempdata<8;tempdata++)
{
if(dd>=0x80)
{
eeprom_sda_dr=1;
}
else
{
eeprom_sda_dr=0;
}
dd<<=1;
_nop_() ; //空指令,相當于一個機器周期
eeprom_scl_dr=1;
_nop_() ; //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
_nop_() ; //空指令,相當于一個機器周期
eeprom_scl_dr=0;
}
}
unsigned char read_eeprom(unsigned int address) //從一個地址讀取出一個字節數據
{
unsigned char dd,cAddress;
cAddress=address; //把低字節地址傳遞給一個字節變量。
start24(); //開始
write24(0xA0); //此字節包含讀寫指令和芯片地址兩方面的內容。
//指令為寫指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定
ack24(); //發送應答信號
write24(cAddress); //發送讀取的存儲地址(范圍是0至255)
ack24(); //發送應答信號
start24(); //開始
write24(0xA1); //此字節包含讀寫指令和芯片地址兩方面的內容。
//指令為讀指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定
ack24(); //發送應答信號
dd=read24(); //讀取一個字節
ack24(); //發送應答信號
stop24(); //停止
Delay_time(800); //此處最關鍵,此處的延時時間一定要,而且要足夠長
return(dd);
}
void write_eeprom(unsigned int address,unsigned char dd) //往一個地址存入一個字節數據
{
unsigned char cAddress;
cAddress=address; //把低字節地址傳遞給一個字節變量。
start24(); //開始
write24(0xA0); //此字節包含讀寫指令和芯片地址兩方面的內容。
//指令為寫指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定
ack24(); //發送應答信號
write24(cAddress); //發送寫入的存儲地址(范圍是0至255)
ack24(); //發送應答信號
write24(dd); //寫入存儲的數據
ack24(); //發送應答信號
stop24(); //停止
Delay_time(2000); //此處最關鍵,此處的延時時間一定要,而且要足夠長
}
void Delay_time(unsigned int Delay11_MS)
{
unsigned int Delay11_us;
for(Delay11_us=0;Delay11_us<Delay11_MS;Delay11_us++)
{
_nop_();
}
}
復制代碼
AT24C02.h
#ifndef __AT24C02_H__
#define __AT24C02_H__
#include<reg52.h>
unsigned char read_eeprom(unsigned int address); //從一個地址讀取出一個字節數據
void start24(); //開始位
void ack24(); //確認位
void stop24(); //停止位
unsigned char read24(); //讀取一個字節的時序
void write24(unsigned char dd); //發送一個字節的時序
void write_eeprom(unsigned int address,unsigned char dd); //往一個地址存入一個字節數據
void Delay_time(unsigned int Delay11_MS); //延時程序
#endif
復制代碼
Key_Scan.c
#include"Key_Scan.h" //按鍵自定義頭文件
#include"AT24C02.h" //IIC自定義頭文件
#define const_KeyTimeLevel 100 //按鍵消抖的時間,可以修改
#define const_VoiceCntLevel 150 //蜂鳴器鳴叫的時間
sbit Key_s1 = P1^6; //數據加
sbit Key_s2 = P1^7; //數據減
unsigned int uiKeyTimeCnt1 = 0; //按鍵延時計數器
unsigned int uiKeyTimeCnt2 = 0; //按鍵延時計數器
unsigned char ucKeyLock1 = 0; //按鍵自鎖標志位,防止按鍵一直觸發
unsigned char ucKeyLock2 = 0; //按鍵自鎖標志位,防止按鍵一直觸發
unsigned char KeySec = 0; //按鍵編號
void Key_Scan() //按鍵掃描程序
{
if(Key_s1 == 1)
{
uiKeyTimeCnt1 = 0; //延時計數器清零
ucKeyLock1 = 0; //自鎖標志位清零
}
else if(ucKeyLock1 == 0) //當有按鍵按下
{
uiKeyTimeCnt1++; //延時計數器加1
if(uiKeyTimeCnt1 >= const_KeyTimeLevel) //去抖動時間到
{
uiKeyTimeCnt1 = 0; //延時計數器清零
ucKeyLock1 = 1; //按鍵自鎖
KeySec = 1; //觸發1號鍵
}
}
if(Key_s2 == 1)
{
uiKeyTimeCnt2 = 0; //延時計數器清零
ucKeyLock2 = 0; //自鎖標志位清零
}
else if(ucKeyLock2 == 0) //當有按鍵按下
{
uiKeyTimeCnt2++; //延時計數器加1
if(uiKeyTimeCnt2 >= const_KeyTimeLevel) //去抖動時間到
{
uiKeyTimeCnt2 = 0; //延時計數器清零
ucKeyLock2 = 1; //按鍵自鎖
KeySec = 2; //觸發2號鍵
}
}
}
void Key_Service() //按鍵服務函數
{
switch(KeySec)
{
case 0:break;
case 1:
ucSetNumber++; //設定值自加1
if(ucSetNumber >= 99) //當加到99,就賦值成0
{
ucSetNumber = 0; //賦值
}
write_eeprom(128,ucSetNumber); //往一個地址存入一個字節數據
uiVoiceCnt = const_VoiceCntLevel;//蜂鳴器
KeySec = 0; //清零按鍵標志
break; //跳出
case 2:
ucSetNumber--; //設定值自減1
if(ucSetNumber>=99) //減到大于99,賦值成99
{
ucSetNumber = 99;
}
write_eeprom(128,ucSetNumber); //往一個地址存入一個字節數據
uiVoiceCnt = const_VoiceCntLevel; //蜂鳴器
KeySec = 0; //清零按鍵標志位
break;
default : break;
}
}
復制代碼
Key_Scan.h
#ifndef __Key_Scan_H__
#define __Key_Scan_H__
#include<reg52.h>
void Key_Scan(); //按鍵掃描程序
void Key_Service(); //按鍵服務程序
extern unsigned int uiVoiceCnt; //變量全局聲名
extern unsigned char ucSetNumber; //變量全局聲名
extern unsigned char ucSetNumber; //變量全局聲名extern可置于變量或者函數前,以表示變量或者函數的定義在別的文件中,
//提示編譯器遇到此變量和函數時在其他模塊中尋找其定義
#endif
復制代碼
Display.c
#include"display.h" //顯示頭文件
#include"delay.h" //延時頭文件
unsigned char code array[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
void display()
{
static unsigned char ucNumber_left = 0; //左邊數碼管顯示的實際內容
static unsigned char ucNumber_right = 0; //右邊數碼管顯示的實際內容
static unsigned char ucDisplayStep = 1; //顯示步驟切換變量
if(ucSetNumber >= 10) //在顯示的數值小于10時,左邊數碼管不顯示
{
ucNumber_left = ucSetNumber/10; //得到左邊顯示的值
}
else
{
ucNumber_left = 10; //小于10就不顯示
}
ucNumber_right = ucSetNumber%10; //右邊數碼管顯示的值
switch(ucDisplayStep)
{
case 1: //左邊數碼管顯示驅動
P0 = array[ucNumber_left];
P2 = 0xfe;
ucDisplayStep = 2;
delay_10ms();
P2 = 0xff;
break;
case 2:
P0 = array[ucNumber_right]; //右邊數碼管顯示驅動
P2 = 0xfd;
ucDisplayStep = 1;
delay_10ms();
P2 = 0xff;
break;
}
}
復制代碼
Display.h
#ifndef __display_h__
#define __display_h__
#include<reg52.h>
void display();
extern unsigned char ucIICDataTemp; //聲名全局變量
extern unsigned char ucSetNumber; //聲名全局變量
#endif
復制代碼
delay.c
#include"delay.h"
void delay_10ms() //延時函數
{
unsigned int x,y;
for(x = 0;x<10;x++)
for(y = 0;y<10;y++);
}
復制代碼
delay.h
#ifndef __delay_h__
#define __delay_h__
void delay_10ms(); //函數聲名
#endif
復制代碼
打包程序下載——>
EEPROM篇—用AT24C02數據保存數據.zip
(108.42 KB, 下載次數: 264)
2015-1-10 23:55 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
liuyy
時間:
2015-1-11 02:59
謝謝版主提供 這么好的學習資料。先下了看看
作者:
liuyy
時間:
2015-1-11 03:01
樓主程序文件很多,但是注釋詳細非常好。有電路圖嗎?
作者:
xiao_yp2014
時間:
2015-1-11 19:55
liuyy 發表于 2015-1-11 02:59
謝謝版主提供 這么好的學習資料。先下了看看
資料還有,我會慢慢的奉獻的。。。。。
作者:
xiao_yp2014
時間:
2015-1-11 19:58
liuyy 發表于 2015-1-11 03:01
樓主程序文件很多,但是注釋詳細非常好。有電路圖嗎?
文件分得很細,是為了以后方便移植,我是用的開發板,原理圖就不上了,很簡單的?梢愿鶕绦騺懋嬙韴D。。。
作者:
wendy666
時間:
2015-2-11 15:02
頂一下!好東西!謝謝樓主,正找這個呢!
作者:
hxk9608
時間:
2016-7-25 09:20
贊一個,很好的資料!
作者:
xyz9836
時間:
2016-8-17 23:13
多謝無私分享
作者:
xd_q
時間:
2018-1-22 13:45
謝謝版主提供 這么好的學習資料
作者:
bingguang
時間:
2019-12-6 17:11
看一看
作者:
mmjjrr
時間:
2020-4-26 22:50
寫得太棒了!
作者:
lhtlhtl
時間:
2023-11-14 08:57
這么詳細,講究
作者:
lllzzzlll
時間:
2023-12-18 22:03
很不錯,很詳細,值得研究
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1