Raspberry Pi - UART - disable TX and enable RX in program C - c

I need connect my raspberry pi 4 model b with a servo via UART, but it is possible only via 1 wire. That means I must connect pin TX and RX together. In order to do so, I must have a way how to manually disable only TX or RX in my C program.
I am able to easily disable RX thanks to termios.h library, but I didn't find any way how to disable TX.
I was trying to disable it through this
tcflow(fd_myUART, TCOOFF); // it should suspend output
But that didn't work, so I thought that maybe if I change the pin of TX to INPUT, it will change the pin from UART to GPIO, but that didn't work either.
Do you have a way, how to do that, please?

First of all, just "randomly" connecting both wires is a bad idea.
Below image shows how to do it better for a prototype.
Slave devices are able to pull the IO line low during a read bit or a reset while the TX signal is high.
When used in this configuration, you should not disable RX nor TX. You can use "normal" UART operation.
More information can be found here (maxim integrated tutorial 214 "USING A UART TO IMPLEMENT A 1-WIRE BUS MASTER")

Since you will have a lot of connected slave, you should consider using a dedicated chip:
I use a DS2482S-100 over I2C.

Related

RS485 communication not supported using FTDI cable

I'm trying to port a program, which communicates over RS485 half-duplex UART, to Raspberry Pi. Since Pi's built-in UARTs don't support the RS485 standard, I'm using the USB-RS485-WE-1800-BT FTDI cable.
When connected, I can confirm that the cable's FTDI chip shows up in dmesg, the ftdi_sio driver is loaded, and properly exposes the /dev/ttyUSB0 serial terminal to the rest of the system. However, when I attempt to enable RS485 mode from a simple C program:
struct serial_rs485 config = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND,
.delay_rts_before_send = 0,
.delay_rts_after_send = 0
};
if (ioctl(fd, TIOCSRS485, &config) < 0) {
fprintf(stderr, "ioctl failed (%d): %s\n", errno, strerror(errno));
exit(0);
}
... I get the following error:
ioctl failed (25): Inappropriate ioctl for device
Looking into a schematic, I realized that the FTDI cable internally uses 2 components:
the FT232R chip, which is controlled by the ftdi_sio driver over USB and produces conventional serial output, and
the ZT485EEN chip, which transforms conventional serial comms to RS485.
So, given that FT232R doesn't technically emit RS485, I understand why its driver complains when asked to enable RS485 mode. What it doesn't know, though, is that the second chip takes care of format conversion transparently.
Having researched this topic for a bit and read answers to a similar question, I'm now curious how to proceed. Should I change the request ID in my ioctl() call to something else than TIOCSRS485? Should I remove the ioctl() call entirely? And if I do that, how can RS485 flags and RTS delays be set? Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Should I change the request ID in my ioctl() call to something else than TIOCSRS485? Should I remove the ioctl() call entirely?
Removing the ioctl() would be the appropriate thing to do in this case, as the serial converter is handling it entirely for you. As far as you are concerned, it is just a serial port that you read and write to.
And if I do that, how can RS485 flags and RTS delays be set?
You can't set any flags or delay using the FTDI cable. However, since the data that comes out of the cable is already RS485, there's no need to set anything. As long as whatever it is you're talking to is half-duplex(it does not talk at the same time as you do), this isn't an issue, and you can use it just like an RS232 cable. This depends on your specific use-case though. I have never encountered the need to have an RTS delay.
Finally, if this means that enabling RS485 mode is not required in this configuration, can the FTDI cable be bypassed entirely by using Raspberry Pi's built-in UARTs combined with a chip like ZT485EEN?
Sure, you can do that. There are also many different models of RS485 transcievers that you could use; Electronics.SE would the the place to ask for more information on that. You may need to enable RS485 at that point with TIOCSRS485, but that's going to be driver-dependent. I don't know about the Pi, but at least on some Atmel chips that I have used before setting the RS485 mode sets a certain bit in the peripheral on the chip that automatically toggles the RTS pin to enable/disable the RS485 transciever; otherwise, Linux needs to toggle a GPIO in order to set the transciever into the correct state.
Specifically on the FTDI, there are GPIOs that can be set that will turn on/off at appropriate times. One of these is the TXDEN signal, which controls the transciever for you automatically. Others are used for the Tx/Rx LEDs.
There’s no “rs485” mode. Just forget about it and everything will be OK. RS485 is just an electrical standard, and the ZT485 does the electrical translation from logic levels to differential signaling and back. You could use that chip (or any equivalent) directly with the UART pins on the Raspberry PI: those are not RS232 nor RS485, just bare asynchronous logic level UART pins. Your assertion that Raspberry PI “doesn’t support” RS485 is meaningless: it doesn’t support RS232 either, and it’s not supposed to. Those electrical standards require level translation/interface chips, and the “other side” is always the same: logic level asynchronous serial streams and control lines. The only “pitfall” is choosing the proper logic levels (3.3V be 5V - I don’t offhand remember what does RPI support).

STM32 I2C set SDA to low

