C8051F I2C (SMBus) Program

Publisher:李国永Latest update time:2020-06-29 Source: eefocusKeywords:C8051F  I2C  SMBus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

/********************************************************************************************************
*
* File : ws_iic_port.h
* Hardware Environment: 
* Build Environment : Silicon LABs 3.42.00 / uVision3 V3.80 20100913
* Version : 
* By : Su Wei Feng
*
*(c) Copyright 2005-2010, WaveShare
*http://www.waveshare.net
*All Rights Reserved
*
*********************************************************************************************************/

#ifndef _WS_IIC_PORT_H_
#define _WS_IIC_PORT_H_

#define SMB_FREQUENCY 100000 // Target SCL clock rate
// This example supports in 100kHz
void SMBus_Init(void);
void Check_SDA(void);
void SMBus_Write(uint wrDAdr,uchar Data1,uchar Data2,uchar Num);
void SMBus_Read(uint wrDAdr,uchar *Data,uchar Num);

/*Hardware Environment:DVK501 && F320+ EX*/
#if defined(_DVK501_F320_EX_)

void Timer1_Init(void);
void Timer3_Init(void);
void Enb_Interrupt(void);
void SMBus_ISR(void);
void Timer3_ISR(void);

// 16-bit SFR declarations
sfr16 TMR3RL = 0x92; // Timer3 reload registers
sfr16 TMR3 = 0x94; // Timer3 counter registers

sbit SDA = P1^0; // SMBus on P1.0
sbit SCL = P1^1; // and P1.1

void SMBus_Init(void) 
{
XBR0 |= 0x07; // Enable SMBus pins
P1MDOUT = 0x00; // All P1 pins open-drain output
P1 = 0xFF;
SMB0CF = 0x5D; // Use Timer1 overflows as SMBus clock source;
// Disable slave mode;
// Enable setup & hold time extensions;
// Enable SMBus Free timeout detect;
// Enable SCL low timeout detect;

SMB0CF |= 0x80; // Enable SMBus 
Timer1_Init();
Timer3_Init();
}


void Timer1_Init(void)
{
// Make sure the Timer can produce the appropriate frequency in 8-bit mode
// Supported SMBus Frequencies range from 10kHz to 100kHz. The CKCON register
// settings may need to change for frequencies outside this range.
#if ((SYSCLK/SMB_FREQUENCY/3) < 255)
#define SCALE 1
CKCON |= 0x08; // Timer1 clock source = SYSCLK
#elif ((SYSCLK/SMB_FREQUENCY/4/3) < 255)
#define SCALE 4
CKCON |= 0x01;
CKCON &= ~0x0A; // Timer1 clock source = SYSCLK / 4
#endif

TMOD = 0x20; // Timer1 in 8-bit auto-reload mode

// Timer1 configured to overflow at 1/3 the rate defined by SMB_FREQUENCY
TH1 = -(SYSCLK/SMB_FREQUENCY/SCALE/3);
TL1 = TH1; // Init Timer1
TR1 = 1; // Timer1 enabled
}


void Timer3_Init(void)
{
TMR3CN = 0x00; // Timer3 configured for 16-bit auto-
// reload, low-byte interrupt disabled

CKCON &= ~0x40; // Timer3 uses SYSCLK/12
TMR3RL = -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect):
// 1/.025 = 40

EIE1 |= 0x80; // Timer3 interrupt enable
TMR3CN |= 0x04; // Start Timer3
}


void Enb_Interrupt(void)
{
EIE1 |= 0x01; // Enable the SMBus interrupt
EA = 1; // Global interrupt enable
}


#else
#warning "iic interface undefined."
#endif

#include <../../../../library/C8051F/ws_iic.h>

#endif /*_WS_IIC_PORT_H_*/

 

/********************************************************************************************************
*
* File : ws_iic.h
* Hardware Environment: 
* Build Environment : Silicon LABs 3.42.00 / uVision3 V3.80 20100913
* Version : 
* By : Su Wei Feng
*
*(c) Copyright 2005-2010, WaveShare
*http://www.waveshare.net
*All Rights Reserved
*
*********************************************************************************************************/

#ifndef _WS_IIC_H_
#define _WS_IIC_H_

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command

