Lab #1: USART GPIO and UART

📚 LAB 1 CMPE2250: Input Capture and Clock Characterization

In this lab you will combine what you have learned about clocks and timers to create an embedded application that

assesses the accuracy of the HSI16 oscillator (and ultimately the PLL), using the LSE Crystal.

📋 Overview

  • Your code will use input capture to timestamp a number of LSE crystal period ticks relative to the main system (PLL/HSI derived) clock. You will use the displacement in these timestamps to assess the accuracy of the HSI16 oscillator.

  • The LSE is a higher accuracy oscillator (crystal) running at 32.768[kHz] (2^15). The HSI16 is a lower accuracy clock running at 16[MHz].

  • If we use the HSI16/PLL to run the system clock and the timer ticks at 64[MHz], the number of ticks per LSE period

    should be 64[MHz] / 32.768[kHz] = 1,953.125. In other words, the HSI16 is 1,953.125 times faster than the LSE.

  • Because this is not a whole number, it would make computation of the inaccuracy in the integer domain more difficult.

    If we simply multiply this number by 8, the math works out much better: 1,953.125 × 8 = 15,625.

  • This means that 8 periods of LSE should be 15,625 periods of the System clock if both clocks were synced and accurate.

  • If we use input capture to timestamp 8 periods of LSE relative to the System clock, the displacement in HSI count from the ideal of 15625 cycles would speak to the inaccuracy (or perhaps accuracy) of the HSI16.

  • Some timers can be configured in input capture mode to use the RTC clock, which can be based on the LSE, as the input channel source. This means that instead of capturing a waveform on a timer pin, internally the input is connected to the RTC clock.

1️⃣ Procedure

  • Run SYSCLK at 64[MHz] using the HSI16 with the PLL.

  • Bring the LSE up, and select it as the RTC clock source.

    • First, enable the LSE in the BDCR register of the RCC and wait for it to be ready (‘LSERDY’ flag).

    • Then, select the LSE as the RTC clock source in the BDCR register of the RCC.

    • Enable the RTC (RTCEN).

  • Configure TIM14:

    • Configure the ticks to be at 64[MHz] (1 tick per system clock cycle) by setting the prescaler to 0.

    • Use input capture with no filtering
    • Detect rising edges only (default)

    • Use the RTC as the input channel (TISEL register)

    • Set the capture to be done every 8 events (8 LSE periods) using the IC1PSC register.

    This means that the timer will only capture the count every 8th rising edge of the LSE, which corresponds to 8 periods of the LSE, which should give you a count of 15625 if the HSI16 is accurate.

    • Enable the timer and input capture channel.RCC->ICSCR &= ~RCC_ICSCR_HSITRIM_Msk; //Clear current trim

    • Turn on the timer

2️⃣ Displaying results

  • Using the Systick, generate an event every 250[ms] to update the display of your results in the main infinite loop. You can use the USART for displaying, or you can use the debug terminal if you prefer.

  • The capture in ticks should be close to 15625, and any deviation speaks to the inaccuracy of the HSI clock.

  • You may implement moving average to increase the accuracy of your assessment.

  • When you have made an accurate measurement, show the accuracy of the HSI as a percentage, and in terms of PPM. Show your math. Note: if you find that the accuracy is off by more than 1%, you’ve likely done something wrong.

  • Feel free to use this: PPM to Hz conversion calculator

3️⃣ Optional: Calibrating the HSI16 (Trimming)

  • Factory calibration for the HSI16 typically keeps the oscillator within ±1% at room temperature,

which is sufficient for most standard applications and usually does not require manual intervention.

  • However, if your measured count deviates significantly from 15625, or if you wish to dial the accuracy in further,

the STM32 allows manual trimming through the Internal Clock Sources Calibration Register (RCC->ICSCR).

Understanding HSITRIM

  • Bits [14:8] of RCC->ICSCR hold the HSITRIM[6:0] field.

  • By default, hardware sets HSITRIM to its mid-point value of 64 (0x40).

  • Each step up or down shifts the HSI16 output frequency in small increments (approximately ±0.5% per step).

    • If your timer capture count is greater than 15625, the system clock is running faster than expected $\rightarrow$ decrease the trim value.

    • If your timer capture count is less than 15625, the system clock is running slower than expected $\rightarrow$ increase the trim value.

Implementation in Clock Library

If you decide to adjust your oscillator, you can add a helper function or snippet in your clock configuration routine:

/* Calibrate HSI16 by adjusting the trim value.
 * Valid trim values range from 0 to 127 (0x7F), with 64 (0x40) being the reset default.
 */
uint32_t trim_value = 64; // Adjust up or down based on your lab measurements

RCC->ICSCR &= ~RCC_ICSCR_HSITRIM_Msk; //Clear current trim
RCC->ICSCR |= (trim_value << RCC_ICSCR_HSITRIM_Pos);

Note: Because the timer capture is running against the LSE, any change to HSITRIM will immediately reflect in your capture count readings.