|
|
View previous topic :: View next topic |
Author |
Message |
Joe Porthouse
Joined: 21 Sep 2003 Posts: 8 Location: orlando, FL
|
Changing baud rates, parity, etc. at run time? |
Posted: Mon Feb 28, 2005 12:37 pm |
|
|
#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
|
|
Posted: Mon Feb 28, 2005 12:51 pm |
|
|
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
|
|
Posted: Mon Feb 28, 2005 1:23 pm |
|
|
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
|
|
Posted: Mon Feb 28, 2005 2:37 pm |
|
|
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
|
|
Posted: Mon Feb 28, 2005 2:42 pm |
|
|
// 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
|
|
Posted: Mon Feb 28, 2005 7:21 pm |
|
|
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
|
|
Posted: Fri Apr 22, 2005 3:49 pm |
|
|
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
|
|
Posted: Fri Apr 22, 2005 6:54 pm |
|
|
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
|
|
Posted: Fri Apr 22, 2005 7:22 pm |
|
|
Sure. Post them in the Code Library. They would be a useful addition. |
|
|
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
|
Posted: Mon Apr 25, 2005 2:46 pm |
|
|
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
|
Re: Changing baud rates, parity, etc. at run time? |
Posted: Tue Apr 26, 2005 4:05 pm |
|
|
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
|
|
Posted: Sun Feb 20, 2011 9:16 am |
|
|
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
|
|
Posted: Fri Jul 29, 2011 2:06 pm |
|
|
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
|
|
Posted: Fri Jul 29, 2011 2:09 pm |
|
|
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
|
|
Posted: Fri Jul 29, 2011 6:31 pm |
|
|
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. |
|
|
|
|
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
|