chipKIT® Development Platform

Inspired by Arduino™

Setting 9600,e,8,1 on the UART

Created Fri, 30 Dec 2011 22:31:05 +0000 by hybridnz


hybridnz

Fri, 30 Dec 2011 22:31:05 +0000

Hey guys,

I am working on a project which one of my UARTS require 9600,e,8,1 communication not 9600,n,8,1 (which is hard coded)

Over at the Arduino forum and doing some research the current Arduino serial libary doesnt support switching of stop bits, odd/even, parity. Only baud rate switching is availible.

They seem to be getting around this problem by low level switching the chip registers EG:

Serial.begin(9600);
UCSR0C = ( UCSR0C & ~_BV(UPM00) | _BV(UPM01) );

Is their a way to do this on the PIC/MAX32 board ?

thanks Josh


Mark

Mon, 02 Jan 2012 18:48:31 +0000

Josh

Sure, you can bypass the abstraction layer just the same as your Atmel example.

The register would be U1MODE

I am going to see about adding a routine to set the data bits, stop bits and parity

I think this would be a good addition to MPIDE and to Arduino. This question has come up before on the Arduino forum.

Mark


hybridnz

Tue, 03 Jan 2012 02:31:46 +0000

Thanks for your reply.

This would be really helpfull if it could be added the serial lib.

thanks again :)


hybridnz

Thu, 12 Jan 2012 02:48:37 +0000

Hi Mark/team

Do you know where I can find any more information on the registers and the code to use for setting Serial1 to 9600,e,8,1

Im pretty beginner to all this and dont have a lot of background in micros .. am a fast/willing learner however :)

Cheers in advance :)


WestfW

Thu, 12 Jan 2012 07:03:23 +0000

Well, there's the microchip documentation.

You ought to be able to put a

#include <plib.h>

at the top of your source to get the microchip peripheral library defines, and then do:

void setup() 
{ 
  Serial.begin(9600);
  UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS|UART_PARITY_EVEN|UART_STOP_BITS_1);

But this seems to result in an error:

ASCIITable.cpp: In function 'void setup()':
ASCIITable.cpp:32:109: error: invalid conversion from 'int' to 'UART_LINE_CONTROL_MODE'
ASCIITable.cpp:32:109: error:   initializing argument 2 of 'void UARTSetLineControl(UART_MODULE, UART_LINE_CONTROL_MODE)'

It looks to me like the various bitmasks are set up as a single enum, and C++ objects to ORing enums together (actually, to making the result back into an enum.) As it should, I think.

Seriously, Microchip?

It looks like casting it might work (don't forget the parens!):

UARTSetLineControl(UART1, (UART_LINE_CONTROL_MODE)(UART_DATA_SIZE_8_BITS|UART_PARITY_EVEN|UART_STOP_BITS_1));

I should note that I'm not sure if Serial1 maps to UART1...


hybridnz

Thu, 12 Jan 2012 22:19:31 +0000

After a bit of research with a friends help we came up with the same as above

#include <plib.h>
UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_EVEN | UART_STOP_BITS_1);

I have set it to UART2 just incase I kill comms to UART1 / Serial. I will just use UART2 / Serial3. to start with. I assume UART1 = Serial. and Serial1. and UART2 = Serial2. and Serial3.

however errors are the following while running the code above.

sketch_jan12a.cpp:5:19: error: expected constructor, destructor, or type conversion before '(' token
sketch_jan12a.cpp: In function 'void setup()':
sketch_jan12a.cpp:66:33: error: no matching function for call to 'HardwareSerial::read(int&)'
C:\Program Files\MPIDE\hardware\pic32\cores\pic32/HardwareSerial.h:104:16: note: candidate is: virtual int HardwareSerial::read()
sketch_jan12a.cpp:68:36: error: expected '}' at end of input

WestfW

Fri, 13 Jan 2012 03:54:03 +0000

You do have the call to UARTSetLineControl() inside your setup() function, right? And the #include statement outside? I get this error when I move the call outside of functions. Calls to functions MUST be inside of "code blocks" (usually: other functions.)


hybridnz

Fri, 13 Jan 2012 06:46:23 +0000

You do have the call to UARTSetLineControl() inside your setup() function, right? And the #include statement outside? I get this error when I move the call outside of functions. Calls to functions MUST be inside of "code blocks" (usually: other functions.)

I have

#include <plib.h>

at the top and put

UARTSetLineControl(UART2, (UART_LINE_CONTROL_MODE)(UART_DATA_SIZE_8_BITS|UART_PARITY_EVEN|UART_STOP_BITS_1));

inside

void setup()

I get

sketch_jan12a.cpp: In function 'void setup()':
sketch_jan12a.cpp:67:33: error: no matching function for call to 'HardwareSerial::read(int&)'
C:\Program Files\MPIDE\hardware\pic32\cores\pic32/HardwareSerial.h:104:16: note: candidate is: virtual int HardwareSerial::read()
sketch_jan12a.cpp:69:36: error: expected '}' at end of input

Im running this on MPIDE 0023

again thank you for your help on this :)


WestfW

Fri, 13 Jan 2012 08:28:53 +0000

I dunno. It worked (compiled) for me (Uno32), starting with the ASCIITable example sketch. You could try fiddling with that till you have a better idea what's going on. Is your sketch short enough that you can post the whole thing?


hybridnz

Fri, 13 Jan 2012 08:36:26 +0000

no worries, will keep bashing away at it. Im running this on a MAX32

More that some of the content is sensitive .. the unit im talking to has taken me a long time to reverse engineer.

Thanks for the help anyways Ive been doing quite a bit of poking around in the librarys because of this.


Ryan K

Tue, 14 Feb 2012 01:02:15 +0000

Hello All,

I would recommend changing the UxMODE (where x is the number of the UART you are using) register directly, it will give you more control over the functionality of the UART. For example if you wish to set the UART1 to 8 data bits, even parity and 1 stop bits you would use:

U1MODE = 0;

U1MODESET = (1 << 15) | (1 << 1); //15 is the on bit and 1 is the 8-data + even parity bit.

This is detailed in the PIC32MX datasheet located

UART Specific:

http://ww1.microchip.com/downloads/en/DeviceDoc/61107F.pdf

Full PIC32MX

http://ww1.microchip.com/downloads/en/DeviceDoc/PIC32MX_Datasheet_v2_61143B.pdf

Best Regards,

Ryan


hybridnz

Fri, 02 Mar 2012 20:41:36 +0000

Thanks for that! :) Will give it a wurl as the other ways are just not working for me


Ryan K

Sat, 03 Mar 2012 01:09:32 +0000

Oh whoops I almost forgot you probably have to add #include <plib.h>


palacio

Mon, 12 Mar 2012 10:48:48 +0000

Software UART written in C language for atmega8? i want to increase serial port of atmega8 (which have 1 serial port,where i need 3 serial port) by using software uart .plz help me.


keyword research ~ keyword tool ~ keyword tracking ~ affiliate elite


hybridnz

Sun, 29 Apr 2012 01:17:47 +0000

Hi guys,

I have dedicated my weekend to working this out .. I have successfully managed to make this work on the Ardiuno Mega 2560 without any issue however when I use any of the code about its just not switching it to even parity.

I am running a 'sniffer' on the line and its still transmitting 9600,n,8,1 not 9600,e,8,1

Again the sniffer confirms the Ardiuno Mega 2560 is infact running 9600,e,8,1 however not the Max32 with the below code or any other in this thread.

here is what I have

#include &lt;plib.h&gt;

void setup() {
// Setup serial monitor coms
Serial.begin(9600); 
Serial3.begin(9600);
U4MODE = 0;

U4MODESET = (1 &lt;&lt; 15) | (1 &lt;&lt; 1); //15 is the on bit and 1 is the 8-data + even parity bit.

}

Note i'm trying to send out and recieve commands on the last UART or RX3/TX3


hybridnz

Sun, 29 Apr 2012 03:33:24 +0000

Reading some of the spec.

bit 2-1 PDSEL&lt;1:0&gt;: Parity and Data Selection bits
11 = 9-bit data, no parity
10 = 8-bit data, odd parity
01 = 8-bit data, even parity
00 = 8-bit data, no parity

The synatax is still confusing me a little with the U4MODESET command.

Doing a lot of searching on this there doesnt seem to be a lot of info on this with examples :(

Does the 4 in U4MODESET = the last UART (serial3 in MPIDE)? Does setting Bit1 to 1 actually set it to binary '01' in U4MODESET = (1 << 15) | (1 << 1); ?


hybridnz

Mon, 30 Apr 2012 07:14:42 +0000

Persistance paid off.

This is the code that works for RX3/TX3 (Serial3) pins on Chipkit Max32

#include &lt;plib.h&gt;

void setup() {

// Setup serial monitor coms
Serial3.begin(9600);

// Switch UxMODE register -  15 is the on bit and 1 is the 8-data + even parity bit.

U5MODESET = (1 &lt;&lt; 15) | (1 &lt;&lt; 1);

}

Thanks to all that helped out and I hope this helps some one else out in their travels :)


