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.

MSP430F5529: Logic gates? How do I combine bits to get say P4.7 = (P2.3 AND P2.5)

Part Number: MSP430F5529

I am working with the MSPF5529 

I would like to set up a set of sampling pulses to drive a photogate on a pendulum. So the drive would be turned on just before it is needed, to measure the pendulum location.  

The sampling pulses could be high frequency and low duty cycle say 300KHz and 10%.  That could be created with one clock source and a divider.  Then a much slower clock could generate a roughly 1 Hz "sample ON" pulse.  

How do I combine these pulses logically?  If each was assigned to an output pin, how do I create NAND, NOR, AND, OR etc? 

So I am imagining  I want " P4.7 = (P2.3 AND P2.5) "  where 2.3 is HF and 2.5 is LF?   I don't see how to name a pin with both the port and the pin number.  
I ran the following code and it compiles, which surprised me, but  it does not light the AND LED.  The "fast" is 16 Hz here and the slow is 1 Hz.  (The example is from the MSP Ware code for the MSPF5529.)    

 I also don't  see how you could assign the AND to a different port such as P4.7 if the inputs were on another port such as P2.3 and P2.5 


#include <msp430.h>//***MSP430F55xx_ta2_08.c***Timer2_A3, Toggle P1.0;P2.3-5,
// Cont. Mode ISR, 32kHz ACLK
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//P2SEL |= BIT3+BIT4+BIT5; // P2.3 - P2.5 option select
//P2DIR |= BIT3+BIT4+BIT5; // P2.3 - P2.5 outputs
P2SEL |= BIT3+BIT4+BIT5+BIT7; // P2.3 - P2.5 & P2.7 selected
P2DIR |= BIT3+BIT4+BIT5+BIT7; // P2.3 - P2.5 & P2.7 are outputs

P1DIR |= 0x01; // P1.0 - Outputs
TA2CCTL0 = OUTMOD_4 + CCIE; // CCR0 toggle, interrupt enabled
TA2CCTL1 = OUTMOD_4 + CCIE; // CCR1 toggle, interrupt enabled
TA2CCTL2 = OUTMOD_4 + CCIE; // CCR2 toggle, interrupt enabled
TA2CTL = TASSEL_1 + MC_2 + TACLR + TAIE; // ACLK =1, contmode, clear TAR,
// interrupt enabled

__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, interrupts enabled
__no_operation(); // For debugger
}

// Timer2 A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER2_A0_VECTOR
__interrupt void Timer2_A0 (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER2_A0_VECTOR))) Timer2_A0 (void)
#else
#error Compiler not supported!
#endif
{
TA2CCR0 += 1024; // Add 1024 Offset to CCR0 = 16 Hz
}

