This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

help! why?

my codes:

unsigned int i=0;
void Timer(void) interrupt 1
    {
    i++;
    }

void Main (void)
    {
    while (1) printf ("i=%d\n", i);

    }

I had thought that I will get below on serial window

"
i=0;
i=1;
i=2;
i=3;
...
"


but I got

"
i=0
i=-9472
i=-28416
i=29184
i=10240
i=-8960
i=-27904
i=29696
i=10752
i=-8192
i=-27392
i=30464
i=11264
i=-7680
......
"


these values are disorderly and unsystematic, why? You had better try it on your own keilc.

Parents
  • hi,

    firstly, about disorderly and unsystematic. You know, printf() is not simple function which produce result by one assembly command. Processing format string and sending result via COM-port - it all take alot of time. Ofcoz timer does not wait till printf() will be done; so for time within printf() sends a byte, timer may be increased many times. As result you will get randomize values of i variable.

    well, now about negative values. In fact %d prints both negative and positive values depend on bit 15 of i variable. Printf() does not know about your unsigned declaration. If you wish to print all positive values so you should use %ud or %u (it depends on compiler you use).

    Good days!

Reply
  • hi,

    firstly, about disorderly and unsystematic. You know, printf() is not simple function which produce result by one assembly command. Processing format string and sending result via COM-port - it all take alot of time. Ofcoz timer does not wait till printf() will be done; so for time within printf() sends a byte, timer may be increased many times. As result you will get randomize values of i variable.

    well, now about negative values. In fact %d prints both negative and positive values depend on bit 15 of i variable. Printf() does not know about your unsigned declaration. If you wish to print all positive values so you should use %ud or %u (it depends on compiler you use).

    Good days!

Children
  • AND
    when using an int in an ISR and main you will ocasionally get false readings. To avoid that you will need

    EA = 0
    main_int = i;
    EA = 1
    printf .... main_int ...

    Erik

  • Oops, I was sured that Keil compiler does it internaly; doesn't? Seems I need to check my code then ((=

  • when using an int in an ISR and main you will ocasionally get false readings

    This is true because an int is a 16-bit value which takes 2 bytes. On the 8051, everything is handled as a byte. So, 2 reads are required to get the value of an int.

    What Erik is saying is that IF an interrupt happens between the 2 instructions that read the int you may actually get the MSB before the interrupt and the LSB after the interrupt. IF the interrupt causes the int to overflow (0x02FF ->0x0300) the value you get will either be 0x0200 or 0x03FF depending on the order in which the bytes are read.

    The following demonstrates how to disable interrupts, read the value, and re-enable interrupts:

    while (1)
      {
      int i_copy;
    
      EA = 0; i_copy = i; EA = 1;
      printf ("i=%d\n", i_copy);
      }


    Jon

  • To be completely correct, you should also declare i as "volatile", as it might be updated by something (the ISR) without the knowledge of the code generator / optimizer. The volatile declaration will force the compiler to actually read i, rather than using a previous and possibly stale value.

  • I tried

    while (1)
      {
         EA=0;
         printf("i=%d \n",i);
    	 EA=1;
    
      }
     

    The same thing happen

    i=2560
    i=2816
    i=3072
    i=3328
    i=3584
    i=3840
    i=4096
    i=4352
    i=4608
    i=4864
    i=5120
    i=5376
    i=5632
    i=5888

  • Sorry, I make a mistake (char i; printf("%d",i), I cancel my previous reply! Thanks!

  • The result you expect and the result you are now getting is probably not the result you want. Your while() loop is keeping interrupts disabled 99.9% of the time as there is probably only a jump instruction between EA=1 and EA=0. If you changed your code as follows:

    int x;

    while(1)
    {
    EA=0;
    x=i;
    EA=1;
    printf("%d\n",x);
    }

    you should see the value of x incrementing by a lot more than one for each iteration of the loop. Keeping interrupts disabled almost all the time is almost always a bad idea.

    Incidentally, if you want to printf() an 8 bit value in Keil use "%bd" for signed char and "%bu" for unsigned char.

    Stefan