?? 5045.c
字號:
/**************************************************
;5045.c
;功能描述:
;開機后在每1、2位數(shù)碼管顯示00,D8點亮表示目前處于調(diào)整地址的狀態(tài)
;此時按S1和S2,第1、2位數(shù)碼管的數(shù)據(jù)從00~FF變化
;此時若按下S4鍵,則讀出1、2位所示數(shù)據(jù)作為地址的EEPROM中的值,顯示在第5、6位上
;按下S3鍵,D7點亮,表示進入調(diào)整數(shù)據(jù)狀態(tài),此時第5、6位數(shù)碼管點亮顯示值與第1、2位同
;按下S1和S2,第5、6位上的數(shù)據(jù)從00~FF變化
;此時若按下S4鍵,則將5、6位上的數(shù)據(jù)寫入第1、2位指定的地址單元中
**************************************************/
#define uchar unsigned char
#define uint unsigned int
#include "reg52.h"
#include "intrins.h"
sbit CS=P2^1;
sbit SI=P3^7;
sbit Sck=P3^6;
sbit SO=P3^7;
sbit WP=P2^0;
sbit D1Led=P1^0;
sbit D2Led=P1^1;
sbit D8Led=P1^7;
bit KFirst; //第一次
bit KFunc; //代表兩種功能
bit KEnter; //代表執(zhí)行S4鍵的操作
uchar AddrCount=0; //地址計數(shù)值
uchar NumCount=0; //數(shù)據(jù)計數(shù)值
#define Wdt200 0x90 //WD1 WD0=01
#define Wdt600 0xa0 //WD1 WD0=10
#define Wdt1400 0x80 //如果最高位是1代表設置看門狗WD1 WD0 =00
#define NoWdt 0xb0 //WD1 WD0=11
#define ProQtr 0x04 //BL1 BL0=01保護區(qū)域為高128字節(jié)
#define ProHalf 0x08 //BL1 BL0=10寫保護區(qū)域為高256字節(jié)
#define ProAll 0x0c //BL1 BL0=11寫保護區(qū)域為整個存儲器
#define NoPro 0x00 //BL1 BL0=00不寫保護
#define nop2() _nop_();_nop_()
#define WREN_INST 0x06 // 寫允許命令字(WREN)
#define WRDI_INST 0x04 // 寫禁止命令字(WRDI)
#define WRSR_INST 0x01 // 寫狀態(tài)寄存器命令字(WRSR)
#define RDSR_INST 0x05 // 讀狀態(tài)寄存器命令字(RDSR)
#define WRITE_INST 0x02 // 寫存儲器命令字 (WRITE)
#define READ_INST 0x03 // 讀存儲器命令字 (READ)
#define MAX_POLL 0x99 //測試的最大次數(shù)
#define Hidden 0x10; //消隱字符在字形碼表中的位置
uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};
uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};
uchar DispBuf[6]; //6字節(jié)的顯示緩沖區(qū)
uchar code TH0Val=63266/256;
uchar code TL0Val=63266%256;//當晶振為11.0592時,定時2.5ms的定時器初值
/*******************************************************************************************
;名稱: OutByte
;描述:將一個字節(jié)送到EEPROM
;功能:移位送出一個字節(jié),從最高位開始送EEPROM
*******************************************************************************************/
void OutByte(uchar Data)
{ uchar Counter=8;
for(;Counter>0;Counter--)
{
Sck=0;
if((Data&0x80)==0) //最高位是0
SI=0;
else
SI=1;
Sck=1;
Data=Data<<1;
}
SI=0;
}
/*******************************************************************************************
;名稱: InByte
;描述:從EEPROM中接收數(shù)據(jù)
;功能:從EEPROM中接收數(shù)據(jù),高位在先
*******************************************************************************************/
uchar InByte(void)
{ uchar result=0;
uchar Counter=8;
for(;Counter>0;Counter--)
{
Sck=1;
nop2();
Sck=0;
result=result<<1;
if(SO) //如果輸入線是高電平
result|=0x01;
}
return (result);
}
/*******************************************************************************************
;名稱:RdsrCmd
;描述:讀狀態(tài)寄存器
;功能:送命令用以讀狀態(tài)寄存器
*******************************************************************************************/
uchar RdsrCmd()
{ uchar result;
Sck=0;
CS=0;
OutByte(RDSR_INST);
result=InByte(); //讀狀態(tài)寄存器
Sck=0;
CS=1;
return(result);
}
/*******************************************************************************************
;名稱:WipPoll
;描述:器件內(nèi)部編程檢查
;功能:通過檢查WIP位來確定X5045內(nèi)部編程是否結束
*******************************************************************************************/
void WipPoll()
{ uchar tmp;
uchar i;
for(i=0;i<MAX_POLL;i++)
{
tmp=RdsrCmd();
if((tmp&0x01)==0)
break;
}
}
/*******************************************************************************************
;名稱:WrenCmd
;描述:寫允許
;功能:這段程序發(fā)送命令允許寫存儲器單元和狀態(tài)寄存器
*******************************************************************************************/
void WrenCmd()
{ Sck=0; //將SCK拉低
CS=0; //將 /CS 拉低
OutByte(WREN_INST);
Sck=0; //將SCK拉低
CS=1; // 將 /CS 升高
}
#define Wdt200 0x90 //WD1 WD0=01
#define Wdt600 0xa0 //WD1 WD0=10
#define Wdt1400 0x80 //如果最高位是1代表設置看門狗WD1 WD0 =00
#define NoWdt 0xb0 //WD1 WD0=11
#define ProQtr 0x04 //BL1 BL0=01保護區(qū)域為高128字節(jié)
#define ProHalf 0x08 //BL1 BL0=10寫保護區(qū)域為高256字節(jié)
#define ProAll 0x0c //BL1 BL0=11寫保護區(qū)域為整個存儲器
#define NoPro 0x00 //BL1 BL0=00不寫保護
/*******************************************************************************************
;名稱;WrsrCmd
;描述:寫狀態(tài)寄存器
;功能:將WD0、WD1、BP0、BP1的狀態(tài)寫入狀態(tài)寄存器
*******************************************************************************************/
void WrsrCmd(uchar RegCode)
{ uchar tmp;
Sck=0; //將SCK拉低
CS=0; //將 /CS 拉低
tmp=RdsrCmd(); //讀出當前寄存器狀態(tài)
if((RegCode&0x7f)!=0) //RegCode與0x7f(01111111)相與不等于0,說明MSB=1,即設置看門狗的命令
{ tmp&=0x0f; //首先將讀到的數(shù)的高4位清零
tmp|=RegCode;
}
else
{ tmp&=0xf0; //否則是寫保護類指令,清除低4位
tmp|=RegCode;
}
OutByte(WRSR_INST); //寫指令
OutByte(tmp);
Sck=0;
CS=1;
OutByte(WRSR_INST); //寫指令
WipPoll() ; //測試是否已器件內(nèi)部是否寫完
}
/*******************************************************************************************
;名稱:WrdiCmd
;描述:寫禁止
;功能:禁止對存儲單元和狀態(tài)寄存器寫
*******************************************************************************************/
/*void WrdiCmd()
{ Sck=0; //將SCK拉低
CS=0; //將 /CS 拉低
OutByte(WRDI_INST);
Sck=0; //將SCK拉低
CS=1; // 將 /CS 升高
} 本程序中用不到這個函數(shù),故注釋掉,以免編譯警告,需要用時將注釋去掉即可*/
/*******************************************************************************************
;名稱:ByteWrite
;描述:單字節(jié)寫
;功能:本程序用于單字節(jié)寫入EEPROM
*******************************************************************************************/
void ByteWrite(uint Address,uchar Data)
{ uchar tmp;
Sck=0;
CS=0;
tmp=WRITE_INST;
if(Address>255)
tmp|=0x08;
OutByte(tmp);
tmp=(uchar)(Address&0x00ff);
OutByte(tmp);
OutByte(Data);
Sck=0;
CS=1;
WipPoll();
}
/*******************************************************************************************
;名稱:ByteRead
;描述:單字節(jié)讀
;功能:本程序從EEPROM中讀出一個字節(jié)
*******************************************************************************************/
uchar ByteRead(uint Address)
{ uchar tmp;
Sck=0;
CS=0;
tmp=READ_INST;
if(Address>255)
tmp|=0x08;
OutByte(tmp);
tmp=(uchar)(Address&0x00ff);
OutByte(Address);
tmp=InByte();
Sck=0;
CS=1;
return (tmp);
}
/*******************************************************************************************
;名稱:RstWatchDog
;描述:復位看門狗定時器
;功能:這段程序用來復位看門狗定時器,不發(fā)送命令
*******************************************************************************************/
void RstWatchDog()
{ CS=0;
nop2();
CS=1;
}
/*******************************************************************************************
;名稱:WriteString
;描述:字符中寫入
;功能:向X5045指定單元開始寫入一串數(shù)據(jù)
;參數(shù):*s 指向待寫數(shù)據(jù) Adress 指定待寫eeprom地址 Len 待寫入字節(jié)長度
;說明:不能跨頁寫
*******************************************************************************************/
void WriteString(uchar *s,uint Adress,uchar Len)
{ uchar i=0;
WP=1;
WrenCmd(); //寫允許
WrsrCmd(NoPro); //打開寫保護塊
for(i=0;i<Len;i++)
ByteWrite(Adress+i,*(s+i));
WP=0;
}
/*******************************************************************************************
;名稱:ReadString
;描述:字符中讀出
;功能:從X5045指定單元讀出一串數(shù)據(jù),寫入s指定的開始地址
;參數(shù):*s 指向待存數(shù)據(jù)區(qū) Adress 指定待讀eeprom地址 Len 待讀入字節(jié)長度
;說明:不能跨頁寫
*******************************************************************************************/
void ReadString(uchar *s,uint Adress,uchar Len)
{
uchar i=0;
for(i=0;i<Len;i++)
*(s+i)=ByteRead(Adress+i);
}
/*延時程序
由Delay參數(shù)確定延遲時間
*/
void mDelay(unsigned int Delay)
{ unsigned int i;
for(;Delay>0;Delay--)
{ for(i=0;i<124;i++)
{;}
}
}
//以下是中斷程序,實現(xiàn)顯示及鍵盤處理
void Timer0() interrupt 1
{ uchar tmp;
static uchar dCount; //計數(shù)器,顯示程序通過它得知現(xiàn)正顯示哪個數(shù)碼管
static uchar KCount; //用于鍵盤的計數(shù)器,控制去鍵抖延時,首次按下延時,連續(xù)按下時的延時
static bit KMark; //有鍵被按下
static bit KFunc1; //用于S3鍵
TH0=TH0Val;
TL0=TL0Val;
tmp=BitTab[dCount]; //根據(jù)當前的計數(shù)值取位值
P2=P2|0xfc; //P2與11111100B相或,將高6位置1
P2=P2&tmp; //P2與取出的位值相與,將某一位清零
tmp=DispBuf[dCount]; //根據(jù)當前的計數(shù)值取顯示緩沖待顯示值
tmp=DispTab[tmp]; //取字形碼
P0=tmp; //送出字形碼
dCount++; //計數(shù)值加1
if(dCount==6) //如果計數(shù)值等于6,則讓其回0
dCount=0;
P3|=0x3c; //按按鍵的各位置1
tmp=P3;
tmp|=0xc3; //未接鍵的各位置1
tmp=~tmp; //取反各位
if(!tmp) //如果結果是0表示無鍵被按下
{ KMark=0;
KFirst=0;
KCount=0;
KFunc1=0;
return;
}
if(!KMark) //如果鍵按下標志無效
{ KCount=4; //去鍵抖
KMark=1;
return;
}
KCount--;
if(KCount!=0) //如果不等于0
return;
if((tmp&0xfb)==0) //P3.2被按下
{ if(KFunc) //要求計數(shù)值操作
NumCount++;
else
AddrCount++;
}
else if((tmp&0xf7)==0) //P3.3被按下
{ if(KFunc) //要求計數(shù)值操作
NumCount--;
else
AddrCount--;
}
else if((tmp&0xef)==0) //P3.4被按下
{ if(!KFunc1) //該位為0才進行切換,防止長時間按著反復切換
{ KFunc=!KFunc; //切換狀態(tài)
KFunc1=1;
}
}
else if((tmp&0xdf)==0)
{ KEnter=1;
}
else //無鍵按下(出錯處理)
{ KMark=0;
KFirst=0;
KCount=0;
KFunc1=0;
}
if(KFirst) //不是第一次被按下(連加)
{ KCount=20;
}
else //第一次被按下(間隔較長)
{ KCount=200;
KFirst=1;
}
}
void Init()
{ TMOD=0x01;
TH0=TH0Val;
TL0=TL0Val;
ET0=1; //開T0中斷
EA=1; //開總中斷
TR0=1; //T0開始運行
}
void Calc(uchar Dat1,uchar Dat2) //第一個參數(shù)放在第1、2位,第二個參數(shù)放入第5、6位
{ DispBuf[0]=Dat1/16;
DispBuf[1]=Dat1%16;
DispBuf[4]=Dat2/16;
DispBuf[5]=Dat2%16;
}
void main()
{
uchar Mtd[5]; //待寫數(shù)據(jù)存入該數(shù)組
uchar Mrd[5]; //讀出的數(shù)據(jù)存入該數(shù)組
Init();
WrsrCmd(NoWdt); //關閉看門狗
WrsrCmd(NoPro); //不保護
DispBuf[2]=Hidden;
DispBuf[3]=Hidden;
DispBuf[4]=Hidden;
DispBuf[5]=Hidden;
D1Led=0; //點亮"讀"控制燈
CS=1;
SO=1;
Sck=0;
SI=0;
RstWatchDog(); //復位看門狗
for(;;)
{
Calc(AddrCount,NumCount);
if(KFunc)
{ D2Led=0; //點亮"讀"燈
D1Led=1; //關斷"寫"燈
}
else
{ D1Led=0; //點亮"寫"燈
D2Led=1; //關掉"讀"燈
}
if(KEnter) //按下了回車鍵
{ if(KFunc) //寫數(shù)據(jù)
{ Mtd[0]=NumCount;//當前的計數(shù)值作為待寫入的值
WP=1;
D8Led=0; //點亮指示燈
WriteString(Mtd,AddrCount,1); //從Mtd開始的單元中取出1字節(jié)數(shù)據(jù)寫入
WP=0;
}
else //讀數(shù)據(jù)
{ D8Led=0; //點亮指示燈
ReadString(Mrd,AddrCount,1);//讀出1字節(jié)數(shù)據(jù),存入Mrd開始的單元中
NumCount=Mrd[0];
}
KEnter=0; //清回車鍵被按下的標志
mDelay(100); //延時一段時間(為看清D8亮過)
D8Led=1;
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -