Pages: [1] 2   Go Down
Author Topic: Setting Serial Data, Parity and Stop bits.  (Read 19602 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all, I've just started working with the Arduino and have not been able to find a way to set the Data, Parity and Stop bits for the serial libraries.  I've got a motor controller that needs 7-E-1, not 8-N-1.

Thanks!
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
he's not a real doctor
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wrote a library for this, I put off posting it because I wanted to add some more interesting stuff for error checking.   Its short so I am putting the code in line.  I didnt find this elsewhere, but its pretty simple so it may be on the site already.  Note if you dont want to use the library, you can simply lift the setserial sub.
FYI - I have worked out a couple of tricks to check for parity errors if you get into that.  The best one requires editing wiring_serial.c, but I found a kluge that can be done from a program.

File must be named SerialExtension.cpp
Code:
#include <SerialExtension.h>

void SetSerial(long baud, char parity, int wordlength, int stop)
{
// set baud rate
// code lifted straight from wiring_serial.c
#if defined(__AVR_ATmega168__)
      UBRR0H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
      UBRR0L = ((F_CPU / 16 + baud / 2) / baud - 1);
      
      // enable rx and tx
      sbi(UCSR0B, RXEN0);
      sbi(UCSR0B, TXEN0);
      
      // enable interrupt on complete reception of a byte
      sbi(UCSR0B, RXCIE0);

#else
      UBRRH = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
      UBRRL = ((F_CPU / 16 + baud / 2) / baud - 1);
      
      // enable rx and tx
      sbi(UCSRB, RXEN);
      sbi(UCSRB, TXEN);
      
      // enable interrupt on complete reception of a byte
      sbi(UCSRB, RXCIE);
#endif
      // defaults to 8-bit, no parity, 1 stop bit

//clear parity, stop bits, word length
//UCSR0B bit 2=0 for all wordlengths except 9
//Note: Serial.read routines wont work with 9 bit data as written
UCSR0C = UCSR0C & B11000001;
UCSR0B = UCSR0B & B11111011;  

//set parity
if ((parity == 'O')|(parity == 'o'))
  {
    UCSR0C = UCSR0C | B00110000;
  }
else if ((parity == 'E')|(parity == 'e'))
  {
    UCSR0C = UCSR0C | B00100000;
  }
else // ((parity == 'N')|(parity == 'n')))
  {
    UCSR0C = UCSR0C | B00000000;
  }

//set word length
if (wordlength == 5)
  {
    UCSR0C = UCSR0C | B00000000;
  }
else if (wordlength == 6)
  {
    UCSR0C = UCSR0C | B00000010;
   }
else if (wordlength == 7)
  {
    UCSR0C = UCSR0C | B00000100;
  }
else if (wordlength == 9)
  {
    UCSR0C = UCSR0C | B00000110;
    UCSR0B = UCSR0B | B00000100;
  }
else // (wordlength == 8)
  {
    UCSR0C = UCSR0C | B00000110;
  }

//set stop bits
if (stop == 1)
  {
    UCSR0C = UCSR0C | B00000100;
  }
else // (stop == 2)
  {
    UCSR0C = UCSR0C | B00000000;
  }
}


File must be named SerialExtension.h
Code:
#include <WConstants.h>
//#include <wiring_private.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void SetSerial(long baud,char parity, int wordlength, int stop);

#endif
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The #endif at the bottom of SerialExtension.h is missing the associated if, and if I remove it there are a few other errors because it looks like something is missing or redefining something.  What is the #if line at the top of the file?

I'm getting this error now:

In file included from /Applications/arduino-0015/hardware/cores/arduino/WProgram.h:4,

/Applications/arduino-0015/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/include/stdlib.h:111: error: expected unqualified-id before 'int'

/Applications/arduino-0015/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/include/stdlib.h:111: error: expected `)' before 'int'

/Applications/arduino-0015/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/include/stdlib.h:111: error: expected `)' before 'int'

In file included from /Applications/arduino-0015/hardware/cores/arduino/WProgram.h:6,


Thanks!
« Last Edit: June 02, 2009, 04:36:02 pm by jeffcraighead » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Solved using the info from this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237653105
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
he's not a real doctor
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry for the syntax error.  I dont know if I grabbed a bad version from my archive or if it somehow compiled as-is.  Either way thanks for the catch.  

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
he's not a real doctor
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also, you can test as follows.
1) initialize the serial port as usual
2) set the baud/parity/stop bits
3) loop and send a string repeatedly, (delay a second each time makes it a little easier)

