AN138 P O W E R M A N A G E M E N T TE C H N I Q U E S Relevant Devices FOR THE ‘F30 X AND ‘F31 X techniques discussed in this note can be applied in actual systems. This application note applies to the following devices: C8051F300, C8051F301, C8051F302, C8051F303, C8051F304, C8051F305, C8051F310, and C8051F311. Key Points • Introduction The C8051F30x and C8051F31x are excellent • choices for low power applications. They provide flexible clocking hardware and 3V operation which significantly reduces power consumption. In addi- • tion, the pipelined core executes instructions at an average rate of one system clock per opcode byte. This application note discusses power calculation techniques and power saving strategies for for C8051F30x and C8051F31x devices. It discusses how the internal and external oscillators, CPU power management modes, system clock frequency, and supply voltage play a role in the power consumption of the device. This note also discusses and gives examples of implementing a “sleep” mode to reduce power consumption. Software examples are included to demonstrate how the Flexible clocking hardware makes it easy to switch between a high-performance mode and a low-power mode. Managing power smartly can significantly reduce the total power consumption of the system. The missing clock detector will cause a device reset if the operating frequency drops below 10 kHz. Calculating Power Consumption When designing a system with a power budget, being able to estimate the system’s power consumption on paper can save time and resources by allowing the designer to experiment with different configurations before hardware is built. Since Silicon Labs devices often provide single-chip solutions to many applications, the device power TIMEtotal Current TIMEactive Iactive AREA = Charge Iavg TIMEidle Iidle Time 0 Rev. 1.1 12/03 Copyright © 2003 by Silicon Laboratories AN138-DS11 AN138 consumption is often equivalent to the system External CMOS Clock power consumption. When the External Oscillator is in CMOS Clock mode, the external oscillator driver is turned off and the circuitry consumes a negligible amount of current. When a CMOS clock signal is present on XTAL2, it may be used as a clocking source for the CPU, Timers, PCA, or other peripherals. Note that power consumption increases slightly when a high The oscillator power consumption consists of con- frequency signal is applied to any port pin. tributions from the internal and external oscillators. The internal oscillator power consumption is disExternal Crystal cussed in the analog peripherals section. The device power consumption is calculated by taking the sum of individual contributions. The main contributors to power consumption include the oscillators, digital power, analog peripherals, and Port I/O. An external crystal provides the most accurate timebase, but may consume more power at a given frequency when compared with other clocking methods discussed in this note. The external crystal current depends on the crystal frequency and the external oscillator drive current setting (XFCN). Analog peripheral power consumption is domi- Table 1 and Table 2 show typical current values nated by the ADC, VREF, temperature sensor, bias for the external oscillator circuitry when driving generator, and internal oscillator. Comparators also various crystals. contribute a small amount to the total analog Table 1. Typical External Oscillator Power peripheral power consumption. Digital power consumption depends on CPU mode, supply voltage, and system clock frequency. Temperature and the digital peripherals themselves have a minimal effect on digital power consumption. Consumption in Crystal Mode (C8051F30x) All current sourced by a port pin is taken from the device supply current. For example, if 10 mA are being used to power an LED connected to a port pin, the device power consumption will increase by 10 mA. External Oscillator Power Consumption XFCN Crystal Frequency Current (3.0 Volts) 1 32.768 kHz 3.7 µA 5 4.000 MHz 240 µA 7 11.0592 MHz 3.8 mA 7 25.000 MHz 4.1 mA The external oscillator circuitry on these devices is Table 2. Typical External Oscillator Power very flexible. It may derive its timebase from a Consumption in Crystal Mode (C8051F31x) crystal or ceramic resonator, a capacitor, an RC network, or an external CMOS clock. Each of these Crystal Current clocking methods has its advantages. Since the XFCN Frequency (3.0 Volts) oscillator can change clocking modes from applica32.768 kHz 4.1 µA tion code, switching modes on the fly can signifi- 1 cantly reduce power consumption. In C, RC, and 5 4.000 MHz 280 µA CMOS clock modes, it is possible to achieve very 7 11.0592 MHz 4.4 mA low operating frequencies. 2 Rev. 1.1 AN138 possible because of the ability to switch oscillator modes on-the-fly. Table 2. Typical External Oscillator Power Consumption in Crystal Mode (C8051F31x) XFCN 7 Crystal Frequency 25.000 MHz Current (3.0 Volts) Table 3. C mode Frequency Range and Typical Oscillator Power Consumption with a 33 pF Capacitor on XTAL2 (C8051F30x) 4.7 mA External C Mode Approximate Frequency (3.0 Volts) Current (3.0 Volts) 0 5 kHz 2 µA 1 15 kHz 4 µA 2 44 kHz 10 µA 3 130 kHz 26 µA XFCN External C mode can provide low-power clocking to the device with a single capacitor connected to XTAL2. A wide range of frequencies can be achieved by varying the XFCN bits in the OSCXCN register. Table 3 through Table 6 show how frequency and current are affected by capacitance and XFCN settings. 380 kHz 73 µA Since the frequency of the external oscillator in C 4 mode depends on capacitance, it will vary from 5 1.0 MHz 220 µA system to system due to capacitor tolerance and 3.8 MHz 960 µA stray capacitance. The tolerance of the internal cur- 6 rent source also plays a role in determining the 7 9.5 MHz 4.0 mA oscillation frequency. Once the capacitor starts oscillation, the frequency remains relatively stable. Table 4. C mode Frequency Range and Typical Oscillator Power Consumption with a 10 pF The external oscillator frequency may be measured Capacitor on XTAL2 to 2% accuracy using the 24.5 MHz internal cali- (C8051F30x) brated oscillator. For even greater accuracy, the Approximate internal oscillator frequency may first be measured Frequency using a 32.768 kHz watch crystal. Once the fre- XFCN (3.0 Volts) quency of the internal oscillator is found, it may be used to more accurately measure the external oscil- 0 9 kHz lator frequency in C mode. Having up to three 27 kHz clock sources with one hardware configuration is 1 Current (3.0 Volts) 2 µA 4 µA 2 80 kHz 10 µA 3 230 kHz 27 µA 4 650 kHz 78 µA 5 1.8 MHz 230 µA 6 5.8 MHz 990 µA 7 11.9 MHz 4.0 mA Rev. 1.1 3 AN138 Table 5. C mode Frequency Range and Typical Oscillator Power Consumption with a 100 pF Capacitor on XTAL2 (C8051F30x) Approximate Frequency (3.0 Volts) Current (3.0 Volts) 0 2 kHz 2 µA 1 7 kHz 4 µA 2 20 kHz 9 µA 3 56 kHz 24 µA 4 170 kHz 70 µA 5 480 MHz 210 µA 6 2.0 MHz 930 µA 7 6.3 MHz 4.0 mA XFCN Figure 2. C Mode Waveform at XTAL2 Vc VDD VDD/3 Table 6. C mode Frequency Range and Typical Oscillator Power Consumption with a 33 pF Capacitor on XTAL2 (C8051F31x) Approximate Frequency (3.0 Volts) Current (3.0 Volts) 0 7 kHz 2 µA 1 21 kHz 4 µA 2 61 kHz 11 µA 3 170 kHz 29 µA 4 500 kHz 85 µA 5 1.4 MHz 260 µA 6 5.0 MHz 1.1 mA 7 11.2 MHz 4.5 mA XFCN capacitor connected to XTAL2. As Figure 1 shows, the capacitor charges linearly from a constant current source. When the voltage on the capacitor reaches VDD/3, the comparator creates a path to ground, discharging the capacitor. Once the capacitor is discharged, the comparator opens the switch and the cycle repeats. The resulting waveform is shown in Figure 2. The output of the comparator, a digital signal, is fed to a “divide-by-two” circuit whose output can be selected as the system clock. Time External RC Mode RC mode operates similarly to C mode with the exception that in RC mode the capacitor is charged Figure 1. C Mode Overview VDD XTAL2 Frequency Generation in C Mode C Vc The external oscillator in C mode generates a clock signal by constantly charging and discharging the 4 + - + Rev. 1.1 - VDD/3 AN138 through an external resistor, as shown in Figure 3. modeled as a triangular waveform to simplify findOnce the capacitor voltage reaches VDD/3, the ing the average, as shown in Figure 5. comparator creates a path to ground, discharging Figure 5. RC Mode Resistor Voltage the capacitor. Figure 4 shows the waveform at XTAL2 generated by this cycle. VR Figure 4. RC Mode Waveform at XTAL2 VDD 5/6 VDD Vc 2/3 VDD Actual Curve Triangle (Exponential) Model VDD Time VDD/3 With this simplification, Equation 1 can be used to calculate the average voltage. The external oscillator average current and power are shown in Equation 2 and Equation 3, respectively. Time Calculating Power in RC Mode Equation 1. Average Resistor Voltage The average power consumption for the external oscillator in RC mode is determined by the the average current through the resistor. The voltage drop across the resistor is exponential, but can be 5 V avg ≅ --- × VDD 6 Equation 2. Average Current I avg Figure 3. RC Mode Overview = Equation 3. Average Power VDD P avg R XTAL2 + - + C Vc V avg -------------R = 2 V avg -------------R Note that the power consumption of the external oscillator in RC mode depends on the resistor value and not on the capacitor value. VDD/3 - Rev. 1.1 5 AN138 Digital Power Consumption Digital power consumption is dominated by CPU current. The factors that play a major role in determining this current are CPU power management mode, supply voltage, and system clock frequency. Temperature and digital peripherals have a minimal effect on digital power consumption. CPU Power Management Modes The CPU is in Normal mode whenever it is executing instructions. On writing a ‘1’ to the IDLE bit (PCON.0), the CPU finishes executing the current instruction and enters a low-power mode until awakened by an interrupt or device reset. In Idle mode, all analog and digital peripherals, memory, and internal registers remain operational. When awakened, the CPU resumes execution at the instruction following the write to the IDLE bit. The CPU has three modes of operation: Normal, Idle, and Stop. Figure 6 and Figure 7 show typical supply current curves when the internal oscillator is in divide by eight mode (3.0625 MHz) and is selected as the system clock. The Idle mode current is dominated by the internal oscillator. The Normal mode current minus the Idle mode current is approximately the amount of current needed by the CPU to execute instructions at 3.0625 MHz. Figure 6. Effect of CIP-51 Power Management Mode on Supply Current (C8051F30x) Typical Supply Current vs. VDD Voltage SYSCLK = 3.0625 MHz (Internal Oscillator in Divide by 8 Mode) 2500 2200 1900 2000 Current (uA) 1600 Normal Mode Current 1500 Idle Mode Current 1300 Stop Mode Current 1000 650 710 780 840 500 0 2.7 3.0 3.3 VDD Voltage (Volts) 6 Rev. 1.1 3.6 AN138 Figure 7. Effect of CIP-51 Power Management Mode on Supply Current (C8051F31x) Typical Supply Current vs. VDD Voltage SYSCLK = 3.0625 MHz (Internal Oscillator in Divide by 8 Mode) 2500 2300 2000 Current (uA) 2000 1500 1700 Normal Mode Current Idle Mode Current Stop Mode Current 1500 1000 790 940 860 1000 500 0 2.7 3.0 3.3 3.6 VDD Voltage (Volts) Rev. 1.1 7 AN138 Figure 8. Stop Mode Current vs. Supply Voltage (C8051F30x) 0.400 0.350 0.34 Current (uA) 0.300 0.27 0.250 0.200 0.20 Stop Mode Current (uA) 0.150 0.14 0.100 0.050 0.000 2.7 3 3.3 3.6 VDD Voltage (Volts) The CPU enters Stop mode on writing a ‘1’ to the STOP bit (PCON.1). After the current instruction is executed, the internal oscillator, and all digital peripherals are disabled. Analog peripherals such as comparators and the external oscillator remain in their current state. The MCU consumes the least amount of current when in Stop mode. Figure 8 and Figure 9 show that the Stop mode current is typically less than 500 nA when the internal oscillator is used for system clocking. Any reset source can be used to recover from Stop mode. This includes Comparator, Missing Clock Detector, power on, or VDD monitor reset. Software Example 3 at the end of this note shows how Stop mode may be used on C8051F30x and C8051F31x systems to save power. 8 Rev. 1.1 AN138 Figure 9. Stop Mode Current vs. Supply Voltage (C8051F31x) 0.500 0.450 0.45 0.400 0.37 Current (uA) 0.350 0.300 0.28 0.250 Stop Mode Current (uA) 0.200 0.150 0.18 0.100 0.050 0.000 2.7 3 3.3 3.6 VDD Voltage (Volts) Rev. 1.1 9 AN138 Supply Voltage Supply current increases with supply voltage. This relationship can be observed at all operating frequencies but has the greatest impact at higher frequencies. Figure 10 and Figure 11 show typical supply current vs. supply voltage curves when operating from the internal 24.5 MHz system clock. The minimum supply voltage specified in the datasheet is 2.7 Volts. However, since many voltage regulators have a +/10% accuracy, systems are not typically designed for a supply voltage less than 3.0 Volts. Temperature Device temperature does not have an appreciable effect on power consumption on these devices. Figure 10. Effect of Supply Voltage on Power Consumption (C8051F30x) Typical Supply Current vs. VDD Voltage SYSCLK = 24.5 MHz (Internal Oscillator in Divide by 1 Mode) 9000 8700 8000 7400 7000 6100 Current (uA) 6000 5000 Normal Mode Current Idle Mode Current Stop Mode Current 5000 4000 3000 2200 2500 2800 3100 2000 1000 0 2.7 3.0 3.3 VDD Voltage (Volts) 10 Rev. 1.1 3.6 AN138 Figure 11. Effect of Supply Voltage on Power Consumption (C8051F31x) Typical Supply Current vs. VDD Voltage SYSCLK = 24.5 MHz (Internal Oscillator in Divide by 1 M ode) 12000 11000 11000 10000 9600 9000 8100 Normal Mode Current Current (uA) 8000 Idle Mode Current 7000 6700 Stop Mode Current 6000 5000 4500 3600 4000 4100 3000 3200 2000 1000 0 2.7 3.0 3.3 3.6 VDD Voltage (Volts) Rev. 1.1 11 AN138 Operating Frequency (SYSCLK) The CPU operating frequency has the greatest impact on power consumption. Figure 12 and Figure 13 show the effect of operating frequency on power consumption when the CPU is in Normal mode. Near 13 MHz (C8051F30x devices) and 16 MHz (C8051F31x devices), the current drops slightly and changes slope because of a switchover in the FLASH read timing mechanism. Table 7 and Table 8 show the slope and offset for the graphs in Figure 12 and Figure 13, respectively. “Region A” in Figure 12 refers to frequencies less than 13 MHz and “Region B” refers to frequencies higher than 13 MHz. The same is true for Figure 13 except the switchover occurs near 16 MHz. Figure 12. Effect of Operating Frequency on Normal Mode Power Consumption (C8051F30x) Typical Supply Current vs. Operating Frequency (Normal Mode) Internal Oscillator Disabled, Running from an External CMOS Clock 9000 "Region B" "Region A" 8000 7000 Current (uA) 6000 VDD = 3.6v 5000 VDD = 3.3v VDD = 3.0v 4000 VDD = 2.7v 3000 2000 1000 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 SYSCLK Freque ncy (M Hz) 12 Rev. 1.1 AN138 Table 7. Slope and Offset Values for the Curves in Figure 12 (C8051F30x) Slope A Offset A Slope B Offset B mA/MHz mA mA/MHz mA 2.7 0.28 0.01 0.15 1.4 3.0 0.34 0.01 0.16 2.0 3.3 0.42 0.02 0.18 2.8 3.6 0.50 0.02 0.20 3.7 VDD Figure 13. Effect of Operating Frequency on Normal Mode Power Consumption (C8051F31x) Typical Supply Current vs. Operating Frequency (Normal Mode) Internal Oscillator Disabled, Running from an External CMOS Clock 11000 "Region A" "Region B" 10000 9000 Current (uA) 8000 7000 6000 VDD = 3.6v VDD = 3.3v VDD = 3v 5000 VDD = 2.7v 4000 3000 2000 1000 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 SYSCLK Frequency (MHz) Rev. 1.1 13 AN138 Table 8. Slope and Offset Values for the Curves in Figure 13 (C8051F31x) Slope A Offset A Slope B Offset B mA/MHz mA mA/MHz mA 2.7 0.34 0.03 0.16 2.5 3.0 0.41 0.04 0.18 3.2 3.3 0.49 0.05 0.21 4.1 3.6 0.58 0.05 0.24 5.0 VDD in the FLSCL register will extend the “Region B” curve across the entire operating range of the device. This is only useful if operating near the switchover point, where “Region B” operation consumes less power than “Region A”. When the CPU is in Idle mode, the Current vs. Operating Frequency curve is a single line over the operating range of the device. Figure 14 and Figure 15 show the effect of operating frequency on power consumption when the CPU is in Idle mode. When operating in “Region A”, turning off the FLASH one-shot by writing a ‘0’ to the FOSE bit Figure 14. Effect of Operating Frequency on Idle Mode Power Consumption (C8051F30x) Typical Supply Current vs. Operating Frequency (Idle Mode) Internal Oscillator Disabled, Running from an External CMOS Clock 3500 3000 VDD = 3.6v VDD = 3.3v 2500 VDD = 3.0v Current (uA) VDD = 2.7v 2000 1500 1000 500 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 SYSCLK Frequency (MHz) 14 Rev. 1.1 AN138 Table 9. Slope and Offset Values for the Curves in Figure 14 (C8051F30x) Slope Offset mA/MHz mA 2.7 0.09 0.00 3.0 0.10 0.01 3.3 0.11 0.02 3.6 0.12 0.02 VDD Figure 15. Effect of Operating Frequency on Idle Mode Power Consumption (C8051F31x) Typical Supply Current vs. Operating Frequency (Idle Mode) Internal Oscillator Disabled, Running from an External CMOS Clock 4500 4000 VDD = 3.6v 3500 VDD = 3.3v VDD = 3.0v 3000 Current (uA) VDD = 2.7v 2500 2000 1500 1000 500 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 SYSCLK Frequency (MHz) Rev. 1.1 15 AN138 cally enabled whenever the ADC, internal oscillator, or temperature sensor is enabled. Table 10. Slope and Offset Values for the Curves in Figure 15 (C8051F31x) Slope Offset mA/MHz mA 2.7 0.12 0.00 3.0 0.14 0.01 3.3 0.16 0.01 3.6 0.17 0.01 VDD The peak ADC current during a conversion is typically 30% to 50% higher than when the ADC is not converting. The SAR Conversion Clock frequency and sampling rate also affect the power consumption. In general, increasing the SAR Conversion Clock frequency and decreasing the sampling rate will provide the greatest power savings because the ADC will spend less time in each conversion and more time idle between conversions. Digital Peripherals and Port I/O Table 11. Typical Current Contribution for Analog Peripherals at 3.0V (C8051F30x) Digital peripherals (timers, UART, PCA, SPI, etc.) account for a small percentage of the total power consumption. For example, operating a C8051F300 at 3.06 MHz (internal oscillator divided by 8) and 3.0 Volts, the average device supply current without any digital peripherals enabled is approximately 700 µA. This number typically increases by 18 µA ( 3 % ) when Timer 1 is started at its fastest clocking setting with UART0 constantly transmitting data. The power consumption for timers and UART depends on the frequency at which they are clocked and the supply voltage. The Crossbar and configuration of GPIO pins to push-pull mode can also affect power consumption. In the example above, enabling the Crossbar, routing the UART0 TX signal to P0.4, and configuring the port pin to push-pull mode adds another 82 µA (10%) to the total device supply current. The power consumption for output port pins depends on the frequency that the pin is toggled and the external circuitry connected to the pin. Peripheral Internal Bias Generator 110 µA Temperature Sensor (ADC Enabled) 85 µA Temperature Sensor (ADC Disabled) < 1 µA ADC (enabled) 430 µA ADC (converting) 630 µA Internal Oscillator 340 µA Voltage Comparator 0.4 - 7.6 µA (depending on speed mode) Analog Peripherals The ADC, temperature sensor, internal bias generator, and the internal oscillator consume power when enabled. Table 11 and Table 12 show typical current values for the analog peripherals on these devices. The internal bias generator is automati- 16 Typical Current Consumption Rev. 1.1 AN138 Table 12. Typical Current Contribution for Analog Peripherals at 3.0V (C8051F31x) Peripheral Typical Current Consumption Internal Bias Generator 110 µA Temperature Sensor (ADC Enabled) 83 µA Temperature Sensor (ADC Disabled) < 1 µA ADC (enabled) 480 µA ADC (converting) 650 µA Internal Oscillator 360 µA Voltage Comparator 0.4 - 7.6 µA (depending on speed mode) Digital Current. Using the slope and offset information from Table 10 , the CPU current in Idle mode can be calculated using Equation 4. Equation 4. Calculating Digital Current from Slope and Offset Current [mA] = ( SYSCLK [MHz] × Slope ) + Offset Example Calculations In this example, the slope (0.14 mA/MHz) and offset (0.01 mA) give an estimated digital current of ~15 µA for operation at 32.768 kHz and 3.0 V. Analog Current. In this system, the internal oscillator is disabled when running from the external watch crystal. We add 0 µA for the analog current contribution. Total Current. The total supply current is ~19 µA for a C8051F31x in this configuration. This number is an estimate and may vary by a few microamps in an actual system. The following examples show how to calculate the Example 2: 24.5 MHz Internal total device power consumption by adding the con- Oscillator in Normal Mode with ADC tributions from the oscillator, digital power, and On (C8051F30x) analog power. The examples assume a supply voltage of 3.0V. In this example, we calculate the total device power consumption for operating a C8051F30x device Example 1: 32.768 kHz Watch Crystal from the internal 24.5 MHz calibrated oscillator in in Idle Mode (C8051F31x) Normal mode with the ADC turned on. In this example, we calculate the total device power Oscillator Current. From Table 11 , the internal consumption for operating a C8051F31x device oscillator requires ~340 µA to generate the 24.5 MHz clock signal. from a 32.768 kHz watch crystal in Idle mode. Oscillator Current. From Table 2 , the external Digital Current. Using the slope and offset inforoscillator requires ~4.1 µA to drive the watch crys- mation from Table 7 , the CPU current in Normal mode can be calculated using Equation 4. In this tal. example, the slope (0.16 mA/MHz) and offset (2.0 mA) in “Region B” of Figure 12 give an estimated digital current of ~6.0 mA for operation at 24.5 MHz and 3.0 V. Rev. 1.1 17 AN138 Analog Current. Since the internal bias generator automatically switches on whenever the ADC or the internal oscillator are being used, it contributes 110 µA. When the ADC is enabled (not sampling), it contributes 430 µA. The total analog contribution comes to 540 µA. In this example, the slope (0.16 mA/MHz) and offset (2.0 mA) in “Region B” of Figure 12 give an estimated digital current of ~6 mA for operation at 25.0 MHz and 3.0 V. Analog Current. In this system, the internal oscillator is disabled when running from the external Total Current. There are two ways to estimate the crystal. Since we are using the ADC, we add the total current from the data provided in this applica- 110 µA internal bias current to the 430 µA ADC tion note. First, we can sum the contributions from current for a total 540 µA analog contribution. the oscillator, digital current, and analog current. An alternative is using Figure 10 to determine the Total Current. The total supply current is ~11 mA combined digital, internal oscillator, and bias gen- for a C8051F30x in this configuration. Comparing erator current then adding the ADC contribution to this total to the total from Example 2, we find that obtain the total supply current. Both methods using the internal oscillator saves approximately should yield similar results; however, the second 4 mA while achieving a comparable operating frequency. method is faster. Using the first method, we add the 340 µA oscillator current, 6.0 mA digital current, and 540 µA analog current to obtain a total of 6.9 mA. Using the second method, we add 6.1 mA (supply current at 3.0V from Figure 10) and 430 µA ADC current for a total of 6.5 mA. The estimates from the two methods are within 5% of each other. Example 3: 25.000 MHz Crystal in Normal Mode with ADC On (C8051F30x) In this example, we calculate the total device power consumption for operating a C8051F30x device from a 25.000 MHz crystal in Normal mode with the ADC on. Oscillator Current. From Table 1 , the external oscillator requires ~4.1 mA to drive the crystal. Digital Current. Using the slope and offset information from Table 7 , the CPU current in Normal mode can be calculated using Equation 4. 18 Rev. 1.1 AN138 Power Saving Strategies In most low-power applications, the high performance processing capabilities of the device are not needed 100% of the time. The ability of these devices to switch between clock sources and power modes on-the-fly gives them the flexibility of performing high speed tasks and meet the requirements of a low power budget. In most systems with low power requirements, the average power consumption is optimized. For example, in a battery powered application, the average current determines the battery life. Equation 5 shows how to calculate battery life in a system based on its average current and rating. Batteries contain a fixed amount of charge, specified in a battery datasheet in units of milliamp-hours (mAh). Since the supply voltage is typically constant, minimizing average current is directly proportional to minimizing the average power consumption. Average current is the amount of charge consumed per unit time, or the area under a Current vs. Time chart divided by time, as shown in Figure 16. Figure 16. Average Current – Charge Consumed per Unit Time TIMEtotal Current TIMEactive Iactive AREA = Charge Iavg TIMEidle Iidle Time 0 Equation 5. Calculating Battery Life Battery Life [hours] = Qtotal[mA-h] ----------------------------------Iavg[mA] Equation 6 shows that the average current is the total charge (area) divided by the total time. Equation 6. Calculating Average Current Minimizing Average Power Consumption There are two classes of optimizations that can be used to minimize average power consumption. The first kind involves adjusting system parameters that affect the system at all times. One of the main system level parameters is supply voltage. The supply voltage can be derived from a voltage regulator or from a battery. In low power systems, supply voltage should be minimized in order to save power. The second kind involves structuring the firmware to save power. This involves having a high performance mode and a low power “sleep” mode. These two modes have different design criteria. The device should spend as much time as possible in “sleep” mode in order to save power. ( I active × Time active ) + ( I idle × Time idle ) Iavg = --------------------------------------------------------------------------------------------------------Time total The charge required for a given task can be reduced by minimizing the “active” time or minimizing the peak active current. The designer should always consider minimizing “active” time and peak current to save power. Decreasing Supply Voltage Supply voltage can have a large impact on power consumption. Low-power systems should always be designed to use the minimum supply voltage that allows the device to operate reliably within its specified voltage limits. Rev. 1.1 19 AN138 Many voltage regulators have +/-10% accuracy. If a regulator with this accuracy is used, the minimum design voltage should be 3.0 V, since the regulator output can vary between 2.7 V and 3.3 V. to a crystal, two loading capacitors and a resistor. If a high frequency crystal is used in the design, the loading capacitor connected to the XTAL2 pin can be used by the external oscillator in C mode to derive a low-frequency clock source for “sleep” An alternative to a voltage regulator is to use a bat- mode. tery. Lithium manganese dioxide batteries output 2.85 Volts for a majority of their useful life and can Designing a High Performance Mode be directly connected to the power pins on the device. Batteries can provide a constant voltage A high performance mode should be designed to that does not need regulation. In these systems, the accomplish tasks in a minimal amount of time so on-chip VDD monitor should be enabled to ensure that the system can go back to “sleep” mode as that the device is held in reset when the battery is quickly as possible. This involves adjusting the drained. peak current and the SYSCLK frequency to reduce the area under the Current vs. Time curve. Example 1 shows a system in which the average power consumption is reduced by increasing the SYSCLK frequency in the high performance mode. Designing a Low Power “Sleep” Mode The design goal of a low-power “sleep” mode is to minimize current because the system can spend long intervals of time in this mode. A “sleep” mode can be implemented by putting the device in Idle or Stop mode. Stop mode provides a lower standby current than Idle mode, but Idle mode is easier to recover from. Examples of both implementations are provided at the end of this note. From a power standpoint, most systems will benefit by using the internal oscillator in high performance mode. Measuring Average Current The average system current is best calculated by measuring the power consumption in various modes using lab bench equipment and estimating In “sleep” mode it is important to turn off any the amount of time the system spends in each peripherals (ADC, Internal Oscillator, etc. ) that mode. Example 1 shows the power calculations for are not required. a sampling system that uses the on-chip ADC. In “sleep” mode, it is usually best to operate on an external oscillator. This allows the system to disable the internal oscillator and operate from a very low frequency timebase. Two appealing external oscillator configurations to consider for “sleep” mode are a 32.768 kHz watch crystal and a single capacitor. A capacitor oscillator can consume less power than a crystal, but is less accurate. The main advantage of using a capacitor oscillator is the ability to clock peripherals (such as timers) at rates less than 10 kHz. There is also a cost and PCB space savings associated with using a single capacitor, as opposed 20 Examples Four examples are provided that demonstrate the concepts discussed in this application note. The software for these examples is included at at the end of this note. The examples are: • Rev. 1.1 ADC Sampling (C8051F30x). This example compares the power savings of two different ADC sampling systems. One system uses a 32.768 kHz crystal while sampling and the other switches to the internal oscillator to minimize the time that the ADC remains on. Both systems are identical in Idle mode. AN138 • Waking From Idle mode on UART Activity (C8051F30x). This example shows how a “sleep” mode can be implemented using the device’s Idle mode. The device wakes up when it detects UART activity. tems, one with minimized time in Normal mode and the other with minimized peak current. • Waking From Stop Mode Using a Comparator (C8051F30x and C8051F31x). This example shows how a “sleep” mode can be implemented using the device’s Stop mode. The device wakes up when it detects a button press. A connection diagram of how to wake on SMBus activity is also included in this example. • 32.768 kHz Watch Crystal Low Power Startup Procedure (C8051F30x). This example shows how to start a 32.768 kHz watch crystal, minimizing the time in Normal mode waiting for the crystal to start. When the system in Figure 17 wakes from Idle mode, it turns on the internal oscillator and the ADC, switches SYSCLK to the internal oscillator in divide-by-8 mode, and starts the ADC conversion. After the conversion is complete, it reads the ADC value, disables the ADC and internal oscillator, and puts the CPU back in Idle mode. To capture the ADC sample, the device spends less than 400 µs consuming a peak current of 2.2 mA. Both systems use 4.8 µA in Idle mode to drive a 32 kHz watch crystal and Timer 2. Figure 17. Current vs. Time (Minimized Time in Normal Mode) Example 1: ADC Sampling The two systems in this example take an ADC sample from the on-chip temperature sensor at a rate of 10 Hz. A 32.768 kHz watch crystal and associated loading capacitors and shunt resistor are connected between XTAL1 and XTAL2. Timer 2 overflows every 100 ms generating an interrupt that wakes the device up from Idle mode. When the device wakes up, it captures one ADC sample then goes back into Idle mode until the next interrupt occurs. Since this system is battery powered, one of its goals is to minimize the amount of charge consumed per ADC sample. Since charge is current integrated over time, there is a choice between minimizing time or peak current required to take a sample. For example, to capture the ADC sample, the device may switch to the 3 MHz internal oscillator and use a larger amount of current for a short period of time or remain at 32 kHz and use less current for a longer period of time. Figure 17 and Figure 18 show current vs. time for the two sys- Current (uA) 2200 400 us 400 us 4.8 0 100 Time (ms) Figure 18. Current vs. Time (Minimized Peak Current) Current (uA) Rev. 1.1 1.5 ms 1.5 ms 650 4.8 0 100 Time (ms) 21 AN138 When the system in Figure 18 wakes up from Idle mode, it immediately turns on the ADC and initiates a sample. It does not turn on the internal oscillator and SYSCLK remains at 32.768 kHz. After the conversion is complete, it reads the ADC value, turns off the ADC and goes into Idle mode. To capture the ADC sample, the device spends less than 1.5 ms consuming a peak current of 0.65 mA. Example 2: Waking from Idle Mode on UART Activity This example configures External Interrupt 0 to wake the device from Idle mode on detecting activity on the UART receive signal. Once the CPU comes out of Idle Mode, it disables External Interrupt 0 as shown in Figure 19, switches to the internal oscillator, enables UART0 reception, and Using Equation 6, the system in Figure 17 has an discards the first UART frame. In this system, the average current of 14 µA. If the system is powered first UART frame received after a period of inactivfrom an ideal 3.0 Volt (actual voltage 2.85V) lith- ity is interpreted as a “wakeup” signal. ium manganese dioxide watch battery with a capacity of 575 mA-h, the battery life would be In order for the device to wake up and remain synapproximately 42,000 hours, or over four and a half chronized for UART communication, the “wakeup” signal has to have exactly one falling years. edge followed by one rising edge, as shown in The average current for the system in Figure 18 is Figure 20. Since the UART start bit is always ‘0’ 15 µA. If this system is powered with the same 3.0 Volt lithium manganese dioxide watch battery, the battery life would also be around 40,000 hours. Figure 19. Waking from Idle Mode on UART Activity In this example, increasing the system clock frequency in the high power mode decreased the average current. These examples do not take into account changes in temperature and battery performance variations over the life of the battery. One source for Application Manuals and Battery Datasheets is the Technical Info section of the Energizer web site (www.energizer.com). TX UART0 RX External Interrupt 0 Figure 20. UART “Wake-up” Signal UART RX Start Wake-Up Stop Start SYSCLK must increase before this edge to allow UART communication minimum 13 SYSCLK cycles SYSCLK 5 - 10 kHz External Oscillator in C-mode using a 33pF Capacitor on XTAL2 22 3.0625 MHz Internal Oscillator in divide by 8 mode Rev. 1.1 AN138 and the stop bit is always ‘1’, the data bits can be any value as long as there is only one falling edge and one rising edge in the received signal. Keep in mind that characters are sent LSB first. Example “wakeup” characters are 0x00, 0xFF, and 0xF0 but not 0x0F. The average power consumption for this system scales with the amount of UART activity. As Figure 21 shows, the system consumes 4.2 µA of current in Idle mode and approximately 1.5 mA in Active mode at 3.0 Volts. In some applications, it is possible to recover the The maximum baud rate supported by the system first character but this places more restrictions on will be limited by the frequency of the external maximum UART baud rate and minimum external oscillator used while the device is in Idle mode. clock frequency. When programming in ‘C’, it takes a minimum of 13 SYSCLK cycles after the falling edge of the Example 3: Waking from Stop Mode “wakeup” signal to enter an External Interrupt ISR Using a Comparator and switch to the internal oscillator. If the UART character following the “wakeup” signal arrives before the internal oscillator is enabled, then the This example shows how a “sleep” mode can be two UART systems may become unsynchronized. implemented in a system using the Stop mode of the CPU. This application implements a software Equation 7 can be used to calculate the maximum counter that is incremented approximately every baud rate supported by a system with a given exter- second when the device is in Normal mode. If the nal clock frequency. Equation 7 is based upon system is powered down when it is in Stop mode, 10 bits per UART frame and 13 external clock the counter resumes counting the next time it enters cycles required to turn on the internal oscillator. Normal mode. If the system is powered down while For example, if the external oscillator is a capacitor it is in Normal mode, the counter will reset to zero. oscillating at 5 kHz, the highest standard baud rate Every time the counter is updated, the current value of the counter is printed to the UART. supported by the system would be 2400 baud. The S2 switch toggles the system back and forth between Stop mode and Normal mode. On power up, the system is in Stop mode. The system enters Equation 7. Calculating Maximum Supported Baud Rate 10 MAX_BAUD_RATE < ------ × EXTCLK 13 The software for this example uses a 33 pF capacitor connected to the XTAL2 pin as an external oscillator. Considering stray capacitance and other effects, the system clock frequency is between 5 kHz and 10 kHz when the external oscillator is selected and the external oscillator drive current (XFCN) is set to its lowest value. The “wakeup” signal chosen in this example is ‘0xFF’. When the system wakes up, it waits for the next character and transmits a string containing that character. Then it disables UART reception, enables External Interrupt 0, and goes back into Idle mode. Figure 21. Example 2 Active Mode vs. Idle Mode Power Consumption Current (uA) 1500 4.2 Normal Mode 3.0625 MHz Idle Mode 5 - 10 kHz Time Rev. 1.1 23 AN138 Normal mode when the S2 switch on the target tions are needed for the C8051F31x. They are cirboard is pressed, causing a Comparator 0 reset. cled in Figure 22 and Figure 23. The C8051F30x requires one less pin because the CP0+ signal and Upon entering Normal mode, External Interrupt 0 the External Interrupt 0 input can use the same pin. (/INT0) is activated to sense the S2 switch and Comparator 0 is disabled as a reset source. Pressing In this example, the LED on the target board is S2 in Normal mode will cause the INT0_ISR to put used to conveniently provide a voltage that is the system in Stop mode. between VDD and GND. This voltage can be generated using a resistor network or DC power supThree target board connections are needed to run ply. Also, the target board provides a convenient this example on the C8051F30x and four connec- pull-up resistor (R4) for the S2 switch. The on-chip Figure 22. Example 3 Target Board Connection Diagram (C8051F30x) VDD Wire R4 100K 1 P0.0 S2 Jumper 2 CP0 + P0.1 CP0 - + CP0 - Reset Funnel VDD Weak Pullup 3 LED P0.2 Figure 23. Example 3 Target Board Connection Diagram (C8051F31x) 2 P0.0 VDD Wire R4 100K 1 P1.0 S2 Jumper LED 24 4 3 P1.1 CP0 + CP0 - P3.3 Rev. 1.1 + CP0 - Reset Funnel VDD Weak Pullup AN138 weak pull-up for the port pin can replace R4 if the port pin is configured as a digital input and weak pull-ups are enabled. The voltage at the CP0- input is used by Comparator 0 to detect if the CP0+ signal is high or low. When Comparator 0 is enabled as a reset source, it will generate a reset when the non-inverting (CP0+) input is lower than the inverting (CP0-) input. defined to be TRUE if it has a value of 0x55. All other values are defined as FALSE. On every reset, the device decodes the <SLEEP> variable stored in FLASH and the RSTSRC register to determine its state. Note that if the PORSF (Power On Reset Flag) is set in the RSTSRC register, then all other flag bits in that register are undefined. Table 13 shows how the device decodes the RSTSRC register to determine its state. The system remembers its state by storing a single-byte <SLEEP> flag and a copy of the counter in FLASH. The <SLEEP> flag is The techniques in this example can be used to wake a device from Stop mode on SMBus activity. An SMBus start signal consists of a Table 13. Reset Source Register Decoding for Example 3 Reset Type RSTSRC Action Taken Hardware, Power On, Missing Clock Detector, Watchdog Timer, or FLASH error 0x01, 0x02, 0x04, Prepare the device for Stop mode. 1. Enable and configure Comparator 0. 2. Enable Comparator 0 as a reset source. 3. Go into Stop Mode waiting for the User to press the S2 switch to generate a comparator reset. Comparator 0x08, or 0x40 0x20 If the <SLEEP> flag is set to TRUE, then prepare device to operate in Normal Mode and resume counting. 1. Restore the <COUNT> (READ FLASH). 2. Set <SLEEP> flag to FALSE (ERASE FLASH). 3. Enable External Interrupt 0. This interrupt will save the <COUNT> in FLASH, set the <SLEEP> flag, and put the CPU in Stop mode when S2 is pressed. If the <SLEEP> flag is set to FALSE, start counting at zero. This condition only happens the first time after a firmware download or if power is lost while the device is in Normal mode. 1. Set <COUNT> to zero. 2. Enable External Interrupt 0. The device should now be operating in Normal mode. Rev. 1.1 25 AN138 falling edge on SDA while SCL is high. When a start condition is detected, the comparator resets the device. If the device is a slave, it will NACK the first transfer (considered a “wakeup” signal), but respond to all transfers that follow it. Figure 24 shows a possible connection diagram. Figure 24. Example Wake-On-SMBus Connection Diagram SDA SMBus SCL CP0 + CP0 - + - CP0 Example 4: 32.768 kHz Watch Crystal Low-Power Startup Procedure This example shows how to start an external 32.768 kHz watch crystal in low power applications. Since a watch crystal can take longer than one second to start, the device goes into Idle mode after turning on the external oscillator. At 100 ms intervals, Timer 2 generates an interrupt and wakes the device to check the XTLVLD flag. Once the watch crystal has started, the internal oscillator is disabled and the system uses the crystal as the system clock source. 26 Rev. 1.1 AN138 Software Examples Example 1A: ADC Sampling System (Minimized “Active” Time) //----------------------------------------------------------------------------// ADC_A_F30x.c //----------------------------------------------------------------------------// Copyright 2003 Cygnal Integrated Products, Inc. // // AUTH: FB // DATH: 23 JAN 03 // // This example captures ADC samples at a rate of 10 Hz from P0.0 and is clocked // from a 32.768 kHz watch crystal. This program keeps the CPU in Idle mode // until a Timer2 overflow. The Timer2 interrupt turns on the ADC and internal // oscillator, takes a sample, then turns the ADC and the internal oscillator // off to save power. While peak current increases when the internal oscillator // is turned on, the power saved by minimizing the time needed to take a sample // is more than the power consumed by increasing the system clock frequency. // // // Target: C8051F30x // // Tool chain: KEIL Eval ‘c’ // //----------------------------------------------------------------------------// Includes //----------------------------------------------------------------------------#include <c8051f300.h> // SFR declarations #include <math.h> //----------------------------------------------------------------------------// 16-bit SFR Definitions for ‘F30x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 PCA0CP1 PCA0CP2 PCA0 PCA0CP0 = = = = = = = 0x82; 0xca; 0xcc; 0xe9; 0xeb; 0xf9; 0xfb; // // // // // // // data pointer Timer2 reload value Timer2 counter PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 counter PCA0 Module 0 Capture/Compare //----------------------------------------------------------------------------// Global CONSTANTS //----------------------------------------------------------------------------#define INTCLK 24500000 / 8 #define EXTCLK 32768 #define SAMPLERATE 10 sbit LED = P0^2; sbit SW2 = P0^3; // // // // // Internal Oscillator frequency in Hz (divide by 8 mode) Frequency for 32.768 kHz External crystal oscillator ADC Sampling Rate in Hz // LED=’1’ means ON // SW2=’0’ means switch pressed Rev. 1.1 27 AN138 //----------------------------------------------------------------------------// Global VARIABLES //----------------------------------------------------------------------------char ADC_READING = 0; //----------------------------------------------------------------------------// Function PROTOTYPES //----------------------------------------------------------------------------void SYSCLK_Init (void); void PORT_Init (void); void Crystal_Stabilize (void); void Timer2_Init (int counts); void Timer2_ISR (void); //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------void main (void) { // disable watchdog timer PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer // enable) PORT_Init(); SYSCLK_Init(); Timer2_Init(EXTCLK/8/SAMPLERATE); // // // // initialize the Crossbar and GPIO start external oscillator configure Timer2 to overflow at <SAMPLERATE> times per second EA = 1; // enable global interrupts while(1){ PCON |= 0x01; } // put the device in Idle mode } //----------------------------------------------------------------------------// SYSCLK_Init //----------------------------------------------------------------------------// // This routine initializes the system clock to use the external 32.768 kHz // watch crystal as its clock source and disables the internal oscillator. // void SYSCLK_Init (void) { 28 int i; // delay counter OSCXCN = 0x61; // start external oscillator for (i=0; i < 256; i++) ; // wait for osc to start up while (!(OSCXCN & 0x80)) ; // wait for crystal osc. to settle Crystal_Stabilize(); // wait for crystal osc. to stablilize Rev. 1.1 AN138 OSCXCN = 0x60; RSTSRC = 0x04; OSCICN = 0x08; // decrease crystal drive current // enable missing clock detector // switch to external oscillator } //----------------------------------------------------------------------------// Crystal_Stabilize //----------------------------------------------------------------------------// // Low-frequency crystal stabilization wait routine: // // This routine measures the period of the external oscillator with respect // to the internal oscillator and loops until the external oscillator period is // measured to be within 4 internal oscillator periods for 500 cycles in // a row. This is only necessary for tuning fork crystals, which have // abnormally long stabilization times (on the order of seconds). // // Assumes that the internal oscillator operating in divide-by-8 mode is // selected as the system clock source. Also assumes that the external // oscillator has been enabled, configured, and is oscillating. // // Here we measure the number of system clocks in 8 “EXTCLK/8” periods. // We compare successive measurements. When we obtain 500 measurements // in a row that are all within 4 system clocks of each other the // routine will exit. This condition will only occur once the crystal // oscillator has fully stabilized at its resonant frequency. // // Note that this can take several seconds. // void Crystal_Stabilize (void) { int current, last; // used in osc. stabilization check int tolerance_count; // init PCA0 PCA0CN = 0x00; PCA0MD = 0x0b; // init Timer0 TCON &= ~0x30; TMOD &= ~0x0f; TMOD |= 0x01; CKCON |= 0x08; tolerance_count = 500; // // // // Stop counter; clear all flags PCA counts in IDLE mode; EXTCLK / 8 is time base; overflow interrupt is enabled // Stop timer; clear TF0 // Timer0 in 16-bit counter mode // Timer0 counts SYSCLKs // wait for 500 external cycles in // a row to lie within 4 internal // clocks of each other current = 0; do { PCA0CN = 0x00; PCA0L = 0xFF; PCA0H = 0xFF; TCON &= ~0x30; // set PCA time base to ‘-1’ Rev. 1.1 29 AN138 TH0 = 0x00; TL0 = 0x00; // start PCA0 CR = 1; while (CF == 0); TR0 = 1; CF = 0; PCA0L = -8; PCA0H = (-8) >> 8; while (CF == 0); TR0 = 0; last = current; current = (TH0 << 8) | TL0; if (abs (current - last) > 4) { tolerance_count = 500; } else { tolerance_count--; } // init T0 time base // // // // wait for edge Start Timer0 clear PCA overflow set PCA to overflow in 8 cycles // falls outside bounds; reset // counter // in-bounds; update counter } while (tolerance_count != 0); } //----------------------------------------------------------------------------// PORT_Init //----------------------------------------------------------------------------// // Configure the Crossbar and GPIO ports. // P0.0 - ADC Input // P0.1 // P0.2 - XTAL1 // P0.3 - XTAL2 // P0.4 // P0.5 // P0.6 // P0.7 - C2D // void PORT_Init (void) { XBR0 = 0x0d; // skip crystal pins and P0.0 in crossbar XBR2 = 0x40; // enable crossbar and weak pull-ups P0MDIN &= ~0x0c; P0MDIN &= ~0x01; // configure XTAL1 and XTAL2 as analog // inputs // configure P0.0 as an analog input } //----------------------------------------------------------------------------// Timer2_Init //----------------------------------------------------------------------------// // Configure Timer2 to auto-reload at interval specified by <counts> // using EXTCLK / 8 as its time base. // void Timer2_Init (int counts) { TMR2CN = 0x01; // Stop Timer2; 30 Rev. 1.1 AN138 // Timer2 timebase is EXTCLK/8 TMR2RL = -counts; TMR2 = TMR2RL; ET2 = 1; TR2 = 1; // // // // Init reload value Init Timer2 enable Timer2 interrupts start Timer2 } //----------------------------------------------------------------------------// Timer2_ISR //----------------------------------------------------------------------------// // This ISR is called at <SAMPLERATE> Hz on Timer2 overflows // void Timer2_ISR (void) interrupt 5 { TF2H = 0; // clear Timer2 overflow flag OSCICN |= 0x04; OSCICN &= ~0x08; // Start Internal Oscillator // Switch to Internal Oscillator ADC0CN = 0x80; // enable ADC REF0CN |= 0x0A; // Select voltage reference and enable // bias generator AMX0SL = 0x80; // ADC in single-ended mode sampling P0.0 ADC0CF = (INTCLK << 3); // Set SAR clock frequency to ~ 3MHz ADC0CF |= 0x01; // Set PGA gain // Settling time starts at this point. Sampling should not start until // the appropriate settling time has passed. Each SYSCLK cycle is 326.5 ns. AD0INT = 0; AD0BUSY = 1; while(!AD0INT); // Clear conversion complete flag // Start a conversion // Wait until conversion complete AD0EN = 0; REF0CN &= ~0x02; // Disable ADC // Turn off bias generator ADC_READING = ADC0; // Capture ADC Reading OSCICN |= 0x08; OSCICN &= ~0x07; // Switch to external oscillator // disable internal oscillator } Rev. 1.1 31 AN138 Example 1B: ADC Sampling System (Minimized “Active” Peak Current) //----------------------------------------------------------------------------// ADC_B_F30x.c //----------------------------------------------------------------------------// Copyright 2003 Cygnal Integrated Products, Inc. // // AUTH: FB // DATH: 23 JAN 03 // // This example captures ADC samples at a rate of 10 Hz from P0.0 and is clocked // from a 32.768 kHz watch crystal. This program keeps the CPU in Idle mode // until a Timer2 overflow. The Timer2 interrupt turns on the ADC, takes a // sample, then turns it off to save power. // // This program is meant to be used as a comparison to ADC_A_F30x to show that // reducing the peak current required to take an ADC sample does not always // save power. In this case, decreasing the SYSCLK frequency increased the // average system current because the ADC was “on” for a longer period of time. // // Target: C8051F30x // // Tool chain: KEIL Eval ‘c’ // //----------------------------------------------------------------------------// Includes //----------------------------------------------------------------------------#include <c8051f300.h> // SFR declarations #include <math.h> //----------------------------------------------------------------------------// 16-bit SFR Definitions for ‘F30x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 PCA0CP1 PCA0CP2 PCA0 PCA0CP0 = = = = = = = 0x82; 0xca; 0xcc; 0xe9; 0xeb; 0xf9; 0xfb; // // // // // // // data pointer Timer2 reload value Timer2 counter PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 counter PCA0 Module 0 Capture/Compare //----------------------------------------------------------------------------// Global CONSTANTS //----------------------------------------------------------------------------#define INTCLK 24500000 / 8 #define EXTCLK 32768 #define SAMPLERATE 10 sbit LED = P0^2; sbit SW2 = P0^3; // // // // // Internal Oscillator frequency in Hz (divide by 8 mode) Frequency for 32.768 kHz External crystal oscillator ADC Sampling Rate in Hz // LED=’1’ means ON // SW2=’0’ means switch pressed //----------------------------------------------------------------------------- 32 Rev. 1.1 AN138 // Global VARIABLES //----------------------------------------------------------------------------char ADC_READING = 0; //----------------------------------------------------------------------------// Function PROTOTYPES //----------------------------------------------------------------------------void SYSCLK_Init (void); void PORT_Init (void); void Crystal_Stabilize (void); void Timer2_Init (int counts); void Timer2_ISR (void); //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------void main (void) { // disable watchdog timer PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer // enable) PORT_Init(); SYSCLK_Init(); Timer2_Init(EXTCLK/8/SAMPLERATE); // // // // initialize the Crossbar and GPIO start external oscillator configure Timer2 to overflow at <SAMPLERATE> times per second EA = 1; // enable global interrupts while(1){ PCON |= 0x01; // put the device in idle mode } } //----------------------------------------------------------------------------// SYSCLK_Init //----------------------------------------------------------------------------// // This routine initializes the system clock to use the external 32.768 kHz // watch crystal as its clock source and disables the internal oscillator. // void SYSCLK_Init (void) { int i; // delay counter OSCXCN = 0x61; // start external oscillator for (i=0; i < 256; i++) ; // wait for osc to start up while (!(OSCXCN & 0x80)) ; // wait for crystal osc. to settle Crystal_Stabilize(); OSCXCN = 0x60; // decrease XFCN (crystal drive current) Rev. 1.1 33 AN138 RSTSRC = 0x04; OSCICN = 0x08; // enable missing clock detector // switch to external oscillator } //----------------------------------------------------------------------------// Crystal_Stabilize //----------------------------------------------------------------------------// // Low-frequency crystal stabilization wait routine: // // This routine measures the period of the external oscillator with respect // to the internal oscillator and loops until the external oscillator period is // measured to be within 4 internal oscillator periods for 500 cycles in // a row. This is only necessary for tuning fork crystals, which have // abnormally long stabilization times (on the order of seconds). // // Assumes that the internal oscillator operating in divide-by-8 mode is // selected as the system clock source. Also assumes that the external // oscillator has been enabled, configured, and is oscillating. // // Here we measure the number of system clocks in 8 “EXTCLK/8” periods. // We compare successive measurements. When we obtain 500 measurements // in a row that are all within 4 system clocks of each other the // routine will exit. This condition will only occur once the crystal // oscillator has fully stabilized at its resonant frequency. // // Note that this can take several seconds. // void Crystal_Stabilize (void) { int current, last; // used in osc. stabilization check int tolerance_count; // init PCA0 PCA0CN = 0x00; PCA0MD = 0x0b; // init Timer0 TCON &= ~0x30; TMOD &= ~0x0f; TMOD |= 0x01; CKCON |= 0x08; tolerance_count = 500; // // // // Stop counter; clear all flags PCA counts in IDLE mode; EXTCLK / 8 is time base; overflow interrupt is enabled // Stop timer; clear TF0 // Timer0 in 16-bit counter mode // Timer0 counts SYSCLKs // wait for 500 external cycles in a row // to lie within 4 internal clocks of each // other current = 0; do { PCA0CN = 0x00; PCA0L = 0xFF; PCA0H = 0xFF; TCON &= ~0x30; TH0 = 0x00; TL0 = 0x00; 34 // set PCA time base to ‘-1’ // init T0 time base Rev. 1.1 AN138 // start PCA0 CR = 1; while (CF == 0); TR0 = 1; CF = 0; PCA0L = -8; PCA0H = (-8) >> 8; while (CF == 0); TR0 = 0; last = current; current = (TH0 << 8) | TL0; if (abs (current - last) > 4) { tolerance_count = 500; } else { tolerance_count--; } // // // // wait for edge Start Timer0 clear PCA overflow set PCA to overflow in 8 cycles // falls outside bounds; reset // counter // in-bounds; update counter } while (tolerance_count != 0); } //----------------------------------------------------------------------------// PORT_Init //----------------------------------------------------------------------------// // Configure the Crossbar and GPIO ports. // P0.0 - ADC Input // P0.1 // P0.2 - XTAL1 // P0.3 - XTAL2 // P0.4 // P0.5 // P0.6 // P0.7 - C2D // void PORT_Init (void) { XBR0 = 0x0d; // skip crystal pins and P0.0 in crossbar XBR2 = 0x40; // enable crossbar and weak pull-ups P0MDIN &= ~0x0c; P0MDIN &= ~0x01; // configure XTAL1 and XTAL2 as analog // inputs // configure P0.0 as an analog input } //----------------------------------------------------------------------------// Timer2_Init //----------------------------------------------------------------------------// // Configure Timer2 to auto-reload at interval specified by <counts> // using EXTCLK / 8 as its time base. // void Timer2_Init (int counts) { TMR2CN = 0x01; // Stop Timer2; // Timer2 timebase is EXTCLK/8 Rev. 1.1 35 AN138 TMR2RL = -counts; TMR2 = TMR2RL; ET2 = 1; TR2 = 1; // // // // Init reload value Init Timer2 enable Timer2 interrupts start Timer2 } //----------------------------------------------------------------------------// Timer2_ISR //----------------------------------------------------------------------------// // This ISR is called at <SAMPLERATE> Hz on Timer2 overflows // void Timer2_ISR (void) interrupt 5 { TF2H = 0; // clear Timer2 overflow flag ADC0CN = 0x80; // enable ADC REF0CN |= 0x0A; // Select voltage reference and enable // bias generator AMX0SL = 0x80; // ADC in single-ended mode sampling P0.0 ADC0CF = (EXTCLK << 3); // Set SAR clock frequency to ~32kHz ADC0CF |= 0x01; // Set PGA gain // settling time starts at this point, sampling should not start until // the appropriate settling time has passed. At this point, we using // a 32.768 kHz so each SYSCLK cycle is 30.5 us. AD0INT = 0; AD0BUSY = 1; while(!AD0INT); // Clear conversion complete flag // Start a conversion // Wait until conversion complete AD0EN = 0; REF0CN &= ~0x02; ADC_READING = ADC0; // Disable ADC // Turn off bias generator // Capture ADC Reading } 36 Rev. 1.1 AN138 Example 2: Waking From Idle Mode on UART Activity (C8051F30x) //----------------------------------------------------------------------------// UART_Idle_F30x.c //----------------------------------------------------------------------------// Copyright 2002 Cygnal Integrated Products, Inc. // // AUTH: FB // DATE: 6 NOV 02 // // // This example shows how a system can wake from Idle mode upon receiving // a wakeup signal on the UART RX line. The system operates on the internal // oscillator divided by 8 in Normal mode. When in Idle mode, the system uses // the external oscillator in C-mode as its clock source. This code assumes // a 33pF capacitor is present between XTAL2 and GND. The capacitor causes // oscillation between 5kHz and 10kHz when the external oscillator drive // current (XFCN) is set to its lowest value. // // When in Normal mode, the program gets one character from the UART at 2400 // baud, transmits a string containing the character, and goes back into Idle // mode. The system consumes approximately 4.2 uA in Idle mode and 1.5 mA in // Normal mode. // // The wakeup character must have only one falling edge followed by only one // rising edge. Since the start bit is a ‘0’ and the stop bit is a ‘1’, // example wakeup characters are 0x00, 0xFF, and 0xF0 but not 0x0F. Keep in // mind that characters are sent LSB first. // // The text file “FF_H.txt” contains an 0xFF character followed by ‘H’. It // can be sent over UART to wake up the system from Idle mode. // // Target: C8051F30x // Tool chain: KEIL C51 6.03 / KEIL EVAL C51 // //----------------------------------------------------------------------------// Includes //----------------------------------------------------------------------------#include <c8051f300.h> #include <stdio.h> #include <math.h> // SFR declarations //----------------------------------------------------------------------------// 16-bit SFR Definitions for ‘F30x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 PCA0CP1 PCA0CP2 PCA0 PCA0CP0 = = = = = = = 0x82; 0xca; 0xcc; 0xe9; 0xeb; 0xf9; 0xfb; // // // // // // // data pointer Timer2 reload value Timer2 counter PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 counter PCA0 Module 0 Capture/Compare //----------------------------------------------------------------------------// Global CONSTANTS //----------------------------------------------------------------------------- Rev. 1.1 37 AN138 #define INTCLK 24500000 / 8 #define EXTCLK 5000 #define BAUDRATE 2400 sbit sbit sbit sbit LED = P0^2; SW2 = P0^3; TX0_PIN = P0^4; RX0_PIN = P0^5; // // // // Internal Oscillator frequency in Hz (divide by 8 mode) Frequency of external capacitor oscillator // Baudrate in bits per second // // // // LED=’1’ means ON SW2=’0’ means switch pressed UART TX0 pin UART RX0 pin //----------------------------------------------------------------------------// Function PROTOTYPES //----------------------------------------------------------------------------void PORT_Init (void); void UART0_Init (void); void INT0_ISR (void); //----------------------------------------------------------------------------// Global VARIABLES //----------------------------------------------------------------------------bit UART_ACTIVE = 0; // Flag indicating system is in Normal // mode operating at 3.0625 MHz //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------void main (void) { char c; // Disable Watchdog timer PCA0MD &= ~0x40; PORT_Init (); UART0_Init (); // // // // WDTE = 0 (clear watchdog timer enable) initialize crossbar and GPIO initialize UART0 IT01CF = 0x05; // Configure External Interrupt 0 to // generate an interrupt on the falling // edge of P0.5 (UART RX signal) EA = 1; // Enable global interrupts while (1) { if(UART_ACTIVE){ c = getchar(); // Get the next character printf(“\nThe character you entered was: %c”, c); } printf(“\n\nTransmit an (0xFF) to wake up the system.\n”); 38 Rev. 1.1 AN138 UART_ACTIVE = 0; // Make device ready for Idle mode P0MDOUT &= ~0x10; TX0_PIN = 1; // Make TX0_PIN open-drain // Make TX0_PIN high impedance REN0 = 0; // Disable UART reception OSCXCN = 0x50; // Start external oscillator in C mode RSTSRC = 0x00; // Disable missing clock detector OSCICN = 0x08; // Switch to external oscillator // and disable internal oscillator TR1 = 0; // Disable Timer1 EX0 = 1; // Enable External Interrupt 0 PCON |= 0x01; // Go into Idle mode } } //----------------------------------------------------------------------------// Interrupt Service Routines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// INT0_ISR //----------------------------------------------------------------------------// // This Interrupt Service Routine is called when a UART character is received // when the system is in Idle mode. // // It enables the UART and sets the system state variable <UART_ACTIVE> to ‘1’. // void INT0_ISR (void) interrupt 0 { OSCICN = 0x04; // Enable Internal oscillator in divide // by 8 mode and switch to it EX0 = 0; // Disable External Interrupt0 TR1 = 1; REN0 = 1; // Enable Timer1 // Enable UART reception P0MDOUT |= 0x10; // enable TX0 as a push-pull output UART_ACTIVE = 1; // Indicate UART is ready for communication } //----------------------------------------------------------------------------// Initialization Subroutines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// PORT_Init //----------------------------------------------------------------------------- Rev. 1.1 39 AN138 // // Configure the Crossbar and GPIO ports. // P0.0 // P0.1 // P0.2 - LED (push-pull) // P0.3 - SW2 // P0.4 - UART TX (push-pull) // P0.5 - UART RX // P0.6 // P0.7 - C2D // void PORT_Init (void) { XBR0 = 0x08; // skip XTAL2 in the crossbar assignments XBR1 = 0x03; // UART0 TX and RX pins enabled XBR2 = 0x40; // Enable crossbar and weak pull-ups P0MDOUT |= 0x10; // enable TX0 as a push-pull output P0MDIN &= ~0x08; // Configure XTAL2 as an analog input } //----------------------------------------------------------------------------// UART0_Init //----------------------------------------------------------------------------// // Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. // void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear RI0 and TI0 bits if (INTCLK/BAUDRATE/2/256 < 1) { TH1 = -(INTCLK/BAUDRATE/2); CKCON |= 0x10; // T1M = 1; SCA1:0 = xx } else if (INTCLK/BAUDRATE/2/256 < 4) { TH1 = -(INTCLK/BAUDRATE/2/4); CKCON &= ~0x13; CKCON |= 0x01; // T1M = 0; SCA1:0 = 01 } else if (INTCLK/BAUDRATE/2/256 < 12) { TH1 = -(INTCLK/BAUDRATE/2/12); CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(INTCLK/BAUDRATE/2/48); CKCON &= ~0x13; CKCON |= 0x02; // T1M = 0; SCA1:0 = 10 } TL1 = TH1; TMOD &= ~0xf0; TMOD |= 0x20; TR1 = 1; TI0 = 1; // set Timer1 to reload value // TMOD: timer 1 in 8-bit autoreload // START Timer1 // Indicate TX0 ready } 40 Rev. 1.1 AN138 Example 3: Waking from Stop Mode Using a Comparator (C8051F30x) //----------------------------------------------------------------------------// CP0_Stop_F30x.c //----------------------------------------------------------------------------// Copyright 2003 Cygnal Integrated Products, Inc. // // AUTH: FB / GV // DATE: 23 JAN 03 // // This example shows how a sleep mode can be implemented in a system using // the Stop mode of the CPU. This application implements a software counter // that is incremented approximately every second when the device is in // Normal mode. If the system is powered down when it is in Stop mode, the // counter resumes counting the next time it enters Normal mode. If the // system is powered down while it is in Normal mode, the counter will reset // to zero. Every time the counter is updated, the current value of the // counter is printed to the UART. // // The S2 switch toggles the system back and forth between Stop mode and // Normal mode. On power up, the system is in Stop mode. The system enters // Normal mode when the S2 switch on the target board is pressed, causing // a Comparator 0 reset. // // Upon entering Normal mode, External Interrupt 0 (/INT0) is activated // to sense the S2 switch and Comparator 0 is disabled as a reset source. // Pressing S2 in Normal mode will cause the INT0_ISR to put the system // in Stop mode. // // This program uses Comparator 0 as a reset source. When S2 on the target // board is pressed, the the CP0+ input drops below CP0- (VDD/2). This causes // Comparator 0 to issue a system reset. // // For this example, it is necessary to make the following connections: // 1. P0.3_SW -> P0.0 // 2. P0.2 -> P0.1 // 3. P0.2_LED -> P0.2 // // P0.1 is used as a reference voltage for the comparator and should be // approximately halfway between VDD and GND. When the LED is connected // to P0.2 (high-impedance with weak pull-up), the voltage on P0.2 is // around 1.7 Volts. // // Since this program writes to FLASH, the VDD monitor is enabled. // // Target: C8051F30x // Tool Chain: KEIL C51 6.03 / KEIL EVAL C51 // //----------------------------------------------------------------------------// Include Files //----------------------------------------------------------------------------#include <c8051f300.h> #include <stdio.h> //----------------------------------------------------------------------------- Rev. 1.1 41 AN138 // 16-bit SFR Definitions for ‘F30x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 PCA0CP1 PCA0CP2 PCA0 PCA0CP0 = = = = = = = 0x82; 0xca; 0xcc; 0xe9; 0xeb; 0xf9; 0xfb; // // // // // // // data pointer Timer2 reload value Timer2 counter PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 counter PCA0 Module 0 Capture/Compare //----------------------------------------------------------------------------// Global Constants //----------------------------------------------------------------------------#define SYSCLK 3062500 #define BAUDRATE 9600 // System Clock Frequency in Hz // UART Baud Rate in bps sbit S2 = P0^0; // Switch on Target Board //----------------------------------------------------------------------------// Global Variables //----------------------------------------------------------------------------long COUNT = 0; // Software Counter char code SLEEP _at_ 0x1000; // // // // // Flag that indicates device is in a low-power state. The flag is TRUE when it contains an 0x55 pattern. Any other pattern indicates FALSE. long code COUNT_SAVE _at_ 0x1001; // Non-volatile storage for // the current count //----------------------------------------------------------------------------// Function Prototypes //----------------------------------------------------------------------------void void void void void void void void SYSCLK_Init (void); PORT_Init (void); CPT0_Init (void); ResetSRC_Init(void); EX0_Init(void); UART0_Init (void); Check_Reset_Source(void); wait_ms(int ms); //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------void main (void) { PCA0MD &= ~0x40; RSTSRC = 0x02; 42 // disable the watchdog timer // enable VDD monitor Rev. 1.1 AN138 EX0_Init(); PORT_Init (); SYSCLK_Init(); UART0_Init(); // // // // initialize initialize initialize initialize External Interrupt 0 crossbar and GPIO the system clock UART communication EA = 1; // Enable global interrupts Check_Reset_Source(); // // // // check whether the source of of the last reset was due to a power-on condition or due to a comparator while(1){ // print current count printf(“Current Count: %ld\n”, COUNT); COUNT++; // wait for one second wait_ms(1000); } } //----------------------------------------------------------------------------// Check_Reset_Source //----------------------------------------------------------------------------// // This routine is called on every device reset. // // On each comparator reset, it restores the value of <COUNT> from the // <COUNT_SAVE> variable stored in FLASH if the device was in a low-power state // prior to the reset(i.e. the SLEEP flag in FLASH was set to an 0x55 pattern). // If the <SLEEP> flag was not set then the <COUNT> variable is set to zero and // the device starts normal mode operation. // // On each power-on reset or HW pin reset, the device goes into a low power // mode waiting for a comparator reset. // void Check_Reset_Source(void) { char EA_SAVE; // interrupt state preservation char xdata * idata ptrSLEEP = &SLEEP; // FLASH write pointer printf(“\nDevice Reset -- RESET SOURCE = 0x%02bX\n\n”, RSTSRC); // check for power-on, HW pin, watchdog timer or missing clock detector reset if(RSTSRC & 0x4F){ CPT0_Init(); // initialize comparator 0 ResetSRC_Init(); // set comparator 0 as a reset source printf(“Entering Stop Mode\n\n”); PCON |= 0x02; // put device in stop mode } Rev. 1.1 43 AN138 // check for a comparator reset else if( RSTSRC & 0x20){ while(!S2); wait_ms(5); // wait while switch down // wait until switch stabilizes // if the device was in a low-power state ( <SLEEP> flag is set to TRUE), // then resume counting, otherwise start counting from zero if(SLEEP == 0x55){ // 1. restore <COUNT> COUNT = COUNT_SAVE; // 2. Set <SLEEP> flag to FALSE by erasing the FLASH page containing // the variable EA_SAVE = EA; // preserve interrupt state EA = 0; // disable interrupts PSCTL = 0x01; // MOVX writes write FLASH byte FLKEY = 0xA5; // FLASH lock and key sequence 1 FLKEY = 0xF1; // FLASH lock and key sequence 2 *ptrSLEEP = 0x00; // clear SLEEP flag to indicate device // is no longer in Stop mode PSCTL = 0x00; // disable FLASH writes/erases EA = EA_SAVE; // restore interrupt state // 3. Enable External Interrupt 0 EX0 = 1; } // otherwise start counting at zero else{ // 1. Set <COUNT> to zero COUNT = 0; // 2. Enable External Interrupt 0 EX0 = 1; // Enable External Interrupt0 } } // handle error condition for unrecognized reset source else { printf(“\n**UNRECOGNIZED RESET SOURCE = 0x%02bX\n”, RSTSRC); PCON |= 0x02; // place device in Stop mode } } //----------------------------------------------------------------------------// wait_ms //----------------------------------------------------------------------------// // This routine inserts a delay of <ms> milliseconds. // void wait_ms(int ms) { TMR2CN = 0x00; // Configure Timer 2 as a 16-bit 44 Rev. 1.1 AN138 TMR2RL = -(SYSCLK/1000/12); TMR2 = TMR2RL; TR2 = 1; while(ms){ TF2H = 0; while(!TF2H); ms--; } TR2 = 0; // timer counting SYSCLKs/12 // Timer 2 overflows at 1 kHz // Start Timer 2 // wait until timer overflows // decrement ms // Stop Timer 2 } //----------------------------------------------------------------------------// Interrupt Service Routines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// INT0_ISR //----------------------------------------------------------------------------void INT0_ISR (void) interrupt 0 { // pointer to COUNT unsigned char* ptrCOUNT = &COUNT; // FLASH write pointer char xdata * idata ptrCOUNT_SAVE = &COUNT_SAVE; // FLASH write pointer char xdata * idata ptrSLEEP = &SLEEP; char EA_SAVE = EA; // save interrupt status printf(“Entering Stop Mode\n\n”); EA = 0; // disable interrupts PSCTL = 0x03; FLKEY = 0xA5; FLKEY = 0xF1; *ptrCOUNT_SAVE = 0; // // // // PSCTL = 0x01; // MOVX writes write FLASH byte MOVX writes erase FLASH page FLASH lock and key sequence 1 FLASH lock and key sequence 2 initiate page erase // copy <COUNT> to the <COUNT_SAVE> variable in FLASH FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[0] = ptrCOUNT[0]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy first byte FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[1] = ptrCOUNT[1]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy second byte FLKEY = 0xA5; // FLASH lock and key sequence 1 Rev. 1.1 45 AN138 FLKEY = 0xF1; ptrCOUNT_SAVE[2] = ptrCOUNT[2]; // FLASH lock and key sequence 2 // copy third byte FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[3] = ptrCOUNT[3]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy fourth byte FLKEY = 0xA5; FLKEY = 0xF1; *ptrSLEEP = 0x55; // // // // // PSCTL = 0x00; // disable FLASH writes and erases EX0 = 0; // disable External Interrupt 0 EA = EA_SAVE; // restore interrupt status while(!S2); // wait while switch down CPT0_Init(); ResetSRC_Init(); // initialize comparator 0 // set comparator 0 as a reset source PCON |= 0x02; // put the device in Stop mode FLASH lock and key sequence 1 FLASH lock and key sequence 2 set SLEEP flag to indicate device is in Stop mode and <COUNT> has been saved in FLASH } //----------------------------------------------------------------------------// Initialization Subroutines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// SYSCLK_Init //----------------------------------------------------------------------------// This routine initializes the system clock to use the precision internal // oscillator divided by 8 as its clock source. // void SYSCLK_Init (void) { OSCICN = 0x04; // SYSCLK is internal osc. // in divide by 8 mode running // at 3.0625 MHz } //----------------------------------------------------------------------------// PORT Initialization //----------------------------------------------------------------------------// // Configure the Crossbar and GPIO ports // // P0.0 - CP0+ input (connected to S2) // P0.1 - CP0- input // P0.2 - Comparator Voltage Reference (connected to P0.1) // P0.3 - Used as a weak pull-up for P0.0 // void PORT_Init (void) 46 Rev. 1.1 AN138 { XBR0 = 0x07; // skip P0.0 - P0.2 in crossbar XBR1 XBR2 = 0x03; = 0x40; // Enable UART0 // Enable crossbar and weak pull-ups P0MDOUT |= 0x10; // TX0 is a push-pull output } //----------------------------------------------------------------------------// Comparator0 Initialization //----------------------------------------------------------------------------// // Initialize Comparator 0 to detect when the SW2 switch is pressed. // void CPT0_Init(void) { P0MDIN &= ~0x03; // Comparator 0 inputs (P0.0 // and P0.1) are analog inputs. CPT0CN = 0x8F; // Comparator enabled with maximum // positive and negative hysteresis CPT0MX = 0x00; // // // // wait_ms(500); // wait for comparator inputs to settle CPT0CN &= ~0x30; // clear interrupt flags P0.1 = Inverting Input for the comparator P0.0 = Non-Inverting Input for the comparator } //----------------------------------------------------------------------------// Reset Source Initialization //----------------------------------------------------------------------------// // Configure Comparator 0 as a reset source. // void ResetSRC_Init(void) { RSTSRC = 0x22; // Comparator 0 is a reset source // VDD Monitor enabled } //----------------------------------------------------------------------------// External Interrupt 0 Initialization //----------------------------------------------------------------------------// // Configure External Interrupt 0 to generate an interrupt on the falling // edge of P0.0. // void EX0_Init(void) Rev. 1.1 47 AN138 { IT01CF = 0x00; // Configure External Interrupt 0 to // generate an interrupt on the falling // edge of P0.0 (S2 switch) } //----------------------------------------------------------------------------// UART0_Init //----------------------------------------------------------------------------// // Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. // void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear RI0 and TI0 bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON |= 0x10; // T1M = 1; SCA1:0 = xx } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON &= ~0x13; CKCON |= 0x01; // T1M = 0; SCA1:0 = 01 } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON &= ~0x13; CKCON |= 0x02; // T1M = 0; SCA1:0 = 10 } TL1 = TH1; TMOD &= ~0xf0; TMOD |= 0x20; TR1 = 1; TI0 = 1; // set Timer1 to reload value // TMOD: timer 1 in 8-bit autoreload // START Timer1 // Indicate TX0 ready } 48 Rev. 1.1 AN138 Example 3: Waking from Stop Mode Using a Comparator (C8051F31x) //----------------------------------------------------------------------------// CP0_Stop_F31x.c //----------------------------------------------------------------------------// Copyright 2003 Cygnal Integrated Products, Inc. // // AUTH: FB // DATE: 23 JAN 03 // // This example shows how a sleep mode can be implemented in a system using // the Stop mode of the CPU. This application implements a software counter // that is incremented approximately every second when the device is in // Normal mode. If the system is powered down when it is in Stop mode, the // counter resumes counting the next time it enters Normal mode. If the // system is powered down while it is in Normal mode, the counter will reset // to zero. Every time the counter is updated, the current value of the // counter is printed to the UART. // // The S2 switch toggles the system back and forth between Stop mode and // Normal mode. On power up, the system is in Stop mode. The system enters // Normal mode when the S2 switch on the target board is pressed, causing // a Comparator 0 reset. // // Upon entering Normal mode, External Interrupt 0 (/INT0) is activated // to sense the S2 switch and Comparator 0 is disabled as a reset source. // Pressing S2 in Normal mode will cause the INT0_ISR to put the system // in Stop mode. // // This program uses Comparator 0 as a reset source. When S2 on the target // board is pressed, the the CP0+ input drops below CP0- (VDD/2). This causes // Comparator 0 to issue a system reset. // // // // // // // // // // // // // // // // For this example, it is necessary to make the following connections: 1. P0.7_SW -> P0.0 2. P0.7_SW -> P1.0 3. P3.3 -> P1.1 4. P3.3_LED -> P3.3 P0.1 is used as a reference voltage for the comparator and should be approximately halfway between VDD and GND. When the LED is connected to P0.2 (high-impedance with weak pull-up), the voltage on P0.2 is around 1.7 Volts. Since this program writes to FLASH, the VDD monitor is enabled. Target: C8051F31x Tool Chain: KEIL C51 6.03 / KEIL EVAL C51 //----------------------------------------------------------------------------// Include Files //----------------------------------------------------------------------------#include <c8051f310.h> #include <stdio.h> Rev. 1.1 49 AN138 //----------------------------------------------------------------------------// 16-bit SFR Definitions for ‘F31x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 TMR3 TMR3RL PCA0CP0 PCA0CP1 PCA0CP2 PCA0CP3 PCA0CP4 PCA0 ADC0 ADC0GT ADC0LT = = = = = = = = = = = = = = 0x82; 0xca; 0xcc; 0x94; 0x92; 0xfb; 0xe9; 0xeb; 0xed; 0xfd; 0xf9; 0xbd; 0xc3; 0xc5; // // // // // // // // // // // // // // data pointer Timer2 reload value Timer2 counter Timer3 counter Timer3 reload value PCA0 Module 0 Capture/Compare PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 Module 3 Capture/Compare PCA0 Module 4 Capture/Compare PCA0 counter ADC Data Word Register ADC0 Greater-Than ADC0 Less-Than //----------------------------------------------------------------------------// Global Constants //----------------------------------------------------------------------------#define SYSCLK 3062500 #define BAUDRATE 9600 // System Clock Frequency in Hz // UART Baud Rate in bps sbit S2 = P0^0; // Switch on Target Board //----------------------------------------------------------------------------// Global Variables //----------------------------------------------------------------------------long COUNT = 0; // Software Counter char code SLEEP _at_ 0x1000; // // // // // Flag that indicates device is in a low-power state. The flag is TRUE when it contains an 0x55 pattern. Any other pattern indicates FALSE. long code COUNT_SAVE _at_ 0x1001; // Non-volatile storage for // the current count //----------------------------------------------------------------------------// Function Prototypes //----------------------------------------------------------------------------void void void void void void void void void SYSCLK_Init (void); VDMON_Init (void); PORT_Init (void); CPT0_Init (void); ResetSRC_Init(void); EX0_Init(void); UART0_Init (void); Check_Reset_Source(void); wait_ms(int ms); //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------- 50 Rev. 1.1 AN138 void main (void) { PCA0MD &= ~0x40; // disable the watchdog timer VDMON_Init(); // initialize VDD monitor EX0_Init(); PORT_Init (); SYSCLK_Init(); UART0_Init(); // // // // EA = 1; // Enable global interrupts Check_Reset_Source(); // // // // initialize initialize initialize initialize External Interrupt 0 crossbar and GPIO the system clock UART communication check whether the source of of the last reset was due to a power-on condition or due to a comparator while(1){ // print current count printf(“Current Count: %ld\n”, COUNT); COUNT++; // wait for one second wait_ms(1000); } } //----------------------------------------------------------------------------// Check_Reset_Source //----------------------------------------------------------------------------// // This routine is called on every device reset. // // On each comparator reset, it restores the value of <COUNT> from the // <COUNT_SAVE> variable stored in FLASH if the device was in a low-power state // prior to the reset(i.e. the SLEEP flag in FLASH was set to an 0x55 pattern). // If the <SLEEP> flag was not set then the <COUNT> variable is set to zero and // the device starts normal mode operation. // // On each power-on reset or HW pin reset, the device goes into a low power // mode waiting for a comparator reset. // void Check_Reset_Source(void) { char EA_SAVE; // interrupt state preservation char xdata * idata ptrSLEEP = &SLEEP; // FLASH write pointer printf(“\nDevice Reset -- RESET SOURCE = 0x%02bX\n\n”, RSTSRC); Rev. 1.1 51 AN138 // check for power-on, HW pin, watchdog timer or missing clock detector reset if(RSTSRC & 0x4F){ CPT0_Init(); // initialize comparator 0 ResetSRC_Init(); // set comparator 0 as a reset source printf(“Entering Stop Mode\n\n”); PCON |= 0x02; // put device in stop mode } // check for a comparator reset else if( RSTSRC & 0x20){ while(!S2); wait_ms(5); // wait while switch down // wait until switch stabilizes // if the device was in a low-power state ( <SLEEP> flag is set to TRUE), // then resume counting, otherwise start counting from zero if(SLEEP == 0x55){ // 1. restore <COUNT> COUNT = COUNT_SAVE; // 2. Set <SLEEP> flag to FALSE by erasing the FLASH page containing // the variable EA_SAVE = EA; // preserve interrupt state EA = 0; // disable interrupts PSCTL = 0x01; // MOVX writes write FLASH byte FLKEY = 0xA5; // FLASH lock and key sequence 1 FLKEY = 0xF1; // FLASH lock and key sequence 2 *ptrSLEEP = 0x00; // clear SLEEP flag to indicate device // is no longer in Stop mode PSCTL = 0x00; // disable FLASH writes/erases EA = EA_SAVE; // restore interrupt state // 3. Enable External Interrupt 0 EX0 = 1; } // otherwise start counting at zero else{ // 1. Set <COUNT> to zero COUNT = 0; // 2. Enable External Interrupt 0 EX0 = 1; // Enable External Interrupt0 } } // handle error condition for unrecognized reset source else { printf(“\n**UNRECOGNIZED RESET SOURCE = 0x%02bX\n”, RSTSRC); PCON |= 0x02; // place device in Stop mode } } 52 Rev. 1.1 AN138 //----------------------------------------------------------------------------// wait_ms //----------------------------------------------------------------------------// // This routine inserts a delay of <ms> milliseconds. // void wait_ms(int ms) { TMR2CN = 0x00; // Configure Timer 2 as a 16-bit // timer counting SYSCLKs/12 TMR2RL = -(SYSCLK/1000/12); // Timer 2 overflows at 1 kHz TMR2 = TMR2RL; TR2 = 1; while(ms){ TF2H = 0; while(!TF2H); ms--; } TR2 = 0; // Start Timer 2 // wait until timer overflows // decrement ms // Stop Timer 2 } //----------------------------------------------------------------------------// Interrupt Service Routines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// INT0_ISR //----------------------------------------------------------------------------void INT0_ISR (void) interrupt 0 { // pointer to COUNT unsigned char* ptrCOUNT = &COUNT; // FLASH write pointer char xdata * idata ptrCOUNT_SAVE = &COUNT_SAVE; // FLASH write pointer char xdata * idata ptrSLEEP = &SLEEP; char EA_SAVE = EA; // save interrupt status printf(“Entering Stop Mode\n\n”); EA = 0; // disable interrupts PSCTL = 0x03; FLKEY = 0xA5; FLKEY = 0xF1; *ptrCOUNT_SAVE = 0; // // // // PSCTL = 0x01; // MOVX writes write FLASH byte MOVX writes erase FLASH page FLASH lock and key sequence 1 FLASH lock and key sequence 2 initiate page erase // copy <COUNT> to the <COUNT_SAVE> variable in FLASH Rev. 1.1 53 AN138 FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[0] = ptrCOUNT[0]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy first byte FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[1] = ptrCOUNT[1]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy second byte FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[2] = ptrCOUNT[2]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy third byte FLKEY = 0xA5; FLKEY = 0xF1; ptrCOUNT_SAVE[3] = ptrCOUNT[3]; // FLASH lock and key sequence 1 // FLASH lock and key sequence 2 // copy fourth byte FLKEY = 0xA5; FLKEY = 0xF1; *ptrSLEEP = 0x55; // // // // // PSCTL = 0x00; // disable FLASH writes and erases EX0 = 0; // Disable External Interrupt 0 EA = EA_SAVE; // restore interrupt status while(!S2); // wait while switch down CPT0_Init(); // initialize comparator 0 ResetSRC_Init(); // set comparator 0 as a reset source PCON |= 0x02; // put the device in Stop mode FLASH lock and key sequence 1 FLASH lock and key sequence 2 set SLEEP flag to indicate device is in Stop mode and <COUNT> has been saved in FLASH } //----------------------------------------------------------------------------// Initialization Subroutines //----------------------------------------------------------------------------//----------------------------------------------------------------------------// VDMON_Init //----------------------------------------------------------------------------// This routine initializes the VDD monitor. // void VDMON_Init (void) { VDM0CN = 0x80; // enable VDD monitor while(!(VDM0CN & 0x40)); // wait until power supply is above // VDD threshold } 54 Rev. 1.1 AN138 //----------------------------------------------------------------------------// SYSCLK_Init //----------------------------------------------------------------------------// This routine initializes the system clock to use the calibrated internal // oscillator divided by 8 as its clock source. // void SYSCLK_Init (void) { OSCICN = 0x80; // SYSCLK is internal osc. // in divide by 8 mode running // at 3.0625 MHz } //----------------------------------------------------------------------------// PORT_Init //----------------------------------------------------------------------------// // Configure the Crossbar and GPIO ports // P0.0 - (connected to S2) // P1.0 - CP0+ input (connected to S2) // P1.1 - CP0- input // P3.3 - Comparator Voltage Reference (connected to P1.0) // void PORT_Init (void) { P0SKIP = 0x01; // skip P0.0 in crossbar P1SKIP = 0x03; // skip P1.0, P1.1 in crossbar XBR0 XBR1 = 0x01; = 0x40; P0MDOUT |= 0x10; // Enable UART0 // Enable crossbar and weak pull-ups // TX0 is a push-pull output } //----------------------------------------------------------------------------// Comparator0 Initialization //----------------------------------------------------------------------------// // Initialize Comparator 0 to detect when the SW2 switch is pressed. // void CPT0_Init(void) { P1MDIN &= ~0x03; // Comparator 0 inputs (P1.0 // and P1.1) are analog inputs. CPT0CN = 0x8F; // Comparator enabled with maximum // positive and negative hysteresis CPT0MX = 0x00; // // // // wait_ms(500); // wait for comparator inputs to settle P0.1 = Inverting Input for the comparator P0.0 = Non-Inverting Input for the comparator Rev. 1.1 55 AN138 CPT0CN &= ~0x30; // clear interrupt flags } //----------------------------------------------------------------------------// Reset Source Initialization //----------------------------------------------------------------------------// // Configure Comparator 0 as a reset source. // void ResetSRC_Init(void) { RSTSRC = 0x22; // Comparator 0 is a reset source // VDD Monitor enabled } //----------------------------------------------------------------------------// External Interrupt 0 Initialization //----------------------------------------------------------------------------// // Configure External Interrupt 0 to generate an interrupt on the falling // edge of P0.0. // void EX0_Init(void) { IT01CF = 0x00; // Configure External Interrupt 0 to // generate an interrupt on the falling // edge of P0.0 (S2 switch) } //----------------------------------------------------------------------------// UART0_Init //----------------------------------------------------------------------------// // Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. // void UART0_Init (void) { SCON0 = 0x10; // SCON0: 8-bit variable bit rate // level of STOP bit is ignored // RX enabled // ninth bits are zeros // clear RI0 and TI0 bits if (SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON |= 0x08; // T1M = 1; SCA1:0 = xx } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON &= ~0x0B; CKCON |= 0x01; // T1M = 0; SCA1:0 = 01 } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00 } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON &= ~0x0B; CKCON |= 0x02; // T1M = 0; SCA1:0 = 10 } 56 Rev. 1.1 AN138 TL1 = TH1; TMOD &= ~0xf0; TMOD |= 0x20; TR1 = 1; TI0 = 1; // set Timer1 to reload value // TMOD: timer 1 in 8-bit autoreload // START Timer1 // Indicate TX0 ready } Rev. 1.1 57 AN138 Example 4: 32.768 kHz Watch Crystal Low Power Startup Procedure (C8051F30x) //----------------------------------------------------------------------------// Watch_XTAL_F30x.c //----------------------------------------------------------------------------// Copyright 2003 Cygnal Integrated Products, Inc. // // AUTH: FB // DATE: 23 JAN 03 // // This example shows how to start an external 32.768 kHz watch crystal in low // power applications. Since a watch crystal can take longer than one second // to start, the device goes into Idle mode after turning on the external // oscillator. Timer2, configured to generate an interrupt every 100 ms using // a timebase derived from the internal oscillator, wakes the device to check // the XTLVLD flag. Once the watch crystal has started, the internal oscillator // is disabled and the system uses the crystal as the system clock source. // // Target: C8051F30x // // Tool chain: KEIL Eval ‘c’ // //----------------------------------------------------------------------------// Includes //----------------------------------------------------------------------------#include <c8051f300.h> // SFR declarations //----------------------------------------------------------------------------// 16-bit SFR Definitions for ‘F30x //----------------------------------------------------------------------------sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 sfr16 DP TMR2RL TMR2 PCA0CP1 PCA0CP2 PCA0 PCA0CP0 = = = = = = = 0x82; 0xca; 0xcc; 0xe9; 0xeb; 0xf9; 0xfb; // // // // // // // data pointer Timer2 reload value Timer2 counter PCA0 Module 1 Capture/Compare PCA0 Module 2 Capture/Compare PCA0 counter PCA0 Module 0 Capture/Compare //----------------------------------------------------------------------------// Global CONSTANTS //----------------------------------------------------------------------------#define INTCLK 24500000 / 8 #define EXTCLK 32768 // // // // Internal Oscillator frequency in Hz (divide by 8 mode) Frequency for 32.768 kHz External crystal oscillator //----------------------------------------------------------------------------// Global VARIABLES //----------------------------------------------------------------------------bit OSC_READY = 0; // flag to indicate when external // oscillator is ready //----------------------------------------------------------------------------- 58 Rev. 1.1 AN138 // Function PROTOTYPES //----------------------------------------------------------------------------void SYSCLK_Init (void); void PORT_Init (void); void Timer2_Init (int counts); void Timer2_ISR (void); //----------------------------------------------------------------------------// MAIN Routine //----------------------------------------------------------------------------void main (void) { // disable watchdog timer PCA0MD &= ~0x40; PORT_Init(); SYSCLK_Init(); // WDTE = 0 (clear watchdog timer // enable) // initialize the crossbar and GPIO // start external oscillator // The system should be running from the external oscillator at this point while(1){ PCON |= 0x01; } // put the device in Idle mode } //----------------------------------------------------------------------------// SYSCLK_Init //----------------------------------------------------------------------------// // This routine starts the external 32.768 kHz watch crystal and puts the system // in Idle mode. Timer 2 interrupts check the status of the XTLVLD bit and // switches the system clock to the external oscillator when it is ready. The // system remains in Idle mode until the oscillator starts. // void SYSCLK_Init (void) { OSCXCN = 0x61; // start external oscillator Timer2_Init(INTCLK/12/10); // configure Timer2 to overflow // at 10 Hz (every 100 ms) EA = 1; // enable global interrupts while(!OSC_READY){ PCON |= 1; } // put device in Idle mode } //----------------------------------------------------------------------------// PORT_Init //----------------------------------------------------------------------------// Rev. 1.1 59 AN138 // Configure the Crossbar and GPIO ports. // P0.0 // P0.1 // P0.2 - XTAL1 // P0.3 - XTAL2 // P0.4 // P0.5 // P0.6 // P0.7 - C2D // void PORT_Init (void) { XBR0 = 0x0c; // skip crystal pins XBR2 = 0x40; // enable crossbar and weak pull-ups P0MDIN &= ~0x0c; // configure XTAL1 and XTAL2 as analog // inputs } //----------------------------------------------------------------------------// Timer2_Init //----------------------------------------------------------------------------// // Configure Timer2 to auto-reload at interval specified by <counts> // using the system clock / 12 as its time base. // void Timer2_Init (int counts) { TMR2CN = 0x00; // Stop Timer0; // Timer2 timebase is SYSCLK/12 TMR2RL = -counts; TMR2 = TMR2RL; ET2 = 1; TR2 = 1; // // // // Init reload value Init Timer2 enable Timer2 interrupts start Timer2 } //----------------------------------------------------------------------------// Timer2_ISR //----------------------------------------------------------------------------// // This interrupt service routine is called on Timer2 overflows // void Timer2_ISR (void) interrupt 5 { TF2H = 0; // clear Timer2 overflow flag if(OSCXCN { OSCXCN RSTSRC OSCICN 60 & 0x80) // if crystal osc. has settled = 0x60; = 0x04; = 0x08; // // // // decrease crystal drive current enable missing clock detector switch to external oscillator and disable internal oscillator TR2 = 0; // stop Timer2 OSC_READY = 1; // indicate that the external osc. Rev. 1.1 AN138 // is ready } } Rev. 1.1 61 AN138 Contact Information Silicon Laboratories Inc. 4635 Boston Lane Austin, TX 78735 Tel: 1+(512) 416-8500 Fax: 1+(512) 416-9669 Toll Free: 1+(877) 444-3032 Email: [email protected] Internet: www.silabs.com The information in this document is believed to be accurate in all respects at the time of publication but is subject to change without notice. Silicon Laboratories assumes no responsibility for errors and omissions, and disclaims responsibility for any consequences resulting from the use of information included herein. Additionally, Silicon Laboratories assumes no responsibility for the functioning of undescribed features or parameters. Silicon Laboratories reserves the right to make changes without further notice. Silicon Laboratories makes no warranty, representation or guarantee regarding the suitability of its products for any particular purpose, nor does Silicon Laboratories assume any liability arising out of the application or use of any product or circuit, and specifically disclaims any and all liability, including without limitation consequential or incidental damages. Silicon Laboratories products are not designed, intended, or authorized for use in applications intended to support or sustain life, or for any other application in which the failure of the Silicon Laboratories product could create a situation where personal injury or death may occur. Should Buyer purchase or use Silicon Laboratories products for any such unintended or unauthorized application, Buyer shall indemnify and hold Silicon Laboratories harmless against all claims and damages. Silicon Laboratories and Silicon Labs are trademarks of Silicon Laboratories Inc. Other products or brandnames mentioned herein are trademarks or registered trademarks of their respective holders. 62 Rev. 1.1