0
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心
发布
  • 发文章

  • 发资料

  • 发帖

  • 提问

  • 发视频

创作活动
AN113

AN113

  • 厂商:

    SILABS(芯科科技)

  • 封装:

  • 描述:

    AN113 - SERIAL COMMUNICATION WITH THE SMBUS - Silicon Laboratories

  • 数据手册
  • 价格&库存
AN113 数据手册
A N 113 S E R I A L C O M M U N I C A T I O N W I T H T H E S MB U S Relevant Devices This application note applies to the following devices: C8051F000, C8051F001, C8051F002, C8051F005, C8051F006, C8051F010, C8051F011, C8051F012, C8051F020, C8051F021, C8051F022, and C8051F023. nizes its own address and responds, it becomes the slave device for that transfer. It is important to note that assigning one specified master device is not necessary. Any device may assume the role of master or slave for any particular transfer. In the case that two devices attempt to initiate a transfer simultaneously, an arbitration scheme forces one device to give up the bus. This arbitration scheme is nondestructive (one device wins and no information is lost). Arbitration is discussed in depth in the arbitration section. Two wires are used in SMBus communication: SDA (serial data), and SCL (serial clock). Each line is bi-directional, with direction depending on what modes the devices are in. The master always supplies SCL; either device may transmit on SDA. Both lines should be connected to a positive power supply through a pull-up circuit. All devices on the SMBus line should have an open-drain or open collector output, so that the lines may remain high when the bus is free. The line is pulled low if one or more devices attempts to output a LOW signal. All devices must output a HIGH for the line to stay high. A typical SMBus configuration is shown in Figure 1 on page 2. Introduction C8051F0xx devices are equipped with an SMBus serial I/O device that is compliant with the System Management Bus Specification version 1.1, as well as the I2C serial bus. The SMBus is a bi-directional, 2-wire interface capable of communication with multiple devices. SMBus is a trademark of Intel; I2C is a trademark of Philips Semiconductor. This application note describes configuration and operation of the SMBus. Example assembly and C code is given: (1) Interfacing a single EEPROM with 1-byte address space, in assembly; (2) Interfacing multiple EEPROMs with 2-byte address space, in C; and (3) Peer-to-peer communication between two C8051F0xx devices, in C. SMBus Specification This section presents a description of the SMBus protocol. The SMBus discussion begins in the next section--Using the SMBus. SMBus Structure An SMBus system is a 2-wire network, where each device has a unique address and may be addressed by any other device on the network. All transfers are initiated by a master device; if a device recogRev. 1.3 12/03 Copyright © 2003 by Silicon Laboratories AN113-DS13 A N11 3 VDD = +5V/+3V Device 1 SDA SCL Device 2 Device 3 Figure 1. Typical SMBus Configuration Handshaking SMBus employs various line conditions as handshaking between devices. Note that during a data transfer, SDA is only allowed to change levels while SCL is low. Changes on SDA while SCL is high represent START and STOP signals, as follows: START: This initiates a transfer. It consists of a falling edge on SDA while SCL is high. When a receiving device fails to ACK, the sending device sees a NACK. In typical transfers, a received NACK indicates that the addressed slave is not ready for transfer, or is not present on the bus. A receiving master may transmit a NACK to indicate the last byte of a transfer. Both of these situations are discussed further in the next section. Figure 2 illustrates the handshaking signals. Transfer Modes Two types of transfers are possible: a WRITE STOP: This ends a transfer. It consists of a rising (transfer from master to slave) and a READ (transedge on SDA while SCL is high. fer from slave to master). During a transfer, any device may assume one of four roles. These four ACKNOWLEDGE: Also referred to as an ACK, roles are explained below. Note that ‘slave address this is transmitted by a receiving device as a confir- + R/W’ refers to an 8 bit transfer (7 address, 1 R/ mation. For example, after device_X receives a W). byte, it transmits an ACK to confirm the transfer. An ACK consists of a low level on SDA sampled 1) Master Transmitter: In this mode, the device when SCL is high. transmits serial data on SDA and drives the clock on SCL. The device initiates the transfer with a NOT_ACKNOWLEDGE: Also referred to as a START condition, sends the slave address + W, and NACK, this is a high SDA while SCL is high. waits for an ACK from the slave. After the ACK, SCL SDA SLA6 SLA5-0 R/W D7 D6-0 START Slave Address + R/W ACK Data Byte NACK STOP Figure 2. SMBus Timing 2 Rev. 1.3 A N113 the device transmits one or more bytes of data, with the last byte, the master will issue a NACK foleach byte ACK’ed by the slave. After the last byte, lowed by a STOP. the device transmits a STOP. 4) Slave Receiver: In this role, a device receives a 2) Master Receiver: In this role, the device receives START followed by its own slave address + W serial data on SDA while driving the clock on SCL. from a master device. The device sends an ACK The device initiates the transfer with a START fol- and enters slave receiver mode. The device now lowed by the slave address + R. After the slave receives serial data on SDA and the clock on SCL. ACK’s the address, the device will output the clock The device ACK’s after each byte is received, and on SCL, and receive data on SDA. After the last exits slave mode after the master issues a STOP. byte, the device will issue a NACK followed by a Figure 3 shows the typical WRITE scenarios. (1) STOP. shows a successful transfer. 3) Slave Transmitter: In this role, a device outputs serial data on SDA and receives the clock on SCL. The device receives a START followed by its own slave address + R, then ACK’s, and enters slave transmitter mode. The device transmits serial data on SDA and receives an ACK after each byte. After In (2), the master receives a NACK after sending the slave address + W. This occurs when a slave is ‘offline’, meaning it is not responding to its own address. In this case, the master should issue a STOP or repeated START. To retry the transfer, the master follows the STOP with a START and the slave address + W again. The master will repeat the (1) Successful WRITE S SLA + W A Data A Data AP (2) NACK received after SLA + W AP (3) Repeat start issued after Acknowledge S SLA + R A (4) NACK received after data AP S = Start SLA = Slave Address (7 bits) W = Write (1 bit) R = Read (1 bit) Data = Serial data (8 bits) A = Acknowledge A = Not-Acknowledge P = Stop From Master to Slave From Slave to Master Data Any number of data bytes and acknowledges Figure 3. Typical WRITE Transfer Scenarios Rev. 1.3 3 A N11 3 cycle until it receives an ACK. This is referred to as master receives a NACK after sending the slave “acknowledge polling”. address + R. This situation is handled in the same fashion as in (2) of the WRITE discussion. The In (3), the master issues a repeated START after an master can use acknowledge polling to retry the ACK. This process allows the master to initiate a transfer, or it can give up the transfer. (3) Shows the new transfer without giving up the bus (to switch master sending a repeated START after sending a from a WRITE to a READ, for example). The byte of data. This is the same repeated START state repeated START is commonly used in EEPROM as in the WRITE discussion. A master may send a memory access applications, where a memory repeated START after any data byte, and may iniREAD must be directly preceded by a WRITE of tiate a READ or a WRITE following the repeated the desired memory location. The repeated START START. Generally a repeated START is used to is demonstrated in all three code examples. change direction (R/W) or to change addresses (slave devices). In (4), a NACK is received after a data byte. In typical SMBus systems, this is how the receiving Note that the READ and WRITE diagrams show device indicates an error. The master sends a STOP, only the typical scenarios. Bus errors, time outs, and retries the transfer as in (2), or gives up the and arbitration are also possible occurrences. Timetransfer. Note that the use of NACKs is not outs are used to detect when a transfer has stalled restricted to error situations; the acknowledge level or when the bus is free. Often a device may hold is a user-definable characteristic, and may vary in SCL low until it is ready to continue a transfer. This different applications. process allows a slower slave device to communicate with a faster master, since stalling the bus Figure 4 shows the typical READ scenarios. (1) effectively reduces the SCL frequency. The SMBus shows a successful READ operation. In (2), the protocol specifies that all devices on the SMBus (1) Successful READ S SLA + R A Data A Data AP (2) NACK received after SLA + R AP (3) Repeat start issued after ACK S SLA + R A S = Start SLA = Slave Address (7 bits) W = Write (1 bit) R = Read (1 bit) Data = Serial data (8 bits) A = Acknowledge A = Not-Acknowledge P = Stop From Master to Slave From Slave to Master Data Any number of data bytes and acknowledges Figure 4. Typical Read Scenarios 4 Rev. 1.3 A N113 must declare any SCL signal held low for more than 25 ms a “timeout”. In this case, all devices on the bus must reset communication. A high SCL timeout may also occur. If both SDA and SCL remain high for more than 50 µsec, the bus is designated as free. Using the SMBus The SMBus can operate in both master and slave modes. The hardware provides timing and shifting control for the serial transfers; byte-wise control is user-defined. The SMBus hardware performs the following application-independent tasks: Timing Control: In master mode, the hardware generates the clock signal on SCL and synchronizes the data on SDA. Hardware also recognizes timeouts and bus errors. Arbitration If multiple masters are configured on the same SMBus system, it is possible that two will attempt to initiate a transfer at the same time. If this happens, an arbitration scheme is employed to force one device to give up the bus. Serial Data Transfers: The hardware controls all shifting of data to and from SDA, including the What the scheme is: both masters continue to trans- acknowledge level. The acknowledge level is usermit until one attempts a HIGH while the other defined, as explained in the register definitions attempts a LOW. Due to the open-drain bus, the below. device attempting a LOW will win the bus. The HIGH device gives up the bus, and the other device Slave Address Recognition: The hardware recogcontinues its transfer. Note that the collision is non- nizes a START from another device, and reads the destructive: one device always wins. following slave address. If the slave address matches the contents of the SMBus Address RegisHow it works: Assume device_X and device_Y ter (defined below), then the hardware acknowlcontend for the bus. The winner, device_X, is not edges the address. Note that this features is only affected at all by the arbitration. Since data is enabled if AA (Address Acknowledge) is set. shifted into the SMBus data register as it is shifted out, device_Y does not miss any data. Figure 5 Configuration and Control shows an example output sequence between two devices during arbitration. Note that Device_Y SMBus operation is determined by the contents of the following registers. begins receiving data after it gives up the bus. Figure 5. Arbitration Sequence Device_X 1 Device_Y 1 Seen on the Bus 0 1 1 1 0 1 1 0 1 1 0 1 0 1 1 0 Device_Y gives up the bus 1 1 0 Rev. 1.3 5 A N11 3 SMB0STA. The SMBus Status Register holds an 8-bit status code for the current state of the SMBus. The contents of SMB0STA are only defined when the SI bit is set. There are 28 possible states, all of which have a unique code (the codes are multiples of 8). SMB0STA should never be written to. The 28 possible states and their descriptions are given in Table 1 on page 12. The SMBus is enabled by setting the SMBus enable bit, ENSMB. SMB0CR. The SMBus clock register is used to control the SCL clock rate when the device is in master mode. The 8 bits held in the SMB0CR register determine the clock rate as follows: SYSCLK SMB0CN. The SMBus control register is used to SMB0CR ≅ – -----------------------2 × F SCL enable the SMBus and navigate the possible SMBus states. This register includes START and Where SMB0CR is a 2’s complement negative STOP control, as well as interrupt, acknowledge, number. So for a SCL frequency of 100 kHz and a and timeout control. SYSCLK of 16 MHz, SMB0CL should be loaded with -80, or 0xB0. A transfer is initiated by setting the STA bit. The SMBus hardware will wait until the bus is free, SMB0CR also defines the limit for the bus free then transmit a START. Note that STA is not time period (high SCL timeout). The bus free time cleared by hardware. User software must manuis defined by the following equation, where ally clear STA so that an unwanted repeated SMB0CR is a 2’s complement negative number. START is not generated. User software must also Note that TFree is about 5 bit periods. manually clear STO prior to setting STA. A transfer is ended by setting the STO bit. In master mode, setting STO will cause a STOP condition to be generated. If STA is set when STO is set, a STOP followed by a START will be transmitted. In slave mode, setting STO will cause the hardware to act as if a STOP was received, though no STOP condition is transmitted. The SI bit is set when any of the possible 28 SMBus states are entered (excluding the idle state). This bit is not automatically cleared by hardware. Note that SCL is held low while SI is set. This means that the bus is stalled until SI is cleared, synchronizing the master with the slave. The AA bit determines the type of acknowledge returned during the acknowledge cycle. If AA=1, an ACK will be sent; if AA=0, a NACK will be sent. This means the device will respond to its slave address only if AA is set. SCL high and low timeout detection is enabled by setting the FTE and TOE bits, respectively. T Free = – ( 10 × SMB0CR ) + 1 ----------------------------------------------------SYSCLK SMB0ADR. The SMBus Address Register holds the slave address that the device will respond to in slave mode. Bits(7:1) hold the slave address; bit0 is the General Call Enable. If bit0 is set, the device will respond to the general call address (0x00). SMB0DAT. The SMBus Data Register is used to hold data to be transmitted or data that has just been received by the SMBus. Data read from this register is only valid while SI = 1. When SI is not set, the SMBus may be in the process of shifting data in or out of SMB0DAT. Note that when transmitting, data shifted out of the most significant bit of SMB0DAT is shifted back into the least significant bit, so that after a transmit the original data is still contained in SMB0DAT. 6 Rev. 1.3 A N113 Implementation Choices User software controls the SMBus on a state-bystate basis. Upon each state change, the SI bit is set by hardware, and an interrupt generated if interrupts are enabled. The SMBus is then halted until user software services the state change and clears the SI bit. The SMBus operation is most easily defined in a state table; however, note that it is not necessary to define all 28 states. For example, if the SMBus is the only master in the system, the slave and arbitration states may be left undefined. If the SMBus will never operate as a master, the master states may be left undefined. If states are left undefined, a default response should be programmed to account for unexpected or error situations. The SMBus state table lends itself to a case-switch statement definition in C. However, for simple or time-restricted systems, an assembly state decoding can be more efficient. Note that the status codes held in SMB0STA are multiples of 8. If the SMBus states are programmed in 8-byte segments, SMB0STA may be used as a software index. In this case, a status code is decoded in 3 assembly commands. However, only 8 bytes of code space are available for each state definition. For states that require more than 8 bytes, the program must branch out of the state table so that subsequent states are not disturbed. The Send operation is a 1-byte random WRITE. The SMBus sends a START followed by three bytes: the EEPROM’s device address + W (this address is found in the EEPROM datasheet), the memory location to be written, and then the data byte. The slave should ACK after each byte. If the master receives an ACK after each byte, it sends a STOP and the transfer is over. If at any time the master receives a NACK, it will retry the transfer using acknowledge polling. It is common for an EEPROM to NACK if multiple read/write operations are performed sequentially, since most selftimed EEPROMs go offline to actually perform the memory write. Figure 6 shows SDA for the Single EEPROM send operation. Figure 6. Single EERPOM Send Sequence S SLA WA 8-bit Address A Data Byte AP Examples Three examples are provided: a single EEPROM with 1-byte address space, in assembly; multiple EEPROMs with 2-byte address space, in C; and a peer-to-peer interface between two devices, in C. Each example uses interrupt-driven operation. The Receive operation is a 1-byte random READ. The transfer begins, as in the WRITE function, with the master sending a START followed by the EEPROM device address + W (a WRITE is used to set the EEPROM’s “current address”). After the slave ACK’s, the master sends the memory location to be read. Upon receipt of an ACK, the master then issues a repeated START followed by the slave address + R. Now after the slave ACK’s, it will send the data byte read from the location given in the preceding “aborted” WRITE. The master sends a NACK (since this data is the last and only byte), followed by a STOP. The repeated START is used in this case so that no other transfers may begin between the WRITE of the memory address and the READ of the data byte. Figure 7 shows SDA for a Single EEPROM Receive operation. Single EEPROM The software for this example was written in assembly to demonstrate the advantage of using This is a simple interface between the SMBus and a 256-byte EEPROM. The SMBus acts as the master SMB0STA as a software index. The SMBus state at all times. The transfer procedure is similar to that table written in 8-byte memory segments (8 bytes for each state). This is accomplished through the of any 2-wire EEPROM interface. use of an ‘org’ statement for each state, offset from the beginning of the table by the corresponding sta- Rev. 1.3 7 A N11 3 tus code. For example, if the state table is labeled This process allows for very efficient state decodSTATE_TABLE, and State_1 is 0x08, the code seg- ing. However, it is important to note that only 8 ment for State_1 should begin with: bytes of code space are available for each state. If a state requires more than 8 bytes, the program must ; State_1 jump to a segment outside of the state table, so that org STATE_TABLE + 08h the next state definition is not disturbed. ; State_1 code Now when SMB0STA holds 0x80, State_1 may be To keep the states simple and understandable, the accessed with the following: SMBus is assumed to be the only master in the system. The slave states are not defined, and the arbi; Load current State tration states ignore any received data. Also, the mov A, SMB0STA; repeated START state may assume the transfer is a ; Point DPTR to start of table READ. The code listing begins on page 14. mov DPTR, #STATE_TABLE; ; Jump to indexed state jmp @A+DPTR; Figure 7. Single EEPROM Receive Sequence S SLA WA 8-bit Address AS SLA RA Data Byte NP . Figure 8. Multiple EEPROM Receive Sequence S SLA WA High Low Address AS A Address Byte Byte SLA RA Data Byte NP 8 Rev. 1.3 A N113 Multiple EEPROMs Example 2 uses multiple EEPROMs with 2-byte address space. The software is written in C. The three EEPROMs used are 8k-bytes. Note that three identical EEPROMs are used. The EEPROMs have three address selection pins, A0 - A2, that are used to set the slave address for the devices. The four high bits of the device address are set in EEPROM to “0101”; the lower three bits of the slave address are determined by the setting of the address pins (VDD for 1, GND for 0). Figure 9 shows the device configuration. The distinction with this example is that the EEPROMs have a 2-byte address space. This means that the READ and WRITE operations must send an extra address byte for each transfer (see Figure 8) When the Interrupt Service Routine reaches the “Data Transmitted, ACK Received” state, it must know which byte was transmitted--the high address byte, the low address byte, or the data byte. This information is kept in the BYTE_NUMBER state variable. The SMBus ISR is implemented as a case-switch statement, with the SMBus status code (SMB0STA) used as the switch variable. The code listing for this example begins on page 23. VDD A2 VDD CHIP_A 2.7k 2.7k Addr = 000 CHIP_B Addr = 001 A1 A0 A2 A1 A0 VDD A2 A1 A0 CF000 SDA SCL CHIP_C Addr = 010 Figure 9. Multiple EEPROM Configuration Rev. 1.3 9 A N11 3 Peer-to-Peer Interface The final example features two C8051F0xx devices configured to communicate as peers. The peer-topeer interface uses a set of op codes to perform the set of tasks below. Either device may initiate a transfer. Write to slave DAC: The master device sends a WRITE_DAC op code followed by a byte of data. Upon receipt, the slave device writes the data to its DAC0 port. Write to buffer: The master device sends a WRITE_BUF op code, followed by a byte of data for the receiving device to store in a buffer. The upper 4 bits of the WRITE_BUF op code hold the buffer index. Figure 10 shows a peer-to-peer WRITE sequence (same for both DAC and buffer writes). Figure 10. Peer-to-Peer Write Sequence S SLA WA Write Op Code A Data Byte AP START. The slave reads its ADC input, and places the data in its SMB0DAT register. In this case, the slave clears AA to go ‘offline’ during the ADC conversion. While the slave is offline, the master receives a NACK after the repeated START and slave address. The master continues acknowledge polling until the slave responds. This technique is useful if the slave’s operation is time-consuming, since other devices may use the bus while the slave is offline. The slave sets AA=1 when it is ready, and the transfer continues. The master requests a READ after the slave acknowledges. See Figure 11 for the transmission sequence. Read buffer: The master sends a READ_BUF op code followed by a repeated START. The upper 4 bits of the op code hold the buffer index. In this case the slave holds the SCL line low while it decodes the op code. While SCL is held low, the master cannot attempt to continue the transfer. Additionally, no other masters on the bus may attempt a transfer. This bus stalling technique is useful when the slave’s delay is short. The slave releases SCL when it has finished decoding the op code and is ready to transmit the data. The master issues the repeated START and the slave address + R. See Figure 11. Bus stalled here until slave decodes the Op Code The SMBus operation in this example is defined as Read ADC: The master device sends a a case-switch statement in the SMBus ISR. All posREAD_ADC op code followed by a repeated sible states are defined, including the arbitration states. If arbitration occurs, the losing device stores Figure 11. Peer-to-Peer Read Sequence Buffer Read S SLA WA Read_Buf Op Code A S SLA RA Data Byte NP Bus stalled here until slave decodes the Op Code ADC Read S SLA WA Read ADC Op Code AS SLA RA Data Byte NP Slave goes 'offline' here until ADC conversion is complete. 10 Rev. 1.3 A N113 its current transfer data (target slave address, op code, relevant data) and responds to the received op code. After the transfer is finished, the losing device retries the transfer by reverting to the saved transfer data. An OP_CODE_HANDLER function runs in polled mode to process received data. When the device receives a valid op code, the OP_CODE_HANDLER decodes it and reacts appropriately. To test the bus, comment out the OP_CODE_HANDLER call in the code for CHIP_A. This will allow CHIP_A to run the provided test code. Note that the constant MY_ADD must be unique to each device on the bus. The code listing for this example begins on page 29. Rev. 1.3 11 A N11 3 Table 1. SMBus Status Codes and States Mode Status Code 0x08 SMBus State START condition transmitted. Repeated START condition transmitted. Slave Address + W transmitted. ACK received. Slave Address + W transmitted. NACK received. Data byte transmitted. ACK received. Typical Action Load SMB0DAT with Slave Address + R/W Load SMB0DAT with Slave Address + R/W Load SMB0DAT with data to be transmitted. Clear STA Acknowledge poll to retry. Set STO + STA 1) Load SMB0DAT with next byte, OR 2) Set STO, OR 3) Clear STO, then set STA for repeated START 1) Retry transfer OR 2) Set STO Save current data Clear STA. Wait for received data. Acknowledge poll to retry. Set STO + STA Read SMB0DAT. Wait for next byte. If next byte is last byte, clear AA Set STO MT/ MR Master Transmitter 0x10 0x18 0x20 0x28 0x30 0x38 Data byte transmitted. NACK received. Arbitration Lost. Slave Address + R transmitted. ACK received. Slave Address + R transmitted. NACK received. Data byte received. ACK transmitted. Data byte received. NACK transmitted. Master Receiver 12 0x40 0x48 0x50 0x58 Rev. 1.3 A N113 Table 1. SMBus Status Codes and States Mode Status Code 0x60 0x68 SMBus State Own slave address + W received. ACK transmitted. Arbitration lost in sending SLA + R/W as master. Own address + W received. ACK transmitted. General call address received. ACK transmitted. Arbitration lost in sending SLA + R/W as master. General call address received. ACK transmitted. Data byte received. ACK transmitted. Data byte received. NACK transmitted. Data byte received after general call address. ACK transmitted. Data byte received after general call address. NACK transmitted. STOP or repeated START received. Own address + R received. ACK transmitted. Arbitration lost in transmitting SLA + R/W as master. Own address + R received. ACK transmitted. Data byte transmitted. ACK received. Data byte transmitted. NACK received. Last data byte transmitted (AA=0). ACK received. SCL Clock High Timer per SMB0CR timed out Bus Error (illegal START or STOP) Idle Typical Action Wait for data Save current data for retry when bus is free. Wait for data Wait for data Save current data for retry when bus is free. Read SMB0DAT. Wait for next byte or STOP Set STO to reset SMBus Read SMB0DAT. Wait for next byte or STOP Set STO to reset SMBus No action necessary Load SMB0DAT with data to transmit. Save current data for retry when bus is free. Load SMB0DAT with data to transmit. Load SMB0DAT with data to transmit. Wait for STOP Set STO to reset SMBus 0x70 Slave Receiver Slave Transmitter Slave 0x78 0x80 0x88 0x90 0x98 0xA0 0xA8 0xB0 0xB8 0xC0 0xC8 0xD0 0x00 0xF8 Set STO to reset SMBus Set STO to reset SMBus State does not set SI All Rev. 1.3 13 A N11 3 Software Examples for the C8051F00x and C8051F01x series ;--------------------------------------------------------------------------------; ; Copyright 2001 Cygnal Integrated Products, Inc. ; ; Program: SMBus_EX1.asm ; Created on: 2/21/01 ; Last mod : 27 AUG 03 -- BW ; Created by: JS ; ; Example code to interface a single 256-byte EEPROM to a C8051F00x via the SMBus ; Code assumes a single EEPROM with slave address 1010000 is connected on ; the SDA and SCL lines, and no other masters are on the bus. ; ; The SEND routine performs a 1-byte write to the EEPROM. This consists of (1) START, ; (2) slave address + W, (3) memory location byte write, and (4) a data byte write. ; ; STEPS FOR WRITING TO EEPROM: ; 1) Load slave address into SLA_ADD ; 2) Load memory address into MEM_ADD ; 3) Load data byte into TRANSMIT_BYTE. ; 4) Call SEND ; ; The RECEIVE routine performs a 1-byte read from the EEPROM. This consists of (1) ; START, (2) slave address + W, (3) memory location byte write, (4) repeated START, ; (5) slave address + R, (6) data byte read. ; ; STEPS FOR RECEIVING DATA: ; 1) Load slave address into SLA_ADD ; 2) Load memory address into MEM_ADD ; 3) Call RECEIVE ; 4) Read RECEIVE_BYTE ; ; The SMBus state table is broken into 8-byte state segments, allowing the SMBus ; status code (SMB0STA) to be used as a state index. Note that this leaves only ; 8 bytes of code space per SMBus state definition. As a result, certain tasks ; have been altered to limit state definition lengths: ; ; 1) The SMB_MTDBACK state (Master transmitter, data byte sent, ACK received) is ; reduced to a bit-check and branch operation. The branch is outside of the state ; table, so that a larger code segment may be executed for this state. ; ; 2) Three data bytes are used for slave address storage: SLA_ADD, WRI_ADD, READ_ADD. ; Rather than using bit-wise operations in the SMBus states, each transfer routine ; pre-loads the address values. Since a RECEIVE includes both a WRITE and READ ; transfer, two address bytes are necessary - WRI_ADD and READ_ADD. SLA_ADD is used ; as a generic slave chip select before a function call. ; ; Note that SLA_ADD is equivalent to WRI_ADD, since WRI_ADD = SLA_ADD + W (W=0). ; The two are left separate to clarify the demonstration. ; ;----------------------------------------------------------------------------------- 14 Rev. 1.3 A N113 ;----------------------------------------------------------------------------------; EQUATES ;----------------------------------------------------------------------------------$include (c8051f000.inc) WRITE READ CHIP_A ; SMBus States SMB_BUS_ERROR SMB_START SMB_RP_START SMB_MTADDACK SMB_MTADDNACK SMB_MTDBACK SMB_MTDBNACK SMB_MTARBLOST SMB_MRADDACK SMB_MRADDNACK SMB_MRDBACK SMB_MRDBNACK EQU EQU EQU 00h 01h 0A0h ; Include register definition file. ; SMBus WRITE command ; SMBus READ command ; EEPROM slave address EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU 00h 08h 10h 18h 20h 28h 30h 38h 40h 48h 50h 58h ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; (all modes) BUS ERROR (MT & MR) START transmitted (MT & MR) repeated START (MT) Slave address + W transmitted; ACK received (MT) Slave address + W transmitted; NACK received (MT) data byte transmitted; ACK rec’vd (MT) data byte transmitted; NACK rec’vd (MT) arbitration lost (MR) Slave address + R transmitted; ACK received (MR) Slave address + R transmitted; NACK received (MR) data byte rec’vd; ACK transmitted (MR) data byte rec’vd; NACK transmitted ;----------------------------------------------------------------------------------; VARIABLES ;----------------------------------------------------------------------------------MYDATA SEGMENT DATA RSEG MYDATA ; declare DATA segment ; select DATA segment TRANSMIT_BYTE: RECEIVE_BYTE: SLA_ADD: WRI_ADD: READ_ADD: MEM_ADD: DS DS DS DS DS DS 1 1 1 1 1 1 testing. 1 1 1 ; ; ; ; ; ; Holds a byte to be transmitted by the SMBus Holds a byte just received by the SMBus Holds the slave address Holds the slave address + WRITE Holds the slave address + READ EEPROM memory location to be accessed ; Variables used for TEST_COUNT: DS TEST_BYTE: DS TEST_ADDR: DS MYBITS SEGMENT BIT RSEG MYBITS DBIT DBIT DBIT ; Test counter variable ; Test data ; Test memory location RW: SM_BUSY: BYTE_SENT: 1 1 1 ; R/W command bit. 1=READ, 0=WRITE ; SMBus Busy flag (kept in software) ; Used to indicate what byte was just sent: ; 1: EEPROM memory address sent ; 0: Data byte sent Rev. 1.3 15 A N11 3 ;------------------; STACK STACK SEGMENT IDATA RSEG STACK DS 80h ; declare STACK segment ; reserve 128 bytes for stack ;-----------------------------------------------------------------------------------; RESET and INTERRUPT VECTORS ;-----------------------------------------------------------------------------------CSEG ; Reset Vector org 00h ljmp Reset_Vector ; SMBus Interrupt Vector org 03Bh ljmp SMBus_ISR MYCODE SEGMENT CODE RSEG MYCODE USING 0 ;-------------------------------------------------------------------------------------; Reset Vector ; ; - Disables Watchdog Timer ; - Routes SDA and SCL to GPIO pins via the crossbar ; - Enables crossbar ; - Jumps to MAIN Reset_Vector: mov mov mov orl WDTCN, #0DEh WDTCN, #0ADh SP, #STACK OSCICN, #03h ; Disable Watchdog Timer ; Initialize Stack Pointer ; Set internal oscillator to highest setting ; (16 MHz) ; Route SMBus to GPIO pins through crossbar ; Enable crossbar and weak pull-ups mov mov ljmp XBR0, #01h XBR2, #40h MAIN ;-----------------------------------------------------------------------------------; MAIN PROGRAM ;-----------------------------------------------------------------------------------MAIN: acall SMBus_Init setb EA mov TEST_BYTE, #0ffh ; Initialize SMBus ; Enable global interrupts ; 16 Rev. 1.3 A N113 mov mov TEST_ADDR, #00h TEST_COUNT, #0feh ; Load initial test values ; ; TEST CODE-------------------------------------------------------------------------- TEST: ; Send TEST_BYTE to memory location mov SLA_ADD, #CHIP_A ; mov TRANSMIT_BYTE, TEST_BYTE ; mov MEM_ADD, TEST_ADDR ; acall SEND ; TEST_ADDR Load slave address Load transmit data into TRANSMIT_BYTE Load memory address into MEM_ADD Call send routine ; Read memory location TEST_ADDR into RECEIVE_BYTE mov SLA_ADD, #CHIP_A ; Load slave address mov MEM_ADD, TEST_ADDR ; Load memory address into MEM_ADD acall RECEIVE ; Call receive routine ; Compare byte received to byte sent mov A, RECEIVE_BYTE ; Load received byte into accumulator cjne A, TEST_BYTE, END_TEST ; Compare sent byte to received byte ; Jump to END_TEST if not equal ; Change test variables dec TEST_BYTE inc TEST_ADDR ; If sent=received, change test variables ; and cycle through again. ; Cycle through again if TEST_COUNTER not zero djnz TEST_COUNT, TEST ; Decrement counter, loop back to beginning mov A, #99h ; Load accumulator with 99h if test successful. END_TEST: jmp $ ; Spin ;--------------------------------------------------------------------------------------; SUBROUTINES ;--------------------------------------------------------------------------------------;--------------------------------------------------------------------------------------; SEND subroutine. Assumes that the slave address, memory location, and transmit ; data have all been loaded into their associated variables. This routine manages ; the SM_BUSY bit, sets RW=WRITE, loads the WRI_ADD, and initiates the transfer. ; SEND: push jb clr ACC SM_BUSY, $ RW ; Preserve accumulator ; Wait for SMBus to be free ; RW = 0 (WRITE) mov orl mov setb setb pop A, SLA_ADD A, #WRITE WRI_ADD, A SM_BUSY STA ACC ; Store SLA_ADD + WRITE ; in WRI_ADD ; ; Occupy SMBus ; Initiate Transfer ; Restore accumulator Rev. 1.3 17 A N11 3 ret ;--------------------------------------------------------------------------------------; RECEIVE subroutine. Assumes that the slave address and memory location have been ; loaded into their associated variables. This routine manages the SM_BUSY bit, sets ; RW=READ, loads the READ_ADD and WRI_ADD, and initiates the transfer. ; ; Note that the RECEIVE transfer consists of a WRITE of the memory location to be accessed, ; followed by a repeated START and a READ operation. Therefore, both WRI_ADD ; and READ_ADD are used by this routine. RECEIVE: push jb setb mov orl mov mov orl mov setb setb jb pop ret ;--------------------------------------------------------------------------------------; SMBus_Init ; SMbus initialization routine ; ; ; ; ; Configures and enables the SMBus. Sets SMBus clock rate. Enables SMBus interrupt. Clears SM_Busy flag for first transfer. ACC SM_BUSY, $ RW A, SLA_ADD A, #WRITE WRI_ADD, A A, SLA_ADD A, #READ READ_ADD, A SM_BUSY STA SM_BUSY, $ ACC ; Preserve accumulator ; Wait for SMBus to be free ; RW = 1 (READ) ; Store SLA_ADD + WRITE ; in WRITE_ADD ; ; Store SLA_ADD + READ ; in READ_ADD ; ; Occupy SMBus ; Initiate Transfer ; Wait for receive to finish ; Restore accumulator SMBus_Init: mov mov SMB0CN, #04h SMB0CR, #0B0h ; Configure SMBus to send ACKs on acknowledge cycle ; SMBus clock rate = 100KHz, per SMB0CR equation: ; SMB0CR = -(SYSCLK)/(2*Fscl) ; Enable SMBus ; Enable SMBus interrupts orl orl clr ret SMB0CN, #40h EIE1, #02h SM_BUSY ;-------------------------------------------------------------------------------------; INTERRUPT VECTORS ;-------------------------------------------------------------------------------------- 18 Rev. 1.3 A N113 ;-------------------------------------------------------------------------------------; SMBus ISR ; ; Implemented as a state table lookup, with the SMBus status register as the index. ; SMBus status codes are multiples of 8; thus the status code can be used to index ; program segments that are spaced by 8 bytes. Each ‘org’ command indicates ; a new state, offset from the beginning of the table by its status code value. ; ; Note that only 8 bytes are available to process each state. In the cases where ; more than 8 bytes are necessary, the code jumps to a program location outside ; of the state table. This is only necessary in the state ‘SMB_MTDBACK’. SMBus_ISR: push push push push push mov PSW ACC DPH DPL ACC A, SMB0STA ; ; ; Resource preservation ; ; ; Load accumulator with current SMBus state. ; State corresponds to the address offset ; for each state execution ; Mask out upper bit, since any states that ; set this bit are not defined in this code. ; Point DPTR to the beginning of the state table ; Jump to the current state anl A, #7Fh mov jmp DPTR, #SMB_STATE_TABLE @A+DPTR ; SMBus State Table-----------------------------------------------------------------------SMB_STATE_TABLE: ; SMB_BUS_ERROR ; All Modes: Bus Error ; Reset hardware by setting STOP bit org SMB_STATE_TABLE + SMB_BUS_ERROR setb jmp STO SMB_ISR_END ; Jump to exit ISR ; SMB_START ; Master Transmitter/Receiver: START transmitted. ; The R/W bit will always be a zero (W) in this state because ; for both write and read, the memory address must first be written. org SMB_STATE_TABLE + SMB_START mov clr jmp SMB0DAT, WRI_ADD STA SMB_ISR_END ; Load slave address + W ; Manually clear START bit ; Jump to exit ISR ; SMB_RP_START ; Master Transmitter/Receiver: Repeated START transmitted. ; This state should only occur during a read, after the memory ; address has been sent and acknowledged. org SMB_STATE_TABLE + SMB_RP_START Rev. 1.3 19 A N11 3 mov clr jmp SMB0DAT, READ_ADD STA SMB_ISR_END ; Load slave address + R ; Manually clear START bit ; SMB_MTADDACK ; Master Transmitter: Slave address + WRITE transmitted. ; ACK received org SMB_STATE_TABLE + SMB_MTADDACK mov setb SMB0DAT, MEM_ADD BYTE_SENT ; ; ; ; Load memory address BYTE_SENT=1: In the next ISR call, the memory address will have just been sent. jmp SMB_ISR_END ; SMB_MTADDNACK ; Master Transmitter: Slave address + WRITE transmitted. ; NACK received. The slave is not responding. Try again with ; acknowledge polling. Send STOP + START. org SMB_STATE_TABLE + SMB_MTADDNACK setb setb jmp STO STA SMB_ISR_END ; SMB_MTDBACK ; Master Transmitter: Data byte transmitted. ACK received. ; This state is used in both read and write operations. ; Check BYTE_SENT; if 1, memory address has just been sent. Else, ; data has been sent. org SMB_STATE_TABLE + SMB_MTDBACK jbc BYTE_SENT, ADDRESS_SENT ; If BYTE_SENT=1, clear bit and ; jump to ADDRESS_SENT to process ; outside of state table. jmp DATA_SENT ; If BYTE_SENT=0, data has just been sent, ; transfer is finished. ; jump to end transfer ; SMB_MTDBNACK ; Master Transmitter: Data byte transmitted. NACK received. ; Slave not responding. Send STOP followed by START to try again. org SMB_STATE_TABLE + SMB_MTDBNACK setb setb jmp STO STA SMB_ISR_END ; SMB_MTARBLOST ; Master Transmitter: Arbitration Lost. ; Should not occur. If so, restart transfer. org SMB_STATE_TABLE + SMB_MTARBLOST setb setb jmp STO STA SMB_ISR_END 20 Rev. 1.3 A N113 ; SMB_MRADDACK ; Master Receiver: Slave address + READ transmitted. ACK received. ; Set to transmit NACK after next transfer since it will be the ; last (only) byte. org SMB_STATE_TABLE + SMB_MRADDACK clr jmp AA SMB_ISR_END ; NACK sent on acknowledge cycle ; SMB_MRADDNACK ; Master Receiver: Slave address + READ transmitted. NACK received. ; Slave not responding. Send repeated START to try again. org SMB_STATE_TABLE + SMB_MRADDNACK clr setb jmp STO STA SMB_ISR_END ; SMB_MRDBACK ; Master Receiver: Data byte received. ACK transmitted. ; Should not occur because AA is cleared in previous state. ; Send STOP if state does occur. org SMB_STATE_TABLE + SMB_MRDBACK setb jmp STO SMB_ISR_END ; SMB_MRDBNACK ; Master Receiver: Data byte received. NACK transmitted. ; Read operation completed. Read data register and send STOP org SMB_STATE_TABLE + SMB_MRDBNACK mov setb setb clr jmp RECEIVE_BYTE, SMB0DAT STO AA SM_BUSY SMB_ISR_END ; Set AA for next transfer ; End of State Table-------------------------------------------------------------;--------------------------------------------------------------------------------; Program segment to handle SMBus states that require more than 8 bytes of program ; space. ; Address byte has just been sent. Check RW. ; If W, load data to transmit into SMB0DAT. ADDRESS_SENT: jb mov jmp RW, RW_READ SMB0DAT, TRANSMIT_BYTE SMB_ISR_END If R (1), jump to RW_READ. ; Load data ; Jump to exit ISR Send ; Operation is a READ, and the address byte has just been sent. ; repeated START to initiate memory read. RW_READ: clr setb jmp STO STA SMB_ISR_END ; Send repeated START ; Jump to exit ISR Rev. 1.3 21 A N11 3 ; Operation is a WRITE, and the data byte has just been sent. ; is finished. Send STOP, free the bus, and exit the ISR. DATA_SENT: Transfer setb STO ; Send STOP and exit ISR. clr SM_BUSY ; Free SMBus jmp SMB_ISR_END ; Jump to exit ISR ;--------------------------------------------------------------------------------; SMBus ISR exit. ; Restore registers, clear SI bit, and return from interrupt. SMB_ISR_END: clr pop pop pop pop pop reti END SI ACC DPL DPH ACC PSW 22 Rev. 1.3 A N113 //-----------------------------------------------------------------------------------// // Copyright 2001 Cygnal Integrated Products, Inc. // // FILE NAME : SMB_Ex2.c // TARGET DEVICE : C8051F000 // CREATED ON : 2/20/01 // CREATED BY : JS // // // Example code for interfacing a C8051F0xx to three EEPROMs via the SMBus. // Code assumes that three 16-bit address space EEPROMs are connected // on the SCL and SDA lines, and configured so that their slave addresses // are as follows: // CHIP_A = 1010000 // CHIP_B = 1010001 // CHIP_C = 1010010 // // Slave and arbitration states are not defined. Assume the CF000 is the only // master in the system. // Functions: SM_Send performs a 1-byte write to the specified EEPROM // SM_Receive performs a 1-byte read of the specified EEPROM address (both include // memory address references). // // Includes test code section. //-----------------------------------------------------------------------------------// Includes //-----------------------------------------------------------------------------------#include // SFR declarations //-----------------------------------------------------------------------------------// Global CONSTANTS //-----------------------------------------------------------------------------------#define WRITE 0x00 #define READ 0x01 // SMBus WRITE command // SMBus READ command // Device addresses (7 bits, lsb is a don’t care) #define CHIP_A 0xA0 // Device address for chip A #define CHIP_B 0xA2 // Device address for chip B #define CHIP_C 0xA4 // Device address for chip C // SMBus states: // MT = Master Transmitter // MR = Master Receiver #define SMB_BUS_ERROR 0x00 #define SMB_START 0x08 #define SMB_RP_START 0x10 #define SMB_MTADDACK 0x18 #define #define #define #define #define #define SMB_MTADDNACK SMB_MTDBACK SMB_MTDBNACK SMB_MTARBLOST SMB_MRADDACK SMB_MRADDNACK 0x20 0x28 0x30 0x38 0x40 0x48 // // // // // // // // // // // // // (all modes) BUS ERROR (MT & MR) START transmitted (MT & MR) repeated START (MT) Slave address + W transmitted; ACK received (MT) Slave address + W transmitted; NACK received (MT) data byte transmitted; ACK rec’vd (MT) data byte transmitted; NACK rec’vd (MT) arbitration lost (MR) Slave address + R transmitted; ACK received (MR) Slave address + R transmitted; Rev. 1.3 23 A N11 3 #define #define SMB_MRDBACK SMB_MRDBNACK 0x50 0x58 // NACK received // (MR) data byte rec’vd; ACK transmitted // (MR) data byte rec’vd; NACK transmitted //----------------------------------------------------------------------------------//Global VARIABLES //----------------------------------------------------------------------------------char COMMAND; // Holds the slave address + R/W bit for // use in the SMBus ISR. char WORD; // Holds data to be transmitted by the SMBus // OR data that has just been received. // Used by ISR to check what data has just been // sent - High address byte, Low byte, or data // byte // High & Low byte for EEPROM memory address // This bit is set when a send or receive // is started. It is cleared by the // ISR when the operation is finished. char BYTE_NUMBER; unsigned char HIGH_ADD, LOW_ADD; bit SM_BUSY; //-----------------------------------------------------------------------------------// Function PROTOTYPES //-----------------------------------------------------------------------------------void SMBus_ISR (void); void SM_Send (char chip_select, unsigned int byte_address, char out_byte); char SM_Receive (char chip_select, unsigned int byte_address); //-----------------------------------------------------------------------------------// MAIN Routine //-----------------------------------------------------------------------------------// // Main routine configures the crossbar and SMBus, and tests // the SMBus interface between the three EEPROMs void main (void) { unsigned char check; // Used for testing purposes WDTCN = 0xde; WDTCN = 0xad; OSCICN |= 0x03; // disable watchdog timer // Set internal oscillator to highest setting // (16 MHz) // Route SMBus to GPIO pins through crossbar // Enable crossbar and weak pull-ups // Enable SMBus with ACKs on acknowledge // cycle // SMBus clock rate = 100kHz. // SMBus interrupt enable // Global interrupt enable XBR0 = 0x01; XBR2 = 0x40; SMB0CN = 0x44; SMB0CR = -80; EIE1 |= 2; EA = 1; 24 Rev. 1.3 A N113 SM_BUSY = 0; // Free SMBus for first transfer. // TEST CODE--------------------------------------------------------------------SM_Send(CHIP_A, 0x0088, 0x53); // Send 0x53(data) to address 0x88 on CHIP_A SM_Send(CHIP_B, 0x0001, 0x66); // Send 0x66(data) to address 0x01 on CHIP_B SM_Send(CHIP_C, 0x0010, 0x77); SM_Send(CHIP_B, 0x0333, 0xF0); SM_Send(CHIP_A, 0x0242, 0xF0); check = SM_Receive(CHIP_A, 0x0088); // Read address 0x88 on CHIP_A check = SM_Receive(CHIP_B, 0x0001); // Read address 0x01 on CHIP_B check = SM_Receive(CHIP_C, 0x0010); check = SM_Receive(CHIP_B, 0x0333); check = SM_Receive(CHIP_A, 0x0242); // END TEST CODE----------------------------------------------------------------} // SMBus byte write function----------------------------------------------------// Writes a single byte at the specified memory location. // // out_byte = data byte to be written // byte_address = memory location to be written into (2 bytes) // chip_select = device address of EEPROM chip to be written to void SM_Send (char chip_select, unsigned int byte_address, char out_byte) { while (SM_BUSY); // Wait for SMBus to be free. SM_BUSY = 1; // Occupy SMBus (set to busy) SMB0CN = 0x44; // SMBus enabled, // ACK on acknowledge cycle BYTE_NUMBER = 2; COMMAND = (chip_select | WRITE); // 2 address bytes. // Chip select + WRITE HIGH_ADD = ((byte_address >> 8) & 0x00FF);// Upper 8 address bits LOW_ADD = (byte_address & 0x00FF); // Lower 8 address bits WORD = out_byte; STO = 0; STA = 1; } // SMBus random read function-----------------------------------------------------// Reads 1 byte from the specified memory location. // // byte_address = memory address of byte to read // chip_select = device address of EEPROM to be read from char SM_Receive (char chip_select, unsigned int byte_address) { while (SM_BUSY); // Wait for bus to be free. SM_BUSY = 1; // Occupy SMBus (set to busy) SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle BYTE_NUMBER = 2; COMMAND = (chip_select | READ); // 2 address bytes // Chip select + READ // Data to be writen // Start transfer Rev. 1.3 25 A N11 3 HIGH_ADD = ((byte_address >> 8) & 0x00FF);// Upper 8 address bits LOW_ADD = (byte_address & 0x00FF); // Lower 8 address bits STO = 0; STA = 1; while (SM_BUSY); return WORD; } // Start transfer // Wait for transfer to finish //-----------------------------------------------------------------------------------// Interrupt Service Routine //------------------------------------------------------------------------------------ // 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. // The R/W bit of the COMMAND word sent after this state will // always be a zero (W) because for both read and write, // the memory address must be written first. case SMB_START: SMB0DAT = (COMMAND & 0xFE); // Load address of the slave to be accessed. STA = 0; // Manually clear START bit break; // Master Transmitter/Receiver: Repeated START condition transmitted. // This state should only occur during a read, after the memory address has been // sent and acknowledged. case SMB_RP_START: SMB0DAT = COMMAND; // COMMAND should hold slave address + R. STA = 0; break; // Master Transmitter: Slave address + WRITE transmitted. ACK received. case SMB_MTADDACK: SMB0DAT = HIGH_ADD; // Load high byte of memory address // to be written. break; // Master Transmitter: Slave address + WRITE transmitted. NACK received. // The slave is not responding. Send a STOP followed by a START to try again. case SMB_MTADDNACK: STO = 1; STA = 1; break; // Master Transmitter: Data byte transmitted. ACK received. // This state is used in both READ and WRITE operations. Check BYTE_NUMBER // for memory address status - if only HIGH_ADD has been sent, load LOW_ADD. // If LOW_ADD has been sent, check COMMAND for R/W value to determine // next state. case SMB_MTDBACK: switch (BYTE_NUMBER){ 26 Rev. 1.3 A N113 case 2: SMB0DAT = LOW_ADD; BYTE_NUMBER--; break; case 1: if (COMMAND & 0x01){ STO = 0; STA = 1; } else { SMB0DAT = WORD; BYTE_NUMBER--; } break; default: STO = 1; SM_BUSY = 0; } break; // If BYTE_NUMBER=2, only HIGH_ADD // has been sent. // Decrement for next time around. // If BYTE_NUMBER=1, LOW_ADD was just sent. // If R/W=READ, sent repeated START. // If R/W=WRITE, load byte to write. // If BYTE_NUMBER=0, transfer is finished. // Free SMBus // Master Transmitter: Data byte transmitted. NACK received. // Slave not responding. Send STOP followed by START to try again. case SMB_MTDBNACK: STO = 1; STA = 1; break; // Master Transmitter: Arbitration lost. // Should not occur. If so, restart transfer. case SMB_MTARBLOST: STO = 1; STA = 1; 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: AA = 0; // NACK sent on acknowledge cycle. break; // Master Receiver: Slave address + READ transmitted. NACK received. // Slave not responding. Send repeated start to try again. case SMB_MRADDNACK: STO = 0; STA = 1; break; // Data byte received. ACK transmitted. // State should not occur because AA is set to zero in previous state. // Send STOP if state does occur. case SMB_MRDBACK: STO = 1; SM_BUSY = 0; break; // Data byte received. NACK transmitted. // Read operation has completed. Read data register and send STOP. Rev. 1.3 27 A N11 3 case SMB_MRDBNACK: WORD = SMB0DAT; STO = 1; SM_BUSY = 0; break; // Free SMBus // All other status codes meaningless in this application. Reset communication. default: STO = 1; // Reset communication. SM_BUSY = 0; break; } SI=0; } // clear interrupt flag 28 Rev. 1.3 A N113 //-----------------------------------------------------------------------------------// // Copyright 2001 Cygnal Integrated Products, Inc. // // FILE NAME : SMB_Ex3.c // TARGET DEVICE : C8051F000 // CREATED ON : 2/20/01 // CREATED BY : JS // // Example code to demonstrate the use of the SMBus interface between two CF000 devices. // The devices operate in a peer-to-peer configuration. // // Demonstration includes use of op codes for each device to command the other to: // // 1) Write a byte to DAC0 // 2) Write a byte to a data buffer // 3) Perform an ADC conversion // 4) Read a byte from a data buffer // // These op codes are can be tested easily if each chip has DAC0 routed to AIN0. // With this configuration, a READ_ADC command can be used to test the output // of a WRITE_DAC command. // // Code assumes that two CF0xx devices are connected via SCL and SDA, with // slave addresses (held by register SMB0ADR) // CHIP_A = 1111000 // CHIP_B = 1110000 // // Test code is included. For testing purposes, the test code should be omitted // in one device, and run in the other. This can be accomplished by commenting // the OP_CODE_HANDLER() call before the test code in the device that will assume // the master role. // // PLEASE NOTE that the constant MY_ADD must correspond with the // current device - change it to CHIP_B when downloading code to CHIP_B. // //------------------------------------------------------------------------------------ //-----------------------------------------------------------------------------------// Includes //-----------------------------------------------------------------------------------#include // SFR declarations //-----------------------------------------------------------------------------------// Global CONSTANTS //-----------------------------------------------------------------------------------#define #define WRITE READ 0x00 0x01 // WRITE direction bit // READ direction bit // Device addresses #define CHIP_A #define CHIP_B #define MY_ADD 0xF0 0xE0 CHIP_A // Corresponds to the chip currently // being programmed. // Peer-to-Peer OP_CODEs #define READ_ADC 0x01 #define WRITE_DAC 0x02 // OP_CODE to read from slave ADC // OP_CODE to write to slave DAC Rev. 1.3 29 A N11 3 #define #define //SMBus // MT = // MR = // ST = // SR = #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define WRITE_BUF READ_BUF 0x03 0x04 // OP_CODE to write to slave buffer // OP_CODE to read from slave buffer states: Master Transmitter Master Receiver Slave Transmitter Slave Receiver SMB_BUS_ERROR SMB_START SMB_RP_START SMB_MTADDACK SMB_MTADDNACK SMB_MTDBACK SMB_MTDBNACK SMB_MTARBLOST SMB_MRADDACK SMB_MRADDNACK SMB_MRDBACK SMB_MRDBNACK SMB_SROADACK 0x00 0x08 0x10 0x18 0x20 0x28 0x30 0x38 0x40 0x48 0x50 0x58 0x60 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // (all modes) BUS ERROR (MT & MR) START transmitted (MT & MR) repeated START (MT) Slave address + W transmitted; ACK received (MT) Slave address + W transmitted; NACK received (MT) data byte transmitted; ACK rec’vd (MT) data byte transmitted; NACK rec’vd (MT) arbitration lost (MR) Slave address + R transmitted; ACK received (MR) Slave address + R transmitted; NACK received (MR) data byte rec’vd; ACK transmitted (MR) data byte rec’vd; NACK transmitted (SR) SMB’s own slave address + W rec’vd; ACK transmitted (SR) SMB’s own slave address + W rec’vd; arbitration lost (SR) general call address rec’vd; ACK transmitted (SR) arbitration lost when transmitting slave addr + R/W as master; general call address rec’vd; ACK transmitted (SR) data byte received under own slave address; ACK returned (SR) data byte received under own slave address; NACK returned (SR) data byte received under general call address; ACK returned (SR) data byte received under general call address; NACK returned (SR) STOP or repeated START received while addressed as a slave (ST) SMB’s own slave address + R rec’vd; ACK transmitted (ST) arbitration lost in transmitting slave address + R/W as master; own slave address rec’vd; ACK transmitted (ST) data byte transmitted; ACK rec’ed (ST) data byte transmitted; NACK rec’ed (ST) last data byte transmitted (AA=0); ACK received (ST & SR) SCL clock high timer per SMB0CR timed out (FTE=1) (all modes) Idle SMB_SROARBLOST 0x68 SMB_SRGADACK 0x70 SMB_SRGARBLOST 0x78 #define #define #define #define #define #define #define SMB_SRODBACK SMB_SRODBNACK SMB_SRGDBACK SMB_SRGDBNACK SMB_SRSTOP SMB_STOADACK 0x80 0x88 0x90 0x98 0xa0 0xa8 SMB_STOARBLOST 0xb0 #define #define #define #define #define SMB_STDBACK SMB_STDBNACK SMB_STDBLAST SMB_SCLHIGHTO SMB_IDLE 0xb8 0xc0 0xc8 0xd0 0xf8 //----------------------------------------------------------------------------------- 30 Rev. 1.3 A N113 //Global VARIABLES //----------------------------------------------------------------------------------char COMMAND; // Holds the slave address + R/W bit for // use in the SMBus ISR. // Holds data to be transmitted by the SMBus // OR data that has just been received. // Holds an op code to be sent or one // that has just been received. // Used to hold relevant data after a // lost arbitration. // Data buffer accessed by OP_CODE_HANDLER // Arbitration lost flag, set when // arbitration is lost while in master mode. // Used to resume a failed transfer. // This bit is set when a send or receive // is started. It is cleared by the // ISR when the operation is finished. // Flag used to determine if byte received // as a slave is an OP_CODE or data. // Used by OP_CODE handler to flag when // valid data has been received from the // master char WORD; char OP_CODE; char LOST_COMMAND, LOST_WORD, LOST_CODE; char DATA_BUF[16]; bit LOST; bit SM_BUSY; bit VALID_OP; bit DATA_READY; //-----------------------------------------------------------------------------------// Function PROTOTYPES //-----------------------------------------------------------------------------------void char void void SMBUS_ISR (void); SLA_READ(char chip_select, char out_op); SLA_SEND(char chip_select, char out_op, char out_data); OP_CODE_HANDLER(void); //-----------------------------------------------------------------------------------// MAIN Routine //-----------------------------------------------------------------------------------void MAIN (void) { char i, check_1, check_2; WDTCN = 0xde; WDTCN = 0xad; XBR0 = 0x01; XBR2 = 0x40; SMB0CN = 0x44; SMB0CR = -80; SMB0ADR = MY_ADD; // Variables used for testing purposes only. // disable watchdog timer // Route SMBus to GPIO pins through crossbar // Enable crossbar and weak pull-ups // Enable SMBus with acknowledge low (AA = 1) // SMBus clock rate = 100 kHz // Set own slave address. Rev. 1.3 31 A N11 3 ADC0CN = 0x80; // Enable ADC, conversions to start with // write to ADBUSY. // ADC data registers left-justified. // enable DAC0, with left justified data // registers. // reference voltage enabled. // SMBus interrupt enable // Global interrupt enable // Free bus for first transfer. // // // // // // // // This line should be commented in only one of the two peer devices. It is for testing purposes only. In a normal setup, the OP_CODE_HANDLER would be running at all times in order to react to OP_CODES being sent to the device. ADC0CN |= 0x01; DAC0CN = 0x84; REF0CN = 0x03; EIE1 |= 2; EA = 1; SM_BUSY = 0; SI = 0; // OP_CODE_HANDLER(); // // // // // 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 | WRITE_BUF), 0x24); SLA_SEND(CHIP_B, (0x60 | WRITE_BUF), 0x25); SLA_SEND(CHIP_B, (0x80 | WRITE_BUF), 0x26); SLA_SEND(CHIP_B, (0x10 | WRITE_BUF), 0x27); check_1 check_1 check_1 check_1 = = = = SLA_READ(CHIP_B, SLA_READ(CHIP_B, SLA_READ(CHIP_B, SLA_READ(CHIP_B, (0x40 (0x60 (0x80 (0x10 | | | | READ_BUF)); READ_BUF)); READ_BUF)); READ_BUF)); // // // // // // // // // Write to index 4 in the data buffer Write to index 6 Write to index 8 Write to index 1 Read Read Read Read index index index index 4 from the buffer 6 8 1 // Loop to continuously increase the DAC output on CHIP_B, and read its // ADC each round. DAC output on CHIP_B should ramp. for (i=0;i
AN113 价格&库存

很抱歉,暂时无法提供与“AN113”相匹配的价格&库存,您可以联系我们找货

免费人工找货