UART asynchronous communication 115200 spacing 121us between bytes 8N1 - Page 1
Forum section: electronics / projects

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 09:09:58 am
content: Hello,I've in AVR UART asynchronous communication at baud rate 115200 (114.3kHz) high level separators 121us wide between bytes (8N1) as shown in attached screenshotAre there any requirements in UART asynchronous communication how wide such spacing is allowed at given baud rate ?I'd like to send data bytes to HC05 BT module/PC Linux UART from AVR MPU with external quartz 16MHz/8MHz using software serial UART at baud rate 115200 ~114.3kHz and such ~121us separators between bytes gives MPU more time to do other tasks and prepare new data bytes to be transmitted.

author: moffy
author_rank: Super Contributor
timestamp: August 26, 2023, 09:41:56 am
content: There should be no problem with that as long as the bit timing and format are correct, the gap is flexible.

author: I wanted a rude username
author_rank: Frequent Contributor
timestamp: August 26, 2023, 10:06:53 am
content: As moffy says, technically it's fine.There is one subtlety you might want to keep in mind though.Depending on your UART adaptor, this could create a lot of interrupts (and consequently context switches). That's because the UART adaptor might decide that the break in transmission means it should alert the CPU that it has data, even if its buffer isn't at the high water mark. I saw this on a project, where an FTDI USB UART adaptor receiving data in small packets generated an acceptable number of interrupts (about 1,000/second) but a Silicon Labs equivalent generated over 6,500/second. It's a good idea to check with vmstat or similar to see how many interrupts the CPU has to deal with when data are being streamed like this.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: August 26, 2023, 10:45:11 am
content: As has been written already, there is no inherent requirement for this for uart communication. The startbit is the signal that a byte is going to be sent, and each byte has it's own startbit. The stop bit (wich is the same as the idle level) ensures a minimum delay before the the next startbit. but there is no maximum delay.About the baudrate 115200/114300 = 1.00787 an that is just fine. The theoretical limit is half a bit difference over a byte (Inclusive start /stop bit) so 5%. Some microcontrollers (for example the ubiquitous arduino's running at 16MHz) can eat up a significant part of that tolerance, and this can cause problems if the clocking on the other side of the wire also has a deviation, but in the opposite direction.-------------But there are other considerations too. Higher level protocols stacked on top of of the uart may have additional requirements. For modbus for example the delay between bytes is interpreted as an "end of packet" and can be used to re synchronize if for example a half or damaged packet has been sent. (From memory, I think the maximum allowed delay for modbus is 2 byte times before it times out).

author: Peabody
author_rank: Super Contributor
timestamp: August 26, 2023, 02:37:45 pm
content: At the UART level the delay doesn't matter. UART is "asynchronous" after all. But are you unable to use the AVR's hardware UART peripheral?

author: DavidAlfa
author_rank: Super Contributor
timestamp: August 26, 2023, 03:11:15 pm
content: It's actually beneficial! You can send a byte every 3 months if you wish, there no timeout unless made in the software protocol.At hardware level, only when a transfer started, it must keep going until the entire byte is sent.Usually the baudrate frequency has some error, specially with 115200, it's weird frequency so you rarely get it perfect with 8-16MHz reference clock.For small transfers there's no problem up to 3% error or so, as the receiver has time to resync between transfers, or if the sender is slighly slower than the receiver.But if you pack the transfers without any gap between them and sender is a bit faster, let's say 115800 instead 115200, the start bit happens sooner every time, until it'll eventually drifts too much for the receiver and causes a transfer error.For example, I recently did this sending non-stop data using DMA, there was a baudrate error of 1-2% or so.The first 40 chars or so (I can't tell right now, just an example) went perfect, then got garbage.Either adding a small software delay of 1-2 bits after few transfers, setting the sender baudrate error to be slower, or perfectly matching the receptor and sender (For example, both @ 1Mbit) worked properly.The attached picture shows a very exaggerated example, but this can actually happen.The first two bytes are correctly received but then havoc starts. So sometimes it's important to allow some time between stop and start bits.

author: Peabody
author_rank: Super Contributor
timestamp: August 26, 2023, 03:30:31 pm
content: What would happen if you set it to 8N2? Does the receiver test for the second stop bit, or does it go back into waiting for a start bit after receiving one stop bit? If the latter, 8N2 should take care of any reasonably fast transmission rate.

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 04:54:25 pm
content: Quote from: I wanted a rude username on August 26, 2023, 10:06:53 amI've Silicon Labs CP2102 on PC Linux, while developing custom app and its Android version will communicate via mentioned HC05 BT module with custom electronics AVR MPUs, so PC Linux is rather development environment, however it would be nice to have Linux version of app - I do not use Window$ at all.AVR timer is configured for 10kHz, so I should be able send from AVR MPU 5kB of data at baud rate ~114300 since some I'd like to skip every second byte or more if needed.I've external 16MHz quartz, but for the moment run it as F_CPU 8MHz system clock, so it is decent quality timing in this software UART, but of course I can't fit perfectly into UART baud rate 115200, but it is very close, while I've only around 1% frequency error since we have ~8.750us baud rate period ~114.286kHz, while given baud rate period is:1/115200 ~8.681us, so difference is: +0.795% ~1%

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 05:01:37 pm
content: Quote from: Peabody on August 26, 2023, 02:37:45 pmYep, maybe, but sometimes for debug and testing purposes such custom AVR UART software library might better fit your needs when you know exactly how it works and when you have logic analyzer

author: Peabody
author_rank: Super Contributor
timestamp: August 26, 2023, 05:13:13 pm
content: Well, there may be a good reason to use software serial, but the built-in hardware serial does all the bit handling for you, so you ony have to send or receive one byte at a time. It's literally one-tenth of the processing load of software serial.

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 05:16:26 pm
content: Quote from: DavidAlfa on August 26, 2023, 03:11:15 pmI think that by adding additional spacing between send bytes it should be easier receive such data bytes since we have more time to prepare while next byte will be send ~100us laterReceiving many bytes with only START spacing is much more difficult since we need very good timing, but... electromagnetic waves at speed of light travel in space less than... only 300 meters within 1us299792458 m/s * 0.000001 ~299.792m < 300m

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 05:46:24 pm
content: Quote from: Peabody on August 26, 2023, 05:13:13 pmSometimes it might be a problem that in hardware AVR USI UART there is no extra sampling, while hardware have to be configured to probe data byte bits by using reference to the middle of the start bit, while in software UART implementation we can make extra oversampling and for example decide to skip receiving other byte bits at the at the beginning of the transmission when we notice noisy bits signal around the middle of the received data bits

author: eneuro
author_rank: Super Contributor
timestamp: August 26, 2023, 07:43:48 pm
content: Quote from: DavidAlfa on August 26, 2023, 03:11:15 pmHow do you know in the middle of transmission without extra IDLE time spacing between STOP START that you have high IDLE -> low START instead of next byte high STOP -> low STARTI found something like this and what can I say... it is so sickCode:Because UART is asynchronous, the transmitter needs to signal that data bits are coming. This is accomplished by using the start bit. The start bit is a transition from the idle high state to a low state, and immediately followed by user data bits.

author: DavidAlfa
author_rank: Super Contributor
timestamp: August 26, 2023, 07:57:19 pm
content: UART is rarely used with parity bit.If everything goes right, you know its a start because you counted the previous start+8 data bits+stop.If you miss any of these events, then yeah everything goes nuts, any data bit will be treated as start.Just don't worry about it, it won't fail using that scheme you're using, the receiver has a lot of time to settle down.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: August 26, 2023, 07:59:21 pm
content: I have also been bitten by what DavidAlfa described.When you send a lot of bytes without pause, then slight deviations in the clock frequency can add up and can be a cause for trouble.Quote from: DavidAlfa on August 26, 2023, 03:11:15 pmQuote from: DavidAlfa on August 26, 2023, 03:11:15 pmIf the sender is slightly faster then the receiver, then this can happen, but I think most microcontrollers can tolerate this by compensating in the length of the stop bit. I guess that most uC's can tolerate it if the stop bit is only 1/2 to 3/4 of a bit length, but it is hardware dependent. And of course, it is also valid to send with 8n2 and receive with 8n1. It's probably extremely rare to actually check whether that second stop bit is actually present. Note that a stop bit and an idle line are both the same logic level. They look the same on an oscilloscope.For me, the problem was the other way around. The sender was slower then the receiver, and the receiver had to do some special things and then re-transmit over another uart.I used a few ISR's to handle uart data. First received about 5 bytes in a circular buffer before I started re-sending them again. It turned out that the original sender was so slow that after 50 or so bytes the circular buffer ran empty before a transmission of a complete packet (which had a variable length) was complete. And instead of just releasing the RS485 transceiver after the circular buffer was empty, I had to actually decode the length of the packet and count all the bytes.Quote from: DavidAlfa on August 26, 2023, 03:11:15 pmThe arduino's with 16MHz clock are especially atrocious. In the old days it was very common to use a crystal that was a multiple of the "traditional" baudrates. Crystals of 1.8432MHz or 11.0592MHz are examples for this. These can generate perfect (well within the generic 200ppm frequency deviation of cheap Crystals.) baudrates. A problem with the "simple" microcontrollers is that they divide the main clock frequency by 16 to generate a clock for the "internal" uart timing. (such as sampling the signal on the 8th of those 16 clocks to sample in the center of a bit). Uarts that do not do this have a thing called a "fractional baudrate generator". All (I guess) STM32 uC's have this, and recently I looked at a datasheet of a new ATtiny and it also has a fractional baudrate generator. With a fractional baudrate generator, there is some jitter in the bit timing, but it's all within normal tolerances, and as a result you can program any baudrate, regardless of the crystal frequency for the uC. (Some run out of bits for the baudrate divider when they have to generate 150baud from a 20MHz crystal, so there are other limits too).

