STM32F401 use of external crystal with STM32duino - Page 1
Forum section: electronics / general

author: timdf911
author_rank: Contributor
timestamp: January 19, 2023, 07:45:00 pm
content: Hi guysa little while back I posted a question about how to measure frequencies up to 30MHz with 1kHz resolution.Thanks to some very helpful responses I managed to get my code working ok - albeit using the on chip 16MHz RC oscillator.However I've found the stability and accuracy of the RC oscialltor to be marginal, so I've modified my code to use an external 16Mhz crystal.The attached zip file contains the entire sketch.I though I had cracked it until just for kicks I shorted out the 16MHz xtal and it kept working leading me to think that it was actually still using the internal RC osc.I know the 16MHz xtal is running ok as I can see it on my scope.I also added a line of code to turn off the internal16MHz Rc HSI oscillator, but it still works even with the internal RC off and the xtal shorted out.I suspect I'm doing something wrong in the config as the accuracy / stability is just like it was before with the internal RC.As ever any help gratefully received.Regards Tim

author: timdf911
author_rank: Contributor
timestamp: January 19, 2023, 09:51:17 pm
content: As often happens, having written the above post triggers another line of thought.As I'm using a Nucleo 64 board by default the master clock signal MCO comes from a 8MHz crystal on the ST link side thus I suspect the jitter I'm seeing in the measurement is inherent to the strategy I'm using. (of course this doesn't explain why my code works with the external xtal disabled).For example for a frequency of 3MHz should result in a count of 3000 +/- 1 count ie 2999 or 3001 but in reality I see a spread of +/- 3 or 4 counts.FYI I'm using a prescaler of /8 and a 8mS gate time.I suspect I need a longer gate time to get a more consistent kHz reading (allowing the jitter to be 100's of Hz rather than kHz), this means the 16 bit will be allowed to overflow multiple times and need counting to calculate the actual frequency.Time to revisit my frequency counter code - of course this could have been a lot easier if I'd been able to use a 32 bit counter from the outset !

author: thm_w
author_rank: Super Contributor
timestamp: January 20, 2023, 12:57:08 am
content: - in the future use this forum:https://www.eevblog.com/forum/microcontrollers/I'll ask to move it.- use register defines instead of (1<<x) bit shifts, it makes the code incredibly difficult to read- your code turns off HSI first before starting up anything else, which doesn't seem like it would work to me, because what will the processor use to perform the next instructions?From the ref manual:QuoteIf you have printf or SWD debug you could read out the status bits as verification.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: January 20, 2023, 01:42:42 am
content: Clock setup and distribution of the STM32 is quite complicated. It's also got configurations that if it detects a failure of the external crystal, it automatically switches to an internal oscillator. So, when both have a similar frequency, it won't be obvious when it does this switching. So either program the internal oscillator for a different frequency, or swap the external crystal for one with a bit different frequency, and the measured frequency should then deviate proportionally.

author: DavidKo
author_rank: Frequent Contributor
timestamp: January 20, 2023, 06:16:32 am
content: Maybe you can start with GPSDO code - which do the same for 10MHz. In principle you want to have precise counter in a given time interval. For your precision you can use x:1 divider depending on your integration time to get resolution you need. Makes no sense to go higher with the clock frequency.

author: timdf911
author_rank: Contributor
timestamp: January 20, 2023, 10:57:42 am
content: Thankyou for moving my post to this new location.Regarding my code style being difficult to read - apologies as I struggled to use register defines due to not fully understanding the syntax, so I went back to basics to ensure I was setting the bits I wanted to set.Just for kicks I changed the xtal to 10MHz expecting it break the serial comms and other stuff - but it didn't, still uses the internal 16MHz RC even though the xtal is actually running ok at 10MHzI deleted the line RCC->CR &= ~(1<<0); which turns off the HSI but still it runs at 16MHz RC osc.As I'm using the stm32duino environment I'm going to investigate what the default clock is - 16MHz RC or external 8MHz MCO signal from the STlink built into the Nucleo 64.If it turns out it uses the 16MHz RCosc by default (which I suspect is the case) then switching to the crystal derived 8MHz MCO signal might be the easiest way forward to improve stability and accuracy of the measurements.Regards Tim

author: timdf911
author_rank: Contributor
timestamp: January 20, 2023, 04:01:35 pm
content: Ok so I've made some progress thanks to a snippet of code I found - but the master clock is running twice as fast as it should.With a 16MHz xtal I have to set the baud rate to 57600 but it actually generates 115200 - I found this out by running a simple blinky program.I used CubeMX with a 16MHz crystal generate the clock tree numbers as per below for the STM32F401 nucleo board.Shorting out the xtal stops it running and the xtal measure 16MHz so all good there - just this factor of two.Any ideas ?EDIT - fixed it, had to delete #include <Arduino.h> from my sketchCode:RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = 4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}}

author: thm_w
author_rank: Super Contributor
timestamp: January 20, 2023, 11:27:48 pm
content: Where is the code where the baud rate was set?Depending on the UART it may use a specific clock source, or the clock source may be able to be selected via register. eg SYS or APB1.With the code you show SYSCLK should be at 84MHz and APB1 at 42MHz.

author: timdf911
author_rank: Contributor
timestamp: January 21, 2023, 09:10:53 am
content: Hithe uart is behaving normally now - ie generating the desired baud rate as selected.FYI I'm using the 8MHz xtal clock MCO from the STlink to drive the clock tree (after making sure SB16 and SB50 were in place).The uart baud rate is set using the usual stm32duino commands.Now when measuring frequency I get a steady +/- 1kHz result as expected.The counter itself rolls over at 65535kHz as expected due to the 16 bit counter, but it actually keeps counting to in excess of 142MHz due to the high speed /8 input presecaler.Regards Tim

author: ozcar
author_rank: Frequent Contributor
timestamp: January 21, 2023, 07:04:21 pm
content: Quote from: timdf911 on January 19, 2023, 09:51:17 pmSo that particular horse from your previous thread has come back to haunt you. I'm still not convinced that you could not get to use a 32-bit timer, but then you never did give us the full picture of what pins you are using, and how you might need to use the timers for other purposes.