Is there any way to set the SDA and SCL pin of the I2C1 connection of the STM32 to low or high signal?
I use a security chip and I have to send a wake condition, with the following condition:
if SDA is held low for a period of greater than 60us, the device will exit low power mode and
after a delay of 1500us, it will be ready to receive I2C commands.
I've already tried to toggle the actual pin with HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);, but this isn't working.
I've configured my project with STM32CubeMX.
Thanks for your help.
In I2C, the START condition requires a High to Low transition, if you then send a dummy address 0, a NACK will be generated (or rather the lack of any response will be interpreted as a NACK). In a normal transaction, the software would respond to the NACK by generating a repeated START or a STOP condition, however this must be done in software, so all you have to do is nothing for 1.5ms. Thereafter you can generate the START with the device's actual address, and if the device is running it will generate an ACK.
I am not familiar with the HAL library driver, and frankly the documentation is abysmal, but it is possible that it does not give you the necessary control, and you will have to access the I2C peripheral at the register level for at least this procedure. You might try a zero-length I2C_MasterRequestWrite() call to address zero followed by a delay. An oscilloscope would be useful here to ensure the expected signal timing is being generated.
When you initialize I2C, GPIO pins mode is set to ALTERNATE MODE,so writing HAL commands won't work on it.
Using normal HAL libraries won't help you in this. You have to configure I2C protocol on your own using stm32 registers.
I recommend that the ownaddress of the slave address using the device of the using I2C channel sets like the below code.
I2C_InitStructure.I2C_OwnAddress1 = 0x30; // the unique slave address of the deviecs
because the master could be send the broadcast operation not the unique operation.

Changing hardware flow control pins on STM32

I have been reading up on handshaking and hardware flow control for serial communication and I have a question that I can't seem to find an answer to.
If you set up hardware flow control for a serial port on cubeMX it will set the pins up that are required. I know you can use alternative pins as well and this can be done through cubeMX.
My question is, could you set up hardware flow control manually by using different pins or do you strictly have to use the implemented pins?
I am using a STM32F207ZETx and I am using USB as well as serial - however when using the USB peripheral it blocks the hardware flow control pins for USART1 which I need, and I need hardware flow control for my project! The alternate pins for hardware flow control are also already used so I'm in a bit of a pickle.
My question is, could you set up hardware flow control manually by using different pins or do you strictly have to use the implemented pins?
You can do hardware flow control yourself in software, and in fact it is quite simple to do.
The USART1_RTS is an output pin. It is set/high when the USART1 is ready to receive data. The USART1_CTS is an input pin. The other end sets it high when it is ready to receive data, and low when it is not.
Let's say that you send and receive one character at a time, and use two GPIO pins for USART1_RTS and USART1_CTS instead of the hardware support.
Normally, you keep USART1_RTS high. When receiving data, if you are running out of receive buffer, you set USART1_RTS low. When you make more room in the receive buffer, you set USART1_RTS high. (If you have a buffering scheme that cannot run out of receive buffer, you can tie the RTS line high.)
Before sending each character, you check if USART1_CTS is high. If it is low, you don't send the data, but wait for USART1_CTS to become high before you do.
That's it.

STM32F2x Is it possible to request multiple DMA streams with single request

I want to setup an application, where a single trigger-factor (compare-match of a timer) shall request mutliple DMA streams (I.e. set new timer-value and send data to SPI)
Is this possible with the STM32F2x µC or have you got an idea for a µC with the following properties:
compare-match free running uint16 timer
~8 DMA channels
SPI HW unit (best would be with 9 chipselects, but these could be simulated via further DMA channels.
clock-frequency >= 80MHz
<=64 pins (I want to set my own layout and >64 is expected to be to complicate
~128kB RAM
~256kB ROM
cheep (developer board ~20-100 EUR, "easy to use" toolchain, complete with JTAG or other programmer (best would be connection via USB)
I'm not sure if I understand what you're asking here, but a single timer channel can be used to trigger two different DMA streams. See Table 22 in Section 9.3.3 of the manual: for instance, TIM2_CH4 can be used to trigger both stream 6 and stream 7. Also, you can configure a timer to be a slave to a second timer, which I believe could be used to make them fire simultaneously, and then you could use the two different timers as a trigger to the DMA peripheral.
Sorry if I'm unable to elaborate further, as I'm more familiar with the STM32F1xx series which doesn't have the concept of streams, only channels.

RS232 Serial Pin Read in C in Linux

Ist there any possibility to read values from the pins of the COM Port? Any solution in C under Linux is appreciated!
Yes, see for instance this guide.
You use the ioctl() function, to read the various control pins. Data is, of course, best read through the normal read() handling, you don't want to be polling asynchronuous serial data.
I don't think your assumption (expressed in a comment) that the driver must check the pin-states to handle data is correct, normally a serial port is "backed" by an UART and that typically handles the RX/TX pins in hardware.
Am pretty sure , you can't read/write pins of UART.
Even at the hardware level , you have to read/write an entire byte.There is no bit access or read/write pin access.
The Byte is read/written in the Receive/Transmit UART buffer .
In either ways you can't just access the buffer directly , on your behalf the linux driver will do the job. You just have to make use of the driver in your application , to work with the UART , the linux driver for UART provides , standard API's like open(),read(),write(),ioctl() through which you interact the UART device.
If you want to work with drivers , and new to this field , the best place to start will be
this book.
The exact answer to this question depends on the precise hardware in question. I know of a piece of code where I worked, based on receiving the letter 'a' as the indication of bitrate, and it would poll the RX pin to detect the transitions between 0 and 1 to detect the "width" of the bits, and it would then calculate the correct clock-rate for the serial port and configure the serial port to match the bitrate of the other end.
A "PC" type hardware solution will not be able to read the RX/TX pins. In other hardware, it may be possible to do so. Many embedded systems allow various pins to be configured as inputs, outputs or "have a function" (in our case, RX, TX, CTS, RTS, etc) - so for example, you could configure the RX pin to be a input, and thus read the state of it. Of course, the normal serial port drivers will probably set these pins to "have a function" [or expect the boot code running before the kernel is started to have configure it this way]. So you would have to reconfigure the pins in some kernel code of your own, most likely. Beware that this may cause unexpected side-effects with the driver for the actual serial port - it may "get upset" when it tries to do things to the serial port and it's "not working as expected" because it's been "misconfigured".
You can almost certainly read (and/or write) the state of the control pins, such as CTS, RTS via IOCTL calls.

Resources