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.

Capture Mode Timer A

Other Parts Discussed in Thread: MSP430G2231

Hello! I just wanna begin by saying how much I am loving the msp430 Launchpad! Its a very versatile learning tool. I am okay at programming hardware and have had some experience with the launchpad, tinkering with it my self. However I have run into a problem:

I am trying to develop a code that accepts input through one of the general purpose I/O pins( specifically a set of two inputs spaced apart at a particular time interval) and outputs a logic high at another pin to drive a transistor circuit (external) if the duration between two input signals has met a predetermined requirement.

At first I though of sampling a particular channel through the ADC10. I set up the code but I saw that it consistently sampled(even in sample once mode) an input pin and even the slightest physical touch triggered a voltage detection. So that solution was of the door.

Second one was to access the capture of the TimerA in msp430g2231. The pseudo code i have developed is :

1- Wait for an external trigger to start the capture
2- wait for another external trigger to stop the capture
3- check the difference of the two captures
4- IF the difference has met the predetermined requirement, then output high on a pin
5- IF NOT, then begin from step 1 again, till the requirement has been met

A point to mention is that I am not going to be feeding a particular waveform for that matter. Its just going to be a voltage level held a particular value  for 1 sec and then drop down to zero. This should trigger the capture for timer A. The second signal, like the first one, should do the same.

Is this do-able or am I looking in the wrong direction? Thanks in advance for looking and trying to help!!! :)

  • It is do-able.

    Usman Maqsood said:
    ... Its just going to be a voltage level held a particular value  for 1 sec and then drop down to zero....

    That particular value must be a voltage between Vcc and 2/3 of Vcc.

    Usman Maqsood said:
    ... The pseudo code i have developed is :

    1- Wait for an external trigger to start the capture
    2- wait for another external trigger to stop the capture
    3- check the difference of the two captures
    4- IF the difference has met the predetermined requirement, then output high on a pin
    5- IF NOT, then begin from step 1 again, till the requirement has been met

    Is your Step 1 and Step 2 concurrent or sequential?

  • Thanks for replying to my post.

    1- step 2 and step 3 are sequential--I am trying to send a general purpose I/O pin 5 'high' based the difference between the first capture and second capture.

    2- The voltage level that you mentioned---why does it have to be between 3.55V and 2.36V? --- Is that considered a logic "HIGH" by the micro-controller?

    How feasible is my method? Is it overkill for such a trivial task or do I need to look into it further.

  • 1. I was trying to find if your Step 1 and Step are in parallel or in sequence. For example, the incoming signals may consist of: Start#1, Start#2, Stop, If you do them in parallel, you will capture the time between Start#2 and Stop. If you do them in sequence, you will capture the time between Start#1 and Stop instead.

    2.. GPIO pins are digital. Voltage from 0 to 1/3 Vcc is "low". From 1/3 Vcc and 2/3 Vcc is undesirable. From 2/3 Vcc to Vcc is "hight".

    It is a easy but not trivial task for a MSP430. A slightly modified method is, use TACC0 and TACC1 to capture the two digital input signals independently. Take the difference between them in your Step 3.

  • I am under the impression (from reading and understanding) that the capture mode can record values at the rising, falling or rising+falling edges. Why do I need to separate control registers to control the time duration between two discrete events?------CCTL1 and CCTL0

    1- One signal (3 volts) triggers the timer--CCRO value is noted

    2- One more signal (3 volts) stops the timer--CCRO value is noted

    3- The difference can then be calculated.

    From the above procedure, I dont think I need two use two distinct control registers. But then again, I might be over looking something.

  • There are many different ways to do it.

    Yes, TACC0 can be used to capture the rising, falling, or both edges of an input, but only P1.1 can be used as the input of TACC0.

    You have two input signal, you cannot connect both of them to P1.1

     

  • I am not sure if I fully understand your point. Let me explain my self further:

    1- I just want to measure the time between input signals.

    2- That difference would then be checked to see if it meets a requirement.

    3- If it does, then set pin 1.5 high

    4- if not, then wait for two input signals again and repeat step 1


    Basically. I want the timer running. It should record the time at which an input signal is recieved. Then wait for another input signal at the same input pin and record that time. Is that not how a basic capture mode works for a timer.?----using the same pin as input for any number of input signals and recording the value of the time elapsed between incoming signals.

    Thanks for all your input by the way, highly valuable!!

  • Sorry, it was I who misunderstood.

    When you said "another signal", I thought you have two separate signal lines, one for Start and another for Stop. Now I understand you have only one signal line for both Start and Stop signals. For example, a rising edge means Start and a falling edge means Stop. (Or the other way around.)

    Yes, you only need to use one Capture/Compare channel, not two.

     

     

  • Well I  was specifically want to start and stop on a 'high' signal. Do i need to drive the input low first and then high to tell the timer that a rising edge has occured? or its doesnt matter?

  • So both Start and Stop are on the same signal line and both are indicated by a rising edge. How can the Timer CC tell which is which? That is, if a rising edge appears on the signal line, is that a Start or is it a Stop?

    I think you either (a) use two separate signal lines, or (b) share the same signal line and use rising edge for one signal and falling edge for the other.

  • haha this is funny. I cant seem to relay my point over. I'll try again.. this time with a little more background. Okay so here goes:

    1- I start the timer A in continuous mode.

    2-  I will then feed in a voltage of about 3+ volts at the input pin for the timer. This would be recorder in the TACCR0 register and I will store that value

    3- A few seconds later, I will then feed in another voltage of about 3+ volts again on the same pin and record the current value of the TACCR0.

    4- I will then substract the two value to yield the time difference between the two recordings.

    5- If the substracted result meets a certain requirement, then set pin 1.5 high

    6- If not, repeat from step 2 again--overwriting any previous values of the stored TACCR0s

    Please remember that the input signals ARE NOT pulse waves or any other form of wave. Its just a particular voltage level that stays at that voltage level for about 1sec and then drops down to zero.

     

    Hope I have clarified any confusing points

  • Okay.

    One can make MSP430 to work exactly the way you described. I just did not think that was exactly what you really want. (My mistake.)

    So, the first such certain 3+ level is a Start. The second such 3+ level is a Stop. They are at least ~1 second apart.

    The third such 3+ level is a Start again. And it must be at least ~1 second after the previous Stop.

    The forth such 3+ level is a Stop instead. ...etc.

    If at some point the Start-Stop pair meets that certain requirement, the LED at P1.5 will turn on and no one cares what happen next.

    If no such Start-Stop pair meets that requirement, the 3+ level keeps coming....

    You are sure that the10 millionth such 3+ level is a Stop and definitely not a Start. All because (a) the first one is a Start and (b) Start and Stop alternates there after.

  • Usman Maqsood said:
    haha this is funny. I cant seem to relay my point over.

    Well, you didn. OCY (and I, now that I read it) jsu tcouldn't believe that it was really meant this way.
    The reson is that in your description ther eis no synchronization between signal source and detector. And no difference between start signal and stop signal.

    So what if the MSP for some reson resets after gettign a start? Once it ha scome up again, it would take the next stop as a start, the next start as a stop etc.

    You should add anoteh rlevel of complexity. e.g. have start and stop different lengths. A start is between x and y, while a stop is between x+y and x+2y or something liek this.

    Then measurte the time between rising and falling edge (It's not enough just to apply 3V and nothing. You need to at least have a pulldown resistor, so you have a clean falling edge and can detect the next rising edge too. Else parasitic capacitances might hold the line high and no edges are detected at all. Or you apply 3V and GND).
    Then you knwo whetehr it is a start ot a stop. You can note down the tiem of the rising or falling edge, as you like. Together with the info whether it was a start or a stop. On th enext rising and fallign edge you determine again whether it was start or stop and hten you can calculate the difference.

    As fo rthe voltages: the MSPs inptu pins are schmitt-trigger-inputs. That means a rising edge (and a subsequent high level) is detected if the voltage rises above a certain threshold. The falling edge (and a low signal) are detected if the voltage falls below a certain threshold. The two thresholds are not identical, the port has a certain hysteresis. o a voltage that slowly rises above the upper thershold won't cause multiple triggers or oscilaltions if there is some noise on the signal (so the threshold is crossed up and down several times).

    The threshold voltages depend on VCC and also on teh individual device. worst-case values are in the datasheet.

    As long as the delays between two edges do not exceed 65535 tiemr counts, the further programming is trivial and straight.

  • Hello thanks for getting back to me guys! good information. So let me get something clear:

     

    1- I should attach a pull down resistor (10K ohm to 100K ohm) to the input pin of the timer--since applying a +3V to the signal followed by a clear 0V would be registered by the micro controller. Merely a 3V and then left floating would be "unknown" to the micro controller

    2- Provided I set the up timer correctly ( that is that it should note down the CCR0 value when it detects a 'HIGH'),  the time value of the CCRO should get recordedd when I apply 3V to the timer input.--- the transistion from LOW (0V) to HIGH (3V) should be recorded right

    3- Then I will be able to read the TACCRO value and do the rest of the task

    I am going to try this and report back. Thanks for looking everyone and do point out if I have managed to overlook something!! :)

     

     

  • 1. yes. Applying a voltage and then just removing it, leaving the pin floating, causes the parasitic capacitance of the PCB and the pins to slowly discharge through the high input impedance of the input pin. Th epin will eventually detect a voltage drop below the low-going threshold, but the time it takes depends on many things. Actually this is how capacitive touch-sensing works: measure the tiem and calculate the change in parasitic capacitance (which rises on a touch).

    2. yes. When the programmed edge (low-to-high in your case) is detected, the tiemr copies its current value into CCRx register, and sets the CCIFG bit. If you set the CCIE bit too, an interrupt is triggered and you can read the value. You should check the overflow bit that tells you that since the first interrupt occurred, a second rising edge was detected before you reset the IFG bit/handled the interrupt.

    3. yes.

    If your signals are clear, this should do the job. However, if you apply the voltage using a pushbutton or such, the whole thing could be subject to bouncing effects. In this case, you should define some 'dead time' before you look for the next rising edge. E.g. setting the CCR into compare mode for some (50 to 100) ms, and when this tiem expires (another interrupt) go back to capture mode.

  • Hello. This is the code I have used to configure the timer to respond to a HIGH at the capture input.

    Do I need to enable the pull down resistor using software or do I need to manually attach a resistor to input pin for the capture?

    The count variable is there to check that the code is successfully working--count 6 'high'  triggers and turn on green led to show that its done

    BUT ITS NOT WORKING---> I googled a lot of sample codes and I am fairly okay at coding and understanding it, but i really cant figure out what am i doing wrong or what am I overlooking. Please take a look at it...its a small code..for debugging purposes. Thanks in advance... you have been a great help!!!

    BTW: I am using msp430g2231 uC (launchpad emulation)

    #include <msp430g2231.h>

    int count=0;

    void timer(void){
    TACCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE;
    TACTL = TASSEL_2 + MC_2;
    }

    void main (void)
    {
        WDTCTL = WDTPW + WDTHOLD;
        BCSCTL1 = CALBC1_1MHZ;     
          DCOCTL = CALDCO_1MHZ;
        timer();
        P1DIR=0x40;
        P1OUT=0;
        P1SEL=0x2;
        _BIS_SR(LPM0_bits + GIE);
        
        while (1);
    }

    #pragma vector=TIMERA0_VECTOR
    __interrupt void TIMERA(void)
    {    
        if (count==6){
            while(1){
            P1OUT=0x40;    
            }
        }
            count++;
    }

  • Usman Maqsood said:
    Do I need to enable the pull down resistor using software or do I need to manually attach a resistor to input pin for the capture?

    Both will work.

    Your intended input pin, TA.0 = P1.1 is used as TXD isignal on the lauchPad and connected to the FET. maybe that's what cause the code to fail.
    Why don't you use P1.5 instead?

    Also, if you 'touch' the pin with your wire, thsi may cause many interrupts (bumping). So don't coutn on the '6' counter. Even if everything works as it should, the LED could go on with the first touch. (You have closed J5-2, did you? Else the LED is not connected)

    And I would init the LED port before arming the timer. jus tto be sure that the ISR didn't already reach teh trigger point and then the port is inited and cleared. Unlikely but possible.

    But other than that, I don't see what it isn't working.

    One side note: if you want to use count in main() too, it must be declared voltatile, or main() won't notice a change of count done in the ISR (due to compiler optimization) - which is a 'magic change' from main view.

  • Hello Gross, Firstly I want to thank you. Your very nice and well informed and you are taking out the time to help me through it--tht is very kind of you.

    "Your intended input pin, TA.0 = P1.1 is used as TXD isignal on the lauchPad and connected to the FET. maybe that's what cause the code to fail.
    Why don't you use P1.5 instead?"

    But according the data sheet for msp430g2231, the timer capture CC10A uses P1.1 as the input pin for the capture. Can I use P1.5? I will try that but I am not clear as how would the timer capture an input other than P1.1

    "Also, if you 'touch' the pin with your wire, thsi may cause many interrupts (bumping). So don't coutn on the '6' counter. Even if everything works as it should, the LED could go on with the first touch. (You have closed J5-2, did you? Else the LED is not connected)"

    I understand that bumping might cause the count = = 6 to be reached faster than antisipated. I have the jumper closed so that the LED works. Why would the LED turn on immediately

    "And I would init the LED port before arming the timer. jus tto be sure that the ISR didn't already reach teh trigger point and then the port is inited and cleared. Unlikely but possible."

    Sounds good. But the only way I know how to do that is P1OUT=0

    I will try messing around with it further and see if I could get it to work properly and I would try to prevent "bumping" of the wires

    Thanks

     

  • Jens-Michael Gross said:
    ... Your intended input pin, TA.0 = P1.1 is used as TXD isignal on the lauchPad and connected to the FET. maybe that's what cause the code to fail.

    Why don't you use P1.5 instead? ...

    P1.1 is used as TXD and pulled up by the FET side. But if you remove the jumper marked "TXD", it is no longer connected to the FET side and not pulled up.

    P1.5 cannot be used as the TACC0 input. The data-sheet may have another mistake that says it can be used.

     

  • I agree with old_cow ----->(lol..never thought I'd say that in my life haha). The TACCO input can only be introduced through P1.1. However, here 's the deal:

    I have connected the P1.1 to a 22K ohm resistor. I have grounded that resistor to the launchpad GND pin. This set up is wired up using a breadboard--to make sure i pull that pin low.

    Now I run the code shown below

    The problem is that when i measure the voltage on the P1.1 pin, its 3.3 volts!! it should be like 0.22 volts or something lower than that. That is because I am forcefully setting up the direction of that pin as input-------Not output!

    Now, coming back to the actual workings of the code: Everytime i feed in Vcc to the capture pin (since I have set up timer to capture rising edges), nothing happens--but if touch P1.1or the resistor with my fingers or any other low voltage (like 0.2 or something similar)..the count increases and eventually the LED turns on.

    what is going on guys. I am so confused at this point! Please help

    #include <msp430g2231.h>

    volatile int count=0;
    volatile int x=0;

    void timer(void){
    TACCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE;                         
    TACTL = TASSEL_2 + MC_2;
    }

    void clock (void){
    BCSCTL1 = CALBC1_1MHZ;    
    DCOCTL = CALDCO_1MHZ;
    IFG1=0x00;       
    }

    void main (void)
    {
        WDTCTL = WDTPW + WDTHOLD;
        clock();   
        timer();
       
        P1DIR=0x40;                      //set led 2 in the out direction and every other pin as input
        P1SEL=BIT1;                   // set up P1.1 to accept inputs for the timer capture
        P1OUT=0x00;               // make sure that everything is off initially
       
        _BIS_SR(LPM0_bits + GIE);             // enable interrupts and low power mode
        while (1);
    }

    #pragma vector=TIMERA0_VECTOR
    __interrupt void TIMERA(void)
    {   
        TACCTL0 &=~CCIFG;                  // clear the  interrupt flag
        x=count;                                   // keep track of count by watching X in the Code Composer Studio ---- place breakpoint
        if (count==6){                      // once count equals 6, turn on LED 2
            while(1){
            P1OUT=0x40;                    // turn on LED for ever
            }
        }
            count++;                            // else increment count
    }

  • old_cow_yellow said:
    ... P1.1 is used as TXD and pulled up by the FET side. But if you remove the jumper marked "TXD", it is no longer connected to the FET side and not pulled up. ...

    Did you?

  • Ok, it seems to be working a lot better now after removing that jumper. The voltage on that pin is now 0.2 volts.. as it should be.

    Thanks cow_yellow! But i still have to tweak it a little bit to get it work properly. Can you please keep an eye on this post over the next couple of days? If you can, it'll help me out because I would be able to bounce of ideas as to how should it work better.

    Also, why was that jumper doing that and why is it included in the launchpad if it creates a problem?

     

    Thanks!!

  • old_cow_yellow said:
    P1.5 cannot be used as the TACC0 input.

    My fault. I was just looking at the pinout, and it reads 'TA0.0' on both pins.
    The terminal function table correctly lists OUT only for P1.5.

    It's a shame. If the out is already routed, one could as well AND the two INs, if selected. Just one gate more...
    Anyway, the port pin schematic for P1.5 is strange. There is a SIMO0 function on this pin that is active in parallel to TA0.0.OUT. Nakes no sense.

    Usman Maqsood said:
    Can you please keep an eye on this post over the next couple of days?

    If you write something, the tread will be marked as unread and pushed up in the thread list.
    So we will automatically see if you write something new.

    Usman Maqsood said:
    why was that jumper doing that and why is it included in the launchpad if it creates a problem?


    The Jumper connects this pin with the FET on the LaunchPad. Through this pin, you can send serial information (if programmed by a software UART) through the FET to the PC and read it there with a simple terminal program like HyperTerm.
    This functionality is part of the original LaunchPad demo software. Just like the LEDs on the board. So it is wired and there is a jumper which you can remove if you don't want/use this functionality, so the pin is left alone again.

  • Jens-Michael Gross said:
    ... The terminal function table correctly lists OUT only for P1.5.

    It's a shame. If the out is already routed, one could as well AND the two INs, if selected. Just one gate more...

    Anyway, the port pin schematic for P1.5 is strange. There is a SIMO0 function on this pin that is active in parallel to TA0.0.OUT. Nakes no sense. ...

    I think the reason is the TACC0 allows only 2 alternative inputs CCI0A and CCI0B (other than Vcc and Vss) and TI wants to have ACLK (internal) as one of the alternatives for software FFL etc. See Table 10. Timer_A2 Signal Connections.

     

  • old_cow_yellow said:
    I think the reason is the TACC0 allows only 2 alternative inputs CCI0A and CCI0B

    A simple AND of the two post pin inputs if the port pin is selected for module usage would be sufficient. Both To CCI0A.
    There is no configuration needed to output thr module output on one or the other pin too. Just select it for module usage. And if you select both, well, the result is the ANDed value of both.

    As I said, just one more gate. No addiitonal configs or register.

  • Hey guys! I had gotten busy with job hunting. Graduating and unemployment is NOT fun!! At any rate, I tweaked the code below to generate an interrupt when the msp430g2231 experiences a HIGH pulse on its timer A input. It works but I had two questions:

     

    1- The interrupt only works if I use TACCTL0 control register  but it does NOT work when I use TACCTL1 control register . The code below uses TACCTL1 but you can assume it be TACCTL0 control register( since I know it works)

    2- When I place a break point in the interrupt to read the value of the TACCRx value using "watch expression" in CCS, sometimes it displays a NEGATIVE number. I dont know why is that.

    Now, I wanted to read the TACCRx value twice at different points in time and find out the difference between the two. But if one the number is negative, then it wont be effective.

    The only reason I can understand why it might display a negative number is during conversion from binary to decimal.

     

    #include <msp430g2231.h>

    volatile unsigned int x=0;

    void timer(void){
    TACCTL1 = CM_1 + SCS + CCIS_0 + CAP + CCIE;        //capture on rising,input,capture and interrupt                        
    TACTL = TASSEL_2 + MC_2;                        //SMCLK and continuous mode
    }

    void clock (void){
    BCSCTL1 = CALBC1_1MHZ;   
    DCOCTL = CALDCO_1MHZ;
    IFG1=0x00;      
    }

    void main (void)
    {
        WDTCTL = WDTPW + WDTHOLD;            // stop watch dog timer
        clock();  
        timer();
      
        P1DIR=0x40;                          //set led 2 in the out direction and every other pin as input
        P1SEL=BIT1;                           // set up P1.1 to accept inputs for the timer capture
        P1OUT=0x00;                           // make sure that everything is off initially
      
        _BIS_SR(LPM0_bits + GIE);           // enable interrupts and low power mode
        while (1);
    }

    #pragma vector=TIMERA1_VECTOR
    __interrupt void TIMERA(void)
    {
        if ((TACTL & 0x1)==1){                // check if the timer rolled over to zero. if it did, remove the TAIFG bit
        TACTL = TASSEL_2 + MC_2;
        }
        TACCTL1&=~COV;                        // Remove capture overflow
        TACCTL1 &= ~CCIFG;                    // dimiss interrupt request flag

         x=TACCR1;             // read TACCR1 value and view it Code Composer Studio "watch expression" --place breakpoint
    }

  • Usman Maqsood said:
    .. 1- The interrupt only works if I use TACCTL0 control register  but it does NOT work when I use TACCTL1 control register . The code below uses TACCTL1 but you can assume it be TACCTL0 control register( since I know it works) ...

    TACCTL0 has its own interrupt vector. TACCTL1 shares the same interrupt vector with TACTL, and thus the isr must handle it differently. See the F2xx Family User's Guide for details.

    Usman Maqsood said:
    .. 2- When I place a break point in the interrupt to read the value of the TACCRx value using "watch expression" in CCS, sometimes it displays a NEGATIVE number. I dont know why is that. ...

    CCS obviously is treating it as a signed integer instead of an unsigned integer.

     

  • Hello old_cow .. thanks for the feedback

    old_cow_yellow said:
    .. TACCTL0 has its own interrupt vector. TACCTL1 shares the same interrupt vector with TACTL, and thus the isr must handle it differently. See the F2xx Family User's Guide for details. ...

    Yeah Ive scanned it very thoroughly and I have yet to figure out how to handle the TACCTL1 interrupt. Ive searched online and everyone who faced the problem says it was fixed with setting the CCIFG bit in the respective control register. That was what i was doing to begin with. I dont see why its not working

     

    old_cow_yellow said:
    .. CCS obviously is treating it as a signed integer instead of an unsigned integer. ...

    So I should change x from 'volatile int' to 'unsigned volatile int' or 'unsigned volatile char'?

  • slau144h.pdf Section 12.2.6 and its sub-sections on pages 369 and 370 have all the details. In your case, it is even simpler. All you need to do is to (a) move the signal from P1.1 to P1.2, (b) remove the jumper labeled RXD, (c) change the P1.1 settings to P1.2, (d) move the interrupt vector from TimerA0 to TimerA1, (e) read the count from TACCR1 instead of TACCR0, and (f) change all the settings for TACCTL0 to TACCTL1, add a statement in the isr to clear CCIFG bit.

    I do no use CCS. I do not know how to fix or workaround its bugs. But in your case, it does not matter. Signed or unsigned, there is always one spot out of 65536 counts that looks strange.

    Using signed int, after 32767 you get -32768. But all other counts look right. E.g., -3, -2, -1, 0, 1, 2, 3,...

    Using unsigned int, after 65535 you get 0. All other counts looks right.

  • Hello once again! If been a little busy with the whole job hunting these days. But today I finally got time to go back to coding. As luck would often have it, I began running into a problem.

    My interrupt runs TWICE. Now, I read up on another thread (reply # 5): http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/p/89180/311327.aspx      and it stated that it had something to do with timer A.

    Now in the ISR, I increment a variable ' y ' to keep track (Code Composer Studio with "watch expression" feature ) of the number of times the program access the ISR. And each time, Y is incremented by two. This means that ISR is for sure being run twice. Can someone please point out where the problem is or might be. I have verified every line of my code above the comments " DO NOT WORRY ABOUT THE PARTS BELOW " **see code** and I think I have set it up correctly.

    PS: Is there a way or function that forces the program out of ISR without completing the entire code in the ISR? I ask it as general curioisty but the problem stated above is the main one

    All hints/helps are welcomed and appreciated.

    Thanks!!!!

     

    #include <msp430g2231.h>

    volatile unsigned int x=0;
    volatile unsigned int y=0;
    volatile unsigned int count1=0;
    volatile unsigned int count2=0;
    volatile unsigned int diff=0;
    volatile unsigned int init=0;

    void timer(void){
    TACCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE;   //capture on rising,input,capture and interrupt
    TACTL = TASSEL_2 + MC_2;            //SMCLK and continuous mode
    }

    void clock (void){
    BCSCTL1 = CALBC1_1MHZ;   
    DCOCTL = CALDCO_1MHZ;
    IFG1=0x00;      
    }

    void main (void)
    {
        WDTCTL = WDTPW + WDTHOLD;            // stop watch dog timer
        clock();  
        timer();
      
        P1DIR=0x41;                          // set leds in the out direction and every other pin as input
        P1SEL=BIT1;                           // set up P1.1 to accept inputs for the timer capture
        P1OUT=0x00;                           // make sure that everything is off initially
      
        _BIS_SR(GIE);           // enable interrupts
        while (1);
    }

    #pragma vector=TIMERA0_VECTOR
    __interrupt void TIMERA(void)
    {
        y+=1;                                // keep track in 'watch expression' to see if the ISR executes only once or twice
       
        TACCTL0&=~COV;                        // Remove capture overflow
        TACCTL0 &= ~CCIFG;                    // dismiss interrupt request flag
       
        TACCTL0 = CM_1 + SCS + CCIS_0 + CAP + CCIE;        //capture on rising,input,capture and interrupt
       
    /*************DO NOT WORRY ABOUT THE PARTS BELOW***********************/


        if (count1==0){                        // read the TACCR0 value
            count1= TACCR0;
           
            P1OUT=0x1;                        // start wait for 6 seconds
            _delay_cycles(6000000);       
            x=3;
        }

        if(count1!=0){
            count2=TACCR0;
            x=1;}

        if (x==1){
            if (count2==0){
                x=3;
            }
            else{diff=count2-count1;}
        }
       
        if (diff>65000){
        while (1){
            P1OUT=0x41;}
        }
        else x=3;
       
        if (x==3){
        P1OUT=0;
        }
    /*****************************************************************************/
    }

  • I assume that you tried to raised the voltage at P1,1 only once. But most likely the contact “bounced” many times within a very short period.

    Your ISR is very slow in handling the very first interrupt. As a result, it can only capture the last “bounce” after that. Thus this ISR is entered only twice.

    If you eliminate all the ISR code after the line /**** DO NOT WORRY ABOUT THE PARTS BELOW ***/. Y will show the true number of "bounces".

  • Let me try to guess what happens.

    You started to run the code, and main() ended up in a while (1) loop doing nothing but waiting for interrupts.

    Next, you try to raise the voltage at P1.1 a single time. But the contact bounced and the voltage actually went up and down many times all within a few milliseconds.

    When the voltage raises the first time, the Timer sets the CCIFG flag and captures TAR count in TACCR0. And an interrupt is generated.

    The while (1) loop is interrupted, and the Timer ISR is entered (for the first time). Your ISR changed y from 0 to 1. You try to clear COV bit, clear the CCIFG bit, and reload the TACCTL0. (These three operations did not change anything and did not do any harm.) All the above are accomplished within a few tens of microseconds after the voltage raises the first time. The bouncing of the P1.1 contact did not happen yet.

    Now the G2231 executes your code that are marked as:
    /*************DO NOT WORRY ABOUT THE PARTS BELOW***********************/
    I am not going to worry about it. But the G2231 will execute it anyway. While the CPU is executing this part the ISR, the Timer detected P1.1 voltage raise again many times during the course of a few milliseconds. CCIFG is set many times, TAR count is captured in TACCR0 many times.

    But the current ISR is not finished yet. Only the last capture stays in TACCR0 (all the earlier captures are wipe out by the next one.)

    Finally, the current ISR is finished and CPU returns to the while (1) loop in main(). As soon as this happens, another interrupt is granted because CCIFG is already set.

    The ISR is entered for the second time. Y is changed from 1 to 2.

    By this time, the bouncing is gone. And no more interrupt is generated.

  • Hi Usman!

    I was wondering if you have had your codes working? Could you please share it with me please? my email is zhu_zhixin@hotmail.com  I really appreciate your help!!

    Thanks again!

     

  • Just wanted to thank you all for the interesting thread.

    I am designing what is technically called a Wilkinson AD converter, in which I generate a pulse (positive to ground and back, 0.1 to 10 microsecs) and need to measure its length.

    If anybody has advise, code I can reuse, and specifically ideas on the time resolution that can be achieved @ 25 MHz clock, I would very much appreciate.

    Keep up with the good work!

    Marco

  • Marco Caceci said:
    I am designing what is technically called a Wilkinson AD converter, in which I generate a pulse (positive to ground and back, 0.1 to 10 microsecs) and need to measure its length.
    If anybody has advise, code I can reuse, and specifically ideas on the time resolution that can be achieved @ 25 MHz clock, I would very much appreciate.

    Sorry, no code. But a simple setup would be:

    set up a timer to count with 10MHz.

    Configure two CCR units to do a capture of their (connected9 external pin on rising and falling edge. Configure the one with the rising edge to trigger an interrupt. When the interrupt is triggered, you'll have the timer counts at the edges in the two CCR registers. The difference between the counts (including overflow at 65536, which is automatic on unsigned int operations) is the duration of the pulse in 0.1µs resolution. (0.1µs to 6.5ms range)

    If you set the timer to count with 20MHz (if supported by the MSP), you'll have 0.05µs resolution. Note that the results are rounded to the timer clock edge.

    If you need finer resolution, you'll need to go for an MSP with the high-speed timerD. However, the approach is the same.

**Attention** This is a public forum