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 support@ccsinfo.com

printf problem on 16f819(maybe general)

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







printf problem on 16f819(maybe general)
PostPosted: Thu May 26, 2005 4:11 pm     Reply with quote

hi all,
first of all i must say i am almost new to programming the pic in c(used to do it on assembler before but the floating point math made me turn to c!).

Anyway my problem is that the following code doesn't print numbers correctly!

Code:

#byte SW=0x70
#byte SS=0x71
int IPC=0,ADCNT=125,dotpos=0,dspout[4]={0,0,0,0};
int sts=0,dsp_cnt=0;
int const digits[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07
                      0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
#bit rst=sts.0

int init(void);
void putc_7sg(char);

void main(void)
{
int cal;
float result;

cal=init();

while(1)
   {
   result=read_adc(ADC_READ_ONLY);
   result*=0.707;
   printf(putc_7sg,"%05.1f",result);
   rst=1;

   while(!go_done);
   }
}

int init(void)
{
int ee_val;

set_tris_a(0x21);
set_tris_b(0xC0);
port_b_pullups(TRUE);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
SSPCON=0;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,125,1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);

ee_val=read_eeprom(0);
if(ee_val==0xFF)
   {
   printf(putc_7sg,"0123");
   rst=1;
   while(ra5);
   ee_val=read_adc(ADC_START_AND_READ);
   write_eeprom(0,ee_val);
   }

read_adc(ADC_START_ONLY);
}

void putc_7sg(char c)
{
int i;

if(c!='.')
   dspout[dsp_cnt++]=digits[c-48];
else
   {
   dotpos=1;
   for(i=dsp_cnt-1;i>0;i--)
   dotpos<<=1;
   }
if(rst==1)
   {
   dsp_cnt=0;
        dotpos=0;
   rst=0;
   }
}


The contents of dspout string are printed to 4-7seg displays by the tmr2 interrupt which is written in assembler and to long and nothing important to mention here. It occurs every 2 msecs and prints dspout[0] to first 7seg, dspout[1] to second 7seg... in order and one at a time everytime it occurs and also starts the adc everytime after the 4 digits are printed.

The printf(putc_7sg,"0123"); in function init which occurs first in execution of the program prints everyting ok. The numbers 0123 are displayed on 7seg displays correctly. But the printf in main prints float variable result like this:

if result is 241.2 for example it is printed like 2241.

and when i tried to print with "%05.2f" the result is like that:

if result is 36.47 for example it is printed like 736.4

everytime the last number is printed first. My version is 3.222 and I don't think this is a compiler bug but i also can't find my own bug. How can the first printf print ok but the last don't if it is my own bug.

I don't have any avaible pin on pic and hardware at the time to try it on rs232. Any help is appreciated, thnx to you all for your time...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 26, 2005 4:40 pm     Reply with quote

I didn't look at your main problem, but I immediately see a potential
problem at the top of your code. You have got these two values:
Code:
#byte SW=0x70
#byte SS=0x71

I'm not sure what those are, because in the 16F819 those are RAM
locations, near the end of bank 0.

If those are supposed to be globals, you probably should have
just used int8 to declare them.

The problem is that #byte does not protect the specified RAM address
from use by the compiler. The compiler could assign other variables
to addresses 0x70 and 0x71. To prevent this, you should use #locate
instead of #byte.

Look at the program below. If I compile it with PCM vs. 3.224 and look
at the symbol map, the variable "c" is at 0x21. Now if I add "byte SW =
0x21", recompile and look at the symbol map, SW and "c" share the
same location. If you do this, you risk unexpected program behavior.
Code:
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

#byte SW = 0x21
//===================
void main()
{
char c;

c = 0x55;
SW = 0xAA;

while(1);
}
bfemmel



Joined: 18 Jul 2004
Posts: 40
Location: San Carlos, CA.

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

PostPosted: Thu May 26, 2005 4:51 pm     Reply with quote

Well let me try. Inside the putc_7sg() routine you have the test for rst==1 after you put the first byte into dspout[] so you won't reset dsp_cnt until after you have used it as an index into the array. Only the first time through the routine will dsp_cnt be the correct value of 0;

You also have init() retuning an int value and even assign it to the vairable "cal" but there is no return statement in the init() routine. so what gets returned?

Tell me if I win the cupie doll or if I just goofed. Very Happy

- Bruce
cobfan
Guest







PostPosted: Thu May 26, 2005 7:23 pm     Reply with quote

thnx to u all for your replies.

SW & SS are save registers for the interrupt routine. SW for work and SS for status. I wanted them to be on 0x70 & 0x71 because I wanted them to be accessible from all banks as the int routine may need to use them at any bank. But as I said before I'm new to programming pic in c so I couldn't realise that i should use the #locate preprocessor to declare them. Thnx for that very important detail pcm_programmer. But that didn't solve my problem.

Before, I tried resetting the dsp_cnt by something like

printf(putc_7sg,"%05.1f\n");

and trying to detect the '\n' character but '\n' didn't seem detectable so I declared a reset bit to check and detect that printf is finished. I'm sorry I didn't understand what you meant bfemmel. dsp_cnt should be 0 everytime after the printf function does its job.

Also I pasted the code from the .bak file so my correction for init function wasn't included. Sorry for this mistake of mine. Init returns the value ee_val.

And also adc is used as 10bit but is equelled to an int8 value but I know the upper byte read is lost and that's what I needed.

thnx again for your replies.
Best wishes...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 26, 2005 7:40 pm     Reply with quote

Quote:
And also adc is used as 10bit but is equelled to an int8 value but I
know the upper byte read is lost and that's what I needed.

You should read the forum daily when you're learning CCS.
This question or a related one is asked about once a week.
http://www.ccsinfo.com/forum/viewtopic.php?t=23040&highlight=device+adc
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu May 26, 2005 8:33 pm     Reply with quote

cobfan wrote:
thnx to u all for your replies.

SW & SS are save registers for the interrupt routine. SW for work and SS for status. I wanted them to be on 0x70 & 0x71 because I wanted them to be accessible from all banks as the int routine may need to use them at any bank. But as I said before I'm new to programming pic in c so I couldn't realise that i should use the #locate preprocessor to declare them. Thnx for that very important detail pcm_programmer. But that didn't solve my problem.

Before, I tried resetting the dsp_cnt by something like

printf(putc_7sg,"%05.1f\n");

and trying to detect the '\n' character but '\n' didn't seem detectable so I declared a reset bit to check and detect that printf is finished. I'm sorry I didn't understand what you meant bfemmel. dsp_cnt should be 0 everytime after the printf function does its job.

Also I pasted the code from the .bak file so my correction for init function wasn't included. Sorry for this mistake of mine. Init returns the value ee_val.

And also adc is used as 10bit but is equelled to an int8 value but I know the upper byte read is lost and that's what I needed.

thnx again for your replies.
Best wishes...


The compiler handles saving the status and Wreg unless you write you own interrupt handler. I didn't see any interrupt code so if you wrote you own, chances are that you are not saving enough registers.
cobfan
Guest







PostPosted: Thu May 26, 2005 8:35 pm     Reply with quote

This wasn't a question. I'm sorry if I wrote it like a question but I just wanted to give information in case that somebody realises that I use an int8 for a 10bit adc. That isn't anything important nevermind.

Anyway I replaced the following code for the putc_7sg function and got some progress.

Code:

void putc_7sg(char c)
{
if(c=='.')
dotpos<<=dsp_cnt-1;
else if(c=='\n') {
   dsp_cnt=0;
   dotpos=1;
   }
else
dspout[dsp_cnt++]=digits[c-48];
}


and using printf function like
printf(putc_7sg,"%05.1f\n",result);

I still don't know what was the problem with my previous code but this code solved the sequence problem. But I can't still get dot to correctly appear on the display. The dotpos variable should contain the dot position as a 1 on it like
dotpos=b'00000100'
adresses to the third 7seg display to print it but I don't know whats wrong with dotpos. thnx...

Best wishes...
bfemmel



Joined: 18 Jul 2004
Posts: 40
Location: San Carlos, CA.

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

PostPosted: Fri May 27, 2005 8:49 am     Reply with quote

Quote:
I still don't know what was the problem with my previous code but this code solved the sequence problem.

The problem was with the way that you reset the dsp_cnt array index. Since you used a post increment on the assignment and started the program with the variable set to 0, then the first time you printed your "0123" the variable dsp_cnt gets left at a value of 4, one past the end of your array! Then you don't reset it until after you have used the index in the putc_7sg(char c) to make the first index assingment into your array so that number is actually placed outside of your array somewhere at dspout[4] , where ever that is! By changing the code to use the line feed, you automatically reset the dsp_cnt variable after you are done with it instead of waiting. You could have done the same thing by moving the test for rst to the front of the old routine.

I am not sure of the problem with the radix yet. Confused

Good Luck on this.

- Bruce
cobfan
Guest







PostPosted: Fri May 27, 2005 5:55 pm     Reply with quote

Now I got the point bfemmel. You're right the index is cleared after the 2. printf's first call. I should have checked the rst flag first. Anyway this way is much better I think. Also I have solved the radix problem by directly manipulating the output data.

By the end thank to you all for your replies and time.
Best wishes...
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