Close

The datasheet was lying (six bugs from one bad table)

A project log for Oh No, Not Another Microwave Spot Welder

I didn't just rewind the microwave transformer — I kept its control board and rewrote the firmware to run a spot welder.

wicherswichers 2 小時前0 Comments

Blank chip, my code running, display lighting up. Time to weld. Except the timing was wrong — a 3-second test pulse took over 12 seconds — and the zero-cross timer read out nonsense.

I had no debugger. What I had was a 4-digit 7-segment display, so I built a test mode that shows raw register values in hex and jumps between them with the encoder. The chip told me its own story, one register at a time.

The root cause of everything: the register-reference markdown I started from had OCR errors in the timer chapter's bit tables. Six bugs fell out of it:

  1. 4× slow milliseconds. The time-base timer divider was one setting off (fcgck/2¹² instead of /2¹⁰). Every duration in the firmware ran 4× long. This alone was the original "welds take forever" symptom.
  2. The microsecond timer was never clocked. The peripheral clock-enable bit for the 16-bit timer is bit 0 of the power register — the excerpt said bit 2. Writes to the timer's own registers were silently ignored because the block had no clock.
  3. The boot ROM leaves that timer running. After every flash cycle the bootloader had configured the timer for its baud detection and left it going — and its mode register is write-locked while running. Fix: stop the timer before configuring it.
  4. Wrong timer mode. The mode register's bit fields were laid out differently than the excerpt claimed; my "timer mode, 1 MHz" value was actually selecting external-trigger mode. The chip's own boot-ROM code, quoted elsewhere in the real datasheet, gave the correct value.
  5. Auto-capture bit in the wrong place. The feature that lets you read the live counter is a different bit than documented — I found the truth by pulling the register table out of the datasheet PDF using the word x-coordinates, since the plain-text extraction was ambiguous.
  6. Interrupt enables in the wrong register. Two interrupts (the µs timer and the zero-cross input) had their enable bits placed in the wrong of two enable registers. Neither ever fired. A simple formula — bit = (0xFFFE − vector)/2, split across two registers — got both right.

Each fix, the display showed a little more life: a counter that finally counted, an overflow tally that finally incremented. When the last one landed, timer_us() was accurate to the microsecond and the 3-second pulse took exactly 3 seconds.

Lesson filed under "trust the primary source": the official PDF was correct all along; a well-meaning transcription of it cost a day.

Discussions