2024年2月7日发(作者:)

{XBR0 |= 0x07; // Enable SMBus pinsP1MDOUT = 0x00; // All P1 pins open-drain outputP1 = 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 SMBusTimer1_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 1CKCON |= 0x08; // Timer1 clock source = SYSCLK#elif ((SYSCLK/SMB_FREQUENCY/4/3) < 255)#define SCALE 4CKCON |= 0x01;CKCON &= ~0x0A; // Timer1 clock source = SYSCLK / 4#endifTMOD = 0x20; // Timer1 in 8-bit auto-reload mode// Timer1 configured to overflow at 1/3 the rate defined by SMB_FREQUENCYTH1 = -(SYSCLK/SMB_FREQUENCY/SCALE/3);TL1 = TH1; // Init Timer1TR1 = 1; // Timer1 enabled}void Timer3_Init(void){

TMR3CN = 0x00; // Timer3 configured for 16-bit auto-// reload, low-byte interrupt disabledCKCON &= ~0x40; // Timer3 uses SYSCLK/12TMR3RL = -(SYSCLK/12/40); // Timer3 configured to overflow afterTMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect):// 1/.025 = 40EIE1 |= 0x80; // Timer3 interrupt enableTMR3CN |= 0x04; // Start Timer3}void Enb_Interrupt(void){EIE1 |= 0x01; // Enable the SMBus interruptEA = 1; // Global interrupt enable}#else#warning "iic interface undefined."#endif#include <..>#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* 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 hereunsigned char SMBus_DATA_OUT[2]; // Global holder for SMBus data.// All transmit data is read from hereunsigned char COMMAND,num[2]; // Target SMBus slave addressbit SMBus_BUSY; // Software flag to indicate when the// SMB_Read() or SMB_Write() functions// have claimed the SMBusbit 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 errorvoid Check_SDA(void){uchar i; // Dummy variable counterswhile(!SDA){// Provide clock pulses to allow the slave to advance out// of its current state. This will allow it to release 1 = 0x40; // Enable CrossbarSCL = 0; // Drive the clock low

for(i = 0; i < 255; i++); // Hold the clock lowSCL = 1; // Release the clockwhile(!SCL); // Wait for open-drain// clock output to risefor(i = 0; i < 10; i++); // Hold the clock highXBR1 = 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 _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 transferwhile(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 _BUSY = 1; // Claim SMBus (set to busy)COMMAND = wrDAdr;

num[1] = Num;SMBus_WR = 1;STO = 0;STA = 1; // Start transferwhile(SMBus_BUSY); // Wait for transfer to completefor(i=0;iData[i] = SMBus_DATA_IN[i];}void SMBus_ISR(void) interrupt 7{bit FAIL = 0; // Used by the ISR to flag failed transfersstatic uchar sent_byte_counter,rec_byte_counter;if (ARBLOST == 0) // Check for errors{// Normal operationswitch (SMB0CN & 0xF0) // Status vector{// Master Transmitter/Receiver: START condition SMBus_MTSTA:{SMB0DAT = COMMAND; // Load address of the target slaveSTA = 0; // Manually clear START bitsent_byte_counter = 1;rec_byte_counter = 1;break;}// Master Transmitter: Data byte transmittedcase SMBus_MTDB:{if (ACK) // Slave ACK?{if (SMBus_WR == WRITE) // If this transfer is a WRITE,{if (sent_byte_counter <= num[0])

{// send data byteSMB0DAT = SMBus_DATA_OUT[sent_byte_counter-1];sent_byte_counter++;}else{STO = 1; // Set STO to terminate transferSMBus_BUSY = 0; // And free SMBus interface}}}else // If slave NACK,{STO = 1; // Send STOP condition, followedSTA = 1; // By a START}break;}// Master Receiver: byte receivedcase SMBus_MRDB:{if (rec_byte_counter < num[1]){SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byteACK = 1; // Send ACK to indicate byte receivedrec_byte_counter++; // Increment the byte counter}else{SMBus_DATA_IN[rec_byte_counter-1] = SMB0DAT; // Store received byteSMBus_BUSY = 0; // Free SMBus interfaceACK = 0; // Send NACK to indicate last byte of this transferSTO = 1; // Send STOP to terminate transfer

}break;}default:{FAIL = 1; // Indicate failed transfer and handle at end of ISRbreak;}} // end switch}else{// ARBLOST = 1, abort transmissionFAIL = 1;} // end ARBLOST ifif (FAIL) // If the transfer failed,{SMB0CF &= ~0x80; // Reset communicationSMB0CF |= 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 SMBusSMB0CF |= 0x80; // Re-enable SMBusTMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flagSTA = 0;SMBus_BUSY = 0; // Free SMBus}

#endif /*_WS_IIC_H_*/