• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » MYSTERY! Creating a C++ object causes F2013 P1OUT pins to go high! Please help!
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • Forums

    MYSTERY! Creating a C++ object causes F2013 P1OUT pins to go high! Please help!

    This question is answered
    Sarah Cartwright
    Posted by Sarah Cartwright
    on Apr 11 2012 12:26 PM
    Prodigy140 points

    Hi!

    I wanted to make my little PWM program a bit more scalable, and so I wrote a quick C++ program which is below.

    For the longest time I thought I'd got my logic wrong - because the LED's weren't behaving themselves, but when I tried stepping into the program right from the start, I found that the line of code causing them to illuminate was nothing to do with P1OUT!

    The program is below, and I'm very bemused - could it be the compiler doesn't support objects for the F2013? From what I know, the object data is just stored in a contiguous section of ram, of which there's 128 bytes. So I lowered the 8 objects for my 8 outputs down to 2 objects, and it still goes wrong... so I don't think the object data is writing over the P1OUT port....

    If you have any ideas, or suggestions to try to help debug the program, please let me know!

    Thanks!  =D

    #include <msp430x20x3.h>

    class dimmableLED
        {
        public:
        unsigned short int dutyCycles;
        unsigned short int onCycles;
        unsigned short int currentCycle;
        unsigned char bitNumber;
        dimmableLED(void);
        void cycle();
        };

    dimmableLED::dimmableLED(void)
        {
        dutyCycles=10;
        onCycles=5;
        currentCycle=0;
        bitNumber=2^6;
        }

    void dimmableLED::cycle(void)
      {
      bool output=0;
      if(++currentCycle<onCycles) output=1;
      if(currentCycle==dutyCycles) currentCycle=0;
      if(output) P1OUT |= bitNumber; else P1OUT &= bitNumber;
      }


    int main(void)
    {
    unsigned short int index;

    WDTCTL = WDTPW + WDTHOLD;
    P1DIR = 255; // All out
    dimmableLED* LED = new dimmableLED[2];   <<<<<<< THIS MAKES MY OUTPUTS HIGH! in binary they look like this: LSB>HSB  = 01101000

    for(index=0;index<1;index++)
        {
        LED[index].bitNumber=2^(index+3); // Position the lit LED's a little way down the full 8 LED's.
        }

    for(;;)
        {
        for(index=0;index<1;index++)
            {
            LED[index].cycle();
            }
        }
        
    }

    scalable 
    eZ430-F2013 C++ output objects mystery
    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • old_cow_yellow
      Posted by old_cow_yellow
      on Apr 11 2012 14:06 PM
      Guru25715 points

      PxOUT is unchanged after PUC, POR, or BOR. Thus when you start executing code, They may have any bit patten in them. However, PxDIR, PxSEL, etc. are cleared by PUC, POR or BOR. Thus the corresponding pins are in digital input mode and PxOUT has no effect.  If your code sets any PxDIR bit, the corresponding pin becomes an digital output pin and will go actively high or low according to PxOUT,

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 11 2012 14:36 PM
      Prodigy140 points

      Thanks, I'll try doing a P1OUT=0;

      I'm worried that object data is getting written into places it shouldn't...

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Chester Gillon
      Posted by Chester Gillon
      on Apr 11 2012 17:03 PM
      Mastermind6315 points

      Not sure if this is the cause of the problem, but the following lines look strange:

      bitNumber=2^6;
       LED[index].bitNumber=2^(index+3); // Position the lit LED's a little way down the full 8 LED's.

      The ^ operator in C++ is a bit-wise exclusive or, yet the lines are written as if a 2 to the power operation is wanted.

      Should these lines be:

      bitNumber = 1 << 6;

      LED[index].bitNumber = 1 << (index+3)

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Roger 8421
      Posted by Roger 8421
      on Apr 11 2012 19:11 PM
      Intellectual290 points

      Also

      [code]if(output) P1OUT |= bitNumber; else P1OUT &= bitNumber;[/code]

      looks like it should be

      [code]if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber;[/code]

      to clear a bit

      Regards

      Roger.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 12 2012 13:17 PM
      Prodigy140 points

      Ooops! Thanks! I was using the wrong language.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 12 2012 13:24 PM
      Prodigy140 points

      With the little fixes, and also moving to C, as well as stepping through the C++ code - I can confirm that the C++ one gets crazy figures in the counters.

      The following C program works fine, and is 402 bytes long.

      The equivalent C++ program below it doesn't work correctly, and is 972 bytes long! I don't think the compiler is cut out to make C++ into assembly code for this MPU.

      --------------- --------------- --------------- --------------- --------------- --------------- ---------------

      Working AOK!

      #include <msp430x20x3.h>

      const unsigned short int LEDCount=8;

      unsigned int dutyCycles[LEDCount];
      unsigned int onCycles[LEDCount];
      unsigned int currentCycle[LEDCount];
      unsigned int bitNumber[LEDCount];

      void cycle(unsigned short int LED)
        {
        bool theOut=false;
        if(++currentCycle[LED]<=onCycles[LED]) theOut=true;
        if(currentCycle[LED]>=dutyCycles[LED]) currentCycle[LED]=0;
        if(theOut) P1OUT |= bitNumber[LED]; else P1OUT &= ~bitNumber[LED];
        }

      int main(void)
      {
      unsigned short int index;
      int anim=0;

      WDTCTL = WDTPW + WDTHOLD;

      DCOCTL=CALDCO_16MHZ;
      BCSCTL1=CALBC1_16MHZ;

      P1OUT=0;
      P1DIR = 255; // All out


      dutyCycles[0]=200;
      onCycles[0]  =1;

      dutyCycles[1]=200;
      onCycles[1]  =6;

      dutyCycles[2]=200;
      onCycles[2]  =23;

      dutyCycles[3]=200;
      onCycles[3]  =110;

      dutyCycles[4]=200;
      onCycles[4]  =199;

      dutyCycles[5]=200;
      onCycles[5]  =110;

      dutyCycles[6]=200;
      onCycles[6]  =23;

      dutyCycles[7]=200;
      onCycles[7]  =6;




      for(index=0;index<LEDCount;index++)
          {
      //    dutyCycles[index]=450;
      //    onCycles[index]=index*50+50;
          currentCycle[index]=0;
          bitNumber[index]=1<<index;
          }



      for(;;)
          {
          for(index=0;index<LEDCount;index++)
              {
              cycle(index);
              }

          if(++anim>5000)
              {
              int i,a,b;
              a=dutyCycles[0];
              b=onCycles[0];
              for(i=0;i<LEDCount-1;i++)
                  {
                  dutyCycles[i]=dutyCycles[i+1];
                  onCycles[i]  =onCycles[i+1];
                  }
              dutyCycles[LEDCount-1]=a;
              onCycles[LEDCount-1]  =b;
              anim=0;
              }
          }

      }

      --------------- --------------- --------------- --------------- ---------------

      C++ Fails:


      class dimmableLED
          {
          public:
          unsigned short int dutyCycles;
          unsigned short int onCycles;
          unsigned short int currentCycle;
          unsigned char bitNumber;
          dimmableLED(void);
          void cycle();
          };

      dimmableLED::dimmableLED(void)
          {
          dutyCycles=10;
          onCycles=5;
          currentCycle=0;
          bitNumber=2<<6;
          }

      void dimmableLED::cycle(void)
        {
        bool output=0;
        if(++currentCycle<onCycles) output=1;
        if(currentCycle==dutyCycles) currentCycle=0;
        if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber;
        }


      int main(void)
      {
      unsigned short int index;

      WDTCTL = WDTPW + WDTHOLD;

      P1OUT=0;
      P1DIR = 255; // All out
      dimmableLED* LED = new dimmableLED[8];

      for(index=0;index<8;index++)
          {
          LED[index].bitNumber=1<<index;
          }

      for(;;)
          {
          for(index=0;index<8;index++)
              {
              LED[index].cycle();
              }
          }
          
      }


      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 12 2012 13:51 PM
      Prodigy140 points

      After stepping through the code, and discovering all the random values, I thought that perhaps the constructors weren't getting called.

      Figuring that the array of objects wasn't being initialised properly - and only vaguely remembering that a pointer to the start of memory was what an array name was. I re-wrote the code with some other definition for an array of objects that I found online - I NEED to find out why the constructors weren't called with my original code, but they were with the new code. Coming from C, and Java - the behaviour seems a bit odd.

      Anyway - thanks for all the work : HERE is the working version!

      class dimmableLED
          {
          public:
          unsigned short int dutyCycles;
          unsigned short int onCycles;
          unsigned short int currentCycle;
          unsigned char bitNumber;
          dimmableLED(void);
          void cycle();
          };

      dimmableLED::dimmableLED(void)
          {
          dutyCycles=200;
          onCycles=5;
          currentCycle=0;
          bitNumber=1;
          }

      void dimmableLED::cycle(void)
        {
        bool output=0;
        if(++currentCycle<onCycles) output=1;
        if(currentCycle==dutyCycles) currentCycle=0;
        if(output) P1OUT |= bitNumber; else P1OUT &= ~bitNumber;
        }


      int main(void)
      {
      unsigned short int index;

      WDTCTL = WDTPW + WDTHOLD;

      DCOCTL=CALDCO_16MHZ;
      BCSCTL1=CALBC1_16MHZ;

      P1OUT=0; P1DIR = 255; // All out

      //dimmableLED* LED = new dimmableLED[8];
      //dimmableLED* LED[8] = new dimmableLED();
      dimmableLED LED[8]; << WORKS!

      LED[0].onCycles = 1;
      LED[1].onCycles = 2;
      LED[2].onCycles = 4;
      LED[3].onCycles = 11;
      LED[4].onCycles = 23;
      LED[5].onCycles = 50;
      LED[6].onCycles = 110;
      LED[7].onCycles = 190;

      for(index=0;index<8;index++)
          LED[index].bitNumber=1<<index;

      for(;;)
          for(index=0;index<8;index++)
              LED[index].cycle();
          

      }

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TonyKao
      Posted by TonyKao
      on Apr 13 2012 01:51 AM
      Verified Answer
      Verified by Sarah Cartwright
      Genius3770 points

      Hi Sarah,

      I'm not exactly a C++ guru myself, but I believe

      dimmableLED* LED = new dimmableLED[8];

      tries to allocate a pointer to a newly initialized heap space containing an array of 8 dimmableLED's. Hence using the "dot" notation to access the objects would result in undefined behaviour.

      You should try

      LED[i]->onCycles = n;

      to access the members of the objects. Or you can use the third line, which initializes the objects in the stack (but that comes with its own problems if used unwisely).

      BTW, dynamic memory allocation is inherently more expensive than any "static" version, C++ or otherwise, since the constructor is called for each of the object instances of your class. If you look at the linker produced memory map file, you'd see that half of the code is spent on run-time allocation and initialization of the objects.

      A better way would be to remove your custom constructor and treat the class as a POD ("Plain Old Data"); you can then initialize it using

      dimmableLED LED[8] = {200, 5, 0, 1};

      as if you're treating the object's data members collectively as an array of members (which is actually how it's represented in memory). This dramatically reduces the code size to 274 bytes (in CCS 5.1) and retains all the OOP niceties of C++, sans dynamic allocation.

      Not that this will not work if you have a user-declared constructor, virtual functions, or non-static data members with different access control. See http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176

      Tony

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 13 2012 02:30 AM
      Prodigy140 points

      Thank you!

      You've explained it very well.

      I was impressed with the size you got the code down to, and so I had a go. But I'm having a bit of trouble with the instructions about removing the constructor. =(

      I've removed the constructor, and want to initialise the timers  in the objects, but I don't understand where the following line puts the numbers without a constructor!:

      dimmableLED LED[8] = {1,  2, 4, 11, 23, 50, 110, 190};

      I'm also at a loss how to assign the other values to the objects,. such as duty cycles, I don't think this would work?

      LED[].dutyCycles = {200, 200, 200, 200, 200, 200, 200, 200};

      Have you got any time to point me in the right direction, or even the code itself - I've been programming in Java, and C and stuff for years, so I should be able to understand what's going on with my reference manual, and a bit of time. Finding the syntax is very hard though!

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TonyKao
      Posted by TonyKao
      on Apr 13 2012 03:18 AM
      Genius3770 points

      Hi Sarah,

      Sorry for the confusing, I should've been more clear about the initialization (I blame my insomniac posting at 4am). To initialize the dimmableLED array to the values in your original code, do

      dimmableLED LED[8] = {
          //dutyCycles    onCycles    currentCycles    bitNumber
              {200,        1,          0,               1}, // array element 0
              {200,        2,          0,               1},
              {200,        4,          0,               1},
              {200,        11,         0,               1},
              {200,        23,         0,               1},
              {200,        50,         0,               1},
              {200,        110,        0,               1},
              {200,        190,        0                1}
      };

      which is the same syntax as initializing a 2d array or an array of structures. Of course what you end up with is more than just vanilla C arrays or structures.

      And yes C++ can be appear quite opaque esp. if you come from C or Java (as I do), since it appears to share the same syntax, yet it's almost a completely different language with its own models and paradigms. However, once I (sort of) got the hang of it, I was shocked at how powerful and efficient the language can be; some things you can easily do in C++ are just painful or near impossible in plain C.

      FYI, highly recommend articles by Dan Saks, who is probably the best C++ "evangelist" in embedded programming: http://www.eetimes.com/electronics-blogs/27/Programming-Pointers

      Tony

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 14 2012 03:06 AM
      Prodigy140 points

      Thank you! Brilliant!

      I'll check out the book by Dan - it sounds a good way for me to learn good programming patterns for C++ in embedded systems.

      I've amended my prototype board so there's 4 switches (I know I could have used a matrix, but this was quicker) - and 4 LED's.

      I'm going to write it so that the first 2 buttons select the delay being edited... LED 1 - On time, LED 1 - Off time, LED 2 - On time, etc........

      Then the other 2 buttons will increase and decrease the time. Using debouncing and 'single press' code so it doesn't cycle through values too rapidly.

      Then I realised the line: if(output) P1OUT &= ................. is a BAD idea!

      If I'm using this for PWM tests on several channels, I need the values to change at once - so I'm taking the P1OUT code out of the loop, and putting it after the loop reading the buttons, and amending the PWM timers... so it changes all outputs AT ONCE:

      P1OUT= (LED[0].bitNumber)&(LED[1].bitNumber)&(LED[2].bitNumber)&(LED[0].bitNumber);

      I don't think there's anything that will throw this off.....

      Next step : The Raspberry Pi Inputs!

      Thanks for all your help - it's really appreciated, and you've got no points or awards to show for it either! There should be some sort of ranking table!

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • TonyKao
      Posted by TonyKao
      on Apr 14 2012 15:54 PM
      Genius3770 points

      Hi Sarah,

      Glad to know I'd been of help.

      It occurred to me however that you're trying to do PWM via software. Have you looked into Timer_A generated hardware PWM? They are much more accurate and do not require any CPU intervention aside from the initial setup and optional interrupt servicing; moreover they can continue to operate in low-power modes meaning you can turn the CPU off. They can also source clock from other than MCLK, allowing for async operation.

      You can still use C++ classes to map and program the Timer peripherals; in fact it can be more elegant/efficient than the C equivalent. I have a basic class model for accessing the Timer_A registers using memory-mapped objects, if you're interested I can clean the code up and post it.

      Tony

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Sarah Cartwright
      Posted by Sarah Cartwright
      on Apr 15 2012 02:33 AM
      Prodigy140 points

      Hi Tony!

      >Have you looked into Timer_A generated hardware PWM?

      I haven't yet! That sounds ideal, and it would give accurate timings. (as far as oscillating circuits can).   =)

      > in fact it can be more elegant/efficient than the C equivalent. I have a basic class model for accessing the Timer_A registers using memory-mapped objects, if you're interested I can clean the code up and post it.

      Ohhh, would you? That would be brilliant. =D

      ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -------

      I extended the C++ program to enable a user to control the PWM -  but found that accessing the on-cycles, and duty-cycles values was much easier when I'm using a cursor, by putting them all in one big array. I'd have had to write more code in the C++ to access the right object and value (On time/Duty cycle) based on the cursor position!

      So what I did was drop down to C, and combine the two values for each LED into one homogenous array. That way a simple "cursor" that is simply indexing the array can control all the timers of all the LED's without any code-bloat.

      The code's here: http://sarahs-muse.livejournal.com/1343114.html

      Now, I'd LOVE to write it in C++, but with the streamlined data access of the single array. I'm sure it's possible due to the way the objects are stored in order...

      I'm going to run through the book you recommended - there must be some good design patterns to optimise the C++ in this kind of situation.

      I have to pause my little projects now - the little Pi computer's plugged into the board. =)

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use