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

Changing baud rates, parity, etc. at run time?

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



Joined: 21 Sep 2003
Posts: 8
Location: orlando, FL

View user's profile Send private message Visit poster's website

Changing baud rates, parity, etc. at run time?
PostPosted: Mon Feb 28, 2005 12:37 pm     Reply with quote

#use rs232(baud= 38400,xmit=PIN_C6,rcv=PIN_C7, errors)

This allows a single set of communication parameters to be configured. My problem is that our project uses dip switchs to select the communication parameters to be used.

Does PCH has some method to support this?

In the meantime I am attempting to write directly to the PIC UART registers to modify the configuration. I believe I may have a problem when modifying the parity or data size without the PCH routine's knowledge.

Any ideas?
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Feb 28, 2005 12:51 pm     Reply with quote

Joe,
I had this requirement in one of my projects. I had a eight DIP switch and used an eight input mux chip to scan the switches and store the settings (set flags), then I executed the appropriate #use RS232 statement etc..

You can use (reuse) the RS232 statement multiple times in the code and change the settings on the fly whenever it is required. There is a command to change just the baud rate (SET_UART_SPEED()) for the internal UART if that's all you need to change.

That approach requires 4 pins. Another option to save pins is using a Phillips I2C expander chip to get the DIP switch settings via I2C.
Joe Porthouse



Joined: 21 Sep 2003
Posts: 8
Location: orlando, FL

View user's profile Send private message Visit poster's website

PostPosted: Mon Feb 28, 2005 1:23 pm     Reply with quote

Thanks for the info. I did not see the SET_UART_SPEED() functon before.

I knew you could use multiple #use RS232 statements to use more then one serial port, but when I attempt to use multiple #use RS232 only the last listed in the file gets applied.
Code:

  // setup baud rate
  switch (a)
  {
    case 0:
      // 16Mhz,   1200 Baud
#use rs232(baud=  1200,xmit=PIN_C6,rcv=PIN_C7,parity=N,bits=8,errors)
      break;
    case 1:
      // 16Mhz,   2400 Baud
#use rs232(baud=  2400,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 2:
      // 16Mhz,   4800 Baud
#use rs232(baud=  4800,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 3:
      // 16Mhz,   9600 Baud
#use rs232(baud=  9600,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 4:
      // 16Mhz,  19200 Baud
#use rs232(baud= 19200,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 5:
      // 16Mhz,  38400 Baud
#use rs232(baud= 38400,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 6:
      // 16Mhz,  57600 Baud
#use rs232(baud= 57600,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
    case 7:
      // 16Mhz, 115200 Baud
#use rs232(baud=115200,xmit=PIN_C6,rcv=PIN_C7, errors)
      break;
  }


(I realise SET_UART_SPEED()could have been used in the above example, but my final application requires parity, etc. to also be selectable).

In my listing file it also shows that NO instructions were generated at each #use RS232. Can you post a copy of how you got this to work?
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon Feb 28, 2005 2:37 pm     Reply with quote

The way it is supposed to work is that the last #use RS232 encountered is the one in effect until the next #use RS232 is encountered. Your switch statement should work. The way the compiler works the code generated may not always be where the staement is executed. It usually is placed near the beginning of the listing. I will compile the code and see where it ends up.
fuzzy



Joined: 26 Feb 2005
Posts: 64

View user's profile Send private message

PostPosted: Mon Feb 28, 2005 2:42 pm     Reply with quote

// Set baud rate based on setting
// of pins B0 and B1
Code:

switch( input_b() & 3 ) {
   case 0 : set_uart_speed(2400);   break;
   case 1 : set_uart_speed(4800);   break;
   case 2 : set_uart_speed(9600);   break;
   case 3 : set_uart_speed(19200);  break;
}

this is a built in function of the compiler. there is an example in help.
Joe Porthouse



Joined: 21 Sep 2003
Posts: 8
Location: orlando, FL

View user's profile Send private message Visit poster's website

PostPosted: Mon Feb 28, 2005 7:21 pm     Reply with quote

The set_uart_speed only helps for baud rate, not parity.