4) start your sketch, then EXIT the Arduino GUI.  Start Hyperterm you should receive your test string.  You should have to set hyperterm to match your serial settings.  Make sure you select the right com port in hyperterm.
Logged

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I hope you can help... What you have here looks like the solution to my problems.

I need to interface to a device that uses 2 stop bits, I went searching and found this post.

I fixed SerialExtension.h as shown here:
Code:
#include <WProgram.h>

#ifndef cbi
   #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
   #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void SetSerial(long baud,char parity, int wordlength, int stop);

The corresponding SerialExtension.cpp is as follows:
Code:
#include <SerialExtension.h>

void SetSerial(long baud, char parity, int wordlength, int stop)
{
// set baud rate
// code lifted straight from wiring_serial.c
#if defined(__AVR_ATmega168__)
      UBRR0H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
      UBRR0L = ((F_CPU / 16 + baud / 2) / baud - 1);

      // enable rx and tx
      sbi(UCSR0B, RXEN0);
      sbi(UCSR0B, TXEN0);

      // enable interrupt on complete reception of a byte
      sbi(UCSR0B, RXCIE0);

#else
      UBRRH = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8;
      UBRRL = ((F_CPU / 16 + baud / 2) / baud - 1);

      // enable rx and tx
      sbi(UCSRB, RXEN);
      sbi(UCSRB, TXEN);

      // enable interrupt on complete reception of a byte
      sbi(UCSRB, RXCIE);
#endif
      // defaults to 8-bit, no parity, 1 stop bit

//clear parity, stop bits, word length
//UCSR0B bit 2=0 for all wordlengths except 9
//Note: Serial.read routines wont work with 9 bit data as written
UCSR0C = UCSR0C & B11000001;
UCSR0B = UCSR0B & B11111011;  

//set parity
if ((parity == 'O')|(parity == 'o'))
  {
    UCSR0C = UCSR0C | B00110000;
  }
else if ((parity == 'E')|(parity == 'e'))
  {
    UCSR0C = UCSR0C | B00100000;
  }
else // ((parity == 'N')|(parity == 'n')))
  {
    UCSR0C = UCSR0C | B00000000;
  }

//set word length
if (wordlength == 5)
  {
    UCSR0C = UCSR0C | B00000000;
  }
else if (wordlength == 6)
  {
    UCSR0C = UCSR0C | B00000010;
   }
else if (wordlength == 7)
  {
    UCSR0C = UCSR0C | B00000100;
  }
else if (wordlength == 9)
  {
    UCSR0C = UCSR0C | B00000110;
    UCSR0B = UCSR0B | B00000100;
  }
else // (wordlength == 8)
  {
    UCSR0C = UCSR0C | B00000110;
  }

//set stop bits
if (stop == 1)
  {
    UCSR0C = UCSR0C | B00000100;
  }
else // (stop == 2)
  {
    UCSR0C = UCSR0C | B00000000;
  }
}

 

But I'm getting (kinda expected, from code inspection) the following compile errors:

Code:



SerialExtension.cpp: In function 'void SetSerial(long int, char, int, int)':
SerialExtension.cpp:19: error: 'UBRRH' was not declared in this scope
SerialExtension.cpp:20: error: 'UBRRL' was not declared in this scope
SerialExtension.cpp:23: error: 'UCSRB' was not declared in this scope
SerialExtension.cpp:23: error: 'RXEN' was not declared in this scope
SerialExtension.cpp:24: error: 'TXEN' was not declared in this scope
SerialExtension.cpp:27: error: 'RXCIE' was not declared in this scope
E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp: In function 'void SetSerial(long int, char, int, int)':


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:19: error: 'UBRRH' was not declared in this scope


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:20: error: 'UBRRL' was not declared in this scope


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:23: error: 'UCSRB' was not declared in this scope


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:23: error: 'RXEN' was not declared in this scope


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:24: error: 'TXEN' was not declared in this scope


E:\Internet Downloads\arduino-0015-win\arduino-0015\hardware\cores\arduino\SerialExtension.cpp:27: error: 'RXCIE' was not declared in this scope

I get the same results in versions 15 & 16 of the Arduino environment.

Help would be *greatly* appreciated.

Cheers,



Darren
« Last Edit: June 13, 2009, 10:56:07 pm by dcbeast » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
he's not a real doctor
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The stop bits code I posted is wrong anyway.......

Quick and dirty just
1) set baud rate with the usual command
2) add the following to your setup code:
UCSR0C = UCSR0C | B00001000;

I am pretty sure UCSR0C is predefined (note that is a ZERO not an O).
Word length is also UCSR0C (except for 9 bit).

I double checked with the AVR datasheet and the code I posted doesnt set stop bits right anyway.  Pretty embarrasing. Between the compile errors and that I am going to go retest.
Logged

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey drspectro,

Thank you !!!!!!!!!!!!!!!!

I'm posting very simple code here for anyone else who hits this problem.  You don't need any other library, just the code below.

This is working built using Arduino 16 talking to hyper-terminal on Windows XP.

Code:

byte high = 0;

void setup()
{
  Serial.begin(9600);
  // 2 Stop-bits please!
  UCSR0C = UCSR0C | B00001000;
  pinMode(13, OUTPUT);
}

void loop()
{
  if (high == 0)
  {
    digitalWrite(13, HIGH);
    high = 1;
  }
  else
  {
    digitalWrite(13, LOW);
    high = 0;
  }
  if (high == 0)
  {
    Serial.print("HELLO"); // The text
  }
  else
  {
    Serial.print("WORLD"); // The text
  }
  delay(500);
}
« Last Edit: June 16, 2009, 07:14:49 am by dcbeast » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
he's not a real doctor
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

glad it worked

I still want to get the library fixed because it covers all the parameters at once.  I would hope that would be easier in the long run.....  Also dont be afraid to go straight to the AVR datasheet for stuff like this.  It is usually pretty clear which registers to mess with and you can look at the wiring code to figure out the syntax.
Logged

Louisville, KY
Offline Offline
Newbie
*
Karma: 0
Posts: 49
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey all,
   I have a device that communicates on 1200-8-N-0.  All of that is possible minus the 0 stop bits.  Anyway to get the arduino to do this?
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have a device that communicates on 1200-8-N-0.  All of that is possible minus the 0 stop bits.  Anyway to get the arduino to do this?

Are you really sure about the 0 stop bit requirement? I say that because asynchronous communication hardware is built around the requirement for the stop bit and start bit to determine the ending of one character and the starting of the next, it just doesn't work without the stop bit. I've worked with the RS-232 asynchronous comm links for many decades and I've never heard of a zero stop bit ability. Now there are synchronous communications links that use no start or stop bits but rather either an independent or impeded clock to keep the sender and receiver in step for character transmission.

So might you be working with a serial synchronus communicating device?

Note: the AVR processor can be programmed to use synchronous communications, however with the standard Arduino serial software commands and a new clock wire would have to be wired between the Arduino and the external device.

Lefty
« Last Edit: August 27, 2009, 05:42:08 pm by retrolefty » Logged

New Paltz, NY
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to read data that is coming in with 2 stop bits.  Now I see that the Atmel datasheet says that on page 198, BIT3 of USBSn sets the stop bits, but only the transmitter cares.  From my rough knowledge of how asynchronous communications work, is that because the receiver sees a single stop bit and doesn't care what happens after that until the next start (low) bit?  If not, how would I go about changing the receiver settings for stop bits?  Thanks!
Logged

Whats a warranty?

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
is that because the receiver sees a single stop bit and doesn't care what happens after that until the next start (low) bit?  If not, how would I go about changing the receiver settings for stop bits?  Thanks!

That's exactly right. Remember that after a single character with a proper stop bit detected, there may be no further characters for several seconds or even mins depending on the application.

Once a receiver detects that a expected stop bit is proper, it is willing to wait forever for only one further event, a start bit. That's why it's called asynchronous communications because the receiving end has no advance information on when and if  the next character may be sent.

Interesting the purpose for more then a single stop bits (1&1/2 stop bits was an option in older times as well as 2 stop bits) dates back to the old mechanical teletype machines that  used asyn communications. It allowed a little more time for receiving machines to "catch up" in case the transmitter was sending slightly faster then the agreed on baud rate.

Lefty
« Last Edit: October 04, 2009, 11:02:37 pm by retrolefty » Logged

Manchester (England England)
Online Online
Brattain Member
*****
Karma: 626
Posts: 34153
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The half bit in the old 5 data bit standards also allowed synchronisation to a continuous stream of data. For example a standard way of keeping the channel open (free from other signals) was to transmit a continuous string of "RYRYRYRYRYRY....". These characters were chosen because they were at each end of the mechanical rotation limit of the print head. This was transmitted over short wave. Now if you tuned into this continuous stream you could start anywhere in it. If you had a stop bit time of exactly one or two bits you could tap into this stream and miss read it mistaking start bits and stop bits for data bits. The half period stop bit prevented this from happening.
Logged

Pages: [1] 2   Go Up
Jump to: