|
|
View previous topic :: View next topic |
Author |
Message |
D-Kens
Joined: 09 May 2005 Posts: 35 Location: Toulouse (France)
|
printf or fprintf with a 18F4620 |
Posted: Fri Nov 14, 2008 10:23 am |
|
|
Hi...
Since this morning, I'm having a weird problem, and I've spent the last few hours trying to write a "hello world" function, with no success !
I'm using PCWH Compiler, version 3.249 (and have been using it, and PIC18F4620) for quite some time now. Here is the simple code I use :
Header file
Code: | #include <18F4620.h>
#device adc=8
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV21 //Brownout reset at 2.1V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors,brgh1Ok,stream=COM1)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3) |
Source file
Code: | #include "C:\Program Files\PICC\Coronis\Clocking\wavetherm.h"
#include <stdio.h>
#include <string.h>
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_ON);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
while (TRUE) {
restart_wdt() ;
printf("Hello world !\n\r") ;
delay_ms(2500) ;
}
} |
When I load the program in the PIC, it echoes lines of 0xFF, and not "hello world". But, if I reset the PIC, then it works fine... If I print the line twice in a row, in the main(), it works fine without having to reboot. So I assume I'm missing some initialisation somewhere, but I dunno where, and it's driving me crazy.
Now I think the answer is obvious, but I'm too mad and probably don't see my code clearly. Help me please !!!
Christophe. |
|
|
Guest
|
|
Posted: Fri Nov 14, 2008 10:40 am |
|
|
Hi
In your RS232 init you are using "stream=COM1" but the the printf() is without, try fprintf(com1,"Test1\n"); |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 14, 2008 12:58 pm |
|
|
Quote: |
#FUSES NOBROWNOUT
if I reset the PIC, then it works fine.
|
Change the fuse to BROWNOUT.
Also, that's not a simple program. This is a simple program:
Code: | #include <18F4620.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main(void)
{
printf("Hello World\n\r");
while(1);
} |
|
|
|
D-Kens
Joined: 09 May 2005 Posts: 35 Location: Toulouse (France)
|
|
Posted: Mon Nov 17, 2008 3:07 am |
|
|
Thanks for your answers...
Mr Guest, I believe printf() uses the first #rs232 defined in the code for its output, when you don't specify the output stream. Anyway, I tried removing the "stream=COM1) from my header file, or using fprintf() in the main instead of printf(), but it didn't change anything.
PCM programmer, you pointed out that my programm was not simple, so I tried the piece of code you posted, and still had the same problem. After programming the PIC with a new firmware (I use Tiny Bootloader to load the firmware), I don't see "Hello world" on screen, but only a line of non printable caracters 0xFF. But, if I switch my micronctroller off then on again, the line prints well...
My guess is that I change the default value of some register when I load the firmware, but it's reseted when I switch power off. Except that, if I print (for instance) two lines of "hello world" instead of just one, then both lines print fine on screen.
Actually, my test programm did a little more (in my first attempt). I have a DS1305 real-time-clock tied to the PIC, and I try to read the hour and print it on screen. If I write :
Code: | printf("%02d : %02d : %02d\n\r", hour, minute, second) ; |
it echoes : 00 : 00 : 00
But if I write :
Code: | printf("Current time is %02d : %02d : %02d\n\r", hour, minute, second) ; |
then it echoes the real time...
Seems the printf() function doesn't work fine until I print a regular character at first, to initiate it or something. Am I going crazy ?
Regards,
Christophe. |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 17, 2008 5:03 am |
|
|
Though it does not explain the "two line work, one doesn't", have you tried the simple expedient of:
Code: |
#include <18F4620.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main(void) {
putc(0); //Add this if it still doesn't work.
delay_ms(20); //Just try this on it's own first
printf("Hello World\n\r");
while(1);
}
|
You don't say what your RS232 hardware actually 'is', but some of the transceiver chips, don't power up their internal charge pumps, till the transmit line goes high. This should happen as soon as you send any character, but it will then take time for the voltage levels to reach their proper values. Sending a single dummy character, then waiting for a moment, would allow this to happen.
It could then be that the garbage you see, is the 'Hello World" message, but with the first few _bits_ missed, resulting in garbage being seen.
Best Wishes |
|
|
D-Kens
Joined: 09 May 2005 Posts: 35 Location: Toulouse (France)
|
|
Posted: Mon Nov 17, 2008 6:58 am |
|
|
Based on your piece of code, here is exactly what I used as a test code :
Code: | #include <18F4620.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
void main(void) {
putc(0) ; //Add this if it still doesn't work.
delay_ms(20) ; //Just try this on it's own first
while (1) { printf("Hello World\n\r") ;
delay_ms(1000) ; }
} |
The only difference is that my call to printf() is in the loop. Else, the text prints on screen immediatly after programming, and I have no time to launch the monitor and catch it (and, as I mentionned before, if I launch the monitor then reset the microcontroller, it magically works fine).
So, executing that code, I only get a line of 13 times 0xFF... Repeated every second, of course ! I tried with 3 different PICs, on two different boards, and even used a former version of our hardware, but I always get the same result.
By the way, the interface to the computer is done through a MAX232 (you asked about the hardware configuration).
From my experiments, what I can say is :
- text prints if I wrote 2 lines, but not if I write one
- text prints if I do a MCLR or a reset
- %d of a value doesn't print the actual value, except if I type some text before. In that last case, the text is replaced by some 0xFF and only the value is echoed correctly... A MCLR or reset fixes the problem of the 0xFF.
I guess some people would say I just have to reset my PIC after programming it, and printing some dummy characters at boot, and it would probably work, but I want to understand what's happening there, cause it might be the evidence leading to a greater problem.
Anyway, I keep on testing, but it's gonna be the second day I lose on that function : never thought "Hello world" application would take that long...
Regards,
Christophe.
Edit : I forgot to mention I also tried with another version of CCS Compiler, on another computer... Didn't solve the problem ! |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 17, 2008 8:23 am |
|
|
I'd begin to suspect that your problem is somewhere else. How is the ground connection made between the PIC and the PC?. What are you using to 'monitor'?. Why can't you launch the 'monitor' before the PIC?..
When you compile the program exactly as typed in your last post, does the header on the .lst file look like this _exactly_.
Code: |
CCS PCH C Compiler, Version 3.249, 27955 17-Nov-08 14:03
Filename: test6620prob.lst
ROM used: 160 bytes (0%)
Largest free fragment is 65376
RAM used: 7 (0%) at main() level
8 (0%) worst case
Stack: 1 locations
|
(except for the date and time...).
I'd be suspecting something silly like a ground connection coming via the monitor PC, rather than directly.
Best Wishes |
|
|
D-Kens
Joined: 09 May 2005 Posts: 35 Location: Toulouse (France)
|
|
Posted: Mon Nov 17, 2008 9:44 am |
|
|
I think you're right, the problem seems to come from somewhere else ! I took an old project, kept all the includes and definitions, but changed its main() to use our test code... And it worked ! So I deleted all includes one by one to find the library that fixed the problem...
For some weird reason, seems it's one of my private libraries (written to send AT commands to a specific modem) that's required, even if I don't even call its functions. That library includes 2 CCS libraries, but I can remove them and the program works. All other functions are of my own : they don't do anything special, and I don't even call them in the test program, so they shouldn't even be compiled.
I think it's an issue of the compiler. I don't understand why, but adding that library to the test code fixed the bug. Luckily, I'll need an updated version of that library in my project, so I'll need it in a near future anyway. I only noticed that bug because I began my tests at an early stage of development, before including all my libraries.
Thanks for wasting a bit of your time with my problem ! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 17, 2008 9:51 am |
|
|
Quote: | I use Tiny Bootloader to load the firmware |
I'm not familiar with Tiny Bootloader, but the typical bootloader uses
fuse settings that are in the bootloader firmware. It does not use the
fuses in the application program. So changing the BROWNOUT fuse
in your program above likely would not have any effect.
What are the fuse settings of your Tiny Bootloader ?
Find the source code that you used. Or did you use a .HEX file that
you got from the internet ? Post a link to it. |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 17, 2008 10:06 am |
|
|
Most bootloaders, will interfere to some extent or other with the hardware. They will either, be checking an input pin to see if they should work, or be pausing, and testing the incoming RS232 data to see if they should act. Both things that could have an effect. Also, the code used, will presumably have an offset added, so won't be exactly as being shown/tested.
Remember on your #include file, that defines will still have an effect, as will RAM useage. However my guess would be that it is this file that actually contains the #ORG statements needed for the main code, by the bootloader.
Best Wishes |
|
|
D-Kens
Joined: 09 May 2005 Posts: 35 Location: Toulouse (France)
|
|
Posted: Mon Nov 17, 2008 10:22 am |
|
|
PCM programmer, I didn't get the .HEX for my bootloader from the net (not directly anyway) : the C source code was provided, and I had to change two lines to adapt it to my baudrate and my target device. That should answer one of your question...
When I was working with the PIC16F877 (seems it was in a previous life), I had noticed that the changes I made to the #fuse statements had no effect and that it was the bootloader that could set 'em. It was mosty evident when changing the WDT fuse.
Anyway, the problem has been solved by adding that "famous" library I mentioned in my previous post. I'm not 100% satisfied cause I didn't identify what exact line(s) of that library was the solution, but I've been able to go further in my tests and to validate some functions. After two days of brainstorming, shouting (and almost crying), it's been a real progress...
I'll test some fuse modifications on the fly later, because you raised a good question there, but it's another problem. |
|
|
|
|
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
|