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.

Switching Low Power Modes

Other Parts Discussed in Thread: MSP430G2533

I am working on a project that will remain inactive for the majority of the time.  For this reason, LPM4 is ideal for the vast majority of time.  When the project is active I will have a wheel spinning and for each revolution a capture interrupt will fire.   As the wheel spins I will keep track of the speed and if above a certain point will make measurements using an ADC10 peripheral.  In order to keep track of time I understand I can no longer be in LMP4.  My question has to do with getting out of LPM4 and back into LPM4 once the wheel stops spinning again.  I've added my logic below and was hoping someone could verify if it's good idea or not.

1.  Enter LMP4 in Main

2.  Upon first Capture Interrupt, enter LPM0 in the ISR.  Enable compare interrupt on another Timer_A peripheral.

3.  Monitor time between capture interrupts with a compare interrupt using a global variable and test the time with an if loop in the compare ISR.

4.  If the down time requirement is met, put the MSP430 back into LPM4.  If it does not meet the requirement do nothing.

If I am making a novice mistake please let me know

Take care,

Jon

  • Hi Jon,

    There are a couple of points that you may have already considered but haven't mentioned above. Also, I'm not sure if they're relevant as you haven't mentioned which specific MSP430 you're going to be using. It would be helpful if you would provide details of the hardware setup you plan to use. My experience is with the value line chips only, so bear that in mind when reading my comments.

    First of all, what are your timing requirements; how fast is the wheel spinning and how accurate do the timings need to be? If you can switch to using ACLK (LFXT1) for the timings you'll be able to use LPM3 instead of LPM0 which will reduce current consumption greatly. I don't know whether it will be feasible in your project though.

    Also, you may be able to avoid using the second TimerA peripheral by using a second CCR in compare mode on the same timer, or with the TAIFG interrupt. Again, more detail on the expected input and downtime durations would help with that.

    Something to watch out for is the effects of using TimerA while the clocks are all disabled. I've never tried it myself so I don't know if it works. From the block diagram it looks like you'd have to keep SCS clear, as enabling that flag would make the timer wait forever to sync the input with the clock source.

    Rob

    EDIT: Removed some nonsense about race conditions between capture input and clock tick - if the clock's not ticking there can be no race condition!

  • Rob,

    Thanks for the input.  I should have put both capture and compare in the same timer.  Good point.  I will be using a value line chip the MSP430G2533 to be exact.  I will look into using LPM3 opposed to LPM0.  

    The timing does not need to be overly accurate.  I will be taking measurements in timed intervals about 1 per second.  If it's off a bit it  will not make much of a difference.  I will essentially test to see if the wheel has stopped.  I have not calculated the angular velocity but the application will be used on a bicycle.  As long as I consider the bike moving I will be out of LPM4 ready to take measurements.  I will however have a second check in the ADC10 register to make sure there is minimum speed (3mph+)  reached before taking measurements.

    I will look into the TimerA requirements and the SCS bit.  I appreciate the help.

    Take care,

    Jon

  • Hi Jon,

    If you're just using the timer to detect an approximate threshold speed to wake up for ADC then ACLK should do the job nicely. You might even be able to use the VLO instead of the crystal oscillator, assuming you don't also need to track elapsed time.

    Having said that, I'm now curious about what you're measuring with the ADC. Are you using it to measure the wheel's speed somehow?

    Rob

  • I'll be sure to check out the VLO.  I'll actually be measuring wind data, specifically the yaw angle.  

    Take care,

    Jon

  • For anyone reading this thread I thought I would update my progress.

    I looked into the SCS bit in TimerA and realized I wanted to keep it set.  The problem was that when it is set, getting out of LPM4 is not possible.  Therefore I initially set the pin I use for the capture input to be a digital I/O pin.  When the reed switch is first tripped, I configure the pin to be used as the capture input and change the low power mode from 4 to 3.  This works really well and allows me to keep the SCS bit set.

    I also looked into the VLO and have configured it to run between interrupts instead of LPM0.  This saves a lot of current and works well since timing is not critical.  

    Feel free to ask any questions you like.

    Take care,

    Jon

  • Jonthornham said:
    3.  Monitor time between capture interrupts with a compare interrupt using a global variable and test the time with an if loop in the compare ISR.

    I'd rather use the compare as a timeout. In the capture ISR you setup the compare for distant future (current capture value + a fixed timeout delay). If a capture happens (next turn of the wheel complete) before the compare interrupt happens, just move the compare trigger into future again. If the compare interrupt triggers, it means that there was no capture interrupt for a long time and you can go to bed again.

    it removes a lot of comparisons and alculations.

    Keep in mind that it takes quite some time to revive any crystals that were disabled during LPM4. Depending on your MSP and your use of ACLK and SMCLK this may leave your timeout without clock even though you already switched to LPM0. And for precision time calculation (RPM) I wouldn't trust the DCO frequency. Now on 5x family, there's REFO and might be good enough.

  • Jens-Michael,

    Thanks for the input.  A few comments and one question if I may.   I like the idea of setting up a compare as a time out.  I will look at implementing this into the design.  

    The accuracy does not need to be accurate.  I will be gathering wind angle data once every second and plan to use the VLO.  If it happens once every 0.75 seconds or once every 1.25 seconds it really does not matter.  The same goes for the RPM.  I am simply testing to see if the wheel is spinning faster then 3mph.  If it's not exact it won't make a difference.  Unless I am missing something obvious I can't see how it will really matter.

    If you had a moment for a question I would appreciate your input.  I have been using OUT0 to trigger conversions on an ADC10.  I am using a potentiometer to measure angle and have the goal of tying the positive arm to a Port pin.  The idea is to turn the pin on when I want to take a reading and turn it off when the reading is complete to conserve power.  I can't see how to turn the port pin on and off when triggering from OUT0.  It seems I may have to trigger conversions from software in a compare ISR where I can turn the port pin on and then turn the port pin off in the ADC ISR.  Do you know way to accomplish turning the pin on and off when using OUT0?

    Take care,

    Jon

  • Have you considered using OUT1 routed to a pin as the power source for the potentiometer? I think that would let you apply power just before starting the ADC without needing to wake the CPU. Having said that I don't know anything about ADC10, so I'm not sure if this is feasible.

  • Roberts idea is quite good. Just a few small comments.

    You use OUT0 to trigger the ADC. Since you likely use CCR0 to define the cycle time too, OUT0 (in set/reset mode) generates only a short pulse of one clock cycle, which is sufficient to trigger the ADC but not to source the pot during the ADC sampling phase.
    You can set up OUT1 to generate a PWM signal (reset/ser mode) whose rising edge is when TAR counts to 0 and resets sometime later (when TAR coutns to the specified value in TACCR1).
    Now the ADC will be started when TAR counts to CCR0, but OUT1 will go high one timer tick later. To compensate this, you must pick a long enough sampling time ADC10SHTx (depending on ADC10 clock speed and the timer clock speed) so that the initial off time of the pot for one timer tick is negligible due to the following time where it is on and the ADC is still sampling.

  • Jens-Michael,

    I really like this idea but I think there may be an issue.  In order to take a measurement every second with the ACD10 I have set TACCR0 to 5,999 in Toggle mode.  

    If I set the OUT1 to reset at 16 cycles in TACCR1 does TAR for channel 1 not count to the full 16bits before returning to 0?  Or does the setting of 5,999 in TACCR0 set the upper limit for TAR in both Channel 0 and 1?

    Take care,

    Jon

  • Jonthornham said:
    Or does the setting of 5,999 in TACCR0 set the upper limit for TAR in both Channel 0 and 1?

    There is only one TAR. And in up mode, it counts to CCR0.

    The value in CCR1 is the first trigger point for the output. Single actions or the first of a double-action trigger when TAR counts to CCR1. The second action of a double-action then happens when TAR coutns to 0.

  • Beautiful.  Thanks Jens-Michael.

    Take care, 

    Jon

  • Jens-Michael,

    I am sorry for the delay implementing the above strategy.  I had to put my time elsewhere for a while.  I am having an issue with what's suggested above.

    First, I set up the pot on OUT1 in Reset/Set mode as suggested.  I tested the function with an led and everything worked well.  When I hooked it up to the pot the LCD continually read 0.  I set CCR1 to 16, 200, and 3,000 cycles to test and nothing worked.  

    To see what would happen I switched the mode to Set/Reset and things worked.  After thinking about it more I realized that I essentially had the pot on the entire time. and was turning it off when I was supposed to be sampling.  However there is one clock cycle (from CCR0 to 0) when the ADC could sample.  To test this I set CCR1 to 1 in Set/Reset mode and the LCD still update the angle properly.  

    Ultimately I am a little stumped.  The calculations I have done tell me I need more then 1 cycle to sample the input.  The only thing I can think of is that when starting the sample in Reset/Set the initial 0 value is causing the issue.  Do you have any thoughts on why this is happening and how I could fix it?

    Take care,

    Jon

  • I don't know your actual code, so I can only guess what's going on.

    The ADC has two modes for the sampling. The sampling pulse and sampling gate mode. If oyu set the SHP bit, a pulse starts an internal timer (configured by SHTx bits) for the sampling time and the following conversion. The duration of the pulse is unimportant. Additional pulses during sampling period or convesion are ignored.

    If you don't set the SHP bit, then the ADC begins samplign with the risign edge of your tiemr output signal, and ends sampling and starts conversion with the falling edge. During converison, additional pulses are ignored.

    Take a look at the schematics in the users guide, it shows quite well how things are working.

    Don't forget that writing your result to LCD takes quite some time. Maybe longer than a timer cycle?

  • Jens-Michael,

    Unless I am mistaken, the SHP bit is exclusive to the ADC12.  Since I am using the ADC10 I am not sure I have this option.  I have attached the code I am using below.  I have quite a few comments in the code.  It shows the set up for the Ports, TImerA and the ADC10.  By the way, you were right when you suggested setting a timer to turn the ADC on and off.  While testing I found a loop hole that could cause issues.  Thanks for that suggestion.  It's a great one.

    void port1Init (void)
    {
    	// Port 1 and it's pins are used for the Power LED, ADC10 and the USCI.
    	// P1.0 = Power LED (Pin 2) (Eventually nothing)
    	// P1.1 = SPI SOMI USCI (Pin 3)
    	// P1.2 = SPI SIMO USCI	(Pin 4)
    	// P1.3 = Unconnected (Pin 5)
    	// P1.4 = SPI Clock USCI (Pin 6)
    	// P1.5 = TA0.0 (OUT0 of Timer0A) used in toggle mode to capture the Yaw Angle on the ADC input A5 (Pin 7).  See timer0AInit and adc10Init for more.
    	// P1.6 = TA0.1 (OUT1 of Timer0A) used in reset/set mode to turn on power to the pot. (Pin 14)
    	// P1.7 = Unconnected (Pin 15)
    	P1OUT = 0; 					// This initializes P1OUT to all zeros.  Same as 0b00000000
    	P1SEL = BIT6;				// This sets P1.6 (Pin 14) to OUT1.  Note: OUT0 for the ADC input is set in the ADC10 init method.
    
    	P1DIR = BIT0 + BIT1 + BIT6;	// This is used to set the corresponding pin (2) to an output for the power
    								// LED signal.  This also sets Pin 14 to an output for Reset/Set Mode in the Timer1A OUT1.
    	P1OUT = BIT0;				// This sets the output to 1, turning on the LED
    }
    
    /*-------------------------------------------------------------------------------------------------------*/
    
    void port2Init (void)
    {
    	// Port 2 and it's pins are used for the wind and rider speed inputs and the LCD control.
    	// P2.0 = Unconnected (Pin 8)
    	// P2.1 = TA1.1 CCI1A Capture Input Rider Speed (Pin 9)
    	// P2.2 = LCD RS (Pin 10)
    	// P2.3 = LCD E (Pin 11)
    	// P2.4 = LCD Data 4 (Pin 12)
    	// P2.5 = LCD Data 5 (Pin 13)
    	// P2.6 = LCD Data 6 (Pin 19)
    	// P2.7 = LCD Data 7 (Pin 18)
    	P2OUT = 0; 					// This initializes the P2OUT to all zeros.  Same as 0b00000000
    	P2SEL = 0;					// P2SEL must first be cleared so we can use P2.6 & P2.7 as IO pins.
    	P2SEL2 = 0;					// They are XIN & XOUT by default.
    	
    	//  Pin P2.1 is used initially as an input.  When the pin in P1DIR is 0 the pin is set as an input.
    	//  The default is to have P1DIR = 0.  Below we clear any potential flags for interrupts on the pin
    	//  and then enable interrupts.  When the interrupt is called we will set up the pin to act as a
    	//  capture input for TimerA.  We do this because in LPM4 everything is asleep.  If we were to set
    	//  up the pin as a capture right away we would not be able to set the SCS bit in TimerA which I do
    	//  not like.  This way we are able to wake up the MCU and change everything in the Port2 ISR.
    	P2IFG &= ~BIT1;
    	P2IE |= BIT1;
    
    	P2DIR = MASK;				// This sets the corresponding pins for the LCD control to outputs
    }
    
    /*-------------------------------------------------------------------------------------------------------*/
    
    void timer0AInit (void)
    {
    	// Select ACLK (VLO), Division 0, Up Mode to TACCRO, (NOTE: Interrupts do not need to
    	// enabled.  We will enable interrupts in the ADC10 which handles everything.
    	TA0CTL = TASSEL_1 + ID_0 + MC_1 + TACLR;
    
    	// Set the top in Up Mode to 5,999 which is half of the 12Khz clock.  I want a reading
    	// every second and since toggle mode works on the rising edge only I cut the frequency
    	// in half to trigger the ADC once a second.  Using toggle mode starts the conversion
    	// in the ADC automatically when it "toggles" to the rising edge.  Once the conversion is
    	// complete the ADC ISR is called and the value is handled.
    	TA0CCR0 = 5999;
    
    	// We are using Pin 14 in Reset/Set mode (OUT1) to turn the pot on and off.  When TAR
    	// (the counter) returns to 0, the output it set to 1 (high).  When the TAR counts to
    	//  TAOCCR1 the output is reset to 0.  Since we need 16 clock cycles to sample, we set
    	//  TA0CCR1 to 16.  Not that the Sample from the toggle mode below actually turns on
    	//  when TAR counts to TA0CCR0 which is one clock cycle before we turn the pot on
    	//  when TAR = 0.  As long as we sample long enough this is ok.  
    	TA0CCR1 = 16;
    
    	// Enable Toggle Mode for Pin.  Remember Toggle mode has to be used with an OUT0
    	TA0CCTL0 = OUTMOD_4;
    
    	// Enable Reset/Set mode for Pin.  Remember Reset/Set mode has to be used with an OUT1
    	TA0CCTL1 = OUTMOD_7;
    }
    
    /*-------------------------------------------------------------------------------------------------------*/
    
    void timer1AInit (void)
    {
    	TA1CTL = TASSEL_1 + MC_2 + TACLR;	// Selects ACLK (VLO), Continuous Mode and clears the timer.
    
    	// This simple enables the interrupts on channel 0 of TimerA1 so that when TAR hits 65k in continuous mode
    	// the ISR is called.  This is where I will put the unit back in LMP4 when this is hit.
    	TA1CCTL0 = CCIE;
    
    
    	// Set up Channel 1 to capture the input of the reed switch for rider speed.  Every time the magnet breaks its
    	// connection we capture the value of TAR in TA1CCR1 and raise the interrupt flag.  The following
    	// set up sets Captures on a Falling Edge, Puts the Capture on Pin 8 also known as P2.1, Synschronizes
    	// the capture with the clock, puts Channel 1 in Capture Mode and Enables Interrupts.
    	TA1CCTL1 = CM_2 + CCIS_0 + SCS + CAP + CCIE;
    }
    
    void adc10Init (void)
    {
    	// I am using pin 7 for the input to the ADC10.  This is A5.  OUT0 is also associated with pin 7 so I am
    	// able to drive the conversions by toggling OUT0 in OUTMOD_4.  This is set up in timer0AInit();.
    
    	// Vcc - Vss, 16 clock cycles (with 2kOhm Pot) for the sample, turn on ADC10, enable interrupts
    	ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;
    
    	// Select input on Channel 5, sample and hold source OUT0, clock division 0, use ADC10SC clock, repeat single conversion
    	ADC10CTL1 = INCH_5 + SHS_2 + ADC10DIV_0 + ADC10SSEL_0 + CONSEQ_2;
    
    	// Enable ADC10 on input channel A5.
    	ADC10AE0 = BIT5;
    
    	// Enable conversions.  This only needs to be done once since we selected CONSEQ_2
    	ADC10CTL0 |= ENC;
    }

    Take care,

    Jon

    void port1Init (void)
    {

    // Port 1 and it's pins are used for the Power LED, ADC10 and the USCI.
    // P1.0 = Power LED (Pin 2) (Eventually nothing)
    // P1.1 = SPI SOMI USCI (Pin 3)
    // P1.2 = SPI SIMO USCI (Pin 4)
    // P1.3 = Unconnected (Pin 5)
    // P1.4 = SPI Clock USCI (Pin 6)
    // P1.5 = TA0.0 (OUT0 of Timer0A) used in toggle mode to capture the Yaw Angle on the ADC input A5 (Pin 7).  See timer0AInit and adc10Init for more.
    // P1.6 = TA0.1 (OUT1 of Timer0A) used in reset/set mode to turn on power to the pot. (Pin 14)
    // P1.7 = Unconnected (Pin 15)

    P1OUT = 0;  // This initializes P1OUT to all zeros.  Same as 0b00000000

    P1SEL = BIT6; // This sets P1.6 (Pin 14) to OUT1.  Note: OUT0 for the ADC input is set in the ADC10 init method.

    P1DIR = BIT0 + BIT1 + BIT6;   // This is used to set the corresponding pin (2) to an output for the power   // LED signal.  This also sets Pin 14 to an output for Reset/Set Mode in the Timer1A OUT1.

    P1OUT = BIT0;   // This sets the output to 1, turning on the LED

    }


    /*-------------------------------------------------------------------------------------------------------*/


    void port2Init (void)
    {
    // Port 2 and it's pins are used for the wind and rider speed inputs and the LCD control.
    // P2.0 = Unconnected (Pin 8)
    // P2.1 = TA1.1 CCI1A Capture Input Rider Speed (Pin 9)
    // P2.2 = LCD RS (Pin 10)
    // P2.3 = LCD E (Pin 11)
    // P2.4 = LCD Data 4 (Pin 12)
    // P2.5 = LCD Data 5 (Pin 13)
    // P2.6 = LCD Data 6 (Pin 19)
    // P2.7 = LCD Data 7 (Pin 18)

    P2OUT = 0; // This initializes the P2OUT to all zeros.  Same as 0b00000000

    P2SEL = 0;  // P2SEL must first be cleared so we can use P2.6 & P2.7 as IO pins.

    P2SEL2 = 0;  // They are XIN & XOUT by default. //  Pin P2.1 is used initially as an input.  When the pin in P1DIR is 0 the pin is set as an input. //  The default is to have

    P1DIR = 0.  

    Below we clear any potential flags for interrupts on the pin //  and then enable interrupts.  When the interrupt is called we will set up the pin to act as a //  capture input for TimerA.  We do this because in LPM4 everything is asleep.  If we were to set //  up the pin as a capture right away we would not be able to set the SCS bit in TimerA which I do //  not like.  This way we are able to wake up the MCU and change everything in the Port2 ISR.

    P2IFG &= ~BIT1;

    P2IE |= BIT1;

    P2DIR = MASK; // This sets the corresponding pins for the LCD control to outputs
    }


    /*-------------------------------------------------------------------------------------------------------*/


    void timer0AInit (void)
    {
    // Select ACLK (VLO), Division 0, Up Mode to TACCRO, (NOTE: Interrupts do not need to // enabled.  We will enable interrupts in the ADC10 which handles everything. TA0CTL = TASSEL_1 + ID_0 + MC_1 + TACLR;

    // Set the top in Up Mode to 5,999 which is half of the 12Khz clock.  I want a reading // every second and since toggle mode works on the rising edge only I cut the frequency // in half to trigger the ADC once a second.  Using toggle mode starts the conversion // in the ADC automatically when it "toggles" to the rising edge.  Once the conversion is // complete the ADC ISR is called and the value is handled.
    TA0CCR0 = 5999;

    // We are using Pin 14 in Reset/Set mode (OUT1) to turn the pot on and off.  When TAR // (the counter) returns to 0, the output it set to 1 (high).  When the TAR counts to //  TAOCCR1 the output is reset to 0.  Since we need 16 clock cycles to sample, we set //  TA0CCR1 to 16.  Not that the Sample from the toggle mode below actually turns on //  when TAR counts to TA0CCR0 which is one clock cycle before we turn the pot on //  when TAR = 0.  As long as we sample long enough this is ok.  
    TA0CCR1 = 16;

       // Enable Toggle Mode for Pin.  Remember Toggle mode has to be used with an OUT0
        TA0CCTL0 = OUTMOD_4;

    // Enable Reset/Set mode for Pin.  Remember Reset/Set mode has to be used with an OUT1
    TA0CCTL1 = OUTMOD_7;
    }

    /*-------------------------------------------------------------------------------------------------------*/

    void timer1AInit (void)
    {
    TA1CTL = TASSEL_1 + MC_2 + TACLR; // Selects ACLK (VLO), Continuous Mode and clears the timer.

    // This simple enables the interrupts on channel 0 of TimerA1 so that when TAR hits 65k in continuous mode // the ISR is called.  This is where I will put the unit back in LMP4 when this is hit.
    TA1CCTL0 = CCIE;

    // Set up Channel 1 to capture the input of the reed switch for rider speed.  Every time the magnet breaks its // connection we capture the value of TAR in TA1CCR1 and raise the interrupt flag.  The following // set up sets Captures on a Falling Edge, Puts the Capture on Pin 8 also known as P2.1, Synschronizes // the capture with the clock, puts Channel 1 in Capture Mode and Enables Interrupts.
    TA1CCTL1 = CM_2 + CCIS_0 + SCS + CAP + CCIE;
    }

    void adc10Init (void)
    {
        // I am using pin 7 for the input to the ADC10.  This is A5.  OUT0 is also associated with pin 7 so I am // able to drive the conversions by toggling OUT0 in OUTMOD_4.  This     is set up in timer0AInit();.

        // Vcc - Vss, 16 clock cycles (with 2kOhm Pot) for the sample, turn on ADC10, enable interrupts
        ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;

       // Select input on Channel 5, sample and hold source OUT0, clock division 0, use ADC10SC clock, repeat single conversion
        ADC10CTL1 = INCH_5 + SHS_2 + ADC10DIV_0 + ADC10SSEL_0 + CONSEQ_2;

        // Enable ADC10 on input channel A5.
        ADC10AE0 = BIT5;

        // Enable conversions.  This only needs to be done once since we selected CONSEQ_2
        ADC10CTL0 |= ENC;
    }

  • Jonthornham said:
    Unless I am mistaken, the SHP bit is exclusive to the ADC12.  Since I am using the ADC10 I am not sure I have this option.

    Not exclusive. The ADC10_A of the 5x family and later has it too, but you're right, the 1x/2x family ADC10 doesn't have it.
    So in your case, it is always using the sampling timer and the SHTx bits. And while a conversion is running, additional triggers are simply ignored. What triggers the next converison is the next rising edge (or falling, based on ADC10ISSH bit) after the last conversion is done.

    Sorry, your code is unreadable. Could you please format it? At least line breaks between code lines. (hint: you can edit your post).

  • Jens-Micahel,

    I am sorry for the trouble.  That was my first time uploading code.  I thought the file I uploaded would be downloadable.  I have edited the post to be more readable.  

    Take care,

    Jon

  • Jonthornham said:
    I am sorry for the trouble.

    No trouble at all. Except that I was postponing to look into it for when I have time to take a deeper look wihtout being interrupted by my job :)

    Well. I see that you're using VLO. Don't forget that VLO frequency depends on temperature, voltage and also varies greatly between different MSPs. 12kHz is just the frequency that occurs most, but on your specific MSP it can be as low as 4kHz or as high as 20kHz.
    If this is a problem, you should do some calibraiton run and check how fast VLO really is on each single MSP.

    You use ADC10SSEL_0, which means you're using hte internal ADC10OSC, which is automatically activated once the sampling is started and deactivated after. It runs on 3-6MHz, so your 16 ticks of sampling time take much, much less than one 12kHz timer tick.
    You can't use VLOCKL as clock for the ADC10, as it requires at least 400kHz clock for proper operation (else the charge in the sampling capacitor will vaporize before it can be converted).
    This also explains why it seemed to work (and really did) with the one-timer-tick pulse.

  • You are so very right.  I didn't think about the differing clock speeds.  After I realized it, I spent the next 2 1/2 hours trying to figure out how to fix it.  I looked into rewiring, using an OUT2 and nothing worked with the MSP430 I am using.  I then figured that since I am getting 16 clock cycles before TACCR0 returns to 0, I could use Set/Reset instead of Reset/Set. I turn the pot on at 5,995 and then the Set/Reset mode turns it off when TAR returns to 0.  Below is the code I changed.  I guess technically I could turn it on at 5,998 but I thought this may be pushing it.

    void timer0AInit (void)
    {

    // Select ACLK (VLO), Division 0, Up Mode to TACCRO, (NOTE: Interrupts do not need to
    // enabled. We will enable interrupts in the ADC10 which handles everything.

    TA0CTL = TASSEL_1 + ID_0 + MC_1 + TACLR;

    // Set the top in Up Mode to 5,999 which is half of the 12Khz clock. I want a reading
    // every second and since toggle mode works on the rising edge only I cut the frequency
    // in half to trigger the ADC once a second. Using toggle mode starts the conversion
    // in the ADC automatically when it "toggles" to the rising edge. Once the conversion is
    // complete the ADC ISR is called and the value is handled.
    TA0CCR0 = 5999;

    // We are using Pin 14 in Set/Reset mode (OUT1) to turn the pot on and off. When TAR
    // (the counter) counts to TA0CCR1, the output it set to 1 (high). When the TAR returns to
    // 0 the output is reset to 0. Remember we are using two different clocks. The timer clocks
    // are run from the VLO which is between 4kHz-20kHz and the ADC10OSC is between 3.7mHz-6.3mHz.
    // This means that when I sample for 16 cycles in the ADC10, all samples happen within one cycle
    // of the VLO. I originally set up Reset/Set mode which turned the pot on when TAR returned to 0.
    // The problem was that toggle mode (the trigger and input for the ADC) started at TA0CCR0 and all
    // 16 cycles were complete before the pot ever turned on. Since the cycles in the ADC are so fast
    // I switched from Reset/Set to Set/Reset. This turns the pot on just before we hit TA0CCR0 and off
    // when TAR returns to 0.
    TA0CCR1 = 5995;

    // Enable Toggle Mode for Pin. Remember Toggle mode has to be used with an OUT0
    TA0CCTL0 = OUTMOD_4;

    // Enable Set/Reset Mode for Pin. Remember Set/Reset mode has to be used with an OUT1
    TA0CCTL1 = OUTMOD_3;
    }

    Take care,

    Jon

**Attention** This is a public forum