// Status vector - top 4 bits only
#define SMBus_MTSTA 0xE0 // (MT) start transmitted
#define SMBus_MTDB 0xC0 // (MT) data byte transmitted
#define SMBus_MRDB 0x80 // (MR) data byte received
// End status vector definition

//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
unsigned char SMBus_DATA_IN[3]; // Global holder for SMBus data
// All receive data is written here

unsigned char SMBus_DATA_OUT[2]; // Global holder for SMBus data.
// All transmit data is read from here

unsigned char COMMAND,num[2]; // Target SMBus slave address

bit SMBus_BUSY; // Software flag to indicate when the
// SMB_Read() or SMB_Write() functions
// have claimed the SMBus
bit SMBus_WR; // SMBus READ or WRITE, 0 is READ, 1 is WRITE

//-----------------------------------------------------------------------------
// Check_SDA
//-----------------------------------------------------------------------------
// If slave is holding SDA low because of an improper SMBus reset or error
void Check_SDA(void)

uchar i; // Dummy variable counters
while(!SDA)
{
// Provide clock pulses to allow the slave to advance out
// of its current state. This will allow it to release SDA.
XBR1 = 0x40; // Enable Crossbar
SCL = 0; // Drive the clock low
for(i = 0; i < 255; i++); // Hold the clock low
SCL = 1; // Release the clock
while(!SCL); // Wait for open-drain
// clock output to rise
for(i = 0; i < 10; i++); // Hold the clock high
XBR1 = 0x00; // Disable Crossbar
}
}

//-----------------------------------------------------------------------------
// wrDAdr:I2C address
// dat:I2C data
//-----------------------------------------------------------------------------
void SMBus_Write(uint wrDAdr,uchar Data1,uchar Data2,uchar Num)
{
while(SMBus_BUSY); // Wait for SMBus to be free.
SMBus_BUSY = 1; // Claim SMBus (set to busy)
COMMAND = wrDAdr; 
SMBus_DATA_OUT[0] = Data1;
SMBus_DATA_OUT[1] = Data2;
num[0] = Num;
SMBus_WR = 0;
STO = 0;
STA = 1; // Start transfer
while(SMBus_BUSY); // Wait for SMBus to be free.
}

//-----------------------------------------------------------------------------
// wrDAdr:I2C address
//-----------------------------------------------------------------------------
void SMBus_Read(uint wrDAdr,uchar *Data,uchar Num)
{
uchar i;
while(SMBus_BUSY); // Wait for bus to be free.
SMBus_BUSY = 1; // Claim SMBus (set to busy)
COMMAND = wrDAdr;
num[1] = Num;
SMBus_WR = 1;
STO = 0;
STA = 1; // Start transfer 
while(SMBus_BUSY); // Wait for transfer to complete
for(i=0;iData[i] = SMBus_DATA_IN[i];
}


void SMBus_ISR(void) interrupt 7
{
bit FAIL = 0; // Used by the ISR to flag failed transfers
static uchar sent_byte_counter,rec_byte_counter;

if (ARBLOST == 0) // Check for errors
{
// Normal operation
switch (SMB0CN & 0xF0) // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMBus_MTSTA:
{
SMB0DAT = COMMAND; // Load address of the target slave
STA = 0; // Manually clear START bit
sent_byte_counter = 1;
rec_byte_counter = 1; 
break;
}
// Master Transmitter: Data byte transmitted
case SMBus_MTDB:
{
if (ACK) // Slave ACK?
{
if (SMBus_WR == WRITE) // If this transfer is a WRITE,
{
if (sent_byte_counter <= num[0])
{
// send data byte
SMB0DAT = SMBus_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
}
else
{
STO = 1; // Set STO to terminate transfer
SMBus_BUSY = 0; // And free SMBus interface
}
}
}
else // If slave NACK,
{
STO = 1; // Send STOP condition, followed
STA = 1; // By a START
}
break;
}
// Master Receiver: byte received
case SMBus_MRDB:

if (rec_byte_counter < num[1])
{
SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
ACK = 1; // Send ACK to indicate byte received
rec_byte_counter++; // Increment the byte counter
}
else
{
SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byte
SMBus_BUSY = 0; // Free SMBus interface
ACK = 0; // Send NACK to indicate last byte of this transfer
STO = 1; // Send STOP to terminate transfer
}
break;
}
default:
{
FAIL = 1; // Indicate failed transfer and handle at end of ISR
break;
}
} // end switch
}
else
{
// ARBLOST = 1, error occurred... abort transmission
FAIL = 1;
} // end ARBLOST if

