?? at24c02.#1
字號:
//參考程序A:AT24C02.C SMBUS 24C02 讀/寫 2005.12.25
//程序功能:在AT24C02的地址00---3FH中依次存入連續的數據10H--4FH
//再依次從地址00---3FH中讀出數據并通過SAA1064驅動四位數碼管顯示出來.
//第一,二位數碼管顯示地址,第三,四位數碼管顯示存入該地址內的數據.
//顯示格式:
//存儲器的地址 存儲器單元的內容
//00H---3FH 40H---4FH
#include <c8051f020.h> // SFR declarations
#include <intrins.h>
#define WRITE 0x00 // SMBUS尋址字節的寫標志位
#define READ 0x01 // SMBUS尋址字節的讀標志位
// Device addresses
#define CHIP_A 0xA0 //AT24C02器件自身的尋址字節
#define CHIP_B 0x70 //AT24C02器件自身的尋址字節
#define SMB_BUS_ERROR 0x0 //總線錯誤
//MT為主發送器,MR為主接收器
#define SMB_START 0x08 // (MT & MR) 發送起始位
#define SMB_RP_START 0x10 // (MT & MR) 重復起始位
#define SMB_MTADDACK 0x18 // (MT) 發送從地址 + W 后收到ACK
#define SMB_MTADDNACK 0x20 // (MT) 發送從地址 + W 后收到NACK
#define SMB_MTDBACK 0x28 // (MT) 發送數據后收到ACK
#define SMB_MTDBNACK 0x30 // (MT) 發送數據后收到NACK
#define SMB_MTARBLOST 0x38 //(MT)競爭失敗
#define SMB_MRADDACK 0x40 // (MR) 發送從地址 + R 后收到 ACK
#define SMB_MRADDNACK 0x48 // (MR) 發送從地址 + R 后收到 NACK
#define SMB_MRDACK 0x50 // (MR) 收到數據字節 后已發送ACK
#define SMB_MRDBNACK 0x58 // (MR) 收到數據字節 后已發送NACK
char DATA0[6]={0x17,0x3f,0x06,0x5b,0x4f};
char xdata DATA2[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
char SLAW,DATA1[64]; // 保存從地址+ WRITE 位
char SLAR; // 保存從地址+ WRITE 位
char WORD,WORDADR; // 保存被收/發的數據字節
char xdata sendnumber; // 保存被收/發的數據字節的數目
//unsigned char xdata WORDADR; //保存被傳送的數據在24C02中的首地址.
unsigned char xdata SENDMODE; //SENDMODE作讀/寫控制字
unsigned char xdata i,j,k,sla,n,m,p;
bit SM_BUSY; //忙碌標志位 void sleep_ms( unsigned int count); //延時
void SYSCLK_Init (void); //系統時鐘初始化
void DISPLAY(void); //通過SAA1064驅動四位數碼管顯示
void SMBUS_ISR (void); //中斷服務程序
char SLA_READ(char chip,char wordadr,char number);
void SLA_SEND(char chip,char wordadr, char word,char number);
void sleep_ms(unsigned int count);
void MAIN (void)
{
unsigned char check; // 測試用的工作變量
WDTCN = 0xde; // 關閉看們狗
WDTCN = 0xad;
SYSCLK_Init(); // 時鐘初始化
XBR0 = 0x01; // 選交叉開關 :P0.0-->SDA,P0.1-->CLK
XBR2 = 0x40; // 交叉開關使能
SMB0CN = 0x44; // 允許SMBUS, 應答返回AA(低電平
SMB0CR = 0xc9; // SMBus 速率= 100 kHz,系統時鐘為11.0592MHZ
EIE1 |= 2; // SMBus 中斷使能
EA = 1; // 開中斷
SM_BUSY = 0; // SM_BUSY是忙碌標志位
SI = 0; //SM_BUSY中斷標志位
//寫64個連續的數據到AT24C02中去并依次存放.
//64個連續的數據的存放地址:00H--3fH.第一個數為10H,最后一個數為4FH.
i=0x10;
sla=CHIP_A;
for (j=0;j<0x40;j++) //向24C02的000地址依次寫入64個數據,
{ //64個數據的數值從10H---4FH
SLA_SEND(sla, j, i,0x01); // 寫入AT24C02
i++;
}
for (j=0;j<0x40;j++) //從24C02的00地址依次連續讀出64個數據,
{ //64個數據的數值應該是從10H---3FH(連續存放)
check=SLA_READ(sla, j,0x01);
DATA1[j]=check; //讀出來的數據依次連續存入數組DATA[]中
}
for (j=0;j<0x40;j++) //把要顯示的兩位地址和兩位數據存入DATA2[]中
{ i=DATA1[j];
k=i&0x0f;
m=DATA2[k]; //j為地址,i=DATA1[j]=check,i地址j中存放的數據
DATA0[4]=m;
k=i&0xf0;
k=k>>4;
n=DATA2[k];
DATA0[3]=n;
k=j&0x0f;
m=DATA2[k];
DATA0[2]=m;
k=j&0xf0;
k=k>>4;
n=DATA2[k];
DATA0[1]=n;
DISPLAY();
sleep_ms(1000);
}
while(1);
}
void DISPLAY (void)
{
sla=CHIP_B;
DATA0[0]=0x17; //0x17是SAA1064的控制字.
for (p=0;p<0x5;p++)
{i=DATA0[p]; //向SAA1064寫入五個數:SAA1064的控制字一字節,
SLA_SEND(sla, p, i,0x01); // 地址2字節,數據2字節.共五字節
}
}
void SYSCLK_Init (void)
{
int i; // i 用于延時計數
OSCXCN = 0x67; // 先選擇外捕振蕩器,頻率位11.0592MHZ
for (i=0; i < 256; i++) ; // 再延時(>1ms),
while (!(OSCXCN & 0x80)) ; // 等待外部晶振穩定
OSCICN = 0x88; // 選擇外部晶振,允許時鐘丟失檢測
}
void SLA_SEND(char chip, char wordadr, char word,char number)
{
SENDMODE=0x01;
sendnumber=number+1;
while(SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // 置SM_BUSY位(忙碌標志位)為1
SLAW = (chip| WRITE); // COMMAND = 7 個地址位 + 一位WRITE.
WORD = word; // WORD中存放要送到24C02中去的數據(8位)
WORDADR = wordadr; // OP_CODE 中存放被傳送數據送入24C02的首地址.
STO = 0;
STA = 1; // 啟動數據傳輸
while(SM_BUSY); // 等待傳輸完成
}
char SLA_READ(char chip, char wordadr,char number){
sendnumber=number;
SENDMODE=0;
while(SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // 置SM_BUSY位(忙碌標志位)為1
SLAR = (chip| READ); // COMMAND = 7 個地址位 + 一位READ
WORDADR = wordadr; // OP_CODE 中存放從24C02讀出數據的的首地址.
STO = 0;
STA = 1; // 啟動傳輸
while(SM_BUSY); // 等待傳輸完成
return WORD; //返回讀出來的數據(一個字節)
}
void SMBUS_ISR (void) interrupt 7 //中斷服務程序
{
switch (SMB0STA){ // 根據中斷狀態碼跳轉
//(SMB0STA 是中斷狀態寄存器)
case SMB_START: //0x08, (MT & MR) 發送起始位
SMB0DAT = SLAW ; // 裝入被訪問的從芯片的寫地址
STA = 0; // 人工清除 STA 位
SI = 0; // 清除中斷標志位
break;
case SMB_RP_START: //0x10,(MT & MR) 重復發送起始位
SMB0DAT = SLAR; // 裝入被訪問的從芯片的讀地址
STA = 0; // 人工清除 STA 位
SI = 0; // 清除中斷標志位
break;
case SMB_MTADDACK: //0x18 ,(MT) 發送從地址 + W 后收到ACK
SMB0DAT = WORDADR;
SI = 0; // 清除中斷標志位
break;
case SMB_MTADDNACK: //0x20,(MT) 發送從地址 + W 后收到NACK
STO = 1;
STA = 1;
SI = 0; // 清除中斷標志位
break;
case SMB_MTDBACK: //0x28,(MT) 發送數據后收到ACK
switch (SENDMODE){ // 檢查低1位
case 1:
sendnumber--;
if(sendnumber)
SMB0DAT = WORD;
else{
STO=1;
SM_BUSY=0;
}
break;
case 0:
STO = 0;
STA = 1;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
break;
case SMB_MTDBNACK: //0x30
STO = 1;
STA = 1;
SI = 0; // 清除中斷標志
break;
case SMB_MRADDACK: //0x40
AA = 0;
SI = 0;
break;
case SMB_MRADDNACK: //0x48
STO = 0;
STA = 1;
SI = 0;
break;
case SMB_MRDBNACK: //0x58
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1;
SI = 0;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
}
/*延時子程序*/
void sleep_ms(unsigned int count)
{
unsigned int ii,jj;
for(ii=0;ii<count;ii++)
{
for(jj=0;jj<250;jj++)
_nop_();
_nop_();
_nop_();
_nop_();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -