5 data bits via UART - Page 1
Forum section: electronics / general

author: Kittu20
author_rank: Regular Contributor
timestamp: September 18, 2023, 12:26:58 pm
content: Hello everyoneI've been working with UART communication and typically use the standard 8N1 configuration. However, I recently came across a scenario where I want to configure UART for 5 data bits (5N1). I've already written code to handle UART communication for 8N1, but I'm unsure about how to transfer only 5 bits of data.Can you provide code examples on how to transmitting and receiving data for 5N1 ?Code:#include <xc.h>#include <stdio.h>#include"config.h"void initializeOscillator(void);void initializeEUSART1(void);/****** NOTE: This function configures the oscillator settings for the microcontroller.* It sets the IRCF bits to 110 for HF-INTOSC/2 (8 MHz, default).*****/void initializeOscillator(void){OSCCON = 0x60; // Set IRCF bits to 110 for HF-INTOSC/2 (8 MHz, default)OSCCON2 = 0x00;OSCTUNE = 0x00;REFOCON = 0x00;}void initializePort() {// Set LATx registers to initial states (all low)LATA = 0x00;LATB = 0x00;LATC = 0x00;LATD = 0x00;LATE = 0x00;// Set TRISx registers to configure pins as outputs (all output)TRISA = 0x00;TRISB = 0x00; // RB0 is RED, RB1 is YELLOW and RB2 is GREEN LEDTRISC = 0x80; // RC7 is TX and RC6 TXTRISD = 0x00;TRISE = 0x00;// Additional configuration for unused peripheralsANCON0 = 0x00; // Set all analog pins to digital modeANCON1 = 0x00; // Set all analog pins to digital modeCM1CON = 0x00; // Turn off Comparator 1CM2CON = 0x00; // Turn off Comparator 2ADCON0 = 0x00; // Disable A/D conversionADCON1 = 0x00; // Disable A/D conversionADCON2 = 0x00; // Disable A/D conversion}/******* NOTE: This function configures the EUSART1 settings for communication.******/void initializeUART1() {// Configure BAUDCON1 register// Bit 7: ABDOVF = 0 (Auto-Baud Acquisition Rollover Status bit - Cleared in software)// Bit 6: RCIDL = 0 (Receive Operation Idle Status bit - Receive operation is active)// Bit 5: RXDTP = 0 (Received Data Polarity Select bit - Receive data is not inverted)// Bit 4: TXCKP = 0 (Clock and Data Polarity Select bit - Idle state for transmit is high level)// Bit 3: BRG16 = 1 (16-Bit Baud Rate Register Enable bit - 16-bit Baud Rate Generator)// Bit 2: Unimplemented: Read as ?0? (Reserved, read as '0')// Bit 1: WUE = 0 (Wake-up Enable bit - RX pin is not monitored or rising edge is detected)// Bit 0: ABDEN = 0 (Auto-Baud Detect Enable bit - Baud rate measurement is disabled or completed)BAUDCON1 = 0b00001000; // Set BRG16 bit to 1 (16-Bit Baud Rate Register Enable)// Calculate and set SPBRG1 for a baud rate of approximately 9600 at 8 MHzSPBRG1 = 207;SPBRGH1 = 0;// TXSTA1 register configuration// Bit 7: CSRC = 0 (Clock Source Select bit - Don't care in Asynchronous mode)// Bit 6: TX9 = 0 (8-bit transmission)// Bit 5: TXEN = 1 (Transmit is enabled)// Bit 4: SYNC = 0 (Asynchronous mode)// Bit 3: SENDB = 0// Bit 2: BRGH = 1 (High-speed baud rate)// Bit 1: TRMT = 1 (TSR is empty initially)TXSTA1 = 0b00100100; // Configure TXSTA1 register// RCSTA1 register configuration// Bit 7: SPEN = 1 (Serial Port Enable bit - Serial port is enabled)// Bit 6: RX9 = 0 (8-bit reception)// Bit 5: SREN = 0 (Single Receive Enable bit - Don't care in Asynchronous mode)// Bit 4: CREN = 1 (Continuous Receive Enable bit - Enables receiver)// Bit 3: ADDEN = 0 (Address Detect Enable bit - Don't care in Asynchronous mode)// Bit 2: FERR = 0 (Framing Error bit - No framing error)// Bit 1: OERR = 0 (Overrun Error bit - No overrun error)RCSTA1 = 0b10010000; // Configure RCSTA1 register}void hardwareInitialize() {// Initialize the oscillatorinitializeOscillator();// Initialize Port PinsinitializePort();// Initialize Uart1initializeUART1();}/******* NOTE: This function waits until the transmitter buffer is empty (TXIF is set)* and then sends the character by placing it in the TXREG1 register.******/void UARTWrite(char Character){// Wait until the transmitter buffer is empty (TXIF is set)while (TXIF == 0);// Send the character by placing it in the TXREG1 registerTXREG1 = Character;}/******* NOTE: This function waits until the receiver buffer is full (RCIF is set)* and then reads the received character from the RCREG1 register.******/char UARTRead(void){// Wait until the receiver buffer is full (RCIF is set)while (RCIF == 0);// Read the received character from the RCREG1 registerreturn RCREG1;}/******* main - Main program function******/void main(void){// Initialize hardwarehardwareInitialize();// Delay for 5 seconds__delay_ms(5000);while (1){// Define a character to sendchar Character = 'U';char ReceivedChar;ReceivedChar = UARTRead(); // Read a command from UARTUARTWrite(ReceivedChar); // Send the command back// Delay for 5 seconds before the next transmission__delay_ms(5000);}}

author: Ian.M
author_rank: Super Contributor
timestamp: September 18, 2023, 01:09:45 pm
content: From the look of your code, you are using an 8 bit PIC. AFAIK there aren't any 8 bit PICs with 5 bit UART support (as mechanical teletypes were already a dead technology by the date Microchip was founded), but you can send 5 bit data by OR masking the three high bits to 1. This gives you too many stop bits (5N4) but is compatible with a 5N1 receiver albeit with only 70% of the peak characters per second for the same baud rate. This does *NOT* work for receiving 5N1 data unless there are at least three extra idle bits between characters, so if you need bidirectional comms or the full data rate your only option is to write a 5 bit capable bit-banged software UART.

author: jpanhalt
author_rank: Super Contributor
timestamp: September 18, 2023, 01:29:48 pm
content: I suspect there are 3 viable options:1) Bit bang for 5-bit,2) Pack your 5-bit data into 8-bit bytes, or3) Pad your data to give 8-bits.I suspect you are not interested in bit banging, but here's an example I got from Mike (K8LH) years ago in case you are curious of what it looks like in PIC Assembly. It can be adapted to 5 bit, but you will need to also get the receive end (e.g., Get232).Code:;******************************************************************************; PUT232; Put232 (9600 baud) -- Mike McLaren, K8LH (Jan-09);******************************************************************************Put232movlb2movwftxbyte; save Tx data bytemovlw10; 1 start + 8 data + 1 stop bitmovwfbit_ctr; setup bit counterbcfstatus,0; C = 0 (start bit)DelayCy(104*usecs-10); 104 usecs minus 10 cycles(added)gotoSendBit; send start bitNextBitDelayCy(104*usecs-10); 104 usecs minus 10 cyclesbsfstatus,0; always shift in a 'stop' bitrrftxbyte,f; put data bit in CarrySendBitmovfLATD,W; read portiorlw1<<1; set Ser_out pin bit to 1btfssstatus,0; if data bit = 1 skip, elsexorlw1<<1; set Ser_out pin bit to 0movwfLATD; precise update intervalsdecfszbit_ctr,f; done? yes, skip, elsegotoNextBit; send next bitretlw0;"DelayCy" is a macro. You will need to insert an appropriate delay for your baud rate.

author: DavidAlfa
author_rank: Super Contributor
timestamp: September 18, 2023, 02:24:03 pm
content: Stop bit is a "1":So, it's very simple, use the 8-bit UART, set the 3 MSB to 1, so the last 3 bits and the stop are merged together:Code:TX = DATA_5B | 0xE0;This makes the uart to send:Start D0 D1 D2 D3 D4 1 1 1 StopA 5-bit uart receiver will take D5 as the stop bit, the remaining data is 1 so no new start will happen.This "hack" will work with any number of bits between 1 and 8, but the PIC will be still sending 8bits, so the effective data rate won't be faster, if that was you target.

author: Kittu20
author_rank: Regular Contributor
timestamp: September 18, 2023, 02:26:59 pm
content: I've come across numerous documents and online tutorials that discuss the ability to transfer data with 5 to 9 bits, but most examples and practical applications seem to focus on the standard 8-bit configuration. This has sparked my curiosity about experimenting with 5 or 6 data bits. When shifting the data position to achieve 5 bits, there's still the transmission of 8 bits.Could you share your experiences on how one might effectively experiment with data configurations of 5 or 6 bits, and what considerations are important when attempting such configurations? Additionally, have you encountered any real-world scenarios where non-standard data bit configurations were beneficial

author: jpanhalt
author_rank: Super Contributor
timestamp: September 18, 2023, 03:29:34 pm
content: Quote from: Kittu20 on September 18, 2023, 02:26:59 pmJust bit-bang and set bit_ctr to whatever you want +2. As mentioned, you need the Get232 code, which has a very similar structure.Real world? PIC's hardware does allow 9-bit.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: September 18, 2023, 03:59:19 pm
content: Read the datasheet of your microcontroller.Some microcontrollers can be set up to do 5 bit data with the U(s)ART.

author: mikerj
author_rank: Super Contributor
timestamp: September 18, 2023, 04:30:34 pm
content: Quote from: Kittu20 on September 18, 2023, 02:26:59 pmAs others have already said you can only configure your UART for 5 bit data if the UART supports this. Some do, some don't. The code you posted suggest you are using a PIC of some type, but you haven't told us which one. If your UART does not support 5 bit operation, then you will have to bit bang the data i.e. software emulation of the UART.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: September 18, 2023, 05:04:26 pm
content: Bit banging works adequately for "low baudrates" (and "low" depends on the uC you use and how much other things it has to do)And as other's have already mentioned, pre-formatting the data works, and in it's simplest form you will then just send the data with 4 stop bits, but any "receiving end" should be able to handle that. If you want to send more data, and can't afford to send 5 stop bits for each byte, then you can use dirty tricks such as resetting your U(s)ART after the 5 data bits have been sent.Receiving 5N1 data is easy if there is enough room between the bytes, but if it's sent as a continuous 5n1 steam, then it's probably either bitbanging or using a U(s)ART that supports 5-bit data.

author: PCB.Wiz
author_rank: Super Contributor
timestamp: September 18, 2023, 09:15:34 pm
content: Quote from: Kittu20 on September 18, 2023, 02:26:59 pmNope, not if the UART supports 5 bits. (see #3)Quote from: Kittu20 on September 18, 2023, 02:26:59 pmErr ? Find UARTS that supports the 5 or 6 bits you seek, and try them ?Quote from: Kittu20 on September 18, 2023, 02:26:59 pmThe obvious saving is time. Other reasons may be more obtuse, like if you wanted to avoid casual hacking, or lock customers into your systems...These modes are historic, as inreallyhistoric...https://en.wikipedia.org/wiki/Baudot_codeSo you can see where 5 bit UART came from.

author: jpanhalt
author_rank: Super Contributor
timestamp: September 18, 2023, 09:27:17 pm
content: Mid-range PIC's do not support 5-bit UART. Based on the TS's latest post, I suspect this is just a "what if" waste of time, as the TS has failed to give any specifics whatsoever.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 18, 2023, 09:40:25 pm
content: A couple notes:- The OP didn't bother to say which MCU they were trying to use and made people guess from the posted piece of code. All we know is that it looks like a PIC supported by the XC compiler, probably an 8-bit PIC and XC8, although I'm not even sure. Frankly I didn't bother checking out if the few registers used in the code were indicative of a particular PIC model, there are literally hundreds.- If it turns out it doesn't natively support 5-bit data frames, then as said above, you could use some tricks (with limitations) or just bit-bang it (probably the easiest and making the most sense).- We don't know what baud rate nor what system clock the OP is dealing with, so the bit-banging option may or may not be an option. Also, depending on which interrupts are enabled, it may require some particular care, like disabling interrupts while transmitting/receiving, or selectively disabling the ones appropriate, not completely trivial either.Not to sound like a free lecture, but if you want more accurate, to-the-point answers while making people waste less time, giving more accurate requirements/context will go a long way. Actually, properly defining a problem is often 80% of the solution.

author: Kittu20
author_rank: Regular Contributor
timestamp: September 19, 2023, 01:35:48 am
content: I apologize for not mentioning my microcontroller earlier. I'm using a PIC18F45K80. After reviewing the datasheet, specifically in Section 22.1 on page 327, it appears to me that this microcontroller only supports 8-bit or 9-bit communication

author: westfw
author_rank: Super Contributor
timestamp: September 19, 2023, 05:25:06 am
content: Quote from: Kittu20 onTodayat 07:26:59 amMy first project out of college involved interfacing a mainframe to a newswire that ran a 6bit version of baudot. That was 1981. I haven't seen anything shorter than 7 bits since, despite much of my career revolving round async UART communications.

author: Smokey
author_rank: Super Contributor
timestamp: September 19, 2023, 05:29:34 am
content: Quote from: jpanhalt on September 18, 2023, 01:29:48 pm... 4) send the data in 40-bit (8-byte) buffers (or 8 x 5-bit transmissions at a time).