RS232 Communication - Can I use it to create a steady state signal? - c

In all honesty, I think the answer is "no;" however, I want to get a second opinion. Basically, I need one micro-controller device to send a steady signal to another one, but the communicate between them is using RS232. So I think that I have to create/update the communication messages to get it to do what I want.
What do you think?

You should be able to set something like DTR (Data Terminal Ready), pin 20, or DSR (Data Set Ready), pin 6, high and keep it there as your steady-state signal. This is how modems/terminals detect that there is a device on the other end that is ready to communicate. It all depends on what level of access you have to the hardware through your driver.
[EDIT] This doesn't involve sending data, although you could still do that using TX/RX, pins 2 & 3.
RS-232 Reference on wikipedia

You mean a fixed voltage? Not a square wave? (the letter U) What about a break command (if you want to call it a command)?
Certainly you can use one of the control lines if that helps...Or are you specifically looking for something out of the TX?

If the question is "can I alter the DC state of the Tx line", then the answer is that many uarts (including the ones in PCs) can be asked to create a 'break' condition, which is the opposite to the normal idle condition of the line.
So you can turn 'break' on and off and toggle the line like that.

It might be possible to do something like that, provided you don't mind a burst-like interface. One micro could transmit a byte and the other could do something to that byte and send it back as a response.

If you can control both ends of the line, you may be able to turn the rs-232 tx and rx lines into regular logic lines to give that information.
In most situations, however, each end periodically sends a byte of status information that contains 8 possible digital values - gives much more status information.
A timer on the receiving end is reset everytime a message is received, and if the timer times out then the message has taken too long and yo can act on missing status message.
As others have pointed out, if you're using hardware flow control you have some status lines available as well, though in many cases those lines aren't implemented so that may not be an option.
-Adam

Steady signal could mean:
steady burst of charaters: keep the send buffer full
line held high or low : send nothing or send continual breaks

I think it depends to a large extent on the UART that you are using, e.g. link text, and the level of access you have to it under software. If you check the data sheet there are often ways of controlling most of the pins directly for testing purposes, but you will need to go at it from a pretty low level.
At a higher level, tvanfosson's answer is pretty much the way i'd do it.

While the first answer is correct it may not be possible to use this technique (using DTR or DSR) on many micro controllers as they may not have those signals (many micro controllers may just have the basic RX/TX lines and you would often have to use other i/o ports if you wanted extra control/status lines. However, all is not lost, many RS232 controllers allow you to set the TX line to 'mark' or 'space' (i.e set the TX line to logic high or low). This would allow you to get your steady state signal. The RX line on the receiver can be checked to see if its at mark or space level.

Related

Linux UART imx8 how to quickly detect frame end?

I have an imx8 module running Linux on my PCB and i would like some tips or pointers on how to modify the UART driver to allow me to be able to detect the end of frame very quickly (less than 2ms) from my user space C application. The UART frame does not have any specific ending character or frame length. The standard VTIME of 100ms is much too long
I am reading from a Sim card, i have no control over the data, no control over the size or content of the data. I just need to detect the end of frame very quickly. The frame could be 3 bytes or 500. The SIM card reacts to data that it receives, typically I send it a couple of bytes and then it will respond a couple of ms later with an uninterrupted string of bytes of unknown length. I am using an iMX8MP
I thought about using the IDLE interrupt to detect the frame end. Turn it on when any byte is received and off once the idle interrupt fires. How can I propagate this signal back to user space? Or is there an existing method to do this?
Waiting for an "idle" is a poor way to do this.
Use termios to set raw mode with VTIME of 0 and VMIN of 1. This will allow the userspace app to get control as soon as a single byte arrives. See:
How to read serial with interrupt serial?
How do I use termios.h to configure a serial port to pass raw bytes?
How to open a tty device in noncanonical mode on Linux using .NET Core
But, you need a "protocol" of sorts, so you can know how much to read to get a complete packet. You prefix all data with a struct that has (e.g.) A type and a payload length. Then, you send "payload length" bytes. The receiver gets/reads that fixed length struct and then reads the payload which is "payload length" bytes long. This struct is always sent (in both directions).
See my answer: thread function doesn't terminate until Enter is pressed for a working example.
What you have/need is similar to doing socket programming using a stream socket except that the lower level is the UART rather than an actual socket.
My example code uses sockets, but if you change the low level to open your uart in raw mode (as above), it will be very similar.
UPDATE:
How quickly after the frame finished would i have the data at the application level? When I try to read my random length frames currently reading in 512 byte chunks, it will sometimes read all the frame in one go, other times it reads the frame broken up into chunks. –
Engo
In my link, in the last code block, there is an xrecv function. It shows how to read partial data that comes in chunks.
That is what you'll need to do.
Things missing from your post:
You didn't post which imx8 board/configuration you have. And, which SIM card you have (the protocols are card specific).
And, you didn't post your other code [or any code] that drives the device and illustrates the problem.
How much time must pass without receiving a byte before the [uart] device is "idle"? That is, (e.g.) the device sends 100 bytes and is then finished. How many byte times does one wait before considering the device to be "idle"?
What speed is the UART running at?
A thorough description of the device, its capabilities, and how you intend to use it.
A uart device doesn't have an "idle" interrupt. From some imx8 docs, the DMA device may have an "idle" interrupt and the uart can be driven by the DMA controller.
But, I looked at some of the linux kernel imx8 device drivers, and, AFAICT, the idle interrupt isn't supported.
I need to read everything in one go and get this data within a few hundred microseconds.
Based on the scheduling granularity, it may not be possible to guarantee that a process runs in a given amount of time.
It is possible to help this a bit. You can change the process to use the R/T scheduler (e.g. SCHED_FIFO). Also, you can use sched_setaffinity to lock the process to a given CPU core. There is a corresponding call to lock IRQ interrupts to a given CPU core.
I assume that the SIM card acts like a [passive] device (like a disk). That is, you send it a command, and it sends back a response or does a transfer.
Based on what command you give it, you should know how many bytes it will send back. Or, it should tell you how many optional bytes it will send (similar to the struct in my link).
The method you've described (e.g.) wait for idle, then "race" to get/process the data [for which you don't know the length] is fraught with problems.
Even if you could get it to work, it will be unreliable. At some point, system activity will be just high enough to delay wakeup of your process and you'll miss the window.
If you're reading data, why must you process the data within a fixed period of time (e.g. 100 us)? What happens if you don't? Does the device catch fire?
Without more specific information, there are probably other ways to do this.
I've programmed such systems before that relied on data races. They were unreliable. Either missing data. Or, for some motor control applications, device lockup. The remedy was to redesign things so that there was some positive/definitive way to communicate that was tolerant of delays.
Otherwise, I think you've "fallen in love" with "idle interrupt" idea, making this an XY problem: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem

Send data from a microcontroller to another

I'm making a project that require send data from one microcontroller to another via wireless (I'm going to use 433Mhz RF modules or 2.4Ghz, didn't decide it yet). Specifically, I'm making a joystick which control 4 dc motors. So my question is: When I write the code, should I put the command to accelerate 'x' motor into the receiver's microcontroller (the board that control the motors) or into the transmitter's microcontroller (the joystick's board)? For example, if I put the joystick to the left to accelerate motor 3 and 4, where would I wrote this code?
I'm doing this project in arduino (ATmega328 with arduino bootloader).
Well this is most definitely a "primarily opinion based" question and may very well get closed...but...
This is your design, you need to design it. There isnt a wrong answer in this case, you can have the joystick board simply pass the joystick switch state or analog state depending on what kind they are...OR...you can have the joystick board using timing and how long the joystick is held in a position and perhaps compute what you think the devices position should be and just pass that (you need to rotate m steps this way and n steps that way). Or depending on your overall system design could come up with other solutions to balance the load between the microcontrollers. I assume what you are really wanting to do here is "simply" use the wireless and the extra mcu as a way to have the joystick not wired. If the joystick were wired and you did it with one mcu and these are switch based (not analog resistance) joysticks then that one mcu would simply be reading the switch state at some interval, perhaps debouncing. So then when you add wireless to it you would want the wireless solution to simply pass the same switch state, not in the same register space and not necessarily the same bit positions in whatever data, but just the switch state. As needed you have the added benefit of the joystick mcu can debounce. Also perhaps only send state changes and not have to bother the motor mcu every N units of time.
I tried modules like these recently and was very disappointed, but am considering trying them again or a different vendor/build of them. They should "feel" like a wire for say serial data at some slow rate 4800 baud, 2400 baud, etc. First try I had to do things like constantly send a pattern say the same byte 0xAA, then every so often have a small payload show up in there so search for 0xAA then when you see something else count out so many bytes that is the payload. It went downhill from there when I used separate computers/supplies to send the data as if most of my success although marginal was perhaps through ground noise not actually wireless. They sell tons of these and folks use them so no doubt it was something I did or bought garbage modules, or maybe I shouldnt have bought the ones with antennas, and soldered those on, etc.
I would recommend two things. First get both mcus up and running the application using a wired connection, just some jumper wires. You might have to come back to this as you perhaps change your protocol or baud rate, etc if needed. Perhaps (most likely) you want to send the payload out often even if the data has not changed if the wireless connection is not perfectly reliable, allowing the occasional lost data packet to be handled on the next one. Second learning to use the wireless connection is a separate experiment, the code on both sides should just be working that one problem how to I talk over this interface, no motor drivers no joysticks, just code to talk from one to the other.
Likely a good idea, esp if you dont need to be constantly transmitting, is to design your own packet. Ideally one or more features, a sync pattern and length or a sync pattern and checksum or sync pattern, length and checksum (as well as a payload). So maybe a 0x7E byte as a sync pattern, perhaps you are always going to send 32 bits or 4 bytes of payload so dont need a length and then maybe a checksum of the payload or checksum of the whole thing sync pattern and payload. your reciever then takes in bytes from the uart into a circular buffer basically or not even that just use a very simple state machine, if searching for sync and byte is not 0x7E then discard, if 0x7e then go to payload state with a count of zero, receive the next four bytes (payload) summing them into a checksum as each arrives. after payload the next byte is checksum, if it matches the the whole thing is good pass the payload to the control system to update the switch state and/or just shove it into the global variable that the control system is watching as if it were a direct connection to the joystick switch state.
You can get as complicated or not as you want, but I would never in this kind of a design assume that both sides are always in sync and every N bytes is the N bytes sent in the right position, even if you never drop a byte, this is a one direction communication path so if the receiver comes up while the transmitter is mid payload the receiver comes up in the middle of the payload/packet and is always off in its interpretation of the data. You can do a slip/ppp thing whichever it is and insure the sync pattern is never in the data by adding more work. Or not, I doubt you need to be that complicated as I assume you are likely only sending one or a few bytes of actual data per update.
why I tried the continuous stream as way back the first time i tried products like these, long before they were a buck or so from china on ebay, we had to insure "transition density" you could not string more than a couple bit cells of either state in a row, couldnt have more than say two zeros in a row or two ones in a row basically had to do a biphase-l (manchester II) in software before shoving the bytes into the uart, then undoing it on the other side. Hopefully the hardware does that for you and you dont have to, but push comes to shove you might have to take every byte and only every other bit in the byte is payload the other bit next to it is the inverse might have to send the byte 0x01 (00000001) as (0101010101010110) 0x55 0x56. Hopefully you dont have to do that, it is not much fun.
Your microcontroller development toolbox should include some usb to serial solutions, can get them for a buck or two on ebay from china or from adafruit or sparkfun for 10-15 bucks. The china ones sometimes have a 5v or 3.3v jumper or switch. One way to start with these modules is to hook one to one of these usb to serial breakouts 5V or 3.3 as needed for that rx or tx module. For tx put the uart out (tx) on the data pin, for rx the rx in on the data pin. And then fire up two copies of minicom or whatever dumb terminal program you use, set both to some slow speed like 1200baud, and type in one and see if what you type comes out the other. Hold down a character, U is a good one as with 8n1 it produces a square wave. does that come through clean? what if you slow down both sides? what if you speed up. From simple experiments like that you can start to develop your protocol. If you have a scope (having one is easier these days but can still be pricy, a few hundred bucks, but access to one is pretty important) you can do this even easier, generate the signal either with microcontroller or usb to serial or whatever then look at what shows up on the other side with the scope, how ugly/clean is it? Can you make it better looking by changing the data or by pounding the interface with continuous data.

Relaying UART1 with UART2 within an ISR() (PIC24H)

I am programming a microcontroller of the PIC24H family and using xc16 compiler.
I am relaying U1RX-data to U2TX within main(), but when I try that in an ISR it does not work.
I am sending commands to the U1RX and the ISR() is down below. At U2RX, there are databytes coming in constantly and I want to relay 500 of them with the U1TX. The results of this is that U1TX is relaying the first 4 databytes from U2RX but then re-sending the 4th byte over and over again.
When I copy the for loop below into my main() it all works properly. In the ISR(), its like that U2RX's corresponding FIFObuffer is not clearing when read so the buffer overflows and stops reading further incoming data to U2RX. I would really appreciate if someone could show me how to approach the problem here. The variables tmp and command are globally declared.
void __attribute__((__interrupt__, auto_psv, shadow)) _U1RXInterrupt(void)
{
command = U1RXREG;
if(command=='d'){
for(i=0;i<500;i++){
while(U2STAbits.URXDA==0);
tmp=U2RXREG;
while(U1STAbits.UTXBF==1); //
U1TXREG=tmp;
}
}
}
Edit: I added the first line in the ISR().
Trying to draw an answer from the various comments.
If the main() has nothing else to do, and there are no other interrupts, you might be able to "get away with" patching all 500 chars from one UART to another under interrupt, once the first interrupt has ocurred, and perhaps it would be a useful exercise to get that working.
But that's not how you should use an interrupt. If you have other tasks in main(), and equal or lower priority interrupts, the relatively huge time that this interrupt will take (500 chars at 9600 baud = half a second) will make the processor what is known as "interrupt-bound", that is, the other processes are frozen out.
As your project gains complexity, you won't want to restrict main() to this task, and there is no need to for it be involved at all, after setting up the UARTs and IRQs. After that it can calculate π ad infinitum if you want.
I am a bit perplexed as to your sequence of operations. A command 'd' is received from U1 which tells you to patch 500 chars from U2 to U1.
I suggest one way to tackle this (and there are many) seeing as you really want to use interrupts, is to wait until the command is received from U1 - in main(). You then configure, and enable, interrupts for RXD on U2.
Then the job of the ISR will be to receive data from U2 and transmit it thru U1. If both UARTS have the same clock and the same baud rate, there should not be a synchronisation problem, since a UART is typically buffered internally: once it begins to transmit, the TXD register is available to hold another character, so any stagnation in the ISR should be minimal.
I can't write the actual code for you, since it would be supposed to work, but here is some very pseudo code, and I don't have a PIC handy (or wish to research its operational details).
ISR
has been invoked because U2 has a char RXD
you *might* need to check RXD status as a required sequence to clear the interrupt
read the RXD register, which also might clear the interrupt status
if not, specifically clear the interrupt status
while (U1 TXD busy);
write char to U1
if (chars received == 500)
disable U2 RXD interrupt
return from interrupt
ISR's must be kept lean and mean and the code made hyper-efficient if there is any hope of keeping up with the buffer on a UART. Experiment with the BAUD rate just to find the point at which your code can keep up, to help discover the right heuristic and see how far away you are from achieving your goal.
Success could depend on how fast your micro controller is, as well, and how many tasks it is running. If the microcontroller has a built in UART theoretically you should be able to manage keeping the FIFO from overflowing. On the other hand, if you paired up a UART with an insufficiently-powered micro controller, you might not be able to optimize your way out of the problem.
Besides the suggestion to offload the lower-priority work to the main thread and keep the ISR fast (that someone made in the comments), you will want to carefully look at the timing of all of the lines of code and try every trick in the book to get them to run faster. One expensive instruction can ruin your whole day, so get real creative in finding ways to save time.
EDIT: Another thing to consider - look at the assembly language your C compiler creates. A good compiler should let you inline assembly language instructions to allow you to hyper-optimize for your particular case. Generally in an ISR it would just be a small number of instructions that you have to find and implement.
EDIT 2: A PIC 24 series should be fast enough if you code it right and select a fast oscillator or crystal and run the chip at a good clock rate. Also consider the divisor the UART might be using to achieve its rate vs. the PIC clock rate. It is conceivable (to me) that an even division that could be accomplished internally via shifting would be better than one where math was required.

Best practice to detect two simultaneous signals on two input pins

I need to do the following: I have 2 input pins on a microcontroller, and it is possible, that a signal is received on one or the other, but it is also possible that the two will be physically connected on the outside, and the signal arrives on both at the same time.
The problem: if I use something like
if (PINB.1 && PINB.2)
{
// ...
}
there is the one in a million chance, that the signal arrives between when the two values are loaded into the registers for the logical AND operation to be performed. When I leave the if, both the pins are high, but I still detected that only the second one was high.
I tried out different solutions, and the best so far seems to be to start a very short countdown when either of the inputs is high, and when the timer (a few milliseconds at most) runs down, I check again.
Does anyone know a simpler or better solution? I thought this problem was very common, but I could not find any "tried and true" methods so far.
Edit: I know from the hardware, that after an edge the pin will hold its value for at least a few dozen milliseconds. Noise is already been taken care of.
PINB.1 and PINB.2 were just examples. They might possibly be on different ports, so bitmasking the whole port might have the risk of not being flexible enough.
You have answered your own question: simply use a timer and check the pins again, it is the simplest form of a digital filter you can use. But you must start the timer when you detect a pin level change. If you have a very steep raising edge, ie the pin is connected to some digital IC, then it might even be sufficient to simply read the pins twice, depending on how fast your CPU clock is in comparison to the raising edge.
Another solution is to use an edge-sensitive interrupt, if the MCU has this feature. Then you are guaranteed to read the pin just after the change. With one interrupt for each pin, your program can store the most recent values of the pins for the == comparison. You'll have to ensure that the values are guarded with semaphores between the interrupts and "main", or you are back where you started.
Are you wanting to look for the condition when they are both asserted? If so just sample them if not both asserted then dont bother. if this is an interrupt thing and you are probably using C code? Even if assembler just sample two or three times if after interrupt both are not asserted then it was a false deal and ignore it.
If you are looking at these as two separate events and concerned about the few times you read the port and they are both asserted. You should probably already separate the reading of a port and the handling of what you found. Read the port if bit 0 then do stuff if bit 1 (from the stored value not a re-read of the port) then do bit 1 stuff.
There is no such thing as best practices other than "do your system engineering" (because design goals are different across the different industries that use similar hardware). All of these issues and resolutions are covered by the system engineering. Your system engineering will tell you exactly what the margin is on the event you are concerned about and knowing the properties of the controller/processor you know how the interrupt system responds if used or what your execution and sampling rate is to know how the microcontrollers properties relate to the event in question. I am willing to bet that performing and saving two reads quickly then saying if either one of these reads has both bits asserted then declare the event had happened. You should already be oversampling the input based on the expected/designed signal, and as a result you can probably discard the samples that are on the edge of the state change of the inputs.
I think you're chasing a ghost, or you don't have your problem well specified.
For example, say you put a 1 ms timer between the bit tests - all you've done is 'move the bar' for the race. Is it OK to have the code act as if only one bit is set if the second bit goes high at 1 picosecond after the 1 ms timer expires? If so, why would you want that behavior to be different from what's happening with your current code.
That's not to say it wouldn't be correct, just that you should understand why it is if that's your assertion. And that depends exactly what the problem is.
In order to avoid hard-to-repeat bugs, embedded firmware should adhere to the following schema:
input reading and buffering
computation of buffered outputs from buffered inputs
buffered output writing
In other words, you're moving from a continuous time domain to a discrete one. It's like elaborating snapshots taken of the real continuous world. Fail to do that and you'll end up with input signals which change in the middle of the computation with unpredictable and unrepeatable results.
That being said, if you read [0 1] or [1 0], that is the input for the subsequent computation. You'll read a [1 1] at next run.
You could not be sure to sample a [1 1] even if you connect the same signal to two pins of the same port: there are hardware tolerances which makes it impossible.
In the real world, there's seldom such a thing as two inputs which change "simultaneously". If you know that two inputs will either become active within a few instruction times of each other, or else not become active anywhere near each other, you could do something like:
if (INPUT1)
{
if (INPUT2 || INPUT2 || INPUT2 || INPUT2)
handle_double_input();
else
handle_input_1_only();
}
else if (INPUT2)
{
if (INPUT1 || INPUT1 || INPUT1 || INPUT1)
handle_double_input();
else
handle_input_2_only();
}
INPUT1 and INPUT2 should both be macros defined which use volatile qualifiers to ensure that the inputs are actually polled rather than cached. The repeated terms in the "if" test when one input is detected should allow time for the other input to switch as well. The number of repetitions required may vary with the maximum input skew and the execution speed of the controller.

Interfacing a slow device to a MCF5270 Microcontroller

I'm looking for ways to interface a slow device (an ADC - ~1.2MHz) to my mcf5270 microcontroller, which is a rather fast device (~150MHz). I am using ADC0817, and have tried the following: GPIO read off the data lines, memory mapped access (since the adc is uP compatible).
When mapped as a location in memory, I am using the maximum wait states (15ws, which is about 107ns). The mcf5270 does not support any further waiting without using their bus model (which the ADCs do not support).
Using GPIO, only junk values are read.
Note: The ADC is actually working, and other than reading data the interface to it is functional. I am using C/C++ and assembly.
In short, I am looking for suggestions for ways in which to try to read the data off the ADC0817.
Comments and responses are greatly appreciated.
You could trigger the ADC through some GPIO, do an appropriate number of NOPs and then read the value. Also, you'd need to disable interrupts while doing this.
I think memory mapped should work - normally I would wait for the interrupt from the ADC, then read the byte at the specified address. Since you get an interrupt, there is no wait state needed. Am I missing something? GPIO should also work. How do you know the ADC is working? Can you put a logic analyzer on the data & interrupt to prove the ADC is producing the correct output?
I think from what he's saying MMIO wont' work because he would need more than the maximum number of wait states on the bus to get the glue logic to respond - ie, the A/D won't set its bus pins soon enough for the uC to be happy. That's a problem sometimes.
But the GPIO approach should work. If junk values are being read I assume that you aren't following the timing diagram provided. You'll have to be able to wait certain amounts of time after you signal a read before the data is valid. Check out the datasheet for specifics.

Resources