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

Byte variable corruption

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



Joined: 07 Sep 2003
Posts: 40
Location: Adelaide, Australia

View user's profile Send private message

Byte variable corruption
PostPosted: Tue Feb 10, 2004 9:14 pm     Reply with quote

Hi I am using CCS PCM v3.168 on a 16F876 at 4MHz.

I have a project with a serial LCD and 3 polled pushbuttons. I wrote a function to let the user input a 4 digit number that is returned in a int16. This function was working perfectly, where 0000 was displayed, and the user could adjust each digit up/down (starting from the left most digit) and pressing the "next digit" button to move right to the next digit.

Then when I added some code to display an initial value, which the user would adjust, instead of starting from all zeros, one of the byte variables has become corrupt.

Here's the function:

Code:
/*
**   Function Name:
**       enter_numeric_val
**
**  Parameters:
**      cursor_start   - The x position where the number entry starts on the LCD
**      start_val      - The initial value displayed to the user
**
**   Returns:
**      100 x (the 4 digit number) input by the user
**
**   Description:
**       This function allows the user to enter a 4 digit number using 3 keys.
**      The keys are up/down and "next digit". An initial 4 digit value is displayed,
**      and the user can user can adjust each digit up/down from the initial value.
**      The "next digit" button is pressed to advance right to the next digit.
**      After adjusting the 4th digit, the "next digit" button should be held
**      for 2 seconds for the value to be returned, or momentary to start again.
**      A decimal point is displayed after the 2nd digit, ie the user will see
**      99.99 and the function will return 9999.
*/
int16 enter_numeric_val (int8 cursor_start, int16 start_val) {

   int16 value;
   int16 scale;
   int8 digit_val = 0;
   int8 curs_current;
   int8 i;
   int16 copy_start_val;

   do {

      /* Display current distance */
      lcd_command (cursor_underline);

      /* Erase "Hold" text if it exists */
      goto_xy (chars_per_line - 4, 1);
      printf ("    ");

      /* Reset entry values */
      value = 0;
      scale = 1000;
      copy_start_val = start_val;
      curs_current = cursor_start;

      do {

         digit_val = copy_start_val / scale;
         copy_start_val = copy_start_val % scale;

         /* Display current value */
         goto_xy (curs_current, 1);
         lcd_command ('0' + digit_val);
goto_xy (0, 2);
printf("%03u", digit_val);

         /* Move cursor back to input digit */
         goto_xy (curs_current, 1);

         i = wait_for_any_switch ();

         if (i == 1) {
            /* Up button */
            //digit_val++;
            digit_val = digit_val + 1;

goto_xy (4, 2);
printf("%03u", digit_val);

            if (digit_val == 10) digit_val = 0;
            lcd_command ('0' + digit_val);
         }
         else if (i == 2) {
            /* Down button */
            if (digit_val == 0)
               digit_val = 9;
            else
               digit_val--;
goto_xy (8, 2);
printf("%03u", digit_val);

            lcd_command ('0' + digit_val);
         }
         else if (i == 3) {

            if (++curs_current == (cursor_start + 2)) {
               /* Skip over the decimal point */
               curs_current++;
            }

            value += (scale * digit_val);
            scale /= 10;

         }

      } while ((curs_current - cursor_start) < 5);

      lcd_command (cursor_hide);

      goto_xy (chars_per_line - 4, 1);
      printf ("Hold");

   } while ((!reset_sw_held ()) || (value == 0));

   /* Display reset */
   lcd_command (clear_display);
   printf ("Done!");

   /* Wait until button released */
   while (sw_rst_on);

   return value;

}


The problem is that variable "digit_val" is being corrupted somehow. In the printf's displayed in the margin above, the first printf would display say "7" and if the user pressed the up button, instead of "digit_val" incrementing by 1 and becoming 8, it is becoming 88 as displayed by the second printf. I have been racking my brain to solve this. It is very consistent, happens going up and down, and from any value, and on all digits. I always get 11 times the correct value, eg 88, 77, 66, 55 etc instead of 8, 7, 6, 5. What on earth could cause this?

I read once that the compiler tries to reuse parts of the compiled code, and due to the digit_val = copy_start_val / scale; this is causing a problem when I subsequently go to increment digit_val, and somehow I get 11 * (digit_val + 1).

I'm going to try and reorder the variable declaration, because I saw another post today with a similar problem that was solved by reordering the variable declarations.

Any ideas would be greatly appreciated. Thankyou.
Patrick
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 10, 2004 10:41 pm     Reply with quote

If you suspect that the compiler is re-using a RAM address for
a variable when it shouldn't be, then re-compile your file with the
+LS option.

Then inspect the symbol table at the end of the .LST file.
Note the address of any variables that you are suspicious of.
Then scan the symbols in the list, and see if they use the
same RAM address. In some cases, it's legitimate to re-use the
memory location. For example, if the compiler calls function A
from main() and returns to main(), and then calls function B
from main(), the local variables in functions A and B can share
the same RAM locations.

But if you have a global variable, and it's re-used by a function,
then that's a bug.

If a local variable in an isr re-uses the RAM address used by
other functions, then that's a bug.

If a high level function, such as main(), has the RAM address
of one of its local variables be re-used by a sub-routine that's
called by main(), then that's a bug.
pat



Joined: 07 Sep 2003
Posts: 40
Location: Adelaide, Australia

View user's profile Send private message

PostPosted: Wed Feb 11, 2004 4:47 am     Reply with quote

Now would be a good time to say I love the CCS compiler and I still (touch wood) don't think I've ever found a bug with my style of coding.

It was a simple bloody coding error. Embarassed

My perceived problem of getting 11 times the required value was not happening at all, it was becuase I was displaying the same value twice - derrr.

And the reason I was outputting the debug text in the first place was to identify the real problem, and that was I was calculating the remainder
Code:
copy_start_val = copy_start_val % scale;
in the wrong place, it should have been when the "next_digit" button was pressed.

Anyway, thanks PCM I still learned something from your post, I've now enabled the list file, and understand how to interpret it. Sorry to waste your time.

Cheers,
Patrick
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