CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Interesting UART situation

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
FISH6942



Joined: 03 Feb 2006
Posts: 13
Location: Minnesota

View user's profile Send private message

Interesting UART situation
PostPosted: Fri Mar 03, 2006 3:16 pm     Reply with quote

I came across an interesting situation with an RS-485 app I'm putting together. I'm using the 9th bit and setting it for the first byte of the packet and clearing it for the rest of the packet.

What I found is that if I continually clear the 9th on every iteration of the loop that sends out the packet, the start bit of the second byte gets stretched out (should be 4uS long, ends up being around 7.2uS instead). All other bits in all other bytes appear to be correct. If I write the 9th bit low only once during the loop then the problem goes away.

(I apologize for the formatting, I copied it from my editor and the indenting and spacing is all goofed up... any suggestions for next time?)



#case // Turn on case sensitivity

#device PIC18F4520
#device *=16 // Enable generation of 16 bit pointers

#fuses HS,NOWDT,NOPROTECT,NOLVP,NOPUT,NOBROWNOUT,NODEBUG,NOPBADEN

#define DEBUG_MODE // Uncomment to use ICD2 as debugger
#ifdef DEBUG_MODE
#fuses DEBUG
#device ICD=TRUE
#endif

#include "4520_REGS_PINS.h"

#define XTAL_SPEED 20000000
#use delay( clock = XTAL_SPEED ) // required for delay_ms()


void main() {
bool led;
int8 bytes_sent_cntr;
int8 packet_size;
int8 data_to_send[3];


// ** Set up the chip I/O registers
trisA = 0x0C; // A2:A3 input, others output
portA.whole = 0x30; // Initialize A outputs

trisB = 0xFF; // B0: buttonPress, B1 & B2: tach inputs,
// B3 & B4: limit switches, B5: auto-level set,
// B6 & B7: PGM
portB.whole = 0; // Initialize B outputs

trisC = 0xD0; // C6/TX, C7/RX are used for UART, configure
// both as input. C4/SDI is input.
// C0, C1, C2, C3, C5 are output
portC.whole = 0; // Initialize C outputs

trisD = 0xC0; // D6 & D7 inputs, others outputs
portD.whole = 0x30; // SHUTDOWN pins inactive (high)

trisE = 0; // DEBUG outputs
portE.whole = 0;

adcon0 = 0; // Disable A/D converter
adcon1 = 0x0F; // Configure all I/O as digital

// ** initialize the serial port
baudcon = 0x00; // no autobaud, no wake-up, 8-bit baud rate generator
txsta = 0x46; // high baud rate enabled, asynch mode, 9-bit mode
rcsta = 0xC0; // addr detect disabled, 9-bit mode, enable serial port
spbrg = 4; // 250k baud, xtal = 20MHz, high baud rate mode
// desired baud rate(BR) = (Fosc/[16(n+1)]
// n = 20,000,000/[(250,000)(16)] -1
// n = 4
spbrgh = 0; // ignored in 8-bit baud rate mode


// ** enable trasmit mode, set '485 driver lines
txen = 1;
cren = 0;
PIN_NOT_RECV_EN = true;
PIN_XMIT_EN = true;

// ** initialize test data
data_to_send[0] = 0x55;
data_to_send[1] = 0x55;
data_to_send[2] = 0x55;

packet_size = 3;


for (EVER) {

bytes_sent_cntr = 0;
tx9d = 1; // set address bit

// once the button is pressed, sent the packet of data
if ( PIN_PUSH_BUTTON == 0 ){

do {
// wait for txreg to empty
while( txif == 0 ) {}

txreg = data_to_send[ bytes_sent_cntr ];

tx9d = 0;

//works with the following two lines in place of the previous line
// if( bytes_sent_cntr == 0 )
// tx9d = 0; // clear address bit

} while ( ++bytes_sent_cntr <= ( packet_size - 1 ) );

} // end of if

while( PIN_PUSH_BUTTON == 0 ) {} // wait for button to be released

} // end of for (EVER)

} // end of main()
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Mar 03, 2006 4:44 pm     Reply with quote

Quote:
(I apologize for the formatting, I copied it from my editor and the indenting and spacing is all goofed up... any suggestions for next time?)
On posting your message use the Code button to place markers around the text that you want keep preserved.

Quote:
What I found is that if I continually clear the 9th on every iteration of the loop that sends out the packet, the start bit of the second byte gets stretched out (should be 4uS long, ends up being around 7.2uS instead). All other bits in all other bytes appear to be correct. If I write the 9th bit low only once during the loop then the problem goes away.
Check out the hardware errata for your chip, there are two nasty errors related to the UART and 9-bit transmissions that might be related to your problem.
An easy to perform test would be to use the CCS supplied routines for serial communications and see if the problem still exists. The CCS routines often contain workarounds for known chip problems.

Code:
#device *=16 // Enable generation of 16 bit pointers
You don't need this line, PIC18 processors always use 16 bit pointers.
FISH6942



Joined: 03 Feb 2006
Posts: 13
Location: Minnesota

View user's profile Send private message

PostPosted: Sat Mar 04, 2006 9:39 am     Reply with quote

ckielstra - You are correct, the eratta describes the problem. I'll go with their suggested fix. It was really baffling as to why this was happening.

Thanks!!
FISH6942



Joined: 03 Feb 2006
Posts: 13
Location: Minnesota

View user's profile Send private message

PostPosted: Mon Mar 06, 2006 3:31 pm     Reply with quote

After looking at the errata, I reworked the code and got it to work properly for my application. However, I only need to write to the 9th address bit once during packet transmission. I found that if I continually write to the 9th bit that every start bit after the first will be stretched to about 6.8uS (should be 4.0uS).

What the errata suggests is to only write to the 9th bit IMMEDIATELY after the txif bit gets set (txif == 1 => txreg is ready for another byte). This is seems curious because even if txreg is empty, the transmit shift register may still be shifting out data. The errata goes on to say that the problem stems from "any write to the TXSTA register(which is where the 9th bit is located) will result in a reset of the baud rate timer which will effect any ongoing transmission".

I also tested a version that monitored the trmt bit so that new data was only loaded into the txreg once the shift register was empty. This worked ok except for a delay of a few uS between each stop-start bit.

Here is the new code. Any comments would be welcome.

Code:


#case                   // Turn on case sensitivity

#device PIC18F4520

#fuses  HS,NOWDT,NOPROTECT,NOLVP,NOPUT,NOBROWNOUT,NODEBUG,NOPBADEN

#define DEBUG_MODE   // Uncomment to use ICD2 as debugger
#ifdef DEBUG_MODE
   #fuses  DEBUG
   #device ICD=TRUE
#endif

#include "4520_REGS_PINS.h"

#define XTAL_SPEED 20000000
#use delay( clock = XTAL_SPEED ) // required for delay_ms()


void main() {
   int8 dummy;
   int8 bytes_sent_cntr;
   int8 packet_size;
   int8 data_to_send[4];


   // ** Set up the chip I/O registers
   trisA          = 0x0C;     // A2:A3 input, others output
   portA.whole    = 0x30;     // Initialize A outputs
                             
   trisB          = 0xFF;     // B0: buttonPress, B1 & B2: tach inputs,
                              // B3 & B4: limit switches, B5: auto-level set,
                              // B6 & B7: PGM
   portB.whole    = 0;        // Initialize B outputs

   trisC          = 0xD0;     // C6/TX, C7/RX are used for UART, configure
                              // both as input. C4/SDI is input.
                              // C0, C1, C2, C3, C5 are output
   portC.whole    = 0;        // Initialize C outputs

   trisD          = 0xC0;     // D6 & D7 inputs, others outputs
   portD.whole    = 0x30;     // SHUTDOWN pins inactive (high)

   trisE          = 0;        // DEBUG outputs
   portE.whole    = 0;

   adcon0         = 0;        // Disable A/D converter
   adcon1         = 0x0F;     // Configure all I/O as digital

   // ** initialize the serial port
   baudcon  = 0x00;  // no autobaud, no wake-up, 8-bit baud rate generator
   txsta    = 0x46;  // high baud rate enabled, asynch mode, 9-bit mode
   rcsta    = 0xC0;  // addr detect disabled, 9-bit mode, enable serial port
   spbrg    = 4;     // 250k baud, xtal = 20MHz, high baud rate mode
                     // desired baud rate(BR) = (Fosc/[16(n+1)]
                     // n = 20,000,000/[(250,000)(16)] -1
                     // n = 4
   spbrgh   = 0;     // ignored in 8-bit baud rate mode


   // ** enable trasmit mode, set '485 driver lines
   txen = 1;
   cren = 0;
   PIN_NOT_RECV_EN = true;
   PIN_XMIT_EN     = true;
 
   // ** initialize test data
   data_to_send[0] = 0x55;
   data_to_send[1] = 0x55;
   data_to_send[2] = 0x55;
   data_to_send[3] = 0x55;
 
   packet_size = 4;

   
   for (EVER) {

      // once the button is pressed, sent the packet of data
      if ( PIN_PUSH_BUTTON == 0 ){

         bytes_sent_cntr   = 0;
         tx9d              = 1;        // set address bit

         do {
            txreg = data_to_send[ bytes_sent_cntr ];
               
            dummy++;    // allow time for txif to get cleared after
                        // writing to txreg

            while( txif == 0 ) {}        // wait for txreg to empty
     
            if( bytes_sent_cntr == 0 ) // ** problems if this "if" is removed **
               tx9d = 0;               // clear address bit
       
         } while ( ++bytes_sent_cntr <= ( packet_size - 1 ) );
      }  // end of if()
        
      while( PIN_PUSH_BUTTON == 0 ) {} // wait for button to be released
 
   }  // end of for(EVER)

}  // end of main()



Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group