Common Peripheral Circuits

On this page

The correctness of peripheral circuits is not only reflected in steady-state conditions: buttons bounce, GPIOs may be high-impedance during reset, coils still have current when turned off, and monitoring tasks may still be running when software hangs. Incorporating these state changes into circuit and software models allows us to explain why "components are connected, yet sporadic malfunctions still occur."

RequirementCore MechanismFocus of This Article
Reliable StartupCoordination of power supply, reset, clock, and default levelsEstablish a repeatable initial state first
Button generates only one eventContinuous stable time and state changeDebouncing is not just delayed repeated processing
GPIO controls power loadMOS gate drive and current loopDefault off, freewheeling, and voltage withstand
Signal transmission across isolation boundaryOptical transmission and output current capabilityCTR, logic edges, and power supplies on both sides
LED dimmingCurrent limiting and duty cycleConstant current does not automatically mean high efficiency
Software exception recoveryEvidence of valid progress and resetWatchdog refresh conditions, windows, and fault recording

Before Startup, Ensure the Circuit Has a Defined State

Check every power supply pin, decoupling loop, analog power supply, internal regulation capacitor, and power-on sequence against the MCU's reference design. Decoupling capacitors handle local transient currents; do not ignore the loop near the power supply pin just because there is already a large capacitor on the board. Also, do not apply a uniform value to special capacitor pins for different MCUs.

Reset must cover the period when the power supply is not yet stable. The release time of a simple RC circuit is affected by the power-on slope, threshold, leakage, and fast power-down restarts. When guaranteed undervoltage behavior is required, combine internal BOR/POR with an external monitor. Confirm the sampling timing of startup configuration pins according to the chip manual; external buttons or peripherals must not bring the chip into the wrong startup mode during this window.

External crystals also involve load capacitors, parasitics, drive levels, and oscillator gain margins; identical frequencies do not mean they can be replaced arbitrarily. Output loads must have a defined default level before software initialization; pin states during reset, in particular, must not cause relays or motors to move unexpectedly.

Button Debouncing: Confirm State Change, Not Repeatedly Confirming Level

Instantaneous opening and closing of mechanical contacts creates multiple edges, with durations varying by device and operation. Software debouncing can save the original candidate level and its start time; only when the candidate level remains stable for longer than the set window should the confirmed state be updated. Generate an event only once when the confirmed state changes from released to pressed. Long presses and repeated triggers should be defined separately; do not execute the press action on every loop.

The model below assumes sampling once per millisecond, with low level indicating pressed, using a 5 ms stable window to demonstrate the algorithm. The real window should be determined based on button characteristics and response requirements; 5 ms is not a universal specification. Discrete sampling also cannot observe all glitches between sampling points.

raw = [1]*3 + [0,1,0,1] + [0]*20 + [1,0,1] + [1]*10
stable = candidate = 1
since = 0
presses, releases = [], []
for now, level in enumerate(raw):
    if level != candidate:
        candidate, since = level, now
    if candidate != stable and now-since >= 5:
        stable = candidate
        (presses if stable == 0 else releases).append(now)
assert presses == [12]
assert releases == [34]
print('Bounce and long-press trajectory: generates only one press and one release')

On the MCU, you must also handle counter wraparound using appropriate unsigned time differences, and ensure the comparison window is smaller than the safe range of the time base used. External interrupts can wake up the system or start checks, but do not treat every raw interrupt immediately as a business button event.

Hardware RC reduces fast changes, but slow edges must be paired with Schmitt inputs or appropriate debouncing devices. The simplest circuit with an upper pull-up R, node-to-ground C, and button-to-ground charges the capacitor through R when released, and discharges it quickly through the button when pressed. The time constants for both directions are different; add current-limiting resistors and recalculate the final value and threshold time if necessary. τ = RC is also not the logic flip delay; for example, charging from 0 to 0.7VCC requires −RC ln(0.3) ≈ 1.204RC. TI: Button Debouncing and Schmitt Trigger

Stable level or a new press event?

Flip a sample inside the low interval to 1: candidate timing restarts, but a confirmed press does not immediately release. Shortening the window can turn bounce into events. Window choice trades response delay against false triggers.

