首页 C8051F040的SMBus程序1

C8051F040的SMBus程序1

举报
开通vip

C8051F040的SMBus程序1 //----------------------------------------------------------------------------- // F04x_SMBus_EEPROM.c //----------------------------------------------------------------------------- // Copyright 2006 Silicon Laboratories, Inc. // http://www.silabs.co...

C8051F040的SMBus程序1
//----------------------------------------------------------------------------- // F04x_SMBus_EEPROM.c //----------------------------------------------------------------------------- // Copyright 2006 Silicon Laboratories, Inc. // http://www.silabs.com // // Program Description: // // This example demonstrates how the C8051F04x SMBus interface can communicate // with a 256 byte I2C Serial EEPROM (Microchip 24LC02B). // - Interrupt-driven SMBus implementation // - Only master states defined (no slave or arbitration) // - Timer4 used by SMBus for SCL low timeout detection // - SCL frequency defined by constant // - Pinout: // P0.0 -> SDA (SMBus) // P0.1 -> SCL (SMBus) // // P1.6 -> LED // // all other port pins unused // // How To Test: // // 1) Download code to a 'F04x device that is connected to a 24LC02B serial // EEPROM (see the EEPROM datasheet for the pinout information). // 2) Run the code: // a) the test will indicate proper communication with the EEPROM by // turning on the LED at the end the end of the test // b) the test can also be verified by running to the if statements // in main and checking the sent and received values by adding // the variables to the Watch Window // // FID: 04X000009 // Target: C8051F04x // Tool chain: Keil C51 7.50 / Keil EVAL C51 // Command Line: None // // Release 1.0 // -Initial Revision (TP) // -20 APR 2006 // //----------------------------------------------------------------------------- // Includes //----------------------------------------------------------------------------- Administrator 线条 #include // SFR declarations //----------------------------------------------------------------------------- // Global CONSTANTS //----------------------------------------------------------------------------- #define SYSCLK 3062500L // System clock frequency in Hz #define SMB_FREQUENCY 10000L // Target SCL clock rate // This example supports between 10kHz // and 100kHz #define WRITE 0x00 // WRITE direction bit #define READ 0x01 // READ direction bit // Device addresses (7 bits, lsb is a don't care) #define EEPROM_ADDR 0xA0 // Device address for slave target // Note: This address is specified // in the Microchip 24LC02B // datasheet. #define MY_ADDR 0x02 // Address of this SMBus device // (dummy value since this device does // not have any defined slave states) // SMBus Buffer Size #define SMB_BUFF_SIZE 0x08 // Defines the maximum number of bytes // that can be sent or received in a // single transfer #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; Administrator 线条 Administrator 线条 // ACK transmitted #define SMB_MRDBNACK 0x58 // (MR) data byte rec'vd; // NACK transmitted //----------------------------------------------------------------------------- // Global VARIABLES //----------------------------------------------------------------------------- unsigned char* pSMB_DATA_IN; // Global pointer for SMBus data // All receive data is written here unsigned char SMB_SINGLEBYTE_OUT; // Global holder for single byte writes. unsigned char* pSMB_DATA_OUT; // Global pointer for SMBus data. // All transmit data is read from here unsigned char SMB_DATA_LEN; // Global holder for number of bytes // to send or receive in the current // SMBus transfer. unsigned char WORD_ADDR; // Global holder for the EEPROM word // address that will be accessed in // the next transfer unsigned char TARGET; // Target SMBus slave address bit SMB_BUSY = 0; // Software flag to indicate when the // EEPROM_ByteRead() or // EEPROM_ByteWrite() // functions have claimed the SMBus bit SMB_RW; // Software flag to indicate the // direction of the current transfer bit SMB_SENDWORDADDR; // When set, this flag causes the ISR // to send the 8-bit // after sending the slave address. bit SMB_RANDOMREAD; // When set, this flag causes the ISR // to send a START signal after sending // the word address. // For the 24LC02B EEPROM, a random read // (a read from a particular address in // memory) starts as a write then // changes to a read after the repeated // start is sent. The ISR handles this // switchover if the // bit is set. bit SMB_ACKPOLL; // When set, this flag causes the ISR // to send a repeated START until the // slave has acknowledged its address // 16-bit SFR declarations sfr16 RCAP4 = 0xCA; // Timer4 reload registers sfr16 TMR4 = 0xCC; // Timer4 counter registers sbit LED = P1^6; // LED on P1.6 sbit SDA = P0^0; // SMBus on P0.0 sbit SCL = P0^1; // and P0.1 //----------------------------------------------------------------------------- // Function PROTOTYPES //----------------------------------------------------------------------------- void SYSCLK_Init(void); void Port_Init(void); void SMBus_Init(void); void Timer4_Init(void); void SMBus_ISR(void); void Timer4_ISR(void); void EEPROM_ByteWrite(unsigned char addr, unsigned char dat); void EEPROM_WriteArray(unsigned char dest_addr, unsigned char* src_addr, unsigned char len); unsigned char EEPROM_ByteRead(unsigned char addr); void EEPROM_ReadArray(unsigned char* dest_addr, unsigned char src_addr, unsigned char len); //----------------------------------------------------------------------------- // MAIN Routine //----------------------------------------------------------------------------- void MAIN (void) { char in_buff[8] = {0}; // Incoming data buffer char out_buff[8] = "ABCDEFG"; // Outgoing data buffer unsigned char temp_char; // Temporary variable bit error_flag = 0; // Flag for checking EEPROM contents unsigned char i; // Temporary counter variable WDTCN = 0xde; // Disable watchdog timer WDTCN = 0xad; SYSCLK_Init (); // Set internal oscillator to a setting // of 3062500 Hz // If slave is holding SDA low because of an improper SMBus reset or error 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 } Port_Init (); // Initialize Crossbar and GPIO // Turn off the LED before the test starts LED = 0; SMBus_Init (); // Configure and enable SMBus Timer4_Init (); // Configure and enable Timer4 EIE1 |= 0x02; // Enable the SMBus interrupt EA = 1; // Global interrupt enable SFRPAGE = SMB0_PAGE; SI = 0; // Read and write some bytes to the EEPROM and check for proper // communication // Write the value 0xAA to location 0x25 in the EEPROM EEPROM_ByteWrite(0x25, 0xAA); // Read the value at location 0x25 in the EEPROM temp_char = EEPROM_ByteRead(0x25); // Check that the data was read properly if (temp_char != 0xAA) { error_flag = 1; } // Write the value 0xBB to location 0x25 in the EEPROM EEPROM_ByteWrite(0x25, 0xBB); // Write the value 0xCC to location 0x38 in the EEPROM EEPROM_ByteWrite(0x38, 0xCC); // Read the value at location 0x25 in the EEPROM temp_char = EEPROM_ByteRead(0x25); // Check that the data was read properly if (temp_char != 0xBB) { error_flag = 1; } // Read the value at location 0x38 in the EEPROM temp_char = EEPROM_ByteRead(0x38); // Check that the data was read properly if (temp_char != 0xCC) { error_flag = 1; } // Store the outgoing data buffer at EEPROM address 0x50 EEPROM_WriteArray(0x50, out_buff, sizeof(out_buff)); // Fill the incoming data buffer with data starting at EEPROM address 0x50 EEPROM_ReadArray(in_buff, 0x50, sizeof(in_buff)); // Check that the data that came from the EEPROM is the same as what was // sent for (i = 0; i < sizeof(in_buff); i++) { if (in_buff[i] != out_buff[i]) { error_flag = 1; } } // Indicate communication is good if (error_flag == 0) { // LED = ON indicates that the test passed LED = 1; } while(1); } //----------------------------------------------------------------------------- // Initialization Routines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // SYSCLK_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // This routine initializes the system clock to use the internal oscillator // at 3.0625 MHz (24.5 / 8 MHz). // void SYSCLK_Init (void) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = CONFIG_PAGE; // Set SFR page OSCICN = 0x80; // Set internal oscillator to run // at 1/8 its maximum frequency CLKSEL = 0x00; // Select the internal osc. as // the SYSCLK source SFRPAGE = SFRPAGE_SAVE; // Restore SFR page // detector } //----------------------------------------------------------------------------- // PORT_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Configure the Crossbar and GPIO ports. // // P0.0 digital open-drain SMBus SDA // P0.1 digital open-drain SMBus SCL // // P1.6 digital push-pull LED // // all other port pins unused // // Note: If the SMBus is moved, the SCL and SDA sbit declarations must also // be adjusted. // void PORT_Init (void) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = CONFIG_PAGE; P0MDOUT = 0x00; // All P0 pins open-drain output P1MDOUT |= 0x40; // Make the LED (P1.6) a push-pull // output XBR0 = 0x01; // Enable SMBus on the crossbar XBR2 = 0x40; // Enable crossbar and weak pull-ups P0 = 0xFF; SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector } //----------------------------------------------------------------------------- // SMBus_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // The SMBus peripheral is configured as follows: // - SMBus enabled // - Assert Acknowledge low (AA bit = 1b) // - Free and SCL low timeout detection enabled // void SMBus_Init (void) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = SMB0_PAGE; SMB0CN = 0x07; // Assert Acknowledge low (AA bit = 1b); // Enable SMBus Free timeout detect; // Enable SCL low timeout detect // SMBus clock rate (derived approximation from the Tlow and Thigh equations // in the SMB0CR register description) SMB0CR = 257 - (SYSCLK / (2 * SMB_FREQUENCY)); SMB0ADR = MY_ADDR; // Set own slave address. SMB0CN |= 0x40; // Enable SMBus; SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector } //----------------------------------------------------------------------------- // Timer4_Init //----------------------------------------------------------------------------- // // Return Value : None // Parameters : None // // Timer4 configured for use by the SMBus low timeout detect feature as // follows: // - Timer4 in auto-reload mode // - SYSCLK/12 as Timer4 clock source // - Timer4 reload registers loaded for a 25ms overflow period // - Timer4 pre-loaded to overflow after 25ms // - Timer4 enabled // void Timer4_Init (void) { char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page SFRPAGE = TMR4_PAGE; TMR4CN = 0x00; // Timer4 external enable off; // Timer4 in timer mode; // Timer4 in auto-reload mode TMR4CF = 0x00; // Timer4 uses SYSCLK/12 // Timer4 output not available // Timer4 counts up RCAP4 = -(SYSCLK/12/40); // Timer4 configured to overflow after TMR4 = RCAP4; // ~25ms (for SMBus low timeout detect) EIE2 |= 0x04; // Timer4 interrupt enable TR4 = 1; // Start Timer4 SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector } //----------------------------------------------------------------------------- // Interrupt Service Routines //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // SMBus Interrupt Service Routine (ISR) //----------------------------------------------------------------------------- // // SMBus ISR state machine // - Master only implementation - no slave states defined // - All incoming data is written starting at the global pointer // - All outgoing data is read from the global pointer // void SMBUS_ISR (void) interrupt 7 { bit FAIL = 0; // Used by the ISR to flag failed // transfers static char i; // Used by the ISR to count the // number of data bytes sent or // received static bit SEND_START = 0; // Send a start // Status code for the SMBus (SMB0STA register) switch (SMB0STA) { // Master Transmitter/Receiver: START condition transmitted. // Load SMB0DAT with slave device (EEPROM) address. case SMB_START: SMB0DAT = TARGET; // Load address of the slave. SMB0DAT &= 0xFE; // Clear the LSB of the address for the // R/W bit SMB0DAT |= SMB_RW; // Load R/W bit STA = 0; // Manually clear STA bit i = 0; // reset data byte counter break; // Master Transmitter/Receiver: Repeated START condition transmitted. // For a READ: This state only occurs during an EEPROM read operation // for the EEPROM's "random read", where a write operation with the // data address must be done before the read operation. // // For a WRITE: N/A case SMB_RP_START: SMB0DAT = TARGET; // Load address of the slave. SMB0DAT |= SMB_RW; // Load R/W bit STA = 0; // Manually clear START bit. i = 0; // reset data byte counter break; // Master Transmitter: Slave address + WRITE transmitted. ACK received. // For a READ or WRITE: the word (data) address in the EEPROM must now // be sent after the slave address case SMB_MTADDACK: SMB0DAT = WORD_ADDR; // Send word address if (SMB_RANDOMREAD) { SEND_START = 1; // Send a START after the next ACK cycle SMB_RW = READ; } break; // Master Tra
本文档为【C8051F040的SMBus程序1】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_203055
暂无简介~
格式:pdf
大小:196KB
软件:PDF阅读器
页数:20
分类:互联网
上传时间:2012-10-09
浏览量:34