I have been studying about SPI and would like to clarify few more things:
1.
I am trying to understand about CPOL and CPHA in particular:
I have a device (MCP41 that I want to write SPI drivers for). The datasheet can be found here:
https://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf
According to the timing diagram:
It mentions that Data is always latched in on the rising edge of the SCK. Is that supposed to give me any hints about CPHA?
It also mentions that the Data is always clocked out of the SO pin after the falling edge of SCK. Since it mentions falling edge of the SCK, I understand that the CPHA for this device should be set to 1, is that correct?
2 What if I have 2 SPI devices connected to the same SPI bus. One device requires CPOL = 0, CPHA = 0 and the other device requires CPOL = 0 and CPHA = 1. Does that mean it will not be possible to communicate with both devices via single SPI bus?
The timing diagram shows that this device requires SPI mode 0: CPOL=0 CPHA=0.
The way to read the diagram is that the clock idles low, so CPOL=0. The data is sampled (called "latched" above) on the rising edge. This is the first edge when starting low so CPHA=0 (the rising edge would be the second edge if starting high).
The comment about output data on the falling edge simply means that the device outputs the next data starting on the second edge of the preceding pulse, this way it is ready in time for the first edge of the next clock pulse.
For your second question, yes you can mix different clock modes (polarity, phase and speed) on the same bus, as long as you make all the changes when no device is selected, ie: when all chip-selects are high. You may want to even change the mode of the chip select pins momentarily to GPIO while you deconfigure and reconfigure the SPI peripheral (I'm never sure what alt-function pins will output while you are messing with the registers of a disabled peripheral).
Related
I have connected and tested the two break-board versions of MPR121 Proximity Capacitive Touch Sensor Controller with various mcu's (ESP32, RPI pico, ARDUINO)
The one on a keypad version (Sparkfun compatible) and the one that you can connect custom pads to it. I tried them both with cpp and micropython. I connected them via I2C and everything is functioning on all occasions, with the IRQ option as well.
However I have trouble increasing sensitivity and by that I mean that if I place even a thin piece of paper or other layer before the touch pads, I can't get a touch signal.
Looking into the MPR121 micropython example Library I modified the following:
MicroPython MPR121 capacitive touch keypad and breakout board driver
https://github.com/mcauser/micropython-mpr121
Inside this library I see the following parameters for tuning that I tried:
# Set touch and release trip thresholds
#self.set_thresholds(15, 7) default....
self.set_thresholds(15, 7)
# Set config registers
# Debounce Touch, DT=0 (increase up to 7 to reduce noise)
# Debounce Release, DR=0 (increase up to 7 to reduce noise) .....default was 0x00
self._register8(MPR121_DEBOUNCE, 0x00)
# First Filter Iterations, FFI=0 (6x samples taken)
# Charge Discharge Current, CDC=16 (16uA) .default was 0x10 5-30 less to more sensitive
self._register8(MPR121_CONFIG1, 0x30)
# Charge Discharge Time, CDT=1 (0.5us charge time)
# Second Filter Iterations, SFI=0 (4x samples taken)
# Electrode Sample Interval, ESI=0 (1ms period) .default was 0x20 5-30 less to more sen
self._register8(MPR121_CONFIG2, 0x20)
I tried various combinations but the effect is minimal if non-existent. My target or best case scenario is to be able to place a 3mm plexiglass on top of the breakout board or custom pads.
Here's my configuration:
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = 8;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct);
When I put the signal on the input pin (square, 2Hz, 3.3Vp-p) I get an interrupt every 250ms, so - on every RISING and falling edge of the signal. I changed the test signal duty cycle to test if it's really what is happening and it confirmed it. I get the interrupt on both edges.
I even debugged the HAL driver to test if it does what I think it does. And yes, it seems to configure the EXTI correctly, only for the falling edge for my pin.
What may be the cause of such behavior? My device is STM32H747I-DISCO discovery board with TouchGFX software used for presentation. The software works correctly, I tested it on measuring the time between other timer interrupts.
I monitor the test signal on the oscilloscope to ensure the input signal on my pin is correct. I tried to use another pin on the same port, but I observe identical behavior. I get interrupts on both rising and falling edges of the signal, despite the pin is configured to trigger the interrupt only on the falling edge.
I also tested the case with the rising edge only. Also in this case I get the interrupt on both edges.
The problem turned out to be a hardware error, a voltage spike I overlooked. The STM32 EXTI input worked correctly all the time. There was indeed a spurious falling edge.
Simulated problem illustration, the 10n capacitor causes voltage spikes and spurious edge detection. In the real circuit, when a digital oscilloscope was used and the time base was too long to capture the spike - the signal looked like a proper square wave. After shortening the time base I noticed the spike. As it is shown on the illustration, this behavior can be easily simulated in a circuit simulator:
SIMULATION LINK
Removing the capacitor from the circuit solved the problem.
To avoid getting noise and other spurious signals on the input shielded wires can be used. The real world circuit was tested and it works properly without the capacitor.
The opto-coupler is just a simplified model of the optical sensor used in the real machine.
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.
The clock configurator in STM32CubeMX does not allow the PLL divider DIVP1 frequency to exceed 300MHz so it is impossible to use it to achieve the board's maximum of 480MHz. To do this you must go into the code for the configurator and manually change the multipliers. Is this confusion on my part or an error with the data provided by ST for the board?
Checking CPU performance singing a hardcoded assembler timing loop the subtract and branch instructions of the timing circuit take two clock cycles. On my Nucleo-H723ZG board these two take a total of one cycle. Is DUAL ISSUING not available on H743?
Once again in the STM32CubeMX in the System RCC section Master_Clock_Output_1 is highlighted in RED. (Conflict with: USB_OTG_FS: Activate_SOF). What is this all about?
You need to have the correct voltage scale (VOS) which affects the maximum clock directly. To clock this device at 480MHz.
As for your pin conflict - the MCO pin is a clock output to use for clocking external devices. Pins in the STM32 chip can be multiplexed such that they can serve multiple functions, such as ADC1_CH4 GPIO_OUT etc... You have a conflict that 1 pin is trying to facilitate 2 functionalities, and such you have a conflict. rearrange the functionality or pin to fix the conflict.
Is it possible to measure 3 specific resistor values by using GPIO / Without using a full ADC setup?
I have an alarm sensor that I want to hook up to my GPIO. This sensor has 3 specific resistors value, based on it's state:
1) Normal - 4k7
2) Alarm - 9k3
3) Tamper - infinite.
Due to long lines, I would prefer 12V power on one side.
I would like to be able to detect these states by 2 normal GPIO input pins.
Is that even possible? What would be the schematic needed for this?
Or is the only solution to use (external) ADC's?
I am thinking about a voltage diver with resistors and a 1N4148 diode to clip it to 3v3. But so far my results are unfruitfull.
Thanks.
The problem here is you have three levels to measure. If we had two we could use a simple resistor divider setup to make (say) the 4k7 and 9k3 outputs on the sensor to logic 0 (<=0.8V) or logic 1 (>=1.3V) on a single GPIO pin. We could do this on two GPIO pins if we had two "independent samples" of the sensor output rather than one.
Given the above it is possible to design some simple logic network to do the comparisons but as the other comment mentions you're off into the realms of electronics.
ADC is the simplest way to go if you want to stay in the software domain. The are other SBC devices e.g. ESP8266 which have onboard ADC functionality and built-in Wifi https://esp8266-projects.org/2015/03/internal-adc-esp8266/ or you can hook up an add-on ADC to the Rpi for example https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters
Good luck