?? i2c.#3
字號:
#include <c8051f020.h> // SFR declarations
#include "INTRINS.H"
//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
// Device addresses (7 bits, lsb is a don't care)
#define CLOCK3530_ADDRESS_RESET 0x60 //1 ack
#define CLOCK3530_ADDRESS_STATUS 0x62 //2 ack
#define CLOCK3530_ADDRESS_DATEHOUR 0x64 //8 ack year month day week hour minute second
#define CLOCK3530_ADDRESS_HOUR 0x66 //4 ack hour minute second
#define CLOCK3530_ADDRESS_INT1 0x68 //3 ack
#define CLOCK3530_ADDRESS_INT2 0x6A //3 ack
union
{
unsigned char ClockString[7];
struct RealClock
{
unsigned char Year,Month,Day,Week,Hour,Minute,Second;
} RT;
} RealTime;
// SMBus states:
// MT = Master Transmitter
// MR = Master Receiver
#define SMB_BUS_ERROR 0x00 // (all modes) BUS ERROR
#define SMB_START 0x08 // (MT & MR) START transmitted
#define SMB_RP_START 0x10 // (MT & MR) repeated START
#define SMB_MTADDACK 0x18 // (MT) Slave address + W transmitted;
// ACK received
#define SMB_MTADDNACK 0x20 // (MT) Slave address + W transmitted;
// NACK received
#define SMB_MTDBACK 0x28 // (MT) data byte transmitted; ACK rec'vd
#define SMB_MTDBNACK 0x30 // (MT) data byte transmitted; NACK rec'vd
#define SMB_MTARBLOST 0x38 // (MT) arbitration lost
#define SMB_MRADDACK 0x40 // (MR) Slave address + R transmitted;
// ACK received
#define SMB_MRADDNACK 0x48 // (MR) Slave address + R transmitted;
// NACK received
#define SMB_MRDBACK 0x50 // (MR) data byte rec'vd; ACK transmitted
#define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; NACK transmitted
//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------
char COMMAND; // Holds the slave address + R/W bit for use in the SMBus ISR.
unsigned char *I2CDataBuff;
char BYTE_NUMBER; // Used by ISR to check what data has just been
// sent - High address byte, Low byte, or data byte
unsigned char HIGH_ADD, LOW_ADD; // High & Low byte for EEPROM memory address
bit SM_BUSY; // This bit is set when a send or receive
// is started. It is cleared by the
// ISR when the operation is finished.
//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------
void SMBus_ISR (void);
//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
//
// Main routine configures the crossbar and SMBus, and tests
// the SMBus interface between the three EEPROMs
void ResetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 0; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_RESET | READ); // Chip select + READ
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
}
//======================寫S-3530A內部實時數據寄存器程序=====================
//功能:將設定年、月、日、星期、時、分、秒數據寫入S-3530A |
//入口:發(fā)送數據放在年、月、日、星期、時、分、秒各寄存器 |
//出口:NONE |
//==========================================================================
void SetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 7; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | WRITE); // Chip select + WRITE
I2CDataBuff = &RealTime.ClockString[0]; // Data to be writen
STA = 1; // Start transfer
}
//==================讀S-3530A實時數據寄存器子程序===========================
//功能:從S-3530A讀入當前時間數據 |
//入口:NONE |
//出口:接收數據放在年、月、日、星期、時、分、秒各寄存器 |
//==========================================================================
void GetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 7; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | READ); // Chip select + READ
I2CDataBuff = &RealTime.ClockString[0]; // Data to be writen
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
}
//============================寫狀態(tài)寄存器程序==============================
//功能:讀/寫S-3530A狀態(tài)寄存器,對S-3530A進行設置 |
//入口:NONE 出口:NONE |
//==========================================================================
unsigned char GetRealClockStatus(void)
{
unsigned char result;
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 1;
COMMAND = (CLOCK3530_ADDRESS_STATUS | READ);
I2CDataBuff = &result;
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
return result;
}
void SetRealClockStatus(unsigned char status)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 1;
COMMAND = (CLOCK3530_ADDRESS_STATUS | WRITE);
I2CDataBuff = &status;
STA = 1; // Start transfer
}
unsigned char revolve(unsigned char val)
{
char i;
unsigned char val1=0;
for (i=0;i<8;i++)
{
if (val&0x1)
val1++;
val1=_crol_(val1,1);
val=_cror_(val,1);
}
val1=_cror_(val1,1);
return val1;
}
void Delay1ms(unsigned char T);
void I2c_init(void )
{
unsigned char var ;
P0MDOUT |= 0x1D;
P1MDOUT |= 0x01;
SMB0CN = 0x44; // Enable SMBus with ACKs on acknowledge cycle
SMB0CR = -80; // SMBus clock rate = 100kHz.
EIE1 |= 2; // SMBus interrupt enable
EA = 1; // Global interrupt enable
SM_BUSY = 0;
// Free SMBus for first transfer.
var = GetRealClockStatus();
ResetRealClock();
var = GetRealClockStatus();
SetRealClockStatus(0xc2);
var = GetRealClockStatus();
GetRealClock();
RealTime.RT.Year=0x02;
RealTime.RT.Month=0x12;
RealTime.RT.Day=0x010;
RealTime.RT.Week=0x05;
RealTime.RT.Hour=0x11;
RealTime.RT.Minute=0x59;
RealTime.RT.Second=0x50;
SetRealClock();
}
void TestI2C (void)
{
char year,month,day,week,hour,minute,second ;
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
GetRealClock();
year=RealTime.RT.Year;
month=RealTime.RT.Month;
day=RealTime.RT.Day;
week=RealTime.RT.Week;
hour=RealTime.RT.Hour;
minute=RealTime.RT.Minute;
second=RealTime.RT.Second;
}
//------------------------------------------------------------------------------------
// Interrupt Service Routine
//------------------------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA)
{ // SMBus 狀態(tài)碼SMB0STA 寄存器
// 主發(fā)送器/接收器起始條件已發(fā)送
case SMB_START:
SMB0DAT = COMMAND ; // 裝入要訪問的從器件的地址
STA = 0; // 手動清除START 位
break;
//主發(fā)送器/接收器重復起始條件已發(fā)送
// 該狀態(tài)只應在讀操作期間出現在存儲器地址已發(fā)送并得到確認之后 ?
case SMB_RP_START:
SMB0DAT = COMMAND; // COMMAND 中應保持從地址 + R.
STA = 0;
break;
// 主發(fā)送器從地址 + WRITE 已發(fā)送收到ACK
case SMB_MTADDACK:
// 主發(fā)送器數據字節(jié)已發(fā)送收到ACK
case SMB_MTDBACK:
if (BYTE_NUMBER)
{
SMB0DAT = revolve(*I2CDataBuff); // If R/W=WRITE, load byte to write.
I2CDataBuff++;
BYTE_NUMBER--;
}
else
{
STO = 1; SM_BUSY = 0; // Free SMBus
}
break;
// 主發(fā)送器從地址 + WRITE 已發(fā)送收到NACK
// 從器件不應答發(fā)送STOP + START 重試
case SMB_MTADDNACK:
STO = 1; STA = 1;
break;
// 主發(fā)送器數據字節(jié)已發(fā)送收到NACK
// 從器件不應答發(fā)送STOP + START 重試
case SMB_MTDBNACK:
STO = 1; STA = 1;
break;
// 主發(fā)送器競爭失敗
// 不應出現如果出現重新開始傳輸過程
case SMB_MTARBLOST:
STO = 1; STA = 1;
break;
// 主接收器從地址 + READ 已發(fā)送,收到ACK
case SMB_MRADDACK:
AA = 1; // 在應答周期ACK
if (!BYTE_NUMBER)
{
STO = 1; SM_BUSY = 0; // 釋放SMBus
}
break;
// 主接收器從地址 + READ 已發(fā)送收到NACK
// 從器件不應答發(fā)送重復起始條件重試
case SMB_MRADDNACK:
STA = 1;
break;
// 收到數據字節(jié)ACK 已發(fā)送
// 該狀態(tài)不應出現因為AA 已在前一狀態(tài)被清0 如果出現發(fā)送停止條件
case SMB_MRDBACK:
if (BYTE_NUMBER)
{
*I2CDataBuff=revolve(SMB0DAT);
I2CDataBuff++;
BYTE_NUMBER--;
}
if (!BYTE_NUMBER) AA= 0;
break;
// 收到數據字節(jié)NACK 已發(fā)送
// 讀操作已完成讀數據寄存器后發(fā)送停止條件
case SMB_MRDBNACK:
STO = 1;
SM_BUSY = 0; // 釋放SMBus
break;
// 在本應用中所有其它狀態(tài)碼沒有意義通信復位
default:
STO = 1; // 通信復位
SM_BUSY = 0;
break;
}
SI=0; // 清除中斷標志
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -