How to Use the Built-in Operational Amplifier in CH32V003
The CH32V003 microcontrollers (as well as the CH32V006) feature a very interesting piece of hardware - a built-in operational amplifier (OPA). In this article, I will explore and practically demonstrate how to use it for measuring small voltages, such as reading data from various sensors or current shunts.
Before we get to soldering, let’s take a quick look at the
architecture. The built-in OPA has multiplexed inputs, meaning it can be
software-switched to take a signal from different pairs of pins. For
example, the TSSOP20 package offers two groups: Group 0
(PA1 — OPN0, PA2 — OPP0) and Group 1
(PD0 — OPN1, PD7 — OPP1). However, the output
always remains the same — it is hardwired to the PD4 pin
(OPO).
The situation is slightly different with the smaller chips in the SOP8 and SOP16 packages. The multiplexing mechanism is still present in the silicon, but the required pins are simply not physically broken out, so there are effectively no switching options. (By the way, there is an interesting quirk: on the SOP16, the developers physically broke out the OPP1 pin but left OPN1 internal).
To demonstrate the usefulness of this amplifier with a real-world example, I used a standard Type K thermocouple (TP-01). During testing in boiling water (at 100 °C / 212 °F), it generates an EMF of only about 0.0029 Volts (2.9 mV):
Why do we even need an amplifier? The issue is that the ADC in the CH32V003 is 10-bit. If the microcontroller is powered by 3.3V, the minimum quantization step (even under ideal conditions, ignoring noise) will be: 3.3V / 1024 = 0.0032V (or 3.2 mV).
This means the voltage generated by the thermocouple at 100 °C (212 °F) doesn’t even reach a single ADC step! If we tried to read the sensor directly, our “accuracy” would be around ±100-130 degrees at best.
To convert these microvolts into a usable signal that the microcontroller can actually “see”, we will utilize the built-in OPA. We will connect it using a classic non-inverting amplifier configuration with a gain of 101 (1:101):
The gain is set by the 100 kΩ and 1 kΩ resistors, and a capacitor added in parallel provides additional signal filtering against noise.
Input Offset Voltage: There is one important nuance in operational amplifiers that can be confusing. In practice, I experienced it like this: the circuit assembled on a breadboard worked perfectly — when shorting the OPA+ input to ground, I got almost zero on the ADC (a value of 4–5). But after moving the circuit to a PCB with a different microcontroller, shorting the input gave me an ADC value of 165. For a 10-bit ADC powered by 3.3V, this corresponds to a voltage of about 0.53V at the OPA output.
Initially, I started looking for an issue or a cold solder joint, but
it turned out this is a completely normal and acceptable amplifier
behavior. According to the CH32V003 datasheet, its intrinsic input
offset voltage (Vioffset) is typically ±2.2 mV, and can
reach a maximum of ±7 mV.
Since our gain is 101, this tiny hardware offset gets multiplied along with the useful signal. For example, a typical offset of 2.2 mV turns into 222 mV (~0.22V) at the output. My ADC reading of 165 (0.53V) means that the offset of this specific chip is about 5.2 mV — which perfectly fits within the factory tolerance of ±7 mV.
Next, for a practical test, I will use the CH32V003 microcontroller in a TSSOP20 package. A 128x32 pixel OLED display will be used for data output. The resulting schematic looks like this:
An important note: a thermocouple doesn’t actually measure absolute temperature, only relative temperature. This means the voltage at its outputs depends on how hot (or cold) the measurement point is relative to the connection pads on the board.
Therefore, to obtain the absolute temperature, I added an NTC thermistor to the circuit. It will measure the ambient temperature of the board itself, and we will programmatically add the temperature difference measured by the thermocouple to this baseline value. In electronics, this process is known as cold-junction compensation.
The PCB manufacturing process:
The board is ready — let’s move on to the programming and code.
First, we need to configure the pins and enable the OPA. Here is how it’s done:
// Enable clock for ports A, D, ADC, and alternate functions (AFIO)
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOD |
RCC_APB2Periph_ADC1 |
RCC_APB2Periph_AFIO, ENABLE
);
GPIO_InitTypeDef GPIO_InitStructure = {0};
// Configure PA1 (OPA- input / OPN0) and PA2 (OPA+ input / OPP0) as analog inputs
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure PD3 (NTC) and PD4 (OPA OUT) as analog inputs
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOD, &GPIO_InitStructure);
// The EXTEN_CTR register controls the built-in OPA
EXTEN->EXTEN_CTR |= EXTEN_OPA_EN;
OPA_InitTypeDef OPA_InitStructure = {0};
OPA_InitStructure.PSEL = CHP0; // OPA+ is connected to the physical PA2 pin
OPA_InitStructure.NSEL = CHN0; // OPA- is connected to the physical PA1 pin
OPA_Init(&OPA_InitStructure);
OPA_Cmd(ENABLE);The complete firmware source code is available here: https://neonhero.dev/en/files/ch32opa/main.c
With these settings in place, the amplified thermocouple signal can
be read directly from the PD4 pin (ADC channel
AIN7). Meanwhile, we will read the NTC thermistor value
from the PD3 pin (channel AIN4) for room
temperature (cold-junction) compensation.
I am not aiming for ultra-high precision; an error margin of ±3–5 degrees is perfectly sufficient for my needs. Because of this, I didn’t bother with complex calibration. I simply verified and adjusted the calculated values using two reference points: room temperature and boiling water (100 °C / 212 °F):
Utilizing the built-in operational amplifier in CH32V microcontrollers is a neat engineering solution. It saves PCB space and allows you to read millivolt-level signals with a bare minimum of external components.
P.S. Eagle-eyed readers might spot a silly mistake in the schematic. This is what happens when you get too used to the SOP8 package of the CH32V003.





Comments
Post a Comment