Preparing the visual
Stable level or a new press event?

Each candidate change restarts timing. Events require confirmed state changes; a held button does not retrigger.

MOS Load Switch: Gate-Source Voltage and Default State

GPIO drive capability must be checked against guaranteed VOH/VOL, single-pin, and port total current limits; do not design using only the absolute maximum current. Larger loads are borne by power switches, with GPIOs responsible for control. Although MOSFETs require almost no DC gate current once on, gate charge still needs to be moved during switching.

For a low-side NMOS, the Source connects to the return path, and the Drain connects to the lower end of the load. A resistor in series with the Gate limits charging/discharging speed and helps suppress ringing; a pull-down from G to S provides a default-off state when the GPIO is high-impedance. The resistor value must also balance Miller coupling, leakage, and drive speed; having a pull-down does not guarantee it will never be falsely turned on. Gate clamping should reference the S; do not uniformly add a Zener diode from "Gate to Ground" for all high-side or floating switches.

High-side PMOS switches usually have the Source connected to the positive power supply and the Drain to the load. The Gate is pulled up to the Source to turn off, and then pulled low by a suitable level-shifting stage to turn on. The terminal arrangement here is different from dedicated single-transistor reverse-polarity protection topologies. If the power supply is 12 V, a 3.3 V GPIO cannot directly pull the Gate close to 12 V to complete the turn-off, and may damage the GPIO. Whether level shifting is needed depends on the power domain and actual gate-source window; not all PMOS require the same conversion circuit.

Select on-resistance based on actual VGS and temperature; VGS(th) only describes the onset of conduction under tiny test currents and cannot serve as the basis for the load being fully on. Voltage withstand is determined by the power supply, clamping, and parasitic spikes; do not replace a complete stress budget with "supply voltage multiplied by 1.5."

DC Relay: Draw the Complete Turn-Off Loop

+VCoilR, LNMOSD up · S downKAFreewheeling DiodeRgGPIORGSAfter turn-off: Coil lower end → Diode → Coil upper endLow-side driven DC coil: Freewheeling diode in parallel with the coilThe diode provides the turn-off current loop; it is not in series with the coil, nor is it connected between the drain and ground.

During normal conduction, current flows from the power supply through the coil and NMOS back to the return path, with the freewheeling diode reverse-biased. After the MOSFET turns off, the coil current continues to flow in the original direction. The voltage at the lower end of the coil rises, causing the diode to conduct from the lower end to the upper end, forming a local closed loop. Therefore, the diode's K (Cathode) connects to the power supply side, and A (Anode) connects to the drain side; it is in parallel with the coil.

Assume a 5 V coil with a DC resistance of 70 Ω, resulting in a steady-state current of approximately 71.4 mA. If the inductance is 0.1 H, the stored energy is approximately 0.255 mJ. Estimating solely with a constant 0.7 V reverse voltage drop and ignoring coil resistance, the current decay time LI/V is approximately 10.2 ms. The actual current is also affected by coil resistance, magnetic circuit changes, and clamping characteristics; this is not the measured mechanical release time of the relay.

Standard diodes clamp at a lower voltage, prolonging current decay and thus affecting release speed. If faster release is needed, a higher voltage clamp can be designed, but switch voltage withstand and suppressor energy must be re-verified. Therefore, an appropriate energy release path must be arranged, but this does not mean all coils can only use the same freewheeling diode. OMRON: Relay Suppression Circuits and Release Time

Coil drive protection and protection for the load switched by the contacts are two different matters. If the contact load also has inductance, surges, or large inrush currents, the contact rating, arc suppression, and load-side suppression must be evaluated separately; adding a diode on the drive side cannot solve all contact stress issues.

Optocoupler: Both Isolation Boundary and CTR Must Be Closed

The current in the optocoupler's input LED is converted to output response via light; the two sides do not require a conductive connection. If power supplies, debug lines, or grounds bridge across both sides, the original isolation boundary may be bypassed. The device's rated withstand voltage does not equal the long-term working isolation capability of the entire PCB; spacing, insulation, and power supply design must also comply with application requirements.

