Theja
Theja

Reputation: 75

Error : invalid digit "9" in octal constant

I am trying to write a code for displaying numbers on a four digit seven segment display using STM32-F401RE. The problem lies in the while(1) loop.
Here is the code:

void num_display_func(uint16_t numtodisplay);
void displayDigit(uint8_t number);

int main(void){
while (1)
  {
    /* USER CODE END WHILE */
      num_display_func(0209);
    /* USER CODE BEGIN 3 */
  }


void num_display_func(uint16_t numtodisplay){

    uint8_t digit_extract[4];

    digit_extract[0] = numtodisplay%10;       //extract the last digit of the number
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, SET);
    displayDigit(digit_extract[0]);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, RESET);

    HAL_Delay(10);

    digit_extract[1] = (numtodisplay/10)%10;  //extract the second last digit
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, SET);
    displayDigit(digit_extract[1]);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, RESET);

    HAL_Delay(10);

    digit_extract[2] = (numtodisplay/100)%10; //extract the third last digit
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, SET);
    displayDigit(digit_extract[2]);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, RESET);

    HAL_Delay(10);

    digit_extract[3] = (numtodisplay/1000)%10; //extract the fourth last digit
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, SET);
    displayDigit(digit_extract[3]);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, RESET);

    HAL_Delay(10);

}

void displayDigit(uint8_t number){


    GPIOC->ODR |= GPIOx_SEGMENTS_MASK;  //Clear the segment bits (Setting the bits to HIGH for common Anode config)

    uint8_t digit = segmentCodes[number];

    GPIOC->ODR |= (digit & GPIOx_SEGMENTS_MASK );

}

When I am trying to run the code, here is the error:

./Core/Src/main.c:115:21: error: invalid digit "9" in octal constant
  115 |    num_display_func(0209);
      |                     ^~~~

As far as I know, this can be fixed if the 0 is removed. but in that case how do I display the number, 0209 or any other number starting with zero for that matter?

If I remove the 0 from the number, it may display 209 instead of 0209. How to solve this?

Upvotes: 4

Views: 358

Answers (3)

Clifford
Clifford

Reputation: 93556

Numeric prefixes in C are 0x for hexadecimal and 0 for octal.

but in that case how do I display the number, 0209 or any other number starting with zero for that matter?

That is a whole different misunderstanding. Your question should really be about that. The value is an integer it will be stored in this case as a 16 bit binary value in two bytes of memory. The decimal (or octal) representation in your code is not preserved or represented, it does not matter how many leading zeros you add or what number base you use, it is just an int literal constant.

If you intend to present that value with four digits with leading zeros, then that is a presentation issue, not a representation issue. That is you determined how to display it when you display it.

In your case, you might simply test n < 1000 for the first digit and output a zero if that is true rather than (numtodisplay/1000)%10. Then compare to 100 and 10 for the second and third digits respectively. However you need not even do that because for 209 the expression (numtodisplay/1000)%10 is zero in any case, so the code you have will "just work" as is. If it does not then that is a different question.

However there is a simpler more compact solution:

void num_display_func( uint16_t numtodisplay )
{
    int place_value = 1000 ;
    int num = numtodisplay ;
    uint16_t pin = GPIO_PIN_12 ;
    
    // For each digit
    for( int d = 0; d < 4; d++ )
    {
        uint8_t digit = num / place_value ;

        HAL_GPIO_WritePin(GPIOA, pin, SET) ;
        displayDigit( digit ) ;
        HAL_GPIO_WritePin(GPIOA, pin, RESET) ;

        num %= place_value ;
        place_value /= 10 ;
        pin >>= 1 ;
    
        HAL_Delay( 10 ) ;
    }
}

Upvotes: 7

Lundin
Lundin

Reputation: 214730

Here 0209 is the source code presentation of the number, for the benefit of the programmer, nothing else. It has nothing to do with the user presentation in some GUI.

And as you noticed, 0 is the prefix you use for octal numbers and as such an oddball feature for special scenarios only.

What your display routine spits out is entirely depending on the number of iterations inside it: that is, the number of times you extract a digit using % 10 and then divide the number by / 10.

i=0   209 % 10 = 9
i=1    20 % 10 = 0
i=2     2 % 10 = 2
i=3     0 % 10 = 0
...
i=n     0 % 10 = still 0

Simple example:

#include <stdio.h>

int main()
{
  int n = 10;
  int number = 209;
  int digits[n];
  for(int i=0; i<n; i++)
  {
    int digit = number % 10;
    digits[n-i-1] = digit;
    number /= 10;
  }
  for(int i=0; i<n; i++)
  {
    printf("%d", digits[i]);
  }
}

Output:

0000000209

Btw in embedded systems, a very common misconception is that if we write something like 0x00001234 then we would get a 32 bit integer constant just because we typed 8 hex digits. But we don't - on a 8/16 bit target, this would result in a 16 bit integer constant.

Upvotes: 4

Enzo Ferber
Enzo Ferber

Reputation: 3104

Octal valid values are 0-7 - 8 digits, a base-8. Therefore, 0209 is not a valid octal number. That's why your compiler is complaining. Octal 0209 doesn't exists, the closest you can get is 0207, then 0210, 0211 (which would be "equivalent"). So the compiler is trying to convert 0209 octal to decimal in order to pass that number as argument, but it fails because 9 is not a valid digit.

Furthermore, in your num_display_func you are converting the number as if it was a decimal number (dividing by 10, 100, 1000... and getting the remainder as % 10). So you have a problem there.

If I remove the 0 from the number, it may display 209 instead of 0209. How to solve this?

Have you tested this in the hardware? Because the program should correctly put the zero in it if you pass just 209.

1st digit: 209 % 10 == 9
2nd digit: (209 / 10) % 10 == 20 % 10 == 0
3rd digit: (209 / 100) % 10 == 2 % 10 == 2
4th digit: (209 / 1000) % 10 == 0 % 10 == 0

Because you are writing to the hardware on all four digits, so the number zero will be written.

Upvotes: 4

Related Questions