View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
Changing Baud rates - SOLVED |
Posted: Mon Aug 06, 2012 9:16 pm |
|
|
I'm trying to change clock frequencies AND baud rates unsuccessfully.
below is my small and compilable test program:
I'm using 4.135 on a 16F866 with an FTDI chip.
I've check the timings toggling a pin and they match perfectly (i have an O-scope)
when using the internal osc i _believe_ i am waiting for it to stabilize properly...
the problem is with printing at 9600.... 115200 works fine.
my O-scope tells me that when i switch to 9600 the timing is fine and that i am outputting _something_ via the UART....
hyperterminal says: random smilies and ascii chars...
to use the test code just compile and press any key on your terminal program to "switch" modes...
mode 1 print at 9600
mode 2 toggle pin B2 at 50ms
mode 3 print at 115200
mode 4 toggle pin B2 at 25ms...
Code: | #include <16f886.h>
#device adc=10
#device *=16
#fuses HS,NOWDT,NOPROTECT, NOLVP//,INTRC_IO
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#BYTE OSCCON = 0x8F
void TX_9600();
void TX_1152();
#INT_RDA
void SerialInt();
#INT_TIMER0
void Timer0Int();
// --------- SERIAL BUFFER AND MAIN INDEX DECLARATION --------//
char Receive_String[71];
int counter_read = 0x00;
void Main()
{
ENABLE_INTERRUPTS(GLOBAL); // Enable Interrupts
ENABLE_INTERRUPTS(INT_RDA); // Enable Serial Interrupt
while (1) // Main Loop
{
TX_9600();
counter_read=0;
TX_1152();
counter_read=0;
}
}
void TX_9600()
{
SETUP_OSCILLATOR(OSC_4MHZ);
while(!bit_test(OSCCON,2));
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
while(counter_read==0)printf("9600: %X \r\n", OSCCON);
counter_read=0;
while(counter_read==0)
{
delay_ms(50);
output_toggle(PIN_B2);
}
}
void TX_1152()
{
SETUP_OSCILLATOR(OSC_NORMAL);
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
while(counter_read==0)printf("1152: %X \r\n", OSCCON);
counter_read=0;
while(counter_read==0)
{
delay_ms(25);
output_toggle(PIN_B2);
}
}
#INT_RDA
void SerialInt()
{
Receive_String[counter_read]=getchar();
counter_read++;
if(counter_read==70)counter_read=0;
} |
your help is greatly appreciated.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093
Last edited by Gabriel on Tue Sep 18, 2012 9:16 pm; edited 1 time in total |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Aug 07, 2012 9:51 am |
|
|
Really? no one?
Forever Alone _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Aug 07, 2012 9:59 am |
|
|
Quote: |
#use delay(clock=20000000)
SETUP_OSCILLATOR(OSC_4MHZ);
SETUP_OSCILLATOR(OSC_NORMAL);
#use delay(clock=20000000)
|
is all pretty awkward
have you REALLY got 20 mhz - accurate freq when you THINK you do ??
i would use this arcane tool called a frequency counter to know for sure. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Aug 07, 2012 10:14 am |
|
|
Hi,
I checked my OSC pins (with 20M crystal) and it was running at 20M when the code that is supposed to run 20M is running...
and also when running at 4M the 20M OSC stopped....
So i am pretty sure frequencies are changing accordingly,
furthermore in my initial post i mention that printing at 115200 IS working...
From the datasheet i don't recall that being possible at 4M.... so yeah... i got 20M ...
Also, i checked my frequencies by toggling a pin and testing the _expected_delays.... it tested OK.
I don't understand exactly what you mean by it looks awkward?
how code looks and feels does not necessarily imply its wrong...
... do you have any suggestions?
thank you
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Aug 07, 2012 11:19 am |
|
|
The internal oscillator, is _not_ normally accurate enough for serial on these chips. In some cases, it 'can be', but is borderline. Suggests your chip isnot actually giving 4MHz, accurately enough.
Best Wishes |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Aug 07, 2012 12:04 pm |
|
|
i thought of that at first, but if I _do not_ try to change baudrates and stick to 9600 baud @ 4M it works Perfectly...
changing OSC and Baud rates is Absolutley nessesary in my app....
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Aug 07, 2012 12:53 pm |
|
|
The erroneous belief involved with your code is, that #use rs232() would change a UART baud rate. But it doesn't, as well as #use delay() doesn't reconfigure the clock on it's own. The UART initialization specified by #use delay() is performed in the begin of main, before the first executable statement.
For UART reconfiguration, CCS provides set_uart_speed () and setup_uart(). It should assume clock settings according to last #use delay() statement before. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Aug 07, 2012 1:00 pm |
|
|
Is there some reason you cant just use 20 MHz all the time
and merely change the BAUD ????
That way you get the simplest setup.
Awkward comes from the way you change the delay setting AND baud at the same time - not to mention the internal external osc switch.
I would stay with just the external osc if I was doing this code
and a SINGLE use delay for the whole program.
20 MHz will give BOTH divisors - nicely handled wont it ??? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Aug 07, 2012 1:17 pm |
|
|
I simply assumed that Gabriel has reasons to perform clock switching, no matter if they are mentioned in the post, e.g. power saving. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Aug 07, 2012 1:39 pm |
|
|
Hi all,
I think you have touched a key point...
I was under the impression that the #USE rs232 statement would configure what i need... ill try the setup_uart functions(completely forgot about that).... i think that will at least take care of part of the problem...
I _have_ to change OSC freq. for power reasons indeed...
I'm reading a sensor at 9600 once an hour... battery operated logger...
when i dump my eeprom (25LC512) it takes 45 minutes at 9600 baud... (date, time, data, +2 bytes for checking and debug)
45 minutes is toooo long so i want to print at 115200 @20M (4:40 minutes).... and by going with the internal 4M OSC... i can drain my batteries lower....
Now... after i do this exercise successfully I'll go with software 9600 uart for the sensor and 115200 HW for data dumping...
How do I set up the "new" delay values?
The #use delay line still works at any point in code right?
Thanks for your help. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Aug 07, 2012 2:19 pm |
|
|
#use RS232, changes the internal configurations used for the UART.
These values are used:
1) When the code starts.
2) When you call setup_uart.
So, 'no', it won't change the settings mid code.
However I'd suggest simplifying.
Work out the differences yourself, and don't change the #use delay, or #use RS232 settings.
Leave these setup for your main clock rate (say the 20MHz position). Then:
Code: |
#define 9600bps4MHz (48000)
//Then when you change oscillator down to 4Mhz, just use:
setup_uart(9600bps4MHz);
//Then when you switch back to 20MHz, use
setup_uart(115200);
|
You have to understand that things like delay statements, won't change anyway. These are _hardcoded_ at compile time, so changing the #use delay settings, won't change the durations of delays already in the code.
Best Wishes |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Aug 07, 2012 2:31 pm |
|
|
The droids I was looking for, you´ve found them!
Thank you!
G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Aug 08, 2012 12:16 am |
|
|
Quote: | Work out the differences yourself, and don't change the #use delay, or #use RS232 settings.
Leave these setup for your main clock rate (say the 20MHz position). Then:
Code:
#define 9600bps4MHz (48000)
//Then when you change oscillator down to 4Mhz, just use:
setup_uart(9600bps4MHz);
//Then when you switch back to 20MHz, use
setup_uart(115200); |
Multiple #use delay statements are the method intended by CCS to reflect clock switching, e.g. for delay_xx(). They can also work for set_uart_speed(). I don't see a clear indication why we shouldn't have multiple #use delay() statements in the present code, although I can imagine that manual settings may be favorable in some cases. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Aug 08, 2012 12:49 am |
|
|
Sorry I'm late...
I was going to post code I have that does clock switching with maintaining the same baud rates (sort of different, but the idea gets shown)
looks like you have it solved?
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Aug 08, 2012 1:25 am |
|
|
FvM wrote: | Quote: | Work out the differences yourself, and don't change the #use delay, or #use RS232 settings.
Leave these setup for your main clock rate (say the 20MHz position). Then:
Code:
#define 9600bps4MHz (48000)
//Then when you change oscillator down to 4Mhz, just use:
setup_uart(9600bps4MHz);
//Then when you switch back to 20MHz, use
setup_uart(115200); |
Multiple #use delay statements are the method intended by CCS to reflect clock switching, e.g. for delay_xx(). They can also work for set_uart_speed(). I don't see a clear indication why we shouldn't have multiple #use delay() statements in the present code, although I can imagine that manual settings may be favorable in some cases. |
Problem is that with switched #use delay statements, it can first be difficult to know which one is in force for a particular code flow. They do not work quite as you might expect regarding which one is 'in force'. Remember also they do not directly change delays. They change delay timings _as applied at the time of compilation_, not retrospectively. So if you have a delay_ms(100) statement written so that when compiled the compiler last saw a #use delay (clock=20MHz), it'll have the fixed delays inside it, for this clock rate. If you then take a different code route to this point, and have switched clock rates, the delays _won't_ change to reflect the new route.
The same problem used to apply to switching baud rates with #use RS232. A search here will show just how problematic this could be...
If I'm changing clock rates, I use macro based delays, which generate both timings for the two rates, and switch between which one is used depending on a global flag.
Best Wishes |
|
|
|