Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Posts posted by tripwire

  1. I was looking at oPossum's code and got to

    TA1CCR0 += (s++ & 1) ? (pwm_period[0] - d) : (d = pwm_on[0]);

    and I stopped there as I need to break that line down and figure out what he's doing!


    Yeah, that packs a lot into a single line!


    It's effectively doing this:

    __interrupt void isr_ccr0(void)
        static unsigned s = 0; // State
        static unsigned d;     // On duration
        if(s == 0)
            d = pwm_on[0];     // Save "on" time, which is used later to calculate the length of the "off" half of this cycle
            TA1CCR0 += d;
            s = 1;             // (0++ & 1) == (1 & 1) == 1
            TA1CCR0 += (pwm_period[0] - d);
            s = 0;             // (1++ & 1) == (2 & 1) == 0

    By the way, Katie's appnote can be used for your case. You need to use the "Multiple Time Base Method", which lets you produce as many PWMs as you have CCRx registers (CCR0 included). It's similar to oPossum's code, but shown with fixed PWM duty cycles rather than variable. It's worth reading through for the analysis of the limitations of the method at the end of the document.

  2. I think I will as we're hoping for dimming control on a LED. Getting the motor portion working was more important for now so I can run some experiments.


    Ok, in that case you can use the same setup as in Doug's code, or the similar technique from the post I linked. With regard to the way the ISRs are written I think oPossum's code is a better example, as it uses the correct method to update TACCRx and also handles the interrupt flags properly in TIMERA1_VECTOR.

  3. There are a couple of independent elements in your project, so I'd suggest tackling each in isolation before putting it all together.


    One part is the button handling: detecting the difference between a "quick push" and holding the button down. To keep things simple you could toggle one LED each time there's a quick press, and flash another LED while the button is held down. I expect you'll want to make sure that the "quick push" LED isn't toggled by the start of a long hold, or the other way round. That'll probably involve polling the button's state every so often, toggling the LED when the button is pressed and then released quickly. If the button isn't released quickly that's a long press, and you could flash the other LED on and off for as long as it's held down.


    The other part is varying the PWM duty cycle. You can work on this without needing the input code: just pretend the button is always pressed, and make the duty cycle go up and down continuously. For this part you'll have to figure out the timing of how quickly the duty cycle changes, and keep track of whether the ramp is on the way up or down.


    Once both are working you can bring them together. The main thing to watch out for there is the two parts interfering with each other. When the button is held down the varying duty cycle code needs to happen inbetween the button checks. If the button check shows that the button is still held the duty cycle variation needs to keep going from where it left off before the check.

  4. OK I took out the PSEL and I still am able to show a change on the input on the switch P1.3, But I still can not get an output, I tried the _delay_cycles() and it appears that I have more setup to do for that to work correctly.  Just changing the code to _delay_cycles() the compiler was not happy about that. 


    Thanks again for the help!!!!


    You need to pass __delay_cycles a number of cycles to wait for, eg "__delay_cycles(40)" will busy wait for 40 cycles. That would give a 40 microsecond delay if MCLK frequency is set to 1MHz. MSP430G2553 will default to approx 1.1MHz on startup, which is good enough for rough timing. If you need more accuracy you can use the DCO calibration constants to set it to 1MHz.

  5. P1SEL |= BTN;


    You shouldn't need to set P1SEL for the button (or the LED), setting bits in PxSEL chooses the peripheral function for the corresponding pin (ie not GPIO function).


    Also, a small suggestion on programming style: it's better to use the __delay_cycles() intrinsic than roll-your-own delay loops. __delay_cycles() takes one parameter telling it how many MCLK cycles to wait for, and then the compiler generates code to use exactly that many cycles. It gives predicatable timing, and there's no risk of the compiler optimising it out.

  6. I am curious as to where you got the specific code for the fgets.c for a specific MSP430xxx?  In my CCS environment trying to step into those routines I don't have the source but can see the assembly.  I used Eclipse in the past for other development so attaching source and such is a familiar activity.

    I just noticed that I never got around to answering this question. Sorry about that!


    In case anyone else finds this post in future and wants to know where the library source code lives, you should find it in:


    {CCS Install Folder}\ccsv6\tools\compiler\msp430_4.3.5\lib\src


    The "ccsv6" and "msp430_4.3.5" parts of the path might have different version numbers depending on your CCS install.


    If that folder doesn't exist or is empty, look in the \lib folder and there will be an rtssrc.zip that you can unpack to get the full source.

  7. I shall check out your template, thanks.


    Maybe i'll post this question on TI's E2E forum, may get more answers there.


    The CCS forum on the E2E board is a good place to ask. Actually I just looked on there and found this:


    Adding a "property sheet" to code composer


    It looks like CCS5.3 added a new way to create templates that's less tightly coupled to the CCS version. I've only skimmed over the wiki page linked in there, but it appears that it'll be easier to use than the other project template system.

  8. Hi 43oh-ers!


    Just wanted to let you all know that we've been working with NKC Electronics to bring the LaunchPad to amazon! Check it out here: 


    Excellent bundles! It took me a while to find a suitable source for M/F jumper wires when I first got my launchpads. Everyone sells M/M ones because that's what arduino requires.


    Are these kits only going to be available from amazon.com, or are they getting rolled out to any amazon storefronts outside the US too?

  9. Also, is there a way to turn on the TI-TXT output by default for every projects? Thanks.


    Do you want to change all your existing projects to output TI-TXT, or just make CCS enable that setting by default for new projects?


    If it's the latter you might be able to change the CCS project templates or add a new one. I worked out how to do it a couple of years ago to set up naken430util cycle count output in all my 430 projects. The tricky bit will be figuring out whether the TI_TXT output setting gets copied from the template correctly (IIRC not all settings can be taken from the templates).

  10. [...]

    if (P1IN & BTN==0) //check button status


    I'm afraid you've fallen into one of the traps set by the designers of C there. They got the precedence of the bitwise operators wrong, so that line will be evaluated as:

    if (P1IN & (BTN==0))

    Instead of what you'd expect it to do:

    if ((P1IN & BTN)==0)

    You need to include the parentheses around P1IN & BTN to get the correct result.


    That doesn't explain why CCS can't find the out file, though. Take a look in the C:\Users\Jake\Google Drive\CCS\Turn lights on\Debug\ folder to see if it's there or not. If it is there maybe CCS is having trouble with spaces in the file path.


    If there's no out file that suggests CCS hit some errors during the build and failed to write it. Try right clicking on your project in the "Project Explorer" view and select "Clean Project". Then build it again and see if there are any errors in the "Console" view. If you can't see what's wrong copy all the console output into a text file and attach it here.

  11. That's one step in the right direction, but there are a few more things to fix before it will work. First of all you have an "if" statement with a semicolon at the end of the line. That detaches the following block {in braces} from the if, so it will always be run. It also leaves the "else" hanging out there on its own, which is why the compiler is unhappy about line 25. You need to remove those semicolons:

    if (BTN==0) // <- no semicolon here!
        // Code here will now only be run if BTN==0
    else        // <- no semicolon here!
        // Code here will now only be run if BTN!=0

    Also, once the preprocessor has replaced the defines in your code, it will have changed the "if" statement from:

    if (BTN==0)


    if (BIT3==0)

    and finally to:

    if (0x08==0)

    That expression is always false (eight doesn't equal zero), so the code inside the "if" block will never run. The compiler might even just remove it completely since it's unreachable.


    You need to test whether bit 3 of P1IN is clear, so this should do the job:

    if ((P1IN & BTN)==0)

    Finally, you're setting the whole of P1OUT in both branches of the if. That's bad because you need P1OUT bit 3 to be high for the switch to work properly. Search for a tutorial on "bitwise operators in C", that'll help you test or change specific bits of a value without affecting the others.


    EDIT: Also your program will exit after testing the button just once. You'll probably have to be holding the button down while you start the program to see any effect.

  12. This line in your working energia code does three things:


    pinMode(BTN, INPUT_PULLUP);


    It sets the pin to input mode, but also enables an internal resistor that pulls the pin up to VCC.
    In the plain C version you only have the pin set to input (which is the default), but the pullup resistor is not enabled.
    If you're using the P1.3 button on the MSP430G2 launchpad, for example, you'll need to set P1REN bit 3 to enable the internal resistor, and also set P1OUT bit 3 to make the internal resistor a pullup (rather than pulldown). With that done, P1IN bit 3 will be 1 when the button is not pressed, and 0 when the button is pressed.
    Your last C example also had a bug in the "if" condition. if(P1IN = 0b00001000) assigns the value 0b00001000 to P1IN, then checks if its value is nonzero. I think you probably wanted to use the equality operator instead, like this: if(P1IN == 0b00001000). I'd expect CCS to produce a warning about that, since using the assignment operator instead of the equality operator is a common C programming bug.
    Finally, you need to be careful how you test P1IN; if(P1IN == 0b00001000) doesn't just require bit 3 to be 1, it also requires all the other bits to be zero (which they might not be). It's best to just check the bit(s) you're interested in: if((P1IN & 0b00001000) == 0b00001000) is only true if bit 3 of P1IN is set, no matter what the other bits are set to.
  13. why use delay loops if you can use timers and low power mode to achieve a similar goal?


    Also, if you really need a busy wait it's better to use the __delay_cycles() intrinsic function. That way the compiler definitely won't optimise it out and the length of the delay is clearly defined.

  14. I'm guessing you've jumpered P1.4 to P1.5 so that when P1.4 is toggled it will trigger the capture. Does the capture interrupt never fire, or does it run but not print the output, or is the printed output incorrect?


    It's not clear exactly where the problem lies, so I'm going to throw out some suggestions which may or may not be relevant.


    The condition on the line "if (P1IN & BIT5 ==1)" will never be true, as it is evaluated like so: if (P1IN & (BIT5 ==1)). BIT5 isn't equal to 1, so that becomes if (P1IN & 0), which is always false. You'll need to use parentheses to force the evaluation order.


    The test "if (t2 > t1)" will cause you to lose a pulse if the timer wraps around to zero between the rising and falling edges. If you store t1 and t2 in 16 bit unsigned integer variables it will still be safe to calculate (t2-t1) in this situation. Depending on your compiler you might need to switch t1 and t2 to be unsigned short type rather than unsigned int.


    Testing P1IN bit 5 to check the state of the input after the capture interrupt is dubious. Some microseconds pass between the rising edge of the pulse being detected and the interrupt service routine starting to execute. In this test program that will be OK as the main loop will be halted before it can clear P1OUT bit 4, but if you hook this up to an external input you might get incorrect readings. If you can spare another CCR it would be better to capture rising and falling edges separately, and only interrupt on the falling edge. Then you would have the rising edge capture in CCR1 (for instance) and the falling edge in CCR0, ready for handling.


    Calling UART print functions during the ISR is also not a great idea. It means you'll be stuck in the ISR for a long time and won't be able to process any interrupts until the printing is complete. If the UART code is interrupt-based that could even cause a deadlock.


    By the way, I think this topic belongs in "General" rather than "Compilers and IDEs", so a mod may be along to move it over at some point.

  15. I just tried to send a PM and got an error saying "The member [...] cannot receive any new messages. This personal message has not been sent". That's probably because their messagebox is full or disabled. Fair enough.


    Anyway, I then tried to save the message to send later and got the exact same message. The message didn't save to the drafts folder. Removing the member name doesn't help either (gives a message saying it needs to be specified).


    I'm not sure what's going on here. Perhaps the "Save (Send later)" button is actually trying to send the message. If not then the save function is doing a bit too much validation before it lets you save, and the error message is misleading (should say "not saved" instead of "not sent").


    I'm guessing this is an IP.Boards issue, but they don't let you read posts on their support forum without a client account :(

  16. Table 16 ("TA2 signal connections") on page 33 of the datasheet is a good place to start. The left half of that table shows the inputs for the different module blocks of TA2. For externally connected inputs it gives the corresponding pin numbers for the various package types. In the case of the F5529 this is fairly simple; P2.3-5 are your external inputs to TA2, so the input pins match the output pins. That's not always the case, which is why it's important to check the timer's "signal connections" table in the datasheet.


    Notice how the table says that the three external inputs are called module input CCI0A, CCI1A and CCI2A. You'll need to know that when you set up TA2CCTL0, TA2CCTL1 or TA2CCTL2 later.


    Assuming you've connected the input signal to P2.3, you then need to configure that pin to pass the input through to the timer module. Table 50 on page 83 of the datasheet shows what you need to do. In this case, you want to configure P2.3 for the TA2.CCI0A function. That means clearing bit 3 of P2DIR and setting bit 3 of P2SEL.


    Next you need to set up TA2CCTL0. Set the CAP bit, and set the CCIS bits to 00 to take the input from for CCI0A. You can pick which signal edge(s) trigger a capture with the CM_x bits.


    Finally you need to set up the timer. For capturing you generally want to use continuous mode so the range of timer values is as big as possible.


    To measure the frequency and duty cycle you'll need to capture the timer's value on the rising and falling edge of the input signal. You can either use a single capture register set to capture on both edges, or use separate registers for the rising edge and the falling edge. If you use two registers you'll need to connect the input signal to multiple timer input pins, of course.

  • Create New...