📄 at24c02.c
字号:
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f020.h> // SFR declarations
//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------
#define WRITE 0x00 // WRITE direction bit
#define READ 0x01 // READ direction bit
// Device addresses
#define CHIP_B 0xA0
#define MY_ADD 0xF0 // Corresponds to the chip currently
#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_MRADDACK 0x40 // (MR) Slave address + R transmitted;
// ACK received
#define SMB_MRADDNACK 0x48 // (MR) Slave address + R transmitted;
// NACK received
#define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; NACK transmitted
//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------
char COMMAND; // Holds the slave address + R/W bit for
char COMMAND1; // use in the SMBus ISR.
char WORD; // Holds data to be transmitted by the SMBus
char xdata sendnumber; // OR data that has just been received.
unsigned char xdata OP_CODE; // Holds an op code to be sent or one
unsigned char xdata SENDMODE; // that has just been received.
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 SYSCLK_Init (void);
void SMBUS_ISR (void);
char SLA_READ(char chip_select,char out_op,char number);
void SLA_SEND(char chip_select,char out_op, char out_data,char number);
//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
void MAIN (void)
{
unsigned char check_1; // Variables used for testing purposes only.
WDTCN = 0xde; // disable watchdog timer
WDTCN = 0xad;
SYSCLK_Init(); // turn on the external oscillator
XBR0 = 0x07; // Route SMBus to GPIO pins through crossbar
XBR2 = 0x40; // Enable crossbar and weak pull-ups
SMB0CN = 0x44; // Enable SMBus with acknowledge low (AA = 1)
SMB0CR = -80; // SMBus clock rate = 100 kHz
SMB0ADR = MY_ADD; // Set own slave address.
EIE1 |= 2; // SMBus interrupt enable
EA = 1; // Global interrupt enable
SM_BUSY = 0; // Free bus for first transfer.
SI = 0; //
// TEST CODE--------------------------------------------------------------------------
// This code is used only to test the interface between the two devices. If
// the above OP_CODE_HANDLER line is commented out, this device assumes the master
// role. The other device should be running the OP_CODE_HANDLER at all times, to
// respond to the OP_CODEs below.
//SLA_SEND(CHIP_B, 0x40 , 0x66,0x01);
//check_1 = SLA_READ(CHIP_B, 0x40,0x01 ); // Write to index 4
// in the data buffer
//SLA_SEND(CHIP_B, 0x60, 0x25,0x01); // Write to index 6
//SLA_SEND(CHIP_B, 0x80, 0x26,0x01); // Write to index 8
//SLA_SEND(CHIP_B, 0x10, 0x27,0x01); // Write to index 1
SLA_SEND(CHIP_B, 0x00, 0x33,0x01); // Write to index 6
SLA_SEND(CHIP_B, 0x01, 0x22,0x01); // Write to index 8
SLA_SEND(CHIP_B, 0x02, 0x11,0x01); // Write to index 1
check_1 = SLA_READ(CHIP_B, 0x00,0x01); // Read index 4 from the buffer
check_1 = SLA_READ(CHIP_B, 0x01,0x01); // Read index 6
check_1 = SLA_READ(CHIP_B, 0x02,0x01); // Read index 8
check_1 = SLA_READ(CHIP_B, 0x03,0x01); // Read index 1
check_1 = SLA_READ(CHIP_B, 0x04,0x01); // Read index 8
check_1 = SLA_READ(CHIP_B, 0x05,0x01); // Read index 1
check_1 = SLA_READ(CHIP_B, 0x06,0x01); // Read index 8
check_1 = SLA_READ(CHIP_B, 0x07,0x01); // Read index 1
}
//------------------------------------------------------------------------------------
// Initialization Routines
//------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
void SYSCLK_Init (void)
{
int i; // delay counter
OSCXCN = 0x67; // start external oscillator with
// 22.1184MHz crystal
for (i=0; i < 256; i++) ; // XTLVLD blanking interval (>1ms)
while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settle
OSCICN = 0x88; // select external oscillator as SYSCLK
// source and enable missing clock
// detector
}
//------------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------------
// Send to slave.
// The send function transmits two bytes to the slave device: an op code, and a data
// byte. There are two op code choices for sending data: WRITE_DAC and WRITE_BUF.
// If the op code is WRITE_BUF, then the upper 4 bits of the op code should contain
// the buffer index. For example, to write to index 2 of the data buffer, the
// op_code parameter should be (0x20 | WRITE_BUF).
//
// chip_select = address of slave device.
// out_op = OP_CODE to be sent.
// out_data = data byte to be sent.
void SLA_SEND(char chip_select, char out_op, char out_data,char number){
SENDMODE=0x01;
sendnumber=number+1;
while(SM_BUSY); // Wait while SMBus is busy.
SM_BUSY = 1; // SMBus busy flag set.
SMB0CN = 0x44; // SMBus enabled, ACK low.
COMMAND = (chip_select | WRITE); // COMMAND = 7 address bits + WRITE.
OP_CODE = out_op; // WORD = OP_CODE to be transmitted.
WORD = out_data; // DATA = data to be transmitted.
STO = 0;
STA = 1; // Start transfer.
while(SM_BUSY);
}
// Read from slave.
// The read function transmits a 1-byte op code, then issues a repeated start
// to request a 1-byte read. The two op code choices are READ_ADC and READ_BUF.
// If the op code is READ_BUF, then the upper 4 bits of the op code should
// contain the buffer index. For example, to read index 5 of the data buffer,
// the op code should be (0x50 | READ_BUF).
//
// chip_select = address of slave device.
// out_op = OP_CODE to be sent.
char SLA_READ(char chip_select, char out_op,char number){
sendnumber=number;
SENDMODE=0;
while(SM_BUSY); // Wait while SMBus is busy.
SM_BUSY = 1; // Set busy flag.
SMB0CN = 0x44; // Enable SMBus, ACK low.
COMMAND1 = (chip_select | READ); // COMMAND = 7 address bits + READ
COMMAND = (chip_select | WRITE);
OP_CODE = out_op;
STO = 0;
STA = 1; // Start transfer.
while(SM_BUSY); // Wait for transfer to finish.
return WORD; // Return received word.
}
//------------------------------------------------------------------------------------
// SMBus Interrupt Service Routine
//------------------------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA){ // Status code for the SMBus
// (SMB0STA register)
// Master Transmitter/Receiver: START condition transmitted.
// Load SMB0DAT with slave device address. Mask out R/W bit since all transfers
// start with an OP_CODE write.
case SMB_START: //0x08
SMB0DAT = COMMAND ; // Load address of the slave to be accessed.
// Mask out R/W bit because first transfer
// will always be a write of the OP_CODE.
STA = 0; // Manually clear STA bit
SI = 0; // Clear interrupt flag
break;
// Master Transmitter/Receiver: Repeated START condition transmitted.
// This state only occurs during a READ, after the OP_CODE has been sent. Load
// device address + READ into SMB0DAT.
case SMB_RP_START: //0x10
SMB0DAT = COMMAND1;
STA = 0; // Manually clear START bit.
SI = 0;
break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received.
// Load OP_CODE into SMB0DAT.
case SMB_MTADDACK: //0x18
SMB0DAT = OP_CODE;
SI = 0; // Clear interrupt flag
break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received.
// The slave is not responding. Use ACK polling to retry.
case SMB_MTADDNACK: //0x20
STO = 1;
STA = 1;
SI = 0; // Clear interrupt flag
break;
// Master Transmitter: Data byte transmitted. ACK received.
// Check OP_CODE - If it is a READ code, send repeated START to begin
// read. If it is a WRITE code, load WORD into SMB0DAT for transfer.
// If it is not a valid code, then either 1) data has been transmitted
// and the transfer is finished, or 2) there is an error. In either case,
// send STOP and end transfer.
case SMB_MTDBACK: //0x28
switch (SENDMODE){ // Check only lower 4 bits.
// OP_CODE is a READ. Send repeated START.
case 1:
sendnumber--;
if(sendnumber)
SMB0DAT = WORD;
else{
STO=1;
SM_BUSY=0;
}
//OP_CODE = 0; // Clear OP_CODE so transfer ends the next
break; // time this state occurs
case 0:
STO = 0;
STA = 1;
break; // (after data is sent).
default: // No valid OP_CODE. End transfer.
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
break;
// Master Transmitter: Data byte transmitter. NACK received.
// Use ACK polling to retry transfer.
case SMB_MTDBNACK: //0x30
STO = 1;
STA = 1;
SI = 0; // Clear interrupt flag
break;
// Master Receiver: Slave address + READ transmitted. ACK received.
// Set to transmit NACK after next transfer since it will be the
// last (only) byte.
case SMB_MRADDACK: //0x40
AA = 0; // NACK sent during acknowledge cycle.
SI = 0;
break;
// Master Receiver: Slave address + READ transmitted. NACK received.
// Slave not responding. Send repeated START to try again.
case SMB_MRADDNACK: //0x48
STO = 0;
STA = 1;
SI = 0;
break;
// Master Receiver: Data byte received. NACK transmitted.
// Read operation has completed. Read data register and send STOP.
case SMB_MRDBNACK: //0x58
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1; // Set AA for next transfer
SI = 0;
break;
// All other status codes invalid. Reset communication.
default:
STO = 1;
SM_BUSY = 0;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -