⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at24c02.c

📁 这是一个有关C8051F020单片机的实验教学材料,相信对于单片机的研究人员会有很大的帮助.
💻 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 + -