For phototransistor outputs, CTR = IC/IF, varying with device binning, input current, temperature, aging, and test conditions. Assuming a minimum usable CTR of 50% under certain design conditions and an IF of 2 mA, the output current budget is 1 mA. With a 3.3 V pull-up through 10 kΩ and a desired low level of 0.2 V, approximately 0.31 mA is needed, leaving static budget margin. However, CTR is typically measured at a specified VCE; saturation low-level capability and dynamic propagation time must still be checked. This ratio alone cannot prove all logic specifications. Vishay Phototransistor Optocoupler Data

An excessively large pull-up resistor slows edges due to output capacitance, while one that is too small requires more sink current; deep saturation may also prolong turn-off. High-speed logic optocouplers have different output structures from standard phototransistors and must be connected according to device power and interface specifications. Simply increasing the LED current does not achieve arbitrary baud rates.

LED: PWM Controls Average Value, Current Limiting Controls Instantaneous Value

The current through a series resistor is (V_supply − VF − Switch Voltage Drop)/R. The maximum current must be checked against the highest supply voltage, lowest VF, and tolerance. PWM dimming changes the conduction ratio but does not replace current limiting. A 20% duty cycle does not allow arbitrarily increasing the instantaneous current to five times the rated continuous value; pulse ratings and thermal constraints must still be met.

Constant current drivers also require voltage margin and an allowable operating range. A linear constant current driver dissipates approximately 0.9 W with a 12 V input, 3 V LED, and 100 mA current, while the LED electrical power is 0.3 W. Ignoring control power consumption, the efficiency is only 25%. Switching constant current solutions can improve efficiency under certain conditions, but complexity, ripple, and EMI differ. Addressable RGB LEDs integrate control and driving into the product; their data protocols, voltages, and supply transients must be checked separately.

Watchdog: Prove Health with Progress

Placing the watchdog refresh command in the main loop is not inherently wrong: if the loop must complete all critical work before reaching the refresh point, a hang will typically prevent refreshing. Conversely, an independent monitoring task that refreshes unconditionally may permanently mask faults even if other tasks have all stalled.

Sampling TaskComplete a batch of valid dataProcessing TaskFinish this roundCommunication TaskProgress or recoveryMonitor: fresh health evidence?Yes: refresh; no: log, await resetFeeding the dog should prove that critical tasks are making progress, not just that the monitoring thread is aliveCheck-ins update periodically; a single success flag cannot be retained permanently. Expected states like disconnection should have clear health definitions.

Each critical task should update the current round's health evidence after completing meaningful progress, and the monitor should refresh only after aggregation. Some tasks may allow waiting for external input; bounded waiting, timeout retries, or controlled offline states should be treated as explicit states, rather than requiring continuous data reception. Health flags need to be cleared every cycle or use an incrementing sequence; they cannot be set once and remain valid permanently.

Timeouts and windows are set based on the longest legitimate blocking, startup, Flash erasure, low-power states, and clock tolerances; they cannot be fixed at twice the longest task duration. Independent clocks and "window checks" are different attributes; some independent watchdogs also have window functions. Confirm specific sleep/debug freeze behaviors and whether they can be disabled after startup according to the model manual. ST STM32WB Independent Watchdog and Window Options

Read the reset reason as early as possible after reset, preserve necessary fault context, and limit actuator actions caused by continuous abnormal restarts. The watchdog is used to recover from loss of control; it cannot prove program logic correctness, nor can it replace the hardware default safe state upon failure.

Recalculate Circuit Budget

from math import isclose, log
assert isclose(-log(1-0.7), 1.203972804325936)
i, inductance = 5/70, 0.1
assert isclose(i*1000, 71.42857142857143)
assert isclose(0.5*inductance*i*i*1000, 0.2551020408163265)
assert isclose(inductance*i/0.7*1000, 10.20408163265306)
assert isclose((3.3-0.2)/10000*1000, 0.31)
assert isclose((12-3)*0.1, 0.9)
assert isclose(3/12, 0.25)
print('RC threshold, coil energy storage, CTR load, and linear LED loss calculations passed')

Debounce traces and numerical budgets check model relationships. Coil, contact and isolation performance require measurements under actual operating conditions.

Continue Reading