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: Having code issues with pointer to float

Part Number: MSP430FR2355

Can someone please help me here as I am not getting this...

I have 

float avg = 0;
uint16_t *pTx = &avg;

avg is a bunch of a/d conversions and it looks good at runtime (as an example avg = 3834.0)

I send this value to a function :

UCA1TXBUF = itoa((((uint16_t)(avg)) >> (4 * lowByte)) & 0x0F);

and it gets transmitted just fine....

I would like to use a pointer however bcz I will be calling the function for various data.  The issue I am running into is one time I call the function I will be passing a float (as you can see above), however there are times when the function will get called and I will be passing a volatile uint16_t to the function.  How do I describe the pointer / typecast it to get around this?

Thanks

  • I've never used unions before (hardware guy doing firmware).

    I've got the following in the h file:

    extern __vo uint16_t pwmDiv;
    union rtnVals
    {
        float avg;
        __vo uint16_t pwmDiv;
    };
    

    In the C file is

    #pragma LOCATION (pwmDiv, 0x1800);
    #pragma PERSISTENT(pwmDiv);
    __vo uint16_t pwmDiv = 50;
    
    
    float avg = 0;
    
    
    rtnVals *prtvVals;
    

    The benign function call in the UART in the c file is:

              UCA1TXBUF = itoa((((uint16_t)(*pTx)) >> (4 * lowByte)) & 0x0F);
    

    Somehow I need to have the pTx pointing to prtvVals???  I don't know how to do this?

  • I tried to put the code in a single file for readability...

    //IN H FILE
    extern __vo uint16_t pwmDiv;
    union rtnVals
    {
        float avg;
        __vo uint16_t pwmDiv;
    };
    
    
    //IN C FILE
    
    #pragma LOCATION (pwmDiv, 0x1800);
    #pragma PERSISTENT(pwmDiv);
    __vo uint16_t pwmDiv = 50;
    
    
    uint16_t *pTx;
    
    union rtnVals *prtnVals;
    
    
    prtnVals->avg = (float)sum / numberADSamples;
    pTx = (uint16_t*)(&prtnVals);
    UCA1IE |= UCTXIE;
    
    //ISR piece
          case USCI_UART_UCTXIFG:
    //          UCA1TXBUF = itoa((((uint16_t)(*pTx)) >> (4 * lowByte)) & 0x0F);
              UCA1TXBUF = itoa((((*pTx)) >> (4 * lowByte)) & 0x0F);
              while (!(UCA1IFG & UCTXIFG)); //wait until buffer empty
    
    

  • You want to make the union values pointers, not values:

    union rtnVals
    {
        floatp *avg;
        __vo uint16_t *pwmDiv;
    };

    union rtnvals rvals;

    rvals.floatp = &floatToSave;

    But this is all basic C.

  • My apologies but pointers in C are not 'basic'....Your brevity in response although may be good with those who right firmware every day doesn't do much to help those who are trying to learn.

    My issue is somewhat complex at this end and I feel I am not conveying it completely...

    In short I have a uart and want to send data to the PC....this data is either configuration data or live a/d data.  The configuration data will be a dump of 5 locations upon request.  I want the UCA1TXBUF to point to one piece preferably a pointer within the ISR. I will update the pointer each time within main before I enable the ISR to send.  

    Based on your last comments I have gotten this far but now you are suggesting to use pointers...please see below my attempt as I am getting close (or so I think)

    I have a union which consists of two declarations a float and a uint16_t:

    union rtnVals
    {
        uint16_t memRecall;
        float liveData;
    };
    

    I create an instance of this as well as a pointer to it:

    union rtnVals t_rtnVals = {0};
    union rtnVals *prtnVals = &t_rtnVals;
    

    In different parts of the code I initialize the prtnVals:

    Case 1: (pFRAM is a volatile uint16_t; it points to area in memory)

                            prtnVals->memRecall = *pFRAM;
    

    Case 2:

                        prtnVals->liveData = (float)sum / numberADSamples;
    

    Using the UART I want to send this data back to the PC with the following formula:

    UCA1TXBUF = itoa((((*pTx)) >> (4 * lowByte)) & 0x0F);

    Where pTx has been defined as a uint16_t and takes on the value of prtnVals:

    pTx = (uint16_t*)(prtnVals);

    When I debug prtnVals seems to always look correct.  pTx only looks correct when it takes on prtnVals -> memRecall.  If I followI have tried swapping elements in the union but it makes no difference.  I also tried adding + 4 to prtnVals in the event that it had to do with a float being 4 bytes but that doesn't work either....Can someone tell me how to address this??

    You may be asking why pTx .....It is because I want the formula to UCA1TXBUF to be fixed and don't want to have to change it each time BECAUSE pFRAM when called will be getting advance to return up to 5 configuration values.  So effectively if the code is to read live data it will read an A/D and if it is to read configuration it will read up to 5 values of uint16_t.....

    Thanks for any help here

  • Your problem appears to be that you want to use a single location to store either a float or an integer but the interrupt service routine has no way to tell what is currently stored at that location.

    Actually it is worse as it appears that your code treats integer and float values the same.

    Or try something simpler.  Make your variable "sum" a fixed point value by adding up a power of two samples. (2, 4, 8). With a modest number of samples you will not overflow an integer.

  • Thank you very much....I'm still a little fuzzy BUT I did what I believe you were suggesting and now I seem to at least be able to get correct values returned on both live data and memory config.  I made the following code changes:

    1. liveData no longer a float

    union rtnVals
    {
        uint16_t liveData;
        uint16_t memRecall;
    };
    

    2. removed typecasting of (float)

    prtnVals->liveData = sum / numberADSamples;

    3. changed pTx to such: (finding the right & and * combination was a struggle)

    pTx = (uint16_t *)(*(&prtnVals));

    4.  ISR formula now super basic:

    UCA1TXBUF = itoa((*pTx >> (4 * lowByte)) & 0x0F);

    Fingers crossed I don't overflow or anything and also I can change pTx to other pieces of config data!

  • Just to help a little because you mentioned you're more of a hardware guy. If your code works fine now, I would leave it but for future reference on unions I would check this (Not a TI Site) https://www.tutorialspoint.com/cprogramming/c_unions.htm . It should help a little more with the concept of unions.

    It might be the other missing code portions we aren't seeing but if you're going to use the same data type you won't need the union anymore, as the special use of a union is to have different data types on the same memory address. Though you could keep the union to group those values together, or keep it cause your code is working. 

    For pointers the & is used to get the memory address (reference), and the * is used to get the value at that memory address (dereference). *(&val) is the same as just doing val, so any pair of *& can be removed.

    Since your prtnVals is a pointer just doing

     

    pTx = (uint16_t*)(prtnVals);

    would be equivalent, but this is because prtnVals is a union and currently can be type casted to a uint16_t. In your old code if the last change was the float then this type cast wouldn't work. 

    Regards,

    Luke

  • Thank you for that response!  I will go back to the code to make these changes and test them out....I believe I tried the line you show but had no luck...Will try again....

    Yes as far as both data points the same...I wanted one as a float but couldn't get it to work until I did what David suggested which was change it to a fixed point ....

  • Yes David's suggestion is what fixed that issue you were seeing, changing the line I mentioned only works because all the data is the same type. Type casting pointers doesn't work the same as type casting data types. 

    Regards,

    Luke

**Attention** This is a public forum