The internal oscillator on the STM32 processors can be tuned so that an external crystal or oscillator isn’t necessary.

As Peter pointed out in an earlier blog, the STM32’s internal RC oscillator can be used to eliminate a handful of external clock components (one R, two C’s and a crystal).


Since mice use the serial port for communications, if the RC oscillator’s frequency is off by more than one percent, at higher baud rates, you can expect to see communications errors. To mitigate this, you can use the HSITRIM field in the RCC_CR register to adjust the RC oscillator’s freq. in approx. 40KHz increments.


ST provided the adjustment capability because during processor test, they adjust the freq. of the RC oscillator to within 1% of 8MHz at 25C. Since the initial error is already at the limits of the communication error budget, I decided to use the HSITRIM feature to optimize the RC oscillator freq. to 8MHz.


In my setup, I wanted to run the serial port at 921K. When I calculated the baud rate divider based error with the RC oscillator at 8MHz, I would have an error of -0.8% which with a processor with an almost perfect clock was too close to the 1% max. error for reliable communications. So, I decided I would adjust the RC oscillator’s freq. to 0.8% higher to minimize the baud rate divider error.


To tune freq. is relatively straight forward – enable the clock output (MCO) on the processor and then use a bench counter/timer to measure the clock freq. Then adjust HSITRIM to get to your target value.


On my particular processor, with HSITRIM set to the default value (16), the processor freq. was 8.07MHz. As it turned out, at 8.07MHz, the baud rate error for 921K is 0.07%. So, I didn’t have to trim the RC oscillator!


In playing around, if I did want to set the RC oscillator to 8MHz, I would have had to set HSITRIM to 13. Also, I wanted to see how sensitive the RC oscillator was to temperature. So, I took a can of Freeze spray and sprayed the STM32 processor. The RC oscillator freq. went up. Since I wasn’t monitoring the temp., I can’t provide a temp. coef. but I felt that the temp. coef. was relatively low i.e. with the mouse being in a room environment, the RC osicllator freq. won’t go outside the 1% range necessary for robust async. serial communications.


A mistake I made was that I didn’t put a test point on the pin that MCO can be routed to, so probing the pin to make this measurement was challenging. In hindsight, I think another way to make this measurement would be to write a small program which sets the serial port to 8 bit, no parity, one stop bit and then to output 0x0f on the serial port (continuously). You can then monitor the transmit pin and determine the best trim setting for the oscillator.


This Post Has 7 Comments

  1. peteh

    I wonder how many people could measure system frequency with any great reliablility. The only counter I have is of unknown accuracy and, since my oscilloscope hase never been calibrated, I do not know how reliable it is.

    What I need is a frequency standard but it has been a long time since I played with any thing like temperature  compensated oscillators. Also, I now do not have access to the radio receivers I used to have for comparing signals with broadcast standards.

    So, that leaves a question. Where can I find a good (<0.1% or better) standard frequency to calibrate my oscilloscope or counter.

    I can also see a potentialissu with using the serial port to output a clock signal to measure. I am not sure there is any guarantee about the period between the end of one character and the start of another. However, in the case of a mouse, the PWM output could be used to provide a suitable sugnal for measurement and it will already be brought out to a connector.

  2. Harjit Singh

    The PWM is a good idea!

    I agree that an accurate counter/timer is an issue. I wonder if something like the Bus Pirate ( might work – this is in the vein of the USBee/Open Workbench logic sniffer. I haven’t tried them so don’t know for sure.


  3. Rich

    I know this does not apply to the STM32, but I have just setup the PIC32 to work with the internal 8 MHz clock (multiplied up to 80 MHz), and I have just transferred an 120kb file from a MicroSD card over 115200 serial with no problems at all (not a single incorrect byte), and I have not even touched the tuning.

    I did have problems with the internal oscillators on the 18F devices mind.

    As for references, I think the PWM from an oscillator driven MCU is very good idea.

  4. Harjit Singh

    For what it is worth, I’ve used the default trim on the STM32 to do serial transmit and receive at 921600 with no errors but I’m not sure my results would apply to everyone or even to me at different temperatures/voltages…

  5. Mike

    It is a myth that an inaccurate bit rate clock gives more problems at higher bit rates. If a clock is 1% fast, then the bit timing is 1% out at all bit rates. A separate issue often encountered with high bit rates and non-binary divisible clock frequencies is that as the baud rate clock divisor becomes smaller, the attainable resolution of the bit rate worsens so you may not be able to achieve a low enough error.

    I’d be interested to understand where the 1% accuracy requirement has come from? The maximum total link error (i.e. combined bit rate error at the TX and RX ends of a link) that can be tolerated depends to some extent on the USARTS and the environment the comms link is used in. The absolute maximum possible error for a working link is less than 5% for an 8,n,1 frame, since 5% over 10 bits gives 50%, putting the USART sample point at a bit transition. In practice most USARTs sample the bit multiple times and use a majority voting system to determine the bit value so the maximum error has to be quite a lot less than 5%, and 3% maximum is the usual rule of thumb for non-critical applications.

  6. Harjit Singh

    Mike, you said it better that at higher baud rates, you can’t get as close.

    I agree that most current UARTs oversample the RX waveform. Beyond the baud rate, there are other factors that confound this issue – RX sampling architecture, RX clock freq, line driver and receiver characteristics and cable transmission characteristics.

    The 1% is something I have used as a rule of thumb so that I don’t spend my time chasing something that is easy to make sure is a non-issue.

  7. Petteri Punakuono

    The error tolerance calculation is very simple. If an UART tries to do the sampling in the middle of a bit, determined by edge of start bit, then the maximum error is half a bit per whole transmission. Normally UART oversamples a bit 16 times, so using 10-bit data frames (1 start, 8 data, 1 stop), the sampling clock cannot drift more than 8 clock cycles per 160 clock cycles. That is 5% per one device with simplistic explanation.

    As the UART might actually sample three times in the middle of the bit, and the clock drift has to be divided to both chips talking to each other, and perhaps taking bus tranceiver skews into account, the drift should be max 3 clock cycles per chip, resulting into below 2% tolerance.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.