I try to read a memory cell from a chip with my stm32f103 uC. I send three bytes, one instruction then 2 address bytes. Watching this on a scope I get the MOSI signals back, not the same level, but attenuated. Is that normal? If something's wrong with my chip, should the MOSI signal reflect back on the MISO pin?
You need to send more than 3 bytes master generates the clock. To read something master needs to send dummy bytes.
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 implementing a virtual instrument on STM32 (STM32F103x). Like a normal "hello world", I tried to start with the simplest MIDI message, sending NOTE-ON MIDI message in a loop to see if it works.
I send MIDI NOTE-ON message for every 500ms, only NOTE-ON message in a forever loop, but it not works. Is there any other MIDI message must be sent to make MIDI works? Like some initialize message?
Based on MIDI 1.0 spec, I finish my code on STM32 by sending MIDI message via USART interface.
Then use a logical analyzer, I confirmed my MIDI message is fully match the MIDI 1.0 spec. At least I believe it correct, no issue. 31250 baud rate, 1 start bit, 1 stop bit, one status message 0x92 followed by two data bytes 0x48 and 0x7F, LSB first.
Below is the NOTE-ON message captured by the logical analyzer on TX line of URAT interface. I continue send the same 3 bytes for every 500ms.
The totally time for those 3 bytes are 960 microseconds also match MIDI 1.0 spec mentioned value.
Then, based on "(CA-033) MIDI 1.0 Electrical Specification Update [2014]", I buy one 5 PIN MIDI OUT jack, connect the URAT TX line to PIN-5 through a 10 Ohm resister, connect 3.3V power to Pin-4 through a 33 Ohm resister, PIN-2 and Jack shield connect to GND. Other optional parts (buffer for Rc, ferrite beads) are not used.
However, when I use a USB-MIDI wire connect my MIDI OUT jack to my PC, nothing happen. The USB-MIDI wire has two LED indicators , one for power another for MIDI signal. After connect, the power LED is light, but the MIDI signal LED never light.
I tried to use logical analyzer to analysis PIN-5 of my MIDI OUT jack, the MIDI message byte are totally same with URAT TX line, and every 500ms one NOTE-ON message. However, it never works.
I also tried to create my own PCB with Dream SAM2695 by follow the SAM2695 Evaluation Boards. Then connect the URAT TX directly to MIDI_IN pin of SAM2695, it still no response. Since I have no confidence on my manual soldering PCB, not sure if the PCB itself has issue cause it no response. So I buy a USB-MIDI wire, but the result as I mentioned above, still no response.
======= Apr.26.2021 Update =========
Based on comments, have tried to check the output of the optocoupler.
Before do this check, I bought several BSS138 to transform the MIDI signal to 5V single use below circuit (of course change the resisters near MIDI JACK pin to 220 Ohm as the spec)
After this change I measured voltage of the 5V URAT TX, it show as 4.8+ V, and Logical Analyzer show correct MIDI note on message of this new 5V MIDI signal. However, it still not works.
The only left troubleshooting method for me is measure the output of the optocoupler on this USB-MIDI wire. But I didn't find an optocoupler on this MIDI USB wire PCB. There even do not have any one component has 4 pins on the PCB (based on my understanding, an optocoupler need at least 4 pins).
There only have one main chip on the PCB, it is possible that the optocoupler is embedded in that chip? Since the pin are too small I failed to connect my logical analyzer to those pin to check.
Is DMA chip effective for small data packet like 5 bytes.
I am working on a embedded project with STM32, I am using DMA for receiving 3 bytes packet but when using DMA to transmit 5 bytes packet, I don't get the packet at the receiving side immediately, but when using a normal transfer, I get the packet more quickly.
So can we say that DMA is not effective for small packet ?
The problem with using DMA for receiving is that the DMA transfer interrupt occurs then the DMA buffer if full and/or half-full, if receipt of the packet does not fill the buffer to reach the half or full-transfer threshold you will not get an interrupt to indicate the availability of the data.
So say your receiver has 6 byte DMA buffer and generates an interrupt at the half and full transfer, you send a 3 byte packet and you will get an interrupt at the end of every packet. If you send a 5 byte packet, you will get an interrupt for the first three bytes, then the next two bytes will sit in the buffer indefinitely until one more byte (from the next packet) arrives.
So it is not really a matter of "small packets" but rather packet alignment with the DMA buffer. It is not even in fact a matter of "packets" - if the data were a stream, you end up with the same problem when the data stream ceases if it happens not to be a multiple of the DMA buffer size.
Moreover even if the packets are an exact multiple of the DMA buffer size, if you get data loss over the link, you will no longer be aligned with the buffer and will encounter the same problem.
The solution in this case if to set a timer on each receive DMA half/full transfer to use as a timeout. The timeout would normally be set to something a little more than the time taken to transfer one half of the buffer (assuming you are using the half/full transfer to allow double or "ping-pong" buffering), so that if the buffer half/full transfer is not achieved, the timer expires and on the timer handler you retrieve the data that has been transferred. When the DMA half/full transfer interrupt does occur, you need to account for the data you have already retrieved in the timer interrupt, and just retrieve the new data.
So you would implement a driver where data is retrieved from the buffer on any of a DMA half-transfer, full-transfer or timer interrupt, and in the timer handler you maintain a count or index to the last buffer position retrieved so that in a half or full transfer you only retrieve the new data.
If your buffer is long and your packets small, and the data is not streaming, you could get several timer interrupts between DMA interrupts. In that case you might make your timeout smaller than the DMA buffer fill time. The optimal solution may depend on the nature of the data being transferred and the latency you can sustain.
If you can sustain the interrupt rate of one interrupt per character, then it will always be simpler to avoid DMA for receiving data, but it will never be "ineffective", just more complicated to get right. Your problem here is not that small DMA transfers are ineffective, but rather that your implementation is sub-optimal.
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.
I am trying to loopback the SPI bus on my STM32F0 (with a discovery board, MISO pin connected to MOSI pin).
I am following the tutorial Discovering the STM32 Microcontroller, (edition January 18, 2014), Exercise 6.1 : SPILoopback.
The STM32 is configured as the master.
To send a byte to MOSI pin, the author wrote :
SPI_I2S_SendData (SPIx, *tbuf++);
where :
SPIx is the SPI bus I want to send data
tbuf is the uint8 (in other words an unsigned char ...) I want to send on the bus
To receive this byte from MISO pin, he wrote :
while (SPI_I2S_GetFlagStatus (SPIx, SPI_I2S_FLAG_RXNE) == RESET);
if (rbuf)
{
*rbuf++ = SPI_I2S_ReceiveData(SPIx);
...
...
The flag SPI_I2S_FLAG_RXNE should be SET since I send a data to MOSI pin, and since MOSI pin is connected to MISO pin.
My problem is :
I never go out from the while loop (the SPI_I2S_FLAG_RXNE is never SET, even if I look through the debugger.
(I see CLK and MOSI being alive on my logic analyser, so I'm sure my byte goes out from an electrical point of view.)
It is like the STM32 never received the byte, even if MISO pin is connected on MOSI pin ...
Why ?
It is because on STM32F0, the flag SPI_I2S_FLAG_RXNE is set by default only when 16 bits (so 2 bytes) are received on MISO pin.
If you send 2 bytes and then do you while loop, you should exit of the loop very quickly.
The Reference Manual said (Section SPI status flags) :
The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register:
If FRXTH is set, RXNE goes high and stays high until the RXFIFO level is greater or equal to 1/4 (8-bit).
If FRXTH is cleared, RXNE goes high and stays high until the RXFIFO level is greater than or equal to 1/2 (16-bit).
So, if you want the flag SPI_I2S_FLAG_RXNE to be set when only 1 byte is received, you should use the following function :
SPI_RxFIFOThresholdConfig (SPIx, SPI_RxFIFOThreshold_QF);
SPI_RxFIFOThreshold_QF: RXNE event is generated if the FIFO level is greater or equal to 1/4.
SPI_RxFIFOThreshold_HF: RXNE event is generated if the FIFO level is greater or equal to 1/2. (default value)