hybridnz

Sun, 06 May 2012 00:58:46 +0000

Hmmm so it turns out with a lot of testing that unfortunately Im only half way there.

The above code works and allows the Max32 to transmit in 9600,e,8,1 however there is nothing on the recieve buffer at all.

I have tested with very back to basics code but all that I can get back is nothing.

The my send command is defanitely coming out of the Max32 in even parity. I have tested this with a sniffer on the line and the device im sending the command too is replying back correctly.

The Max32/pic32 just isnt recieveing.

I a friend and I have tested the hardware chain and voltages and they are all working 100%

Again we have tested the same code with a Ardiuno Mega 2560 and it works 100%

I have even attempted some more register 'SET' commands based on the UART documentation to force things like TX/RX on etc but with no luck there either. Im still using the SerialX.begin(9600) command (which I assume covers off a lot of the register setting in one command) and over lay the UxMODESET commands over the top.

I have also used a second Max32 and tested the code to make sure i hadn't blown the RX part of the silicon on mine. Same results with this one too.

Kind of at a real loss of what to try next :(

Any expert help would be much appriecated. I'm really keen on using the PIC32 for its out right grunt but I may have to change platforms to get on with this project.


les1943

Sun, 06 May 2012 21:23:26 +0000

Having enabled parity , what about parity error interrupts ,

INTERRUPTS The UART can generate interrupts reflecting the events that occur during the data communication. The following interrupts can be generated: • Receiver-data-available interrupt, signalled by UxRXIF. This event occurs based on the URXISEL<1:0> control bits (UxSTA<7:6>). Refer to 21.6.3 “Receive Interrupt” for details. • Transmitter buffer-empty interrupt, signalled by UxTXIF. This event occurs based on the UTXISEL<1:0> control bits (UxSTA<15:14>). Refer to 21.5.2 “Transmit Interrupt” for details. • UART-error interrupt, signalled by UxEIF.

  • This event occurs when any of the following error conditions take place: • Parity error PERR (UxSTA<3>) is detected • Framing Error FERR (UxSTA<2>) is detected • Overflow condition for the receive buffer OERR (UxSTA<1>) occurs All these interrupt flags must be cleared in software. Refer to 21.5.2 “Transmit Interrupt” and 21.6.3 “Receive Interrupt” for more information. A UART device is enabled as a source of interrupts through the following respective UART interrupt enable bits: • UxRXIE • UxTXIE • UxEIE

Can you see errors when reading UxSTA . can you loopback tx--Rx .

Not an expert...... :(


hybridnz

Mon, 07 May 2012 03:59:31 +0000

I'll look at the other stuff you've posted tonight ...

Can you see errors when reading UxSTA . can you loopback tx--Rx .

I have run up my code in a loop back (serial1->serial3)

The strange thing is, when I display it in the serial monitor .. with Even parity turned on for serial1 the byte array dump to the serial monitor (serial.print) display without being garbled .. which is very strange. I would execpt it to be inputting rubbish however it comes through as normal.

Here is the code with some random bytes sent

NOTE: I have not set the recieve port to even parity delibrately (its remmed out) you can enable it by unremarking U5MODESET command.

#include &lt;plib.h&gt;

byte inByte[4];

void setup() {

Serial.begin(9600); 
Serial1.begin(9600);
Serial3.begin(9600);

U4MODESET = (1 &lt;&lt; 15) | (1 &lt;&lt; 1);     //(Serial1)  15 is the on bit and 1 is the '8-data + even parity bit' (See PIC32 UART Datasheet for more detail).

//  U5MODESET = (1 &lt;&lt; 15) | (1 &lt;&lt; 1);     //(Serial3)  15 is the on bit and 1 is the '8-data + even parity bit' (See PIC32 UART Datasheet for more detail).

}

void loop() {
byte SendByte[] = {char(1), char(2), char(3), char(4)};

// Send message 
int i;
  for (i=0;i&lt;4;i++){
  Serial1.print(SendByte[i]);
}

// Recieve response

if (Serial3.available()){
int r;
  for (r=0;r&lt;4;r++){
  inByte[r] = Serial3.read();

   // Display in Serial Monitor

Serial.print(inByte[r], HEX);
  }
}
 
// Line feed and Delay
Serial.println("");
delay(1000);

}

les1943

Mon, 07 May 2012 12:44:35 +0000

I would hope the handler for serialx looks at errors before moving the buyte to the rx buffer , my documents seem to suggest the uartx has shared interrupts. I will see what a UNO32 makes of it..........

(its raining and my project is on a soak test....:) Les.

Edit... As uno has only 2 serial ports I tried 9600,e,8,1 on serial1 and looped Rx<->Tx, then serial.print the Rx all was OK with the 1234.

are parity errors being ignored on your example..

Edit 2... using monitor SEND and input to Serial1 at even parity , then sent it back to monitor !!! first(single) byte was OK second was wrong as you would expect,,, UNO seems to do even parity OK , not seen UxSTA errors what ever i do..


hybridnz

Mon, 07 May 2012 23:10:48 +0000

Thanks for you time on this! :)

I have pretty much found the same thing ..

Max32 TX1_9600,e,8,1 -> logic converter -> device accepts and replies back with correct data-> (sniffer (with correct isolated electronics) tapped off the line) -> logic converter -> Max32 RX3_9600,n,8,1 / or Max32 TX3_9600,n,8,1 (doesnt matter) and I get nothing.

Same chain and code works on ATMEL/Ardiuno mega so I dont think its my mosfet logic converter?

To be sure also I have removed the sniffer in case it was causing a voltage drop and the PIC32 just didnt like it.

In loop back mode and bridging UART 1 and 3 together with hookup wire I can send the command and recieve it but if I try change the even on the TX side theRX can read it either way. One thing I think my friend and I have confirmed is that the RX just automatically recognises the N,E or O parity regardless? because it will just work.

This is so weird! and I cant work out if I have multiple things going wrong or not.

I think im just going to have to get hold of an oscilloscope and check the signals and voltages to be sure.


Ryan K

Wed, 09 May 2012 03:50:58 +0000

Hello,

Okay if I understand your problem correctly, it has to do with detecting parity errors?

Let me start with the way MPIDE does UART communication. Whenever data is placed into the receive FIFO it generates an interrupt which pulls the data from the FIFO into an internal buffer. This is the buffer that Serial.available() checks to see if there is anything in it.

Okay the way the PIC32MX works with detecting parity errors is that it sets the 3rd bit in the UxSTA register when the data at the top of the receive FIFO violates the parity rules set in the UxMODE register. But looking at the loop back example you have posted below using Serial1 and Serial3, you will most likely never see the parity error by placing code in the sketch since the interrupt will have already cleared the FIFO. You'll need to place the check in the interrupt itself before the read in HardwareSerial.cpp in the doSerialInt() member function.

As for you having the receive UART with no parity and with the transmit UART with even parity you aren't going to get parity errors on the receiving side. You'll get framing errors (indicated by 2nd bit in the UxSTA) whenever the parity from the transmit would be low because the receive UART expects a stop bit there instead.

For Les, each UART has separate interrupts.

If you have any questions let me know.

Best Regards, Ryan K Digilent


hybridnz

Wed, 09 May 2012 06:53:41 +0000

Hi Ryan,

The issue is not so much with being able to read the parity error register but with the fact that the PIC32mx wont read the incoming line (RX3) (atleast to the buffer) there is 0 data. Parity or no Parity it just doesnt seem to want to work

This is confirmed again last night with some more testing. The Arduino is having no problem with the circuit. We are just starting to think that its a tollerance thing with the PIC32mx oppose the atmel chip.

I'm looking at replacing my circuit with a transciever IC instead of using mosfets to convert the logic level from 12volt to 3.3volt.


les1943

Wed, 09 May 2012 13:17:26 +0000

Hello again...

When I typed " shared ^ Interrupts " above post I missed the word Error ^, in the UNO's 32MX320 UART errors : parity, frame , over-run, raise the same interrupt request flag so call the same routine , as any parity method is not supported in makes sense that the sw should / will / may disregard the byte as it is an error and loose it... That is assuming UART errors are enabled for interrupts and are catered for ?

This could be different for 32MAX.... Iv'e not looked.

Extract from data sheet DS61143G-page 90 91 IRQ V# flags U1E – UART1 Error 26 24 IFS0<26> IEC0<26> IPC6<4:2> IPC6<1:0> U2E – UART2 Error 40 32 IFS1<8> IEC1<8> IPC8<4:2> IPC8<1:0>