Looking at my listing for the multiple #use RS232 shows no code generated other then the one RS232 stub at the beginning of the listing.

For now I am kinda going around the built in functions and doing it brut force with:
Code:

struct {
  short int RX9D;
  short int OERR;
  short int FERR;
  short int ADDEN;
  short int CREN;
  short int SREN;
  short int RX9;
  short int SPEN;
} RCSTAbits;
#byte RCSTA     = 0xFAB
#byte RCSTAbits = 0xFAB

struct {
  short int TX9D;
  short int TRMT;
  short int BRGH;
  short int unused3;
  short int SYNC;
  short int TXEN;
  short int TX9;
  short int CSRC;
} TXSTAbits;
#byte TXSTA     = 0xFAC
#byte TXSTAbits = 0xFAC
#byte TXREG     = 0xFAD
#byte RCREG     = 0xFAE
#byte SPBRG     = 0xFAF
#byte SPBRGH    = 0xFB0


union
{
  struct
  {
    short int serial_baud_sel:3;
    short int serial_even_parity:1;
    short int serial_odd_parity:1;
    short int serial_diag_mode:1;
    short int serial_2_stop_bits:1; // not supported, now card reader captive
    short int unused:1;
  }switches;
  char all;
} serial_configuration;


void configure_serial_port(void)
{
  // stop any current transmittion
  disable_interrupts(GLOBAL);
  tx_enable = FALSE;

  // get current serial selection DIP settings
  serial_configuration.all = (~not_serial_config_port & 0x7F);

  // Reset USART registers to POR state
  TXSTA = 0;
  RCSTA = 0;

  // setup baud rate
  switch (serial_configuration.switches.serial_baud_sel)
  {
    // case x:
      // 16Mhz,  300 Baud
      // TXSTAbits.BRGH = 0; SPBRG = 832; // Err +0.04%
      // Invalid SPBRG
    // case x:
      // 16Mhz,  600 Baud
      // TXSTAbits.BRGH = 0; SPBRG = 416; // Err -0.08%
      // Invalid SPBRG
    case 0:
      // 16Mhz, 1200 Baud
      TXSTAbits.BRGH = 0; SPBRG = 207; // Err +0.16%
      break;
    case 1:
      // 16Mhz, 2400 Baud
      TXSTAbits.BRGH = 0; SPBRG = 103; // Err +0.16%
      break;
    case 2:
      // 16Mhz, 4800 Baud
      TXSTAbits.BRGH = 1; SPBRG = 207; // Err +0.16%
      break;
    case 3:
      // 16Mhz, 9600 Baud
      TXSTAbits.BRGH = 1; SPBRG = 103; // Err +0.16%
      break;
    case 4:
      // 16Mhz, 19200 Baud
      TXSTAbits.BRGH = 1; SPBRG =  51; // Err +0.16%
      break;
    case 5:
      // 16Mhz, 38400 Baud
      TXSTAbits.BRGH = 1; SPBRG =  25; // Err +0.16%
      break;
    case 6:
      // 16Mhz, 57600 Baud
      TXSTAbits.BRGH = 1; SPBRG =  16; // Err +2.12%
      break;
    case 7:
      // 16Mhz, 115200 Baud
      TXSTAbits.BRGH = 1; SPBRG =   8; // Err -3.55%
      break;
    default:
      // 16Mhz, 9600 Baud
      TXSTAbits.BRGH = 0; SPBRG =  25; // Err +0.16%
      break;
  }

  // Asynchronous Operation
  TXSTAbits.SYNC = 0;

  // Continuous or single reception
  RCSTAbits.CREN = 1;

  // Setup 8 or 9 bits
  if( serial_configuration.switches.serial_odd_parity &&
     !serial_configuration.switches.serial_even_parity)
  {
    TXSTAbits.TX9 = 1;
    RCSTAbits.RX9 = 1;
  }
  else if( serial_configuration.switches.serial_even_parity &&
          !serial_configuration.switches.serial_odd_parity)
  {
    TXSTAbits.TX9 = 1;
    RCSTAbits.RX9 = 1;
  }
  else // no parity
  {
    TXSTAbits.TX9 = 0;
    RCSTAbits.RX9 = 0;
  }

  // disable (for now) transmit interrupts as low priority
  disable_interrupts(INT_TBE);
//  IPR1bits.TXIP = 0;
//  PIR1bits.TXIF = 0;
//  PIE1bits.TXIE = 0;

  // enable receive interrupts as low priority
  enable_interrupts(INT_RDA);
//  IPR1bits.RCIP = 0;
//  PIR1bits.RCIF = 0;
//  PIE1bits.RCIE = 1;

  // enable transmitter and receiver
  TXSTAbits.TXEN = 1;
  RCSTAbits.SPEN = 1;

  // enable interrupts
  enable_interrupts(GLOBAL);
}


I know, it's ugly, but it seems to work until the PCH compiler has some clear way to do it.

I still have to manually check the parity in the 9th bit in my receive ISR, and set the 9th bit in my send ISR.

I'm still interested in an easier way to do it if anyone finds a way.
ljbeng



Joined: 10 Feb 2004
Posts: 205

View user's profile Send private message

PostPosted: Fri Apr 22, 2005 3:49 pm     Reply with quote

I am having the same problem....

I need to switch from 300,o,8,1 to 9600,n,8,1 and the compiler only sees the 9600 baud #use statement....

Did anyone see this or figure it out?
Joe Porthouse



Joined: 21 Sep 2003
Posts: 8
Location: orlando, FL

View user's profile Send private message Visit poster's website

PostPosted: Fri Apr 22, 2005 6:54 pm     Reply with quote

Are you using the Hardware or Software UART?

set_uart_speed(9600); and set_uart_speed(300); would change your baud rates, but would not change your parity.

The #use RS232 statements actually do not generate code, but keep the parameters specified to be used in any serial commands that follow, until the next #use RS232 is encountered. Keep in mind that application of the #use RS232 is at compile time, NOT run time. That is why the above listed case statement does not work and only the last #use RS232 parameters were applied.

You could try,
Code:

#use RS232 (...300. O)
void send_300(char c) {...};

#use RS232 (...9600.. N)
void send_9600(char c){...};

....
if(x)
  send_300(c);
else
  send_9600(c);


You also may need to do the same with the kbhit() function to place the hardware uart into the correct baud/parity while waiting for a char.

My brut force method listed above has been working nicely for me. I have developed the parity bit sending/checking since then. I have an interrupt routine that puts received chars into a queue that the application loop can pick up. The send is also interrupt driven where the application loop fills a buffer, then enables the send interrupt. The send interrupt is automatically disabled when the last character is sent. The interrupt also disables my RS485 transmitter at the end of the string. If anyone is interested I can post the complete routines.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 22, 2005 7:22 pm     Reply with quote

Sure. Post them in the Code Library. They would be a useful addition.
ljbeng



Joined: 10 Feb 2004
Posts: 205

View user's profile Send private message

PostPosted: Mon Apr 25, 2005 2:46 pm     Reply with quote

I want to Receive at 300,o,8,1. I want to transmit at 9600,n,8,1. There will very little transmit and a lot of receive. The chip is 18F452 and I want to use the hardware UART.

I am trying this but I don't think it worky...

I still receive all data ok but it is not transmitting anything.

Code:

//abbreviated code....
#use rs232(baud=300,parity=O,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)

#int_RDA
RDA_isr(){
//receive 300 odd parity here

}

main(){

//do stuff....

//if I need to transmit data....
      if (txresp){
         disable_interrupts(INT_RDA);
         set_uart_speed(9600);
         #asm
         BCF    0xFAC.6  // clears the 9 bit transmit enable bit
         #endasm
         txresp = 0;
         putc('@');
         putc('h');
         putc('i');
         set_uart_speed(300);
         enable_interrupts(INT_RDA);
      }


}
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: Changing baud rates, parity, etc. at run time?
PostPosted: Tue Apr 26, 2005 4:05 pm     Reply with quote

Joe Porthouse wrote:
#use rs232(baud= 38400,xmit=PIN_C6,rcv=PIN_C7, errors)

This allows a single set of communication parameters to be configured. My problem is that our project uses dip switches to select the communication parameters to be used.

Does PCH has some method to support this?

In the meantime I am attempting to write directly to the PIC UART registers to modify the configuration. I believe I may have a problem when modifying the parity or data size without the PCH routine's knowledge.

Any ideas?


You can have 3 #use statements that use the same serial port each with a different stream name and different parity settings. For this to work you need to replace putc with a switch that selects from 3 different putc statements, each have a different stream name. This method works for changing parity on the fly. In order to change baud rate on the fly you still have to use the set_uart_speed function.

In your case you can use 2 different stream names and call set_uart_speed between transmitting and receiving.
henriquesv



Joined: 20 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Sun Feb 20, 2011 9:16 am     Reply with quote

Hello Joe,

Would you mind telling me a bit more about your code? Did you manage to do this in some other way?

Still lacking:
tx_enable
and
not_serial_config_port

Where do they come from?

Thank you.

Regards

Henrique

ps: I am using a simple PIC16f628a
JeffCondit



Joined: 29 Jul 2011
Posts: 2
Location: San Diega

View user's profile Send private message

PostPosted: Fri Jul 29, 2011 2:06 pm     Reply with quote

OK, still having difficulties. We are using a PIC with 2 internal hardware EUSARTS, and the baudrates of each of the two must be different. They must be settable by software execution and not require a reboot.

I've tried set_uart_speed() method before each putc() in the ISR to switch the speed at that time. I've tried the #use rs232(baud= 1200,xmit=PIN_C6,rcv=PIN_C7,parity=N,bits=8,errors) commands before each EUSART as well. I've tried defining a number of #use lines with stream names and referencing them in the putc() calls.

The problem is that either the command affects both EUSARTs (even though referencing a specific one), or that the last #use is in effect regardless of the stream used.

Can anyone give a definitive answer for what exactly is going on with these particular pre-compile directives, just how they couple to streams, EUSARTs, Bauds, etc.? In particular, if the pre-processor goes line-by-line through the C code taking on values as it goes without generating code, I could understand why when you reach various putc() the last one encountered by a line-by-line walk through the code file by line number would be used to influence the particular putc(). But what about streams? Is there some way the streams concept tells the pre-processor to remember various sets of parameters and associate them with a stream name? If so, what exactly happens when the putc() to the stream is encountered by the compiler? What does it do differently to the generated code such that when the code is run in all its nonlinear branching, that the correct baud rate or other parameters will be used?

Does anyone have a sample of dual hardware EUSART code with baudrate changes controlled by software execution?
_________________
Jeff Condit, BSEE+38, CID
JeffCondit



Joined: 29 Jul 2011
Posts: 2
Location: San Diega

View user's profile Send private message

PostPosted: Fri Jul 29, 2011 2:09 pm     Reply with quote

I might have to resort to Joe Porthouse's control by direct register manipulation if the #use stuff can't be made to work. The direct register manipulation method is bulkier but gets around all the problems with the #use and #set_baud_rate ambiguities.
_________________
Jeff Condit, BSEE+38, CID
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 29, 2011 6:31 pm     Reply with quote

Quote:

I could understand why when you reach various putc() the last one
encountered by a line-by-line walk through the code file by line number
would be used to influence the particular putc().

Yes, that's correct. Read the #use rs232() section in the CCS compiler
manual. It says:
Quote:

#use rs232()
This directive tells the compiler the baud rate and pins used for serial
I/O. This directive takes effect until another RS232 directive is
encountered
.



Quote:
But what about streams? Is there some way the streams concept tells
the pre-processor to remember various sets of parameters and associate
them with a stream name? If so, what exactly happens when the putc()
to the stream is encountered by the compiler?

It generates code according to the parameters defined in the #use rs232
statement for that particular stream.

Quote:

We are using a PIC with 2 internal hardware EUSARTS. Does anyone
have a sample of dual hardware EUSART code with baudrate changes
controlled by software execution?

Post your PIC and your CCS compiler version.
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