This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2355: Math Question -- abs func and how to declare variables??

Part Number: MSP430FR2355

Good morning...

I have a timer that goes off and I capture the count register in a variable and an overflow counter as well both are declared as volatile unsigned int.  After doing this twice I want to do a difference on the two numbers for each variable.  I recognize that there is no guarantee which of the two numbers will be larger than the other at any given point in time hence I am diffing them with the abs function.  Can some tell me how I should be declaring all my variables as I am having a hard time getting the numbers to give me correct values....

I am assuming that I will have to typecast along the way.  My math looks like this:  I have varied my declarations of tempA and temp and haven't found the right combo....My other declarations look like:

temp = abs(overflowHistory[0] - overflowHistory[1]);
            for (j = 0; j < temp; j++)
                adder +=65536;
            tempA = abs(holdTime[0] - holdTime[1]);
            swVolumeHoldTime = (long)tempA + (long)adder;


volatile unsigned int overflowHistory[2] = {0};
volatile unsigned int holdTime[2] = {0};
long int swVolumeHoldTime = 0, adder = 0;

I have tempA declared as an int and created a tempB as an unsigned int for testing and I cannot see any difference.....On top of all this it appears that something very strange is occuring....For instance I did one run after verifying holdTime[] = {0} on both values in array and got 

holdTime[0] = 50356

holdTime[1] = 13715

and tempA and tempB failed both to show the correct subtraction values!!  They showed 28895??  This subtraction error occurs even after a reset where all variables are initialized to 0.

Thanks

  • holdtime[0]-holdtime[1]=36641 = 0x8f21, which the abs() call casts to (int)-28895 and returns 28895. [I think this conversion is strictly speaking "undefined behavior" but that's what usually happens.]

    If you "know" that holdtime[0] is later than holdtime[1], the simple unsigned subtraction gives the correct result (within the range of the timer).

    If you don't know which one occurred first, the problem is ill-posed, and the difference could be either 36641 or 28895.

  • [Edit: Duplicate post. I couldn't delete it because it didn't exist. Go figure.]

  • Bruce...

    I'm confused as to how to proceed....the short is I will never know which one is the larger of the two numbers....

    I am detecting the length of time a switch has been held for...The switch generates an interrupt, I then disable switches for a debounce period.  Upon waking in the timer ISR I grab TC0R register (which is a background 2 second timer that is always running)....

    Certainly this kind of thing is commonly encountered.....What is the best way to proceed?  With that in mind I do have one more question that seems like it could have a bearing....

    The counter in which I capture the TC0R register is getting triggered by Port 1 switch interrupt...Now I take it upon myself to clear this IFG and disable the P1IE just before leaving the P1IV however there could be a chance that I am falsely jumping into the counter ISR one too many times which would happen to update one of the holdTime registers by the time I get to doing the math in main....Any suggestions or tricks here?  I am using a demo board and do NOT have analog debounce built out....I am using a 1/2 sec timer for this debounce....I hit a switch disable P1IE and clear it's flag THEN upon waking and entering the 1/2 sec timer I AGAIN clear flag (just in case) before re-enabling P1IE and capturing holdTime

    Thanks for all your advice!

    ---sorry but one more question....I have variables that are defined as unsigned int to capture TB0R.....I don't understand why CCS shows these as signed values in the debugger?  Firstly TB0R is an unsigned value isn't it?

    Steve

  • Using abs() on an unsigned value is pretty useless. You would have to cast one of the values to a long for that to work.

    If you need to know which number is larger, a simple comparison will always work: "if(num1 > num2)"

    For switch debouncing I go a different way. I have a periodic timer interrupt and it reads a port and stores it into a circular buffer. Then AND or OR the bytes together and check a particular bit to see the state of a switch. I probably found that here: www.embedded.com/.../

  • I am doing that for P1 switches....that is I have a 1/10 sec timer that activates after a switch hit then logs for 2 seconds...I then do different stats on it....The problem with the P2 is the switches can be held for a short time to a very long time (indeterminate).  With P2 I have to be able to sense both edges, with P1 it is just momentary.....Any thoughts why I get negative values back in my holdTime array that captures TB0R?

    Within the ISR the assignment is :

            holdTime[m] = TB0R;
    

    definition :

    volatile unsigned int history[20] = {0};
    volatile char m = 0;

  • You get negative values because you are interpreting them that way.  (holdTime is declared as signed int.) This is pretty basic number representation stuff.

    TB0R is naturally an unsigned number with range 0 to (2^16)-1. But you can also look at it as a signed 2's complement number. If you do that, it counts differently. 32767 is followed by -32768.

  • no holdTime is declared an unsigned int

  • It sounds as though holdTime reflects two events for the same button -- a start time and an end time -- so one could say that the end time is later than the start time. In that case, just subtract the earlier time from the later time. Unsigned underflow will give you the correct result (within the range of the timer).

    I'm trying to avoid the terms "larger" and "smaller", since that generally isn't relevant with a cyclic counter -- the "later" time could be numerically "smaller" than the "earlier" time due to counter wrap-to-0.

    Eclipse sometimes seems to do what it feels like for displaying variables. Right-click on the value and choose "Number format".

  • I had them displayed as decimal.....just for the heck of it I used the "restore  to preference".....seems to make everything look positive....sounds like an eclipse bug....Thanks for the help....I think I'm back in business again!!

  • You can use the macro implementation that is type agnostic:

    #define MY_ABS(a) (a>0?a:(-a))

  • I think this may better capture the spirit of what you are trying to occomplish:

    volatile unsigned int overflowHistory[2] = { 0, 0 };

    long int swVolumeHoldTime = 0;

     

    if (overflowHistory[0] <= overflowHistory[1])

    {

       swVolumeHoldTime = 65536L + (long int)overflowHistory[0] - overflowHistory[1];

    }

    else

    {

       swVolumeHoldTime = (long int)(overflowHistory[0] - overflowHistory[1];

    }

    … etc.  

**Attention** This is a public forum