Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Quick RS232 Query (16f1827)

Status
Not open for further replies.

Dakta

New Member
Just testing a new build max232 <-> pic 16f1827 pcb I've had made, found a strange issue.

Board initialises okay, and my demo program to just send a single byte to the pc worked. So I made the program a bit more complex and tried to send a sentence...

"Welcome to the world little microcontroller!"

Anyway about half the data was garbled, so I checked the baud rates, checked the registers and am still no better for it. I did think it was a baud rate issue as asynch is so sensitive to it, I know with a 4mhz crystal I can expect some error (0.16% with a baud of 9600) but this is a little much ;)

Anyway, I've not solved the problem but I have shed a little light on it - I set up two examples:


Program one:

Send two bytes in sequence, 127 and 128, with a 500ms gap between each byte, continuously.

Code:
 uart1_write(128);
    delay_ms(500);
    uart1_write(127);
    delay_ms(500);

Result?

128 126 128 126 128 126 ...-> and so forth

Program Two

Count from 0 to 255 (sending each number to the pc) with a 50ms gap.

Code:
while (1) {
   uart1_write(counter);

     counter++;
    
    delay_ms(50);
}

Result: 00 00 02 02 04 04 06 06 08 08

It's almost like the LSB is stuck in a rut!

Has anyone any suggestions? Just spent a lot of time googling because I wanted to figure it out but drawing a bit of a blank now. No doubt a lot of tomorrow will be spent in the baudrate part of the datasheet (minds gone too fuzzy now).



Sorry if this post is a bit breif, only got internet connectivity for 5 minutes but if there's anything needed to know I'll post it up asap.
 
Last edited:
...I can expect some error (0.16% with a baud of 9600) but this is a little much ;)

Theoretically, you can have as much as a total of 5% frequency mismatch (with one start bit, 8 data bits and 1 stop bit) before you start running into errors. Unless your BRG is way off, I really don't think that would be your problem. However, your symptoms match a BRG problem.

Can you show us the code to set up your UART?

Perhaps check that you are using the same data format on each end? e.g. 1 start bit, 8 data bits and 1 stop bit.
 
Last edited:
It looks like you have the two ends configured differently (PC = no start bit). I suggest setting both ends to 1 start, 8 data and 2 stop bits.

Mike.
 
Can you show us the code to set up your UART?

Course I can :)


Perhaps check that you are using the same data format on each end? e.g. 1 start bit, 8 data bits and 1 stop bit.

This is the sort of simple explanation I'm hoping is behind the problem. Unfortunately I don't think it's this specifically though, because I've set up both sides to use 8 bit data, one stop bit, no flow control (bare in mind I want to keep this simple...providing simple works of course). I even wrote my own quick and dirty terminal in vb.net to interface so I had then opportunity to set the comms up exactly as they should be.

Software unlike hardware is flexible, so my priority really is ruling out a hardware issue (loopback test with a paperclip across the max232 pins worked allright). Simulations in proteus using my source code and schematic work flawlessly (well the data is received okay).


Anyway, enough chitchat - here's the config:

Code:
//set up alternate pin config
APFCON0.B7 = 1; //RX is on RB2
APFCON1.B0 = 1; //TX is on RB5

RCSTA.B7 = 1; //serial port enabled
RCSTA.B6 = 0;   //8 bit data reception on

TXSTA.B2 = 1;     //BRGH = 1
TXSTA.B6 = 0;     //select 8 bit transmission
TXSTA.B5 = 1;     //transmit enabled
TXSTA.B4 = 0;     //asynch mode on

//other
baudcon.sckp = 0; //ENSURE DO NOT INVERT DATA
baudcon.b3  = 0; //8 BIT TIMER SELECTED (BRG16 = 0)
SPBRG = 25;
UART1_Init(9600);

So to cut it short:

clock speed (as per crystal) is 4mhz
SPBRG = 25
BRGH = 1
BRG16 = 0

I got these settings from the datasheet, and like you i'd expect a bit less errors for my .16% ;)

Still its a puzzling one. Major concern really is that it could be hardware related though i extemely doubt it as i've built similar schematics before without issues (wish i still had access to the source!).

What might be worth noting, though I did do a search to see if it would be an issue before i did this (and received positive responses) was I used non-polarised 1uf radial caps for the max232. Since my pc is receiving data though i don't think level shifting is the issue though.

anyway thanks a lot for the suggestions so far, I am 100% sure it's going to be something simple. As simple is the only thing I can't put my mind to.
 
Last edited:
because I've set up both sides to use 8 bit data, one stop bit, no flow control

I don't know the chip you are using but all the pics that I've used always send a start bit. I also advise using 2 stop bits as this allows longer for recovery between bytes.

Edit, Shouldn't you set the baud rate before the other registers? Normally UART1_Init() would setup all the registers to a default. Actually, why are you calling the library function anyway?

Mike.
 
Last edited:
Hi Dakta you have your BRG set wrong.

The examples in the datasheet (SPBRG = 25) are based on a 16MHz crystal. Because you are using a 4MHz crystal then you will need to adjust your SPBRG according to the equation.


EDIT: bear with me, I just noticed that your BRGH and BRG16 bits are different from the example in the datasheet. Your BRG is fine.

Try and remove the library reference, like Pommie suggests, and just do it all in your own code.
 
Last edited:
Experimentation is the simple answer, I've tried with and without, i've even got rid of the library calls completely and used assembly directly to fill the transmit register with bytes. So what's result IS a bit messy.

I don't know if it's got anything to do with it whatsoever but the chip i've been burning all evening has just given up the ghost.
 
Only done one test (I'll do a few more to verify) but it looks like a replacement PIC has done the trick.
 
Only done one test (I'll do a few more to verify) but it looks like a replacement PIC has done the trick.

Nice. Strange, but nice.
 
Right, I've had a chance to do some testing.

Transmitting seems to be sorted, as long as I don't let the compiler set the registers itself using the libraries I can get good quality communication... why that is I don't know as all sources from mikroc suggest i shouldn't have to (and tbh i shouldn't, ive used the libraries in the past without so much hassle).

What I have done, is rewritten the program from ground up to do some testing, and ive found that transmitting is virtually 100% good now. Thanks.

What I have realised though is that there doesn't seem to be any receiving done by the PIC, I don't have a scope but I do see the voltage drop at the right pin when data is being transferred to the pic, but whether i poll the rx interrupt flag manually, or enabled interrupts fully, it never seems to trigger.

Configuration seems okay, 8n1 being selected, brgh etc set up manually and the pc is receiving data okay - the pic just doesn't seem to know when it's received something.

Full code listing supplied, in this version I poll the interrupt flag (datasheet says it gets set regardless of whether interrupts are enabled....

Code:
unsigned char counter = 0;


void main() {

//configure chip
APFCON0.B7 = 1; //set alternate pin config so tx and rx go to right pin
APFCON1.B0 = 1; //as schematic was originally made for 16f88 (virtually pin compatible)
ANSELB.B2 = 0; //set pin digital - just to be sure
ANSELB.B5 = 0; //and again, just one less thing to worry about
TRISB.B2 = 1; //RX is input
TRISB.B5 = 0; //TX is output
TRISA.B3 = 0; //LED is output

SPBRG = 25; //set up baud rate generator 
BAUDCON.BRG16 = 1; //^^
TXSTA.BRGH = 0; // ^^
TXSTA.SYNC = 0;
RCSTA.SPEN = 1; //serial port enabled
TXSTA.TXEN = 1; //transmit enabled
TXSTA.TX9 = 0; //8 bit transmission 
RCSTA.CREN = 1; //enable receiver
RCSTA.RX9 = 0; //8 bit reception enabled

//light up led temporarily just to show it works

   LATA.B3 = 1;
delay_ms(750);
lata.b3 = 0;
delay_ms(750);
LATA.B3 = 1;
delay_ms(750);
lata.b3 = 0;

//enter main loop


while (1){

if (Pir1.rcif == 1) { //if data has been received
counter = RCREG; //grab data
LATA.B3 = 1; //put led on to show data has been received
delay_ms(750); //hold led on a short while
lata.b3 = 0; //disable led, we're done
}



}


}

So, am i just being manically unlucky lol.
 
Last edited:
Because I've not solved the problem, I have rewritten the project to try and tidy things up.

(It's easy to get cluttered when you're making a lot of experimental tweaks in the config).


Software scope:

To print 'Hello:' to test transmission from PIC to terminal upon power-on, then very PIC is receiving data by echoing all received data back to terminal.


Revised code listing:

Code:
unsigned char RX_Data = 0;



void main() {

//configure chip
TRISB.B2 = 1;      //RX is input (RB")
TRISB.B5 = 0;      //TX is output (RB5)
TRISA.B3 = 0;      //POWER LED Pin is output
APFCON1.B0 = 1;    //alternate pin configuration - TX is now on RB5
APFCON0.B7 = 1;    //alternate pin configuration - RX is now on RB2
ANSELB.B2 = 0;     //rb2 is digital
ANSELB.B5 = 0;     //rb5 is digital


//set up EUSART
//FOR BAUD 9600 WITH 4MHZ CRYSTAL - SYNC =0, BRGH = 1, BRG16 = 0;
SPBRGH = 0;
SPBRGL = 25;    //SPBRG = 25
TXSTA.BRGH = 1; //BRGH SET
BAUDCON.BRG16 = 0; //BRG16 IS 0
RCSTA.SYNC = 0;   //SYNC CLEARED
RCSTA.SPEN = 1;    //SERIAL PORT ENABLED
RCSTA.CREN = 1;    //CONTINUOUS RECEIVE ENABLED
TXSTA.B6 = 0;      //8 BIT TRANSMISSION SELECTED
TXSTA.B5 =1;       //TRANSMIT ENABLE BIT SET
TXSTA.B4 = 0;      //ASYNCHRONOUS MODE SET

//should be ready to roll?



delay_ms(100);   //allow settling time




 uart1_write_text("Hello: ");    //test transmission
 
 //now test reception:

while (1){

if (uart1_data_ready() == 1){
RX_Data = uart1_read();
 uart1_write(RX_Data);
}


}


}

Key things to note:

- when using compilers own serial port initialisation library, baud rate is slightly out and this half of received data from PIC is garbled. As a result the serial port baud rate has been configured manually which corrects the issue.




Result of program:

'Message "Hello:" is correctly received by terminal upon power on. No data is echoed back when sent to PIC.


Clues: RX_Data (the variable holding received data and retransmitted back to the terminal program) is initialised with a value (0). The fact the terminal never receives a zero suggests that the uart1_data_ready() function is not being called.

As a result the physical schematic has been checked. The alternate pin configuration has been checked, the baud rate settings seem to be fine for transmitted data so i assume fine vice versa. Applying a voltmeter to the RX pic pin shows a momentary dip in voltage when a stream of data is sent (idle high) suggesting the pic is configured to operate correctly and that the circuit is healthy. The received enable bit has been checked. Finally the code has been altered to add a data received interrupt, and check the rx interrupt flag for data reception rather than use the libraries provided with the compiler. The result was unchanged.

The 4mhz crystal oscillator has been replaced once again with one from a seperate batch.

I'll be honest, I do not know why the compilers libraries mess up the baud rate, I do not know why setting up the serial port by library or manually does not allow the reception of data though resolves the issues regarding data transmission from the PIC.

As a final ditch, I created a seperate project with the same goals except using software_uart libraries rather than hardware module. The result was 99% the same however if I sent a hundred characters at the same time from the terminal, the pic would occasionally echo one or two characters back only (and they would be corrupt).

I don't know if anyone has any ideas, I'm seriously thinking of trying another compiler in case there's a bug with the definitions or something, but I don't really know what else to try.

I've also checked the microchip website for an errata which may mention if there are any issues regarding the EUSART module of this chip. This also drew a blank.

Any thoughts?
 
Why use the library functions when the register variety is just as simple,
Code:
    if(RCIF){
        RX_DATA = RCREG;
        Send(RX_DATA);
        RCIF=0;
     }


Send(unsigned char dat){
    while(!TXIF);
    TXREG=dat;
}

Doing the above will remove any doubts over the library functions.

Mike.
 
I actually tried something similar to that, i polled the rcreg register and if i got a non-zero result it would flash the led.

I can't remember exactly what happened but i dont think the answer was a lot. I'll try your version later on when i get back from work and report.
 
pacing...

It's too often overlooked... send a character, give the other end time to process it, Then send the next. Add a pacing delay between characters, start large, you can tune it later. If the first characters are ok, but later get corrupted, look for a bit level pattern indicating one end or the other is going out of timing. May I presume you're using a quality timing reference at both ends?

I like to start with $80, $01, $55 & $aa as test patterns to find speed/timing mismatches. I've written I2C & a variety of serial handlers, timing problems are best diagnosed by spreading everything out. Good Hunting... <<<)))
 
Just tried Pommie's suggestion (thanks bud) - unfortunately there is no change.

I've posted this on the MikroE support board, they too seem a little stumped though have told me the compiler should be fine. I'm a bit unsure as using their libraries to configure my uart to corrupt data seems as repeatable a test as any approach i've so far used to receive data.

In other words, i've never been able to so far succesfully transceive data, but any success with transmitting has only been acheived through manual config.

That said, might be a problem with the chip too. Ordered a 16f88 i'm going to try that.
 
Last edited:
The compiler sets the baudrate based on the PIC clock speed. You need to make sure the compiler knows your xtal value, which is set in the "edit project" dialog.

If you are not using a xtal but are using the internal RC osc, the freq needs to be correct, and if you have erased the osctune value etc the pic might be running a few percent off the correct frequency. :)

Ol'Phart gave some great advice, to just put a delay between each byte sent. This will make the baudrate match less critical as the receiver can re-sync to each new byte. And it removes the chance that you are loading bytes too quickly into the RCREG (which trashes data).
 
Last edited:
Thanks Mr RB, all good advice there...

Just one problem - I am using a crystal and it is set up in the compiler :eek:

I understand what you're saying with the spacing too - I had a go with this and using the library routines I did get a higher accuracy with time perdiods between transmitted bytes.

That said accuracy was still next to useless, I'd say we went from 50% accuracy up to about 75-80%.


When registers set up manually though, transmission from pic is fine. 100%. Even if I send a huge bunch of data at once. It doesn't care, I receive every byte (except for one in every 2-300 perhaps). Perfectly acceptable error rate imo.

So why not just configure it manually and leave it like that?

The reason: I still receive nothing. Nothing at all. And my system requires two way communication. The receive pin scoped sees data, the pins are set, the rcsta registers are set up, yet it does not see data. Unless I send a sequence of about 50 characters at the same time in which case it normally echoes back one, maybe two of them. Even then it gets them wrong.

This applies regardless of the way it's been configured, through library or manually.

I see two options, either try writing the test program in a different language or compiler to test this element, or trying a different chip. I've got some 16f88's on order which i'll try, failing that I will code the program in assembly.

If that all fails i'll look at the hardware but I am seeing correct signal fluctuations on the set rx and tx pins of the pic so I'm loathed to say this is where the problem is.
 
Last edited:
Weird.

If I install MAX232CPE the system goes deaf, transmits but doesn't receive.

Install MAX232N the system transmits but constantly receives - even when no data has been sent?
 
The above was with a 16f88.

Going back to a 16f1827, it doesn't matter which max232 is in, it will transmit but won't receive.

What the hell is with these chips? they're all crap! :mad: There's just nothing consistent here. How the heck can I even start to debug this?
 
Just watch the data on oscilloscope. Set another pin high a few ms before start of transmission so that you can easily trigger the scope and check the waveform(s). Then you should see if it goes through the max232 right, if the edges are square etc. Also checking the boosted voltage on the max could show something.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top