Go Down

Topic: change in serial port setting of parity or stop bits number HAS NO problem???? (Read 251 times) previous topic - next topic

emir22


HELLO every one

this is the 4 th  post i m sharing till now . i have had no any response for my questions till now  :smiley-confuse:

but i think this is because of my poor english .any way i hope some one will reply me at this post  :)


im currently practicing RS485 MODBUS simple programs .

i use an ARDUINO MEGA and a USB TO RS485  converter .
master side is my PC VIA CAS MODBUS  program that can poll 4 function

it has the ability to change the serial parity type and stop bit from software .

i use a very simplest slave program at my MEGA .
Quote
#include <SimpleModbusSlave.h>

/*
   SimpleModbusSlaveV10 supports function 3, 6 & 16.
  
   This example code will receive the adc ch0 value from the arduino master.
   It will then use this value to adjust the brightness of the led on pin 9.
   The value received from the master will be stored in address 1 in its own
   address space namely holdingRegs[].
  
   In addition to this the slaves own adc ch0 value will be stored in
   address 0 in its own address space holdingRegs[] for the master to
   be read. The master will use this value to alter the brightness of its
   own led connected to pin 9.
  
   The modbus_update() method updates the holdingRegs register array and checks
   communication.

   Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is
   limited to its internal buffer which differs between manufactures.
*/

#define  LED 9  

// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.

//////////////// registers of your slave ///////////////////
enum
{    
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  AB,    
  AC,        
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  /* parameters(HardwareSerial* SerialPort,
                long baudrate,
    unsigned char byteFormat,
                unsigned char ID,
                unsigned char transmit enable pin,
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
  
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
    
     You can obviously use SERIAL_8N1 but this does not adhere to the
     Modbus specifications. That said, I have tested the SERIAL_8N1 option
     on various commercial masters and slaves that were suppose to adhere
     to this specification and was always able to communicate... Go figure.
    
     These byte formats are already defined in the Arduino global name space.
  */
  
  modbus_configure(&Serial3, 9600, SERIAL_8N2, 1, 4, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) is not needed but allows for easy update of the
  // port variables and slave id dynamically in any function.
  modbus_update_comms(9600, SERIAL_8N2, 1);
  
  pinMode(LED, OUTPUT);
}

void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
  
  modbus_update();
  
  holdingRegs[AB] = 45; // update data to be read by the master to adjust the PWM
  
  analogWrite(AC, holdingRegs[2]>>2); // constrain adc value from the arduino master to 255
  
  /* Note:
     The use of the enum instruction is not needed. You could set a maximum allowable
     size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
     holdingRegs[] by "Index" addressing.
     I.e.
     holdingRegs[0] = analogRead(A0);
     analogWrite(LED, holdingRegs[1]/4);
  */
  
}
i am using above codes in my mega side .
but my question is:
when i set the both side to 9600  baud rate , then i can sucsessfully send the request and give response from slave .but if i chance the parity type  or  numbers  of  stop bits in masters side , there will be no difference in results . i mean  it works successfully  in every situation and every stop bit number and every parity type,
is not this strange ?
hope some one give a reply even saying HELLO  :)  

westfw

Sending two stop bits is just a timing issue.  Any modern UART should still be able to receive either one or two stop bits.

It's also very common for devices to ignore parity errors.

So it isn't that strange that it still works even when you change those values.

pylon

Quote
when i set the both side to 9600  baud rate , then i can sucsessfully send the request and give response from slave .but if i chance the parity type  or  numbers  of  stop bits in masters side , there will be no difference in results . i mean  it works successfully  in every situation and every stop bit number and every parity type,
In this case I guess you're using an USB to RS485 adapter that uses the CH340/341 chipset. At least the drivers for Windows and Linux simply ignore the parity and stop bits settings. On the Linux side this is because no official documentation for that chipset exists and the current driver got it's information from reverse engineering the Windows driver. Get an adapter with a working chipset (p.e. FTDI) or create your own by using a USB to serial adapter (of course with a different chipset than the CH340/341) together with a UART to RS485 adapter.
I eliminated all CH340 version from my toolset because of that undocumented and silently denying functionality.

emir22

In this case I guess you're using an USB to RS485 adapter that uses the CH340/341 chipset. At least the drivers for Windows and Linux simply ignore the parity and stop bits settings. On the Linux side this is because no official documentation for that chipset exists and the current driver got it's information from reverse engineering the Windows driver. Get an adapter with a working chipset (p.e. FTDI) or create your own by using a USB to serial adapter (of course with a different chipset than the CH340/341) together with a UART to RS485 adapter.
I eliminated all CH340 version from my toolset because of that undocumented and silently denying functionality.
no difference i



Thank you very very much PYLON

firstly  i am using  windows 7  laptop . The converter that i used for has used PL2303 chip .is it the same CH340?

to be honest i do not know if  : having no issue in connecting in  changing serial setting , is an advantage or disadvantage ? because i am able to use it in each situation .  i want to add the other question   : i will use mega as master  (no PC anymore )and uno or uno s  as slaves  in the feature . so   being MEGA as a master , will it be such PC  that have no difference in using any parity or stop bit? 

emir22

Sending two stop bits is just a timing issue.  Any modern UART should still be able to receive either one or two stop bits.

It's also very common for devices to ignore parity errors.

So it isn't that strange that it still works even when you change those values.

Hello WESTFW

thank you very very much for your replying . i am not familiar so completely with serial communication .but i do know that in the digital world  1 0 0 0 0   is not the  same 0 1 0 0 0 .  every bit has a special rule in digital world .so it was interesting to me that how can a digital device act as if there is not difference even if you change the bits .i suppose that these bits has are not real bits and has no effect on real datas .but on the other hand im confused that  how can my pc underestand that which bit is parity bit  or stop bit or how much bit stop is there . so what do you think if i dont use PC as master anymore but instead MEGA for master .then will the MEGA act as PC ? nor difference for stop bit and parity ?

westfw

A UART communications link has an "idle" state (1.)  You wake up the receiving UART by sending a "start bit" (0); the receiver waits for the start bit to end (counts some number of internal clocks), and then starts shifting in data bits.  After 7 or 8 (typically) data bits, the transmitted might send a parity bit as well.  At that point, the receiving UART is done receiving the character.  The "stop bits" are the "guaranteed return to idle state" in between characters, and aren't really necessary to the receiver.  In "ancient times" some mechanical receivers may have needed two bit times between characters to get ready for the next character, but any UART made in the last 20 years or so doesn't really care if there are one, two, or even more stop bits.

Now, for parity, there are a couple of paths:

  • The receiver is configured for parity, but the transmitter isn't, or sends the wrong parity.  This means tha the receiving uart will detect "parity error" when it reads the character.  But it's the responsibility of the receiving uart driver to decide what to do with that error, and most drivers (including the arduino code) simply ignore the error and pass whatever data they did receive to the application.  (we could have a discussion about what it SHOULD do - it's pretty unclear.  I think passing the data is the best choice.)
  • The receiver is configured for NO partity, but the transmitter is sending parity...

  •  2a) For transmitting 7bits+parity (8 bits total), with the receiver configured for 8bits, the uart will actually receive the "wrong" character if the parity bit is one.  You'll get 0x8d instead of 0x0d, for example.  Except most higher-level code is expecting ASCII and will routinely strip off the 8th bit anyway.  So usually, things continue to work.
  •  2b) For transmitting 8bits+parity (9bits total) - the parity bit will appear where there ought to be a stop bit.  If it's a one, then it in fact looks like a stop bit, and so nothing happens.   If the parity bit is 0, it should cause what's known as a "framing error."  Like a parity error, this is something that the driver has to handle, and most don't.  Usually the 8 data bits are just passed to the application, and nothing ever "notices" that there was a parity bit there.