author: Doctorandus_P
author_rank: Super Contributor
timestamp: August 26, 2023, 08:05:58 pm
content: Quote from: DavidAlfa on August 26, 2023, 07:57:19 pmNo, not really. For simple stuff, often you just throw out some bytes and the receiver will receive them.If you need more reliable communications then you normally add a higher level protocol. That higher level protocol usually adds a header, which may have a sync byte, the total number of bytes in the packet and adding a CRC to each packet is also common.And when you already have a CRC, which is much more reliable then parity is not much more then a waste of 10% of bandwidth.Another annoying thing about parity is that there are so many variants of them (Odd, Even, Mark, Space) and if you set this wrong, then you will get parity errors or even framing errors on the receiving end.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: August 26, 2023, 08:16:40 pm
content: Quote from: eneuro on August 26, 2023, 07:43:48 pmWhen a stream of data is sent in 8n1 format, then each byte is being sent as 10 bits over the wire. (Each byte has an extra start and stop bit).As a result, in a continuous data stream, every ten bits there is a high to low transition (from stop bit to the start bit of the next byte). This flank, can (and is) often used to correct for small timing deviations, but as described earlier, errors may accumulate and timing may be off too much. When this happens, the receiver looses synchronization and it generates a framing error.After a framing error, you can attempt to resynchronize on a continuing data stream (Every time there is no negative going flank after 10 bits you know you guessed wrong and must make another guess). There is no guarantee that this sort of resynchronization will ever work, but you can get lucky.However, when there is some idle time on the data stream, the receiver will just receive zero's until it assumes a byte is received, and will then start waiting for the start of the next start bit. So a bit of idle time (longer then 10 bits) is guaranteed to resynchronize on the next byte sent.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 26, 2023, 09:05:40 pm
content: Quote from: eneuro on August 26, 2023, 09:09:58 amIf your host is an AVR, you can set any microsecond delay you like. Don't expect any USB-UART PC to generate this tho, it should receive it ok.However, your capture is a bit strange, and your SW UART may need fixing.The start bit looks too wide and you talk about byte separation but your capture shows 16? bits per character ?

author: eneuro
author_rank: Super Contributor
timestamp: August 27, 2023, 05:55:19 am
content: Quote from: Doctorandus_P on August 26, 2023, 07:59:21 pmYep, I've also implemented something like UART reference clock in software where byte 0x55 can be send to another one AVR MPU pin and slave AVR MPU without quartz crystal clock can connect to master to obtain UART frame bits reference timing and simply connect this UART clock source to its own pin change interrupts and synchronize from time to time its internal oscilatorI've successfully decoded bytes send from AVR Attiny85 UART custom software in logic analyzer and I was also able to export this data to text file with timestamp and decoded data bytes

author: Kleinstein
author_rank: Super Contributor
timestamp: August 27, 2023, 10:54:34 am
content: Quote from: Peabody on August 26, 2023, 03:30:31 pmUsing 2 stop bits extends the idel phase a little. This can help to better handle the case when the receiver clock is slightly faster. So it sometimes helps and the speed penelty is not yet large.The extra stop bit is just a longer idle phase between the bytes. So the intended protocol is something like 10 stop bits, which is fine, but usually not directly supported by the hardware. This is the sending side - the receiver side usually does not case about the stop bits.

author: eneuro
author_rank: Super Contributor
timestamp: August 27, 2023, 09:13:00 pm
content: Quote from: PCB.Wiz on August 26, 2023, 09:05:40 pmNOPE, you need to insert nanoseconds delays into your C code on AVR to be as close as possible at given F_CPU eg. 8MHz to given UART baud rateIn practice it means that when you make changes to your C code what you are looking for is assembler listing and you need to adjust sometimes delays but forget about _delay_us when you want be vely close to given baud rate 115200 on 8MHz AVR mpu - you have to use scope or logic analyzer to see UART TX and calculate how many AVR mpu system clocks you misswhen you want to fit into ~1% baud rate frequency errors on 8MHz AVR mpu

author: BrianHG
author_rank: Super Contributor
timestamp: August 27, 2023, 09:33:56 pm
content: As I have developed my own UART in verilog, when it comes to PC, yes if you are the only one transmitting, gaps are permitted.However, if the PC is sending you characters and you want to send your own return characters at the same time back to the PC, you need to sync up your character transmission timing and baud with the characters you are receiving from the PC. (Called a synchronous UART) If you do not, the PC will miss some or all of the characters you send. If your PC's RS232 port and your terminal software supports reporting the problem, you might get a 'Framing Error'. For example, FTDI's USB-RS232 converters do not report the error, they just drop the characters you are sending to the PC.My Sync UART here had an illustration of what I had to do to guarantee 0 missed characters when operating at high speed full duplex simultaneous bidirectional coms:https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/(See the first attached picture which illustrates my full duplex character timing correction required for clean lossless operation)

author: BrianHG
author_rank: Super Contributor
timestamp: August 27, 2023, 09:41:44 pm
content: If you are using an FTDI USB-RS232 converter and you want the PC to respond instantly to every single or few characters being received, you can do this using my guide here:https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg2801424/#msg2801424Basically you can modify FTDI's latency interrupt timer from the time data is received until the time your software will eventually be interrupted with new characters in the RX buffer.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 27, 2023, 09:53:23 pm
content: Quote from: eneuro on August 27, 2023, 09:13:00 pmI was talking about the delaysbetweencharacters, not the bit timing.The OP already has the SW-baud matching sorted.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 27, 2023, 10:01:55 pm
content: Quote from: BrianHG on August 27, 2023, 09:41:44 pmFor some values of 'instant'Yes, you can improve a terrible 16ms to a somewhat less worse 1ms.The FTDI parts are some of the worst I tested, with their SW driver imposed floor of 1ms, which even applies to their FT232H / FT2232H parts.You also need care that some USB ports may be on motherboard HUB stubs, with worse performance than others.

author: eneuro
author_rank: Super Contributor
timestamp: August 27, 2023, 10:09:10 pm
content: Quote from: BrianHG on August 27, 2023, 09:41:44 pmNOPE, I'm using Silicon Labs CP2102 under PC Linux .... FTDI? NO thanks

author: eneuro
author_rank: Super Contributor
timestamp: August 27, 2023, 11:36:16 pm
content: Quote from: BrianHG on August 27, 2023, 09:33:56 pmI've connected AVR Attiny85 software UART (114285Hz) TX pin to RX pin of Silicon Labs CP2102 USB to PC Linux and I receive on PC from Attiny85 those UART frames 0x41 ('A') by using Linux serial port terminal configured for 115200 baud rate (/dev/ttyUSB0), so it worksIt is time to output from AVR more data bytes with known CRC or MD5 check sums and verify received bytes on PC Linux to see what we get

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 28, 2023, 12:45:52 am
content: Quote from: eneuro on August 26, 2023, 04:54:25 pmKeep in mind, that most USB-UARTS are also not baud perfect, most are 24MHz/N and the crystal less ones, have some small fraction of % jitter.

author: eneuro
author_rank: Super Contributor
timestamp: August 28, 2023, 12:52:33 am
content: Now, on PC Linux I've dumped to test fileavr_uart_frames_0x41.tst10kB of data UART frames 0x41 received from AVR via CP2102 USB from Linux serial port device/dev/ttyUSB0than calculated its MD5 checksum:Code:$ dd iflag=fullblock if=/dev/ttyUSB0 bs=1k count=10 of=avr_uart_frames_0x41.tst10+0 records in10+0 records out10240 bytes (10 kB, 10 KiB) copied, 2.10148 s, 4.9 kB/s$ ls -l avr_uart_frames_0x41.tst10240 bytes avr_uart_frames_0x41.tst$ md5sum avr_uart_frames_0x41.tstb2a3affdfa9805c917df791087ac93d1 avr_uart_frames_0x41.tstLater, I've created on PC another file filled with 0x41 bytes and it looks like there were no transmission errors since we have the same MD5 check sums of both filesCode:unsigned int count= 10240;uint8_t byte_tx= 0x41; // ASCII 'A'for(unsigned int i=0; i<count; i++ ) {fputc(byte_tx, stdout );} //for$ ./avr_uart_frames_0x41 >avr_uart_frames_0x41.out$ md5sum avr_uart_frames_0x41.outb2a3affdfa9805c917df791087ac93d1 avr_uart_frames_0x41.outAdditionally as we can see Linux dump to file of 10kB of data from UART USB port/dev/ttyUSB0was at ~5kB/s speed since we needed around 2s, which is expected, while our real time AVR software UART frames speed is: 114285Hz but we have gaps between frames where only ~43% of UART TX output line is filled with data bits and we need 10bits per each transmited byte, so we get around ~5kB/s UART byte frames speedCode:10240 bytes (10 kB, 10 KiB) copied, 2.10148 s, 4.9 kB/sNot so bad

author: BrianHG
author_rank: Super Contributor
timestamp: August 28, 2023, 02:20:31 am
content: I dont know about linux, but you could try 921600 baud if you want to go faster. It's an available standard on Windows and with the garbage FTDI junk, I managed a flawless full duplex bidirectional link without any handshaking.Note: FTDI say they can go faster, but without hardware handshaking, all I got was garbage.

author: intabits
author_rank: Frequent Contributor
timestamp: August 28, 2023, 01:27:12 pm
content: You can go much faster than 115.2KBaud.I've used an Arduino Nano talking to a Windows PC App at 2MBaud.But 250KBaud is especially good as the baud rate divisor comes out to a precise integer: 3 (16MHz clock) or 4 (20MHz)In assembler (for 20MHz):-BRDIVISOR EQU ($CLOCK/(16*$BAUDRATE))-1 ;BAUD RATE DIVISOR57600 20.70 ;not an integer, but slow enough to work (mostly)74880 15.69 ;nbg115200 9.85 ;nbg128000 8.765 ;nbg230400 4.43 ;nbg250000 4.00 ;Perfect! integer and fast256000 3.88 ;nbg500000 1.50 ;nbg1000000 0.25 ;nbg2000000 -ve ;nbgNot sure how the 2MBaud worked (in Arduino IDE C++), but it did: Serial.begin(2000000);

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 28, 2023, 01:49:08 pm
content: Quote from: BrianHG on August 28, 2023, 02:20:31 amIf you're going throuh an FTDI chip. 1M is a better choice than 921600 as it is an exact fraction of the 24MHz clock

author: eneuro
author_rank: Super Contributor
timestamp: August 28, 2023, 08:35:43 pm
content: Quote from: mikeselectricstuff on August 28, 2023, 01:49:08 pm1M is also an exact fraction of the other clocksCode:48MHz CP210226MHz HC05 BT module16MHz AVR8MHz AVROf course it could be better send software UART frame byte faster on AVR and do not loose MPU time fornopdelays or other tricky delays to get 1 system clock delay resolution, but it can be more tricky to write code for AVR since we have only 8 - 16 system clocks per period when 1000000 baud rate is selected but will see what we can do with a little help of assembler inserted code to standard AVR gcc C

author: eneuro
author_rank: Super Contributor
timestamp: August 29, 2023, 12:29:48 am
content: Quote from: intabits on August 28, 2023, 01:27:12 pmYep, I've managed to output at 0.5M baud rate with almost the same AVR C software UART frame TX on Attiny85@8MHz 3.9Vcc with 16MHz external quartz and still a fewnop(125ns) delays left to optimize code#minicom under Linux displays send UART TX frames @500K baud rate 8-N-1 received by using CP2102 UART USB /dev/ttyUSB0

author: eneuro
author_rank: Super Contributor
timestamp: August 29, 2023, 06:55:51 pm
content: Quote from: Doctorandus_P on August 26, 2023, 08:05:58 pmYep, Now since I've managed to send UART frames at given baud rates I was interested in (~115200 250000 500000 and probbaly I can even go 1000000 @ 16MHz AVr MPU) , by using custom AVR C (asm) library, now I'm going to make this asynchronous UART serial communication more reliable and bidirectional one wireIdea is as simple as it is:Add 10k pull up resistors on sender/receiver one wire sides, than change UART software that it will send at the begining of the transmission byte 0x55 (01010101 -> UART frame data in LSB order: 10101010 ) which can be used on receiver side for clock synchronization etc, than each bytes sequence can be finished with one or more MD5 check sum bytes depending on how many bytes were send.Additionally sender when finishes transmision can release line by changing MPU output pin in high impenance and simply wait a few STOP bit eg. fo confirmation byte send back by receiver by using the same transmission line. eg. it can reply with 0xFF when everything is OK or do not reply at all, but send back eg. 0x00 when there were some errors in transmission to let sender know and can also send back message what was wrong - depending on defined protocol.Pull up resistors on both sides will keep transmission line at high level in a similar way to I2C, but with a difference, that during transmission those pims will be changed again by sender in output mode to drive transmission line not only by connecting O/I pin to ground, but also to logic high, because of 10k rpull up esistors are too big for fast (eg. I2C) communication.Btw, I mean one wire custom asynchronous UART serial communication between AVR MPUs which will share the same code, because of this of course will NOT work with classic UART frames implementations, but we should be able send/read UART frames to devices which support classic UART async serial communication at given baud rate

author: eneuro
author_rank: Super Contributor
timestamp: August 31, 2023, 04:04:45 am
content: Quote from: BrianHG on August 28, 2023, 02:20:31 amHopefully, I wrote a few lines of AVR C inline assembler code for perfect timing UART at 1M baud rate on 8Mhz F_CPU MPU, so only oneNOPinstruction was needed but I had to use MPU carry flags to exchange information between instructions while at this MPU speed 8MHz we have only 8 system clocks (1us) to output next UART bit perfectly synchronized with previous oneAnyway, now we have nice 1Mb UART TX frames from Attiny85 8MHz@3.9Vcc decoded by using 24Mhz Saleae Logic analyzer, but didn't tested this yet with CP2102 USB UART under Linux

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 31, 2023, 04:46:01 am
content: Quote from: eneuro on August 31, 2023, 04:04:45 amCP2102Nmanages 1MBd and above just fine, IIRC SiLabs have limited their driver to 1MBd on non 'N' CP2102

author: eneuro
author_rank: Super Contributor
timestamp: August 31, 2023, 08:53:42 am
content: Quote from: PCB.Wiz on August 31, 2023, 04:46:01 amI've connected AVR MPU Atiny85 software UART TX pin via CP2102 USB UART without any'N'markings (it is only CP2102 etc printed on this IC ) to Linux serial port terminal at port /dev/ttyUSB0 by usingminicomat 1M baud rate 8N1 and it looks good since I send from MPU pseudorandom bytes with prefix 0x55 and stop byte 0xFF with PRNG byte insideHowto check which version of CP2102 IC I've in my USB UART ?Code:[51707.591191] usb 1-1.3: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00[51707.591201] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3[51707.591206] usb 1-1.3: Product: CP2102 USB to UART Bridge Controller[51707.591210] usb 1-1.3: Manufacturer: Silicon Labs[51707.591213] usb 1-1.3: SerialNumber: 0001[51707.620907] usbcore: registered new interface driver cp210x[51707.620919] usbserial: USB Serial support registered for cp210x[51707.620941] cp210x 1-1.3:1.0: cp210x converter detected[51707.623063] usb 1-1.3: cp210x converter now attached to ttyUSB0

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 31, 2023, 09:02:39 am
content: Quote from: eneuro on August 31, 2023, 08:53:42 amIt is clear on the marking as CP2102N (as below)Also, I think their latest drivers refuse to set above 1MBd on CP2102, but allow any 24M/N up to 4MBd on CP2102NI'd be curious if Linux behaves the same ?

author: eneuro
author_rank: Super Contributor
timestamp: August 31, 2023, 03:20:22 pm
content: Quote from: PCB.Wiz on August 31, 2023, 09:02:39 amYep, so probably I've classic CP2102 with baud rates 300 up to 1Mb according to their datasheets which is fine since I do not need to go above those baud rates on 8Mhz AVR Attiny85 MPUsAnyway, I've checked CP2102N Data Sheet USBXpress™ Family:https://www.silabs.com/documents/public/data-sheets/cp2102n-datasheet.pdfand they says about UART baud rates up to 3Mbaud and there is no information about any limitations since Silicon Labs do support Linux drivers

author: tridac
author_rank: Regular Contributor
timestamp: August 31, 2023, 03:32:55 pm
content: At that sort of speed, I would design like a driver, split into two halves. A lower interrupt and mainline parts, with fifo buffer between the two. Advantages are uart register processing done in the background, in interrupt context, so mainline code can get on with other work. Typically, load the fifo with tx data, enable interrupts and wait until tx complete flag set, or similar...

author: eneuro
author_rank: Super Contributor
timestamp: September 03, 2023, 02:56:24 am
content: Quote from: tridac on August 31, 2023, 03:32:55 pmI was able setup HC05 BT module for slave mode for maximum UART baud rate only115200since attempt to configure this thing to 1Mb failed with ERROR:Code:AT+UART=1000000,0,0ERROR:AT+UART?+UART:115200,0,0OKMaybe I wll need some kind of buffer, but I do not need to send via this BT module more than 1KB/s data bytes, so I will use on AVR in my software UART implementation something closest lower baud rate to 115200 and it looks like that on 8MHz F_CPU AVR MPU it is: 114285.714 ~114286 < 115200UPDATE: I've configured HC05 BT module for UART 921600 baud rate in slave modeCode:+UART:921600,0,0OK

author: eneuro
author_rank: Super Contributor
timestamp: September 03, 2023, 03:19:58 am
content: Quote from: BrianHG on August 28, 2023, 02:20:31 amYep, I've tried again setup HC05 BT module for something faster than 115200 and it looks like it accepted baud rate 921600 but failed when tried 1000000I didn't expected this but that is fine lets tune AVR UART software code to something closest to 921600 baud rate on AVR Attiny85 8MHz@3.7Vcc (powered directly from 18650 Li-on battery with 16MHz quartz on PCB)Code:+ROLE:0OK+UART:921600,0,0OK

author: PCB.Wiz
author_rank: Super Contributor
timestamp: September 03, 2023, 05:28:29 am
content: Quote from: eneuro on September 03, 2023, 03:19:58 amI thought you had deliberate delays anyway, because the MCU was already to slow ?Making the UART faster is going to give diminishing returns.921600 from 8M is going to be off by 3.5%, unless you use fractional baud / unrolled loop approach. (or change xtal to 14.7546Mhz)The error per bit is 39.93ns, and you have 125ns granularity, so as the error creeps, after a couple of bits you snap to the closest 125ns edge,

author: eneuro
author_rank: Super Contributor
timestamp: September 03, 2023, 08:04:35 am
content: Quote from: PCB.Wiz on September 03, 2023, 05:28:29 amHopefully, since communication speed is not critical for me at 921600bps baud rate, after a couple of LSB bits in one byte I can send last four as 0xF, than in second byte again four MSB bits first than fill rest of 2nd byte by sending 0xF, so instead of sending 1 byte I need to send 2 bytes but I can do it much faster at close to 1Mbps than by using 115200bps baud rate

author: PCB.Wiz
author_rank: Super Contributor
timestamp: September 03, 2023, 08:55:14 am
content: Quote from: eneuro on September 03, 2023, 08:04:35 amThat's sounding very convoluted.You could look for intermediate bauds, between 115200 and 921600 ?Or, unroll the SW baud loop, so you can do the fractional baud above, which would work ok.A calculator gives the jitter results for fraction baud, see how the drift does not accumulate, by careful choices of when to do /8 and /9 .(1/921600)-(1/(8M/9)) Diff = -39.9ns(2/921600)-((1/(8M/9))+(1/(8M/8))) Diff = 45.1ns(3/921600)-((2/(8M/9))+(1/(8M/8))) Diff = 52.0ns(4/921600)-((3/(8M/9))+(1/(8M/8))) Diff = -34.7ns(5/921600)-((3/(8M/9))+(2/(8M/8))) Diff = 50.3ns(6/921600)-((4/(8M/9))+(2/(8M/8))) Diff = 10.4ns(7/921600)-((5/(8M/9))+(2/(8M/8))) Diff = -29.5ns(8/921600)-((5/(8M/9))+(3/(8M/8))) Diff = 55.5ns(9/921600)-((6/(8M/9))+(3/(8M/8))) Diff = 15.6ns(10/921600)-((7/(8M/9))+(3/(8M/8)))Diff = -24.3ns

author: gnuarm
author_rank: Super Contributor
timestamp: September 03, 2023, 09:19:16 am
content: Quote from: eneuro on August 26, 2023, 09:09:58 amThe purpose of the start and stop bits is to align the data reception, to the data transmission. This should be all the alignment required. If you need to add extra spacing between bytes, it is either an electrical issue with your connections (such as too much wire adding too much capacitance slowing the transmission times) or your receiver simply can't read the received data from the UART quickly enough. In the case of the latter, an error flag for overrun should be set in the UART.If everything else is working properly, the start bit of the next character can follow immediately on the end of the stop bit of the previous character.BTW, your diagram seems to show two levels for each transmitted data bit.

author: eneuro
author_rank: Super Contributor
timestamp: September 03, 2023, 09:50:25 am
content: Quote from: gnuarm on September 03, 2023, 09:19:16 amYep, It was made only to show gaps ~100uS 0.1ms between next UART frame and it doesn't matter what is inside between START green - STOP red bits

author: eneuro
author_rank: Super Contributor
timestamp: September 03, 2023, 10:32:27 am
content: Quote from: PCB.Wiz on September 03, 2023, 08:55:14 amNope, you can't unroll the SW baud loop better than in was done in inline assembler, since I do not know AVR instruction set which could make delay 1/2 or 1/3 system clock at F_CPU 8MHzI had to add only twoNOP1 clk instructions to inline C assembler (to avoid any gcc optymalizations when -Os is given for size optimization) code shown before for 1Mb optimized 1us perfect timed UART TX frames which gives us baud rate period error for 921600bps on 8MHz AVR MPU:Code:|100*( 1.0/(1.0/1000000 +1.0/8000000 ) -921600)/921600| [%] =~3.5%NOTE: 1.0/8000000 = 125ns is 1 clk instructionNOPfor example...so when we use 16Mhz AVR MPU than this baud rate period error will be lower ~2.1%When we use 12MHz AVR MPU than this baud rate period will be ~1.6%Code:( 1.0/(1.0/1000000 +1.0/12000000) -921600 )/921600 = 0.0016025641~1.6% @ ~923077 software AVR MPU UART baud rateBTW: HC05 BT module has 26MHz external clock on PCBCode:( 1.0/(1.0/1000000 +1.0/13000000)-921600 )/921600 = 0.007564~1% baud rate error @ 13MHz AVR MPU

author: BrianHG
author_rank: Super Contributor
timestamp: September 03, 2023, 02:59:24 pm
content: Quote from: eneuro on September 03, 2023, 10:32:27 amAre you sure your math is correct?For example, try replacing the 12MHz with 120MHz. The %error should be the same or less, but it is not.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: September 03, 2023, 07:45:12 pm
content: You need to study loop unroll some more.The HC05 xtal does not matter, as there in a subsequent PLL, it is the peripheral MHz that matters.

author: eneuro
author_rank: Super Contributor
timestamp: September 04, 2023, 07:30:54 am
content: Quote from: PCB.Wiz on September 03, 2023, 07:45:12 pmThe peripheral MHz depends probably on stability of system clock and when it is based on external quartz connected to MPU by xtal pins it helps a lot.I do not need to study any loop unroling - I've wrote a few lines of inline C AVR assembler code and it works.It was written in a way that now it is easy by adding additional 125ns delays on 8MHz MPU with external quartz crystal clock to output UART frame byte as close as possible to choosenbaud rate and limit is one clock instruction execution time.Anyway, it works and running this AVR MPU at 16MHz quartz @ 5Vcc instead of 8MHz@3.3Vcc will allow to be closer to given baud rate frequency.

author: eneuro
author_rank: Super Contributor
timestamp: September 04, 2023, 08:14:07 am
content: Quote from: BrianHG on September 03, 2023, 02:59:24 pm

author: tridac
author_rank: Regular Contributor
timestamp: September 07, 2023, 12:43:20 am
content: Division ratios in baud generators often give slight error, which can be significant at high rates. One way around that, used in the past, is to vary the division ratio of the baud rate generator. Assuming a baud rate of x and available division ratios of x-1, x+1, then use the upper and lower values alternately, or in a count loop, to get a fractional division ratio. Using an interrupt driven timer as generator, it's easy to do that on alternative timer reload interrupts. Can get very high accuracy. Slight jitter on the baud rate, but the uart won't care about that...