|
|
View previous topic :: View next topic |
Author |
Message |
DeniTCH
Joined: 09 Aug 2011 Posts: 6
|
Unpredictable printf behaviour |
Posted: Fri Aug 26, 2011 1:45 am |
|
|
Hi, I am experiencing a strange problem with multiple rs232 ports. I am using compiler version PCH V4.104 with PIC18F6680. The device contains one hardware UART. I have configured the device to use the hardware UART as well as a software UART. In my application I use the SW UART for a debug output stream. As I understand the compiler manual, the last #USE RS232 defines the STDOUT stream, so I expect the printf and putc commands to print to the software UART. The simple program below demonstrates my problem:
Code: |
#include <18F6680.h>
//------------------------------------------------------------------------------
// Pin configuration
//------------------------------------------------------------------------------
#define PIN_TX PIN_C0
#define PIN_RX PIN_C1
//------------------------------------------------------------------------------
// Configuration bits
//------------------------------------------------------------------------------
#pragma fuses HS // Use external crystal as clock source
#pragma fuses NOWDT // Disable watchdog timer
#pragma fuses NOPROTECT // Don't read/write protect program memory
//------------------------------------------------------------------------------
// Compiler magic
//------------------------------------------------------------------------------
#pragma use delay(clock=8000000)
#pragma use rs232(UART1, BAUD=19200, BITS=8, STOP=1, PARITY=N, STREAM=HWSP)
#pragma use rs232(BAUD=19200, BITS=8, STOP=1, PARITY=N, XMIT=PIN_TX, RCV=PIN_RX, STREAM=SWSP)
#pragma use spi(BITS=8)
void main()
{
// Setup SPI
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4);
// Print to the hardware UART
fprintf(HWSP,"HW UART test\r\n");
/* Lets try to print to the stdout (which should be the software UART,
as it is the one last defined */
printf("SW UART test\r\n");
// Try to write directly to the software UART stream
fprintf(SWSP,"SW direct write\r\n");
// Try again to write to STDOUT
printf("Inderectly again\r\n");
// Lets try to print some chars to STDOUT
putc('a');
putc('b');
putc('c');
// Loop forever
while(1);
}
|
When I run this code I get the following output:
On the hardware UART:
Quote: |
HW UART test
SW UART test
abc
|
On the software UART:
Quote: |
SW direct write
Inderectly again
|
As far as I can see, the printf prints to the last stream used. Am I misunderstanding something, or is there a bug?
Best regards
Denis |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Aug 26, 2011 3:58 am |
|
|
Yes, this is the classic 'bad CCS manual description' syndrome....
If you have multiple #USE RS232 statements _without stream names_, then the compiler assigns the name 'STDERR' to the first one, and STDOUT to the last. You can then use the last with the standard PRINTF functions, without using stream names.
However if you use stream names, the default disappears, and STDIO is attached to the last stream used.
So:
Code: |
#use rs232(UART1, BAUD=19200, BITS=8, STOP=1, PARITY=N, STREAM=HWSP)
#use rs232(BAUD=19200, BITS=8, STOP=1, PARITY=N, XMIT=PIN_TX, RCV=PIN_RX)
#use spi(BITS=8)
#include <stdio.h>
void main()
{
// Setup SPI
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4);
// Print to the hardware UART
fprintf(HWSP,"HW UART test\r\n");
fputc('\n',STDOUT); //switch streams to use.
/* Lets try to print to the stdout (which should be the software UART,
as it is the one last _used_ */
printf("SW UART test\r\n");
// Try to write directly to the software UART stream
fprintf(STDOUT,"SW direct write\r\n");
// Try again to write to STDOUT
printf("Inderectly again\r\n");
// Lets try to print some chars to STDOUT
putc('a');
putc('b');
putc('c');
// Loop forever
while(1);
}
|
It is poor documentation...
Best Wishes |
|
|
DeniTCH
Joined: 09 Aug 2011 Posts: 6
|
|
Posted: Fri Aug 26, 2011 6:24 am |
|
|
Thanks for the fast response! Well, this explains a lot. It does not help to manually assign the STDOUT nor STDIO stream name to the correct port. Is there a way to come around this without renaming all of the printf commands to fprintf or redefining the output stream every time? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Aug 26, 2011 8:38 am |
|
|
Just use #define.So:
Code: |
#use rs232(UART1, BAUD=19200, BITS=8, STOP=1, PARITY=N, STREAM=HWSP)
#use rs232(BAUD=19200, BITS=8, STOP=1, PARITY=N, XMIT=PIN_TX, RCV=PIN_RX, STREAM=SWSP)
#use spi(BITS=8)
#define putc(x) fputc(x,SWSP)
#define printf(x) fprintf(SWSP,x)
|
Allows you to set the default to whatever stream you want.
Best Wishes |
|
|
DeniTCH
Joined: 09 Aug 2011 Posts: 6
|
|
Posted: Mon Aug 29, 2011 2:28 am |
|
|
Elegant solution! I should have thought of that myself! Do you know if CCS supports __VA_ARG__ support in macros for full implementation of printf? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 29, 2011 12:54 pm |
|
|
For CCS variable arguments support, look at these functions in the manual:
Quote: |
va_arg()
nargs(),
va_end(),
va_start()
|
and this file:
Quote: |
c:\program files\picc\drivers\stdarg.h |
|
|
|
|
|
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
|