This may sound terrible - "isn't the parity bit supposed to help you detect transmission errors?"  But it seems that:
  • software that cares about errors will have some higher-level error checking - a CRC or checksum, and it would rather actually get "bad" characters" than not see as many characters as it's expecting.
  • If you have a user, they'd probably rather see the wrong character echoed (and then fix it manually) than have either a special error character (still needs fixing) or nothing at all.
  • byte parity isn't actually a very good way to detect the types of errors that actually occur in serial transmission.
  • the "robustness" that you get by ignoring parity errors is "better" than the "accuracy" you might obtain by rejecting bad characters.  (huh.  Sort of like communicating with someone who isn't fluent in your language - am I going to say "you misspelled this word, so I can't understand you"?  No - I'll do the best I can to understand you anyway.)



wbeppler

i try to make a short answer:
1. if 1, or 2, or some uart can make 1.5 stop-bit, it makes no sense, the trigger to read is the start-bit
2. some serial 7 data has the parity-bit not at the end of 7 bit, it's after the 8 bit and it's not ok but it is so
3. it it works by your setting it never mind to check the one byte because you use a protokol modbus and this detects lost bits better than parity check, there is a CRC, it means there is a checksum over oll the bits and the sender and the receiver calculate this checkbyte, if it is different the block repeats

i hop it's helpful and correct enought

westfw

It turns out that I'm partially wrong.   The AVR UART driver claims that it will ignore characters that have the wrong parity.
(SAM and SAMD drivers ... I'm not sure; there's a separate interrupt for errors.)

Another way to look at it is to say that the the transmitter sends 12 bits:
S12345678PXX
(that's in transmission order, not "normal" format for a binary number.)
For the receiver to decide that there is no error, S must be 0, X should be 1, and P should be a correct parity bit.
Most driver/application combinations will only use bits 1-7, and ignore wrong vaues of the other bits.

el_supremo

There isn't a 9th bit for parity. If parity is used it is the high order 8th bit of the 8 bits of data.

Pete
Don't send me technical questions via Private Message.

westfw

Quote
There isn't a 9th bit for parity. If parity is used it is the high order 8th bit of the 8 bits of data.
I'm not sure what 8E1 has come to mean, but the AVR is definitely capable of generating 8 bit data frames PLUS an additional parity bit...  (section 19.4 "Frame Formats"):

el_supremo

The AVR can be capable of transmitting 9 bits but 8E1 means 8 data bits, of which one is an even parity bit, plus one stop bit. i.e. there are actually only 7 data bits plus the parity. When you transmit 8N1 it allows you transmit the full 8 bits of data but there won't be any parity protection. 8E1 or 8O1 only sends 7 bits of data plus a parity bit.

Pete
P.S. @westfw do you have a link to that AVR document? I can't find it.
Don't send me technical questions via Private Message.

westfw

Quote
8E1 means 8 data bits
I'm not convinced.  Do you have a reference?
In arduino, the driver has
Code: [Select]
#define SERIAL_8E1 0x26
which goes directly to UCSR0C, and means "8 bits plus parity."
The IBMPC, which originated the "8E1" syntax, used an 8250 UART, and its data sheet also says:


(note "between")

Almost all of the actual USE of parity in serial communications dates back to when you mostly only used 7 data bits, and the choices were "8 data bits with no parity" (8N1) and "7 bits with parity" (7E1)

emir22



HELLO 


@ WESTFW

@ WBEPPLER

@ L_SUPREMO


thank you all very much for your detailed and useful information and i got very info about the serial communication  using your clues and notes .

@ WESTFW   thank you for your explanation of every possible situation and explaining what happens in every state . it was very clear and was what i need to know .thanks very much  again for your time and effort

may be sound crazy my question ,excuse me but :

 if  8E1  means 1START   + 7 DATA  + 1 EVEN PARITY(as MR Pete said)  + 1 STOP =10 bit ,then we will have the only 7 bit data that is nearly the half of an 8 bit data value .(256/2=128 max) then if i underestand truely , should we send the two byte of 7 bit ? in order to have an 8 bit DATA?

 

i do not know

emir22

OR may be you mean 7 bit   that  is started by 0  , then we will have 8 bit (256) .

 STRART BIT + 0 1 2 3 4 5 6 7 (8 BIT DATA) + 1 PARITY + 1 STOP = 11 BIT ?

el_supremo

I seem to have been labouring under a delusion for lo these many years!
From the 328P detailed datasheet:
Quote
A frame starts with the start bit, followed by the data bits (from five up to nine data bits in total): first the
least significant data bit, then the next data bits ending with the most significant bit. If enabled, the parity
bit is inserted after the data bits, before the one or two stop bits.
So it seems that 8N1 transmits 8 bits plus start+stop . 8E1 and 8O1 transmit 8 bits, parity and start+stop.

Pete
Don't send me technical questions via Private Message.

Go Up