cancel
Showing results for 
Search instead for 
Did you mean: 

Generate a frequency burst

Walter Nazarenus
Associate II

Hello,

i try to implement a 40kHz frequency burst with my NULCEO STM32F411RE. Until now i toggle the GPIO continuously in the HAL_TIM_PWM_PulseFinishedCallback function. But now i have to implement a start Trigger to do a small 40kHz burst. In the attached picture where you can see the yellow start trigger which should start my burst signal. To be flexible with the amplitude, i used the external DAC MCP4921. But as you can see (green signal), sometimes the code is executed faster, which generates a phaseshift. Thats why i want to implement this burst with an GPIO, but i will lose the functionallity of an flexible amplitude. I tried to use the Status Register UIF bit (Update interrupt flag) , which generates an impluse when the counter has overflown. but the result is not 40kHz (scope_4 blue signal). I changed the prescaler of my timer but nothing changed. I guess i have to use a different method.

void PM(void)
 {
   GPIOA->BSRR = (1<<24);; 
  for(int p=0;p<=40;p++)
   { 
    if(TIM2->SR & 0x01) 
    GPIOA->ODR ^= (1<<8);            //Toggle output GPIOA PA8 
  } 
  GPIOA->BSRR = (1<<24);
}

This is the function right after i read the yellow trigger Signal with

if(HAL_GPIO_ReadPin(I_Trigger_GPIO_Port, I_Trigger_Pin)== GPIO_PIN_SET)

How i could use the 40kHz of TIM2 to toggle my GPIO

8 REPLIES 8
DavidAlfa
Senior II

Use the search function! 😂

40KHz timer for manually toggling the IO is very inefficient.

https://community.st.com/s/question/0D53W00000gfldaSAA/generating-specified-number-of-pulses-using-pwm

Walter Nazarenus
Associate II

Okay, the example looks good. But i need in the middle of the Burst a phaseshift like "0 1 0 1 0 1 1 0 1 0 1 0"

DavidAlfa
Senior II

Then be more detailed in your questions.

For example, how long is the burst?

How many pulses?

Toggling an output at a fixed frequency is very easy, but changing it to random values is a very different thing.

40KHz is too slow, leaves out SPI and I2S interfaces.

I2C and UART have start bits, so neither.

I think the only option is PWM. Or refining your code.

Using DMA+PWM burst mode (described in the link provided) should work.

The only difference is that in the example I used fixed DMA memory address, it doesn't increase.

It's easy as going into the Cube Ide settings and ticking the memory address increase.

And setting the correct transfer size of the buffer in the DMA call.

For example, MCU running at 96MHZ, the divider for 40KHz is 2400.

Prescaler= 0, period=2399.

The bad part is that it will take 16 bits for each bit:

Send "1" = set PWM to 2399

Send "0 = set PWM to 0

If you want to send "0 1 0 1 0 1 1 0 1 0 1 0" it would be:

uint16_t PulseBits[12] = {
	0,			// 0
	2400,			// 1
	0,			// 0
	2400,			// 1
	0,			// 0
	2400,			// 1
	2400,			// 1
	0,			// 0
	2400,			// 1
	0,			// 0
	2400,			// 1
	0,			// 0
};
 
// Send 12 pulses. You must stop it when the interrupt triggers, the PWM won't stop itself.
HAL_TIM_DMABurst_MultiWriteStart(&htim4, TIM_DMABASE_CCR1, TIM_DMA_UPDATE, (uint32_t*)&PulseBits, TIM_DMABURSTLENGTH_1TRANSFER, 12);

I set 2400 because that way it's higher than the PWM max, you'll ensure the PWM output stays high until the end.

> Set the SPI frequency to 40KHz

This may be tricky, the SPI baudrate generator is notoriously limiting; but the same interface in I2S setting may have more degrees of freedom in frequency setting, thanks to a dedicated PLL.

Could be pulled out using timers, but not in a simple manner.

JW

Yes, I know, I quickly noticed and edited it! You replied while I was editing... 😁

SPI has simple dividers like /2 / 4 /8 /16.... not ok.

And i2S has a PLL but won't go that slow.

@Walter Nazarenus​ maybe this helps you?

https://www.hackster.io/javier-munoz-saez/face-your-neopixels-baremetally-yeea-stm32-b6b4d0

Pwm+DMA i develop a neopixel controller but can be tweaked for your needs

> And i2S has a PLL but won't go that slow.

The minimum PLLI2S VCO output frequency is 100MHz, maximum RCC_PLLI2SCFGR.PLLR=7, SPI_I2SPR.I2SDIV is 8 bit i.e. max. is 255.

If MCKOE=0, bit (BCK) frequency is I2SxCLK/((2*I2SDIV)+ODD) so the minimum is 100MHz/7/(2*255+1) = 27.96kHz.

If MCKOE=0 and 16-bit transfer is used, bit frequency is I2SxCLK/(((2*I2SDIV)+ODD)*8) so the minimum is 27.96kHz/8=3.495kHz

JW

Walter Nazarenus
Associate II

It should have 10 pulses bevore and 10 after the phaseshift. Doesnt matter if the pulse is two pulses high or low. I attached the output of the DAC. But now i want to realize this with timer and Gpio, to get a more accurate frequency