if (FAIL) // If the transfer failed,
{
SMB0CF &= ~0x80; // Reset communication
SMB0CF |= 0x80;
STA = 0;
STO = 0;
ACK = 0;

SMBus_BUSY = 0; // Free SMBus
}

SI = 0; // Clear interrupt flag
}


void Timer3_ISR(void) interrupt 14
{
SMB0CF &= ~0x80; // Disable SMBus
SMB0CF |= 0x80; // Re-enable SMBus
TMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flag
STA = 0;
SMBus_BUSY = 0; // Free SMBus
}

#endif /*_WS_IIC_H_*/

Keywords:C8051F  I2C  SMBus Reference address:C8051F I2C (SMBus) Program

Previous article:Using PCF8574 to expand the I/O port of C8051F
Next article:Using 74LS165 to expand C8051F's serial port input to parallel port input

Recommended ReadingLatest update time:2024-11-23 06:20

Intelligent two-wire temperature transmitter based on C8051F017
Introduction The two-wire RTD temperature transmitter converts the temperature signal linearly into a 4~20mA DC standard output signal. Most analog two-wire temperature transmitters are composed of discrete components, which have large temperature drifts; at the same time, the RTD itself is nonlinear, and its a
[Microcontroller]
Intelligent two-wire temperature transmitter based on C8051F017
SMBus of C8051F020
The SMBus of C8051F020 is compatible with I2C, so it is easy to connect multiple I2C devices, as shown below: Master transmitter mode: Master Receiver Mode: SMB0STA: bit SM_BUSY; //Busy flag when reading and writing void SMBus_Init() {   SMB0CN=0x44;       SMB0CR=0xec; //Frequency 400k  
[Microcontroller]
Using 74LS164 to expand C8051F's serial port output to parallel port output
System functions Use 74LS164 to expand the AVR's serial port output to parallel port output. hardware design Schematic diagram of the control circuit of the serial output expansion chip 74LS164 parallel output software design The following part is copied from TXT and copied to the web page. There are many spac
[Microcontroller]
Using 74LS164 to expand C8051F's serial port output to parallel port output
I2C bus learning - check for gaps and fill in the gaps - thinking about data validity
The IIC protocol stipulates that the data transmitted on SDA must remain stable during the high level of SCL, and the data on SDA can only change during the low level of SCL. During IIC, data is placed on SDA at the rising edge of the pulse, and data is read from SAD at the falling edge of the pulse. In this way,
[Microcontroller]
I2C bus learning - check for gaps and fill in the gaps - thinking about data validity
Interface design of bank queuing system based on I2C bus
  This paper takes the existing queueing system of the bank as an example and proposes the interface design of the single-chip microcomputer queueing system based on the IIC bus. Through the simulation test of the system, it not only simplifies the design circuit, reduces the circuit board area, saves components in co
[Microcontroller]
Interface design of bank queuing system based on I2C bus
i2c virtual bus universal software package
// ********************************************************************// //------------- Virtual i2c package header file iic.h -----------------------// //****************************************************************// sbit SDA=P1^7; //Define IIC data line// sbit SCL=P1^6; //Define IIC clock line// #define u
[Microcontroller]
Driving control of touch screen by C8051F020 microcontroller
The touch screen is currently the simplest, most convenient, natural input device suitable for China's multimedia information inquiry and national conditions. It has many advantages such as durability, fast response speed, space saving, and easy communication. Touch screen technology is considered to be one of the mai
[Microcontroller]
Driving control of touch screen by C8051F020 microcontroller
Design of Ethernet-CAN conversion circuit based on C8051F040
Abstract: Ethernet and CAN bus are widely used, but due to their different communication protocols, data communication between the two bus devices is impossible. Therefore, an Ethernet bus and CAN bus interface conversion circuit based on CP2200 and C8051F040 is designed, and some related hardware circuits and softw
[Microcontroller]
Design of Ethernet-CAN conversion circuit based on C8051F040
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号