// Timer2_A3 Interrupt Vector (TAIV) handler
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER2_A1_VECTOR
__interrupt void TIMER2_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER2_A1_VECTOR))) TIMER2_A1_ISR (void)
#else
#error Compiler not supported!
#endif
{

switch(__even_in_range(TA2IV,14))
{
case 0: break; // CA2CCR0 value set at line 70 above
case 2: TA2CCR1 += 4096; // Add 4096 Offset to CCR1 4 Hz  // works
break;
case 4: TA2CCR2 += 16384; // Add 16384 Offset to CCR2 1 Hz  // works 
break;
case 6: break; // CCR3 not used
case 8: break; // CCR4 not used
case 10: break; // CCR5 not used
case 12: break; // Reserved not used
case 14: P1OUT ^= 0x01; // overflow is 0.25 Hz
break;
default: break;
}
P2OUT = (BIT3 & BIT5);   // attempt using AND, to get 1 Hz with 4 Hz modulation // fails 
}

  • In general you can't do this. None of the MSP430s (to my knowledge) has the sort of little-logic block  seen in e.g. C2000 CLB or some MCUs from [Other Guys]. The AppNotes I've seen where the authors needed this sort of thing used external logic.

    For specific cases, there might be tricks. I would start with the DMA, which can be triggered using a timer match and can copy things from anywhere to anywhere else, including peripheral registers [Ref data sheet (SLAS590N) Table 6-10]. There might also be a trick with the Comparator, though I haven't tried this.

    >P2OUT = (BIT3 & BIT5);   // attempt using AND, to get 1 Hz with 4 Hz modulation // fails 

    This is a valid C statement -- it takes the result of (0x08 & 0x20)=0 and stores it into P2OUT -- but it doesn't do what you want. To do the logic in software you'll have to spell it out:

    >if ((P2IN&BIT3)&&(P2IN&BIT5)) P2OUT |= BIT7; else P2OUT &= ~BIT7;

    (For this particular case, where both pins are in the same port, you could use a slightly shorter form, but this is the general case.)

    Is the 1Hz enable signal internal or external?

  • Thank you Bruce. 

    I tried pasting that line into the code and compiled it and it ran, but still no AND on the LED. 

    The syntax you show is intriguing.  I would not have guessed it.  Are you sure it should work?  I am working solo on this and only have passing familiarly with C.  

    My conceptual model for this process is that one writes the code to accomplish a task and the microprocessor has enough switches to wire things up internally the way that gives you the output you want.  

    Clearly, there are expected setups that were planned for, the User Guide and the data  sheets have those, but they can't plan for everything. There are too many possibilities.  I would expect a NAND and NOR could be done in software -but making a master slave JK FF is probably not easily done! 

    I have seen examples where an 8 bit port can function as a shift register, or an 8 bit ADC, but those come from the way numbers are stored at the hardware level.  
    I can of course use external logic.  I have some 4000 series CMOS I can use for this.    I am concerned about the speed and drive level at only 3.3 V, but it will probably work.  I could also do a wired AND and buffer it of course.   


      

  • You didn't mention an LED before. Where is it? I offered that line of code as an alternative to the one you pointed out. Among other things, it gives you only an instantaneous indicator, not a continuous signal, so it doesn't solve your stated problem.

    You could gate the timer output in software -- when you encounter an edge (compare interrupt) on the Enable signal, just stop the timer or set OUTMOD to stop the output pulses. There would be some latency, though in the context of a 1Hz signal a few 10s of microseconds of latency might not be noticed. 

  • Hello Bruce and thank  you again for your support and kindness. 

    I plan to use this AND signal to drive the  LED for a photogate that senses the maximum amplitude of a clock pendulum.   I could drive  the photogate all the time, but it is wasteful of battery.  I want high total efficiency. Just for the challenge. 

    I set up the code above so the 1 Hz and the 4 Hz are derived from a CONT mode in the timer, generating toggles of different periods.  I wanted 4 Hz and 1 Hz for this test setup because I can use an LED as a simple indicator of success in the hardware and the software. I can easily see that, and don't need an oscilloscope or any other hardware. These little boards fit in my satchel and it is a minimalist approach to learning how to program them.  

    For the actual pendulum clock I will sample at 32 Khz or faster and maintain the amplitude very tightly using the photogate at the maximum amplitude.  A second photogate will ensure the pendulum is at BDC bottom dead center, when pendulum drive is supplied. That will be done infrequently, to allow the pendulum to be free, as much as possible. Drive at BDC affects the period of the pendulum minimally. 

    The design is derived from the Hipp Toggle Clock which is one of the early electromechanical clock drives and is elegantly simple.  I can't find a clear enough illustration that I can link to here, but I will try tomorrow.  If you are interested.  

  • I have worked with this some.  The syntax for the logic is as you described Bruce, thank you very much for that.  I have not been able to logically AND the output of various timers together. I did use a CD4081BE CMOS chip to AND the  outputs together and that did work. I will work some more with the timers.  

    I tried another approach, having a delay then P1.0 ON, then a while loop that checks if P1.0 is ON and blinks P4,7 if it is.  That works fine.  I used several counts of 60,000 in succession to get a longer delay.    So the basic syntax of a signal is shown in the code below.  One of the "^=" or statements can be commented out if you want to see that the "while (TRUE)" logic does work.  Code is 

    //***From MSP430F55xx_1.c*****Toggle P1.0/LED***********
    // MSP430F552x Demo - Software Toggle P1.0 AND toggle P4.7 when
    // port P1.0 is HIGH. Demonstrates TRUE with "while ( ) " statement.
    //
    // Description: Toggle P1.0 by xor'ing P1.0 inside of a software loop.
    // ACLK = 32.768kHz, MCLK = SMCLK = default DCO~1MHz
    //
    // MSP430F552x
    //         -------------------------------
    //   /|\  |                                     |
    //    |   |                                     |
    //     -- |                     RST P4.7|-->LED
    //        |                                     |
    //        |                              P1.0|-->LED
    //
    //*********************************************************************
    #include <msp430.h> //***MSP430F55xx_1.c*****Toggle P1.0/LED***********
    int main(void) {
    volatile unsigned int i, j;

    WDTCTL = WDTPW+WDTHOLD; // Stop WDT
    P1DIR |= 0x01; // P1.0 set as output
    P4DIR |= 0x80; // set bit 7 (of P4.7) as output
    P4OUT = 0; // "=" works to set zero, or 128 or 0x80.
    P1OUT = 0;

    while(1) // continuous loop // flips starting config immediately
    {
    P1OUT ^= 0x01;       // XOR P1.0? YES WORKS //we blink twice
    for(i=5000;i>0;i--);     //short blink ON
    P1OUT ^= 0x01;      //OFF
    for(i=5000;i>0;i--);    //short blink OFF
    P1OUT ^= 0x01;      //ON
    for(i=5000;i>0;i--);    //short blink ON
    P1OUT ^= 0x01;     //OFF
    for(i=5000;i>0;i--);   //short blink OFF

    for(i=60000;i>0;i--);
    for(i=60000;i>0;i--);     // ADD DELAYs
    for(i=60000;i>0;i--);
    P1OUT ^= 0x01;       //ON

    j = 0;
    while ((P1OUT&BIT0) && ( j < 20)) {        //only blink P4.7 if P1.0 is ON
    P4OUT ^= 128;
    for (i=5000; i>0; i--);
    j++;
    }
    P1OUT ^= 0x01;                    //OFF
    for(i=60000;i>0;i--);            //delay

    //P1OUT ^= 0x01;           //ON        //if commented out it alternates P1.0


    j = 0;
    while ((P1OUT&BIT0) && ( j < 20)) {
    P4OUT ^= 128;
    for (i=5000; i>0; i--);
    j++;
    }
    P1OUT ^= 0x01;
    for(i=60000;i>0;i--);          //long delay
    for(i=60000;i>0;i--);
    for(i=60000;i>0;i--);
    }
    }



**Attention** This is a public forum