According tot the datasheet, the ADC generates a DMA request at the end of each conversion:
Does the ADC use an interrupt to generate this DMA request? Or is it done in the background using hardware automatically? I am asking this today because in STM32CubeMX, you get to choose either the End of Conversion (EOC) or End of Sequence (EOS) interrupt.
I am wondering if choosing either EOC or EOS interrupt will have any effect on the ADC's ability to generate DMA requests.
Related
I have a STM32F417IG microcontroller an external 16bit-DAC (TI DAC81404) that is supposed to generate a Signal with a sampling rate of 32kHz. The communication via SPI should not involve any CPU resources. That is why I want to use a timer triggered DMA to shift the data with a rate of 32kHz to the SPI data register in order to send the data to the DAC.
Information about the DAC
Whenever the DAC receives a channel address and the new corresponding 16bit value the DAC will renew its output voltage to the new received value. This is achieved by:
Pulling the CS/NSS/SYNC – pin to low
Sending the 24bit/3 byte long message and
Pulling the CS back to a high state
The first 8bit of the message are containing among other information the information where the output voltage should be applied. The next and concurrently the last 16bit are containing the new value.
Information about STM32
Unfortunately the microcontroller of ST are having a hardware problem with the NSS-pin. Starting the communication via SPI the NSS-pin is pulled low. Now the pin is low as long as SPI is enabled (. (reference manual page 877). That is sadly not the right way for communicate with device that are in need of a rise of the NSS after each message. A “solution” would be to toggle the NSS-pin manually as suggested in the manual (When a master is communicating with SPI slaves which need to be de-selected between transmissions, the NSS pin must be configured as GPIO or another GPIO must be used and toggled by software.)
Problem
If DMA is used the ordinary way the CPU is only used when starting the process. By toggling the NSS twice every 1/32000 s this leads to corresponding CPU interactions.
My question is whether I missed something in order to achieve a communication without CPU.
If not my goal is now to reduce the CPU processing time to a minimum. My pIan is to trigger DMA with a timer. So every 1/32k seconds the data register of SPI is filled with the 24bit data for the DAC.
The NSS could be toggled by a timer interrupt.
I have problems achieving it because I do not know how to link the timer with the DMA of the SPI using HAL-functions. Can anyone help me?
This is a tricky one. It might be difficult to avoid having one interrupt per sample with this combination of DAC and microcontroller.
However, one approach I would look at is to have the CS signal created as a timer output-compare (like PWM). You can use multiple channels of the same timer or link multiple timers to create a delay between the CS output and the DMA trigger. You should allow some room for jitter, because depending on what else is happening the DMA might not respond instantly. This won't hurt your DAC output signal though, because it only outputs the value on the rising edge of chip select (called SYNC in the DAC datasheet) which will still be from your first timer.
I'm testing the SPI capabilities of STM32H7. For this I'm using the SPI examples provided in STM32CubeH7 on 2 Nucleo-H743ZI boards. I will perhaps not keep this code in my own development, rigth now the goal is to understand how SPI is working and what bandwith I can get in the different modes (with DMA, with cache enabled or not, etc...).
I'd like to share the figures I've computed, as it doesn't seem very high. In the example, if I understood correctly, the CPU is # 400Mhz and the SPI bus frequency # 100MHz.
For polling mode I've measured the number of cycles of the call to function HAL_SPI_TransmitReceive.
For DMA I've measured between call to HAL_SPI_TransmitReceive_DMA and call to the transfer complete callback.
Measurements of cycles where made with SysTick clocked on internal clock. Since there is no low power usage, it should be accurate.
I've just modified ST's examples to send a buffer of 1KB.
I get around 200.000 CPU cycles in polling mode, which means around 2MB/s
And around 3MB/s in DMA mode.
Since the SPI clock runs at 100Mhz I would have expected much more, especially in DMA mode, what do you think ? Is there something wrong in my test procedure ?
I'm working on a firmware development on a STM32L4. I need to sample an analog signal at around 200Hz. So basically one analog to digital conversion every 5ms.
Up to now, I was starting the ADC in continuous conversion mode, triggered by a timer. However this prevents to put the STM32 in Stop mode in between conversions, which would be very efficient in terms of power consumption since 99%+ ot the time the product has nothing to do.
So my idea is to use the single conversion mode: use a low power timer to wakeup the product from Stop mode every 5ms, launch a single conversion in the LPTIM interrupt handler (waiting for ADC end of conversion in polling), and go back to Stop mode.
Do you think it makes sense or do you see problems to proceed like this ? I'm not sure about polling for a single ADC conversion inside a handler, what do you think ? I think a single conversion on one channel should be pretty fast (I run at 80MHz, the datasheet mentions a maximum sampling time of 8us)
Do I have to disable/enable ADC (the bit ADEN) between each single conversion ?
Also, I have to know how long a single conversion lasts to assess whether the solution is interesting or not. I'm confused about the sampling time (bits SMP). The reference manual states: "This sampling time must be enough for the input voltage source to charge the embedded capacitor to the input voltage level." What is the way to find the right SMP value ?
There are no problems with the general idea, LPTIM1 can generate wakeup events through the EXTI controller even in Stop2 mode.
I'm not sure about polling for a single ADC conversion inside a handler, what do you think ?
You might want to put the MCU in Sleep mode in the timer interrupt, and have the ADC trigger an interrupt when the conversion is complete. So disable SLEEPDEEP in the timer interrupt, and enable it in the ADC interrupt.
What is the way to find the right SMP value ?
Empirical method: start with the longest sampling time, and start decreasing it. When the conversion result significantly changes, go one or two steps back.
I am doing a quadcopter using a STM32F407 discovery. I was finally able to stabilize it. Now i am trying to use the RC receiver so i can control my quadcopter movements. Is there a way to read the signal of PWM of my RC receiver channels ??
Also my RC receiver supports PPM and according to what i understand it receives a packet of duty cycles strong textbut still don't know how to receive this.
You can use the SPI interface to encode the PPM (or the PWM) signal of your RC receiver.
General approach:
Connect the PPM signal to the MISO pin and a second one of the controller (simultaneously). MOSI, CLK, and CS pins are not needed.
Initialize the SPI interface with a appropriate clock. With this frequency the signal will be shifted in the controller. Try to use 4kHz.
Depending on the idle state of the signal enable either rising or falling edge interrupt trigger on the second pin. This will used to trigger incoming frames.
If the interrupt occurs disable the trigger temporary and start spi transmission to get several bytes (outgoing ingored and not connected). Depending on the Frame length 8 or 10 Bytes should do it. This will catch frames up to 20ms.
After you get the all bytes enable the trigger again and repeat for the next frame.
The received data should contain the pattern of the pwm/ppm signal.
You should also match the sampling rate and the amount of bytes to receive with your RC receiver.
using cortex M3, arduino due
does anyone know if its possible so get a pwm channel to disable itself after so many pulses.
what i want to try out is something like this
Interrupt 1 fires (timer0),
it sets the delay of the pwm and how many cycles to go for
pwm starts and each pulse increments the counter, once the counter reaches its limit the pwm disables itself
what im NOT interested in is any other loop outside of the pwm settings doing the counting/disabling
Just add a interrupt to the timer which does the PWM (either from "update" of from "compare" - the result will slightly vary, so you must pick the one you prefer) and increment the counter there. Once the counter reaches your target value just disable the timer from interrupt and that's all.
There is a better way to handle this if your controller has DMA and DMA Iteration counter.
Configure the DMA channel to transmit a dummy byte upon each pulse. configure the DMA to raise an interrupt when Iteration counter reaches the threshold. You can stop the PWM counter inside this ISR handling. Since we are using DMA for pulse counting, there is very little load on the CPU.