Electronics > Projects, Designs, and Technical Stuff
variable frequency square wave
dpenev:
Hello,
I am designing a STM32L4 based MCU system.
One of the requirement is to generate square wave with arbitrary frequency in the range 1KHz - 1MHz.
I need something like 0.1% accuracy of the frequency control.
Initially I thought that the PLL inside the STM32L4 will do but it looks as it is intended to clock the whole CPU (and I2S peripherals) only.
This PLL is quite limited in terms of M/N counters.
Then I tough that probably I can use one of the STM32L4 timers to improve the frequency I can get out of the PLL.
Unfortunately the STM32L4 timers can be clocked from the PLL but only thru the system clock.
So adjusting the frequency I will have to change the system clock as well. This means as special procedure..
So I seems to give up with the pure STM32L4 solution.
Then I have started to look at external PLL chips and I found Si5351.
It looks as if will work for me.
Anyone willing to suggest an alternative or just share some thoughts?
Thank you
Dimitar
OM222O:
why are you trying to reinvent the wheel? I haven't used the STM chips but the solution is pretty much standard. No need to use PLLs / change clock frequency, etc
Just use the built in timers. There also usually exists a compare register (I will be extremely surprised if the STM MCUs don't have this, as even the cheapest MCUs have timer compare registers! arduino as an example and their lowest end micros: ATTINY10 have this!). Knowing the clock frequency of the timer register, you set the value at the comparator register, which then causes an interrupt at that set value. you then create an interrupt service routine to change the pin state high or low. the frequency of the output will be the easy to calculate based on the known factors and maybe a few clock cycles out due to instructions being carried out, but certainly much better than 0.1%
Edit: here is an article from adafruit with detailed explanations for arduino, but you should be able to read the datasheet of the STM32 and easily figure out the details such as registers and whatnot:
https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers
Kleinstein:
One could use the timers to divide the system clock frequency. So one gets system clock divided by N .
This gives good resolution at least for the lower frequencies. For the higher frequencies the resolution is limited however. This is a principle limit of the µC, as time steps are limited to the system clock.
For higher resolution also at higher frequency, there are several options, e.g.:
1) if only the average frequency needs to be right one could use a fractional divider - however this has quite some jitter.
2) use an external PLL to multiply a frequency by something like a factor of e.g. 64 or 256 (fixed) for the highest frequencies.
The divider in the µC could than also use a fractional divider as the PLL filters the jitter.
3) Use DDS to generate a sine wave first and than convert to square with a comparator. The DDS part could be a special chip or possibly in software with the µC (could be tricky near 1 MHz).
4) Use an VCO and external divider for the coarse part to generate the raw frequency and use the µC to do the PLL in software.
dpenev:
Hi Guys,
@OM222O Thank you, I will take a look at your article to see if I can get rational out of it.
@Kleinstein Thank you! I will comment your sentences as i think those are very relevant.
--- Quote ---One could use the timers to divide the system clock frequency. So one gets system clock divided by N .
This gives good resolution at least for the lower frequencies. For the higher frequencies the resolution is limited however. This is a principle limit of the µC, as time steps are limited to the system clock.
--- End quote ---
Indeed my current solution is using 16MHz as base clock and by simple division I get something like 0.6% error at 100KHz and error goes more than 6% at 1MHz
--- Quote ---1) if only the average frequency needs to be right one could use a fractional divider - however this has quite some jitter.
--- End quote ---
Yes jitter will be a problem for my application. Also implementing of fractional divider for 1MHz output will be very difficult I believe.
Any practical results about this on 32MHz ARM M4?
--- Quote ---2) use an external PLL to multiply a frequency by something like a factor of e.g. 64 or 256 (fixed) for the highest frequencies.
The divider in the µC could than also use a fractional divider as the PLL filters the jitter.
--- End quote ---
What would be the benefits of generating 64/256 times bigger target clock first by the external PLL?
(compared to the exact target clock)
Do you consider PLL chip for 1KHz impractical, so that's why you suggest this?
Or this will just reduce the jitter?
I believe external PLL will generate signals with acceptable jiter for my application.
--- Quote ---3) Use DDS to generate a sine wave first and than convert to square with a comparator. The DDS part could be a special chip or possibly in software with the µC (could be tricky near 1 MHz).
--- End quote ---
Interesting! But I believe this will be an overkill for my application.
--- Quote ---4) Use an VCO and external divider for the coarse part to generate the raw frequency and use the µC to do the PLL in software.
--- End quote ---
Do you mean real PLL in software with phase detector or just a divider here?
In fact can the STM32L4 timer system (input capture, output compare) is able to implement PLL efficiently?
Unless efficient PLL can be implemented by the STM32L4 timer I believe that 2) (and external PLL) is my best option.
Anyone willing to suggest an inexpensive PLL/controllable oscillator.
My target output clock frequency is quite low. range (1kHz - 1MHz)
Thank you
Dimitar
ogden:
1MHz with 0.1% precision using integer divider (of hardware timer) means 1GHz clock. I agree that Si5351 is best way to achieve needed performance. Other way around would be DDS IC (AD9837) + comparator for square wave output.
Navigation
[0] Message Index
[#] Next page
Go to full version