2
\$\begingroup\$

I can blink the led but the time of it's very 1 second or 2 second.I try to increase but it did not.But my question I'm using L293D motor driver to control motors.I want to Dc motors turn when button switched 15 second.This my code but I can't find a solution.I m asking how to increase the time

#include "io430.h"
void delay(unsigned long int d)
{
  d*=9999999999999999;
  for(;d>0;d--);
}
void main(void)
{

  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer

P1DIR = BIT6 + BIT4  + BIT7 + BIT0;          // Toggle P1.0 using exclusive-OR
P1DIR &= ~BIT3;
if((P1IN&BIT3) == 0){ 
P1OUT |= BIT6 + BIT4  + BIT7;
}
else
{
 P1OUT |= BIT0;
delay(9000);
}
}
\$\endgroup\$
  • \$\begingroup\$ are you using mspgcc or IAR or CCS? \$\endgroup\$ – jsolarski May 2 '11 at 0:03
  • 1
    \$\begingroup\$ any update on this? How are you coming along with your project? \$\endgroup\$ – Dave May 5 '11 at 19:49
2
\$\begingroup\$

My suggestion would be get rid of the delay function and use the built in if you are using IAR or CCS."__delay_cycles (cycles);" using the built ins, will give you more predicable results and better timing. You could probably just replace your delay for the built in, to get closer to the results you are looking for.

personally I would go about the whole thing using interrupts and timers to pull the whole thing off and use the peripherals that the msp430 has. I would suggest using the WDT as an interval timer, doing this would leave the other timer for your motor control. p1.3 is used as the wake up pin and p1.0 is the led pin.

example code

volatile int counter;
void main(void) {
    WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
    P1DIR = 0x01;                             // P1.0 output, else input
    P1OUT =  BIT3;                            // P1.3 set, else reset
    P1REN |= BIT3;                            // P1.3 pullup
    P1IE |= BIT3;                             // P1.3 interrupt enabled
    P1IES |= BIT3;                            // P1.3 Hi/lo edge
    P1IFG &= ~BIT3;                           // P1.3 IFG cleared
    _BIS_SR(GIE);
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
    WDTCTL = WDT_MDLY_64; //enables intervals of 64mS
    IE1 |= WDTIE;  // set WDT interrupt
}
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer (void)
{
    ++counter;
    P1OUT |= BIT0;
    if (counter == 245) {  //245 x 64mS = 15.6 seconds
        P1OUT &= ~BIT0;
        WDTCTL = WDTPW + WDTHOLD; 
    }
}

Not complete nor has this code been tested, but it should turn the led on for 15 seconds every time the P1.3 button is pushed.

\$\endgroup\$
  • \$\begingroup\$ this is a much better way to implement the delays! great example. \$\endgroup\$ – Dave May 2 '11 at 5:33
0
\$\begingroup\$

That "d *= 9999..." looks suspicious. That many nines times 9000 is 0xE100 3B28 D927 DCD8 hex - 64 bits. I don't know what sizeof(unsigned long int) * CHAR_BIT evaluates to on MSP430 but on most systems it's 32. In other words it would be overflowing the variable. So assuming an unsigned long int is 32 bits, the value your code is using is D927 DCD8.

Are you getting a compiler warning about truncation?

A good way to experiment with delay loops is with a binary search. Start the value off at 0x1. That won't work (of course), so move to 0x2, 0x4, 0x6, 0x10... each value double the prior. If it's too slow, back off and start setting lower order bits but from the top down. Once you hit 0x8000 0000 (again assuming a 32-bit long) you only get one more doubling if you set every lower-order bit, so unless you are close you need to think about using two delays (nested loop).

\$\endgroup\$
0
\$\begingroup\$

If you're using the built in oscillator, you don't need to delay that long for 15 seconds. In a tight for loop, I think a 15 second delay is closer to 1500000 loops. Plus, you can't multiply by such a large number.

I think the other problem is with your if/else statement. You're using |= in both cases, so when you push the button, you aren't toggling the bits -- BIT0, BIT4, BIT6, and BIT7 eventually will all be high. If you can provide more information about what you're doing with all of the bits, and maybe a circuit diagram, that will help me help you more.

EDIT -- To address the delay implementation part of your question, jsolarski certainly has the best solution for the timer. I looked into it some more since I haven't used timers with the MSP430, and ended up with some questions of my own. I'm going to put my findings here just for discussion's sake, and hopefully jsolarski can add comments where appropriate.

You've got a several core clock sources, which include LFXT1CLK, XT2CLK, DCOCLK, and VLOCLK. I'm personally going to be using an internal clock source for my application, and am going to try VLOCLK first.

Once you have a clock source selected, now you have to determine where three other internally-generated clock sources will originate from. These other three clocks are ACLK, MCLK, and SMCLK. Conveniently enough, VLOCLK is a valid clock source for all three. You can also set a prescaler for these clocks, in case you don't need high-speed timing.

You will want to configure the WDT to use interval mode via WDTTMSEL. This also requires you to set WDTIE bit in IE1. You'll also want to set your clock source via WDTSSEL and prescaler via WDTISx.

I couldn't figure out what WDT_MDLY_64 equates to, based on his numbers, but that's expected because you haven't specified what clock source you intend to use.

Hopefully this edit to my answer has given you some more information on how to set up the WDT for intervals, should you decide to try it. However, I think your problem is more fundamental as my original answer stated, regarding your use of |=, and whether you use a tight for loop or intervals, it just wouldn't work.

\$\endgroup\$
  • \$\begingroup\$ I want to control Dc Motor with L293D.I connected the pins with each other.So I want to motor turns for more than 3 second.But first,for experimental I'm trying to blink led for5 second but it took 1 or 2 seconds.What should I do \$\endgroup\$ – Cenk May 1 '11 at 7:40
  • \$\begingroup\$ If you're okay using a tight loop for now to do delays (I wouldn't recommend it for the final implementation), then I'd hook a scope up to an output pin and have it set a bit high, delay X ticks, set the bit low, delay X ticks again in a loop. Then modify the number of loop iterations until you get the desired time delay. You can't just use a ginormous number like you are currently doing, like what John Lopez already said. If you need a bigger delay than what a 32 bit number gives you, then you need to use a nested for loop. \$\endgroup\$ – Dave May 2 '11 at 4:02
  • \$\begingroup\$ You are correct you can source from all those clocks, but in the case of the launchpad, he will have the choice of the aclk or smclk or mclk sourced from either the DCO or crystal. no VLO on the value line series chips. From the code he posted he will be using the defualt mclk @1MHz. as for WDT_MDLY_64 64ms is based on SMCLK @1MHz. I can elaborate more later if needed. \$\endgroup\$ – jsolarski May 2 '11 at 15:55
  • \$\begingroup\$ @jsolarski thanks for the info -- but I cannot find data confirming the lack of VLO in the Valueline series. I'm looking at the datasheet for the MSP430G2231 right now, and it discusses the DCO and VLO, but makes no mention about the VLO not being available in certain series. \$\endgroup\$ – Dave May 2 '11 at 18:41
  • \$\begingroup\$ I will have to correct my self a bit, If you look at the basic clock module chapter in the user guide, BCSCTL3 LFXT1Sx bits 5-7, VLO can be sourced instead of the crystal. the info is a bit cryptic and buried lol, the VLOCLK is a valid source for value line chips, instead of the crystal. \$\endgroup\$ – jsolarski May 2 '11 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.