I am using Code Composer Version: 5.2.1.00018 and a MSP430G2553 processor. I did a post called Port 1 Interrupt Problem. I spent two weeks tracking down a problem and it turned out to be one of these "|". I put the following:
P1OUT = LED1;// Set P1.0 to output direction.
It turns on the LED but it locks up the PORT 1 ISR.
If I put "P1OUT |= LED1;// Set P1.0 to output direction" it turns on the LED and doesn't lock out Port1 ISR.
Yes there is a question:
Does anyone know a reference that explains when to use "=" verses "|="?
For example the following that sets up a UART
P1SEL = BIT1 + BIT2; // Set P1.1 to RXD and P1.2 to TXD P1SEL2 = BIT1 + BIT2; // UCA0CTL1 |= UCSSEL_2; // Have USCI use SMCLK AKA 1MHz main CLK UCA0BR0 = 104; // Baud: 9600, N= CLK/Baud, N= 10^6 / 9600 UCA0BR1 = 0; // Set upper half of baud select to 0 UCA0MCTL = UCBRS_1; // Modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // Start USCI IE2 |= UCA0RXIE;
Why = in some places and |= in others?
P1OUT |= LED1;
is the same as
P1OUT = P1OUT | LED1; // put the result of P1OUT OR'ed with LED1 into P1OUT
i.e. set some more bits in P1OUT but dont clear any bits that are already set.
P1OUT = LED1
i.e. discard or clear what was in P1OUT then only set the bits indicated by LED1.
Some examples might help:
#define LED1 0x01 // 00000001 in binary i.e. bit 0 set
#define LED2 0x02 // 00000010 in binary i.e. bit 1 set
-
Example 1:
P1OUT = LED1; // overwrite P1OUT with 0x01
result is P1OUT contains 0x01 i.e. bit 0 only is set.
Example 2.
P1OUT |= LED2; // OR in 0x02
result is P1OUT contains 0x03. bit 0 is set in the first instruction bit 1 is set in the second
Hope this helps.
You are giving me examples of oring bits.
What is the difference between
and
P1OUT |= LED1
Why does one lock out my Port 1 ISR and the other doesn't?
Some guessing as I don't have this platform. From looking at the user guide, I would guess you have a pin on port 1 configured as an input with pull-up. The direction of the pull is determined by P1OUT. Using "P1OUT = LED1" would set bit LED1 but clear other bits. This changes the pull-up to pull-down. Loss of the ISR implied your input signal requires a pull-up to function, ie. open-collector, switch connected to ground.
Donald VarelaYou are giving me examples of oring bits.
Because that was the question you asked!
You asked about the |= operator - and that is about ORing bits!
Donald VarelaWhat is the difference between P1OUT = LED1 and P1OUT |= LED1
That has already been explained to you - which part(s) did you not understand?
Note that these are entirely standard 'C' operators - there is nothing about them that is specific to the MSP430. See any 'C' textbook for details...
Donald VarelaWhy does one lock out my Port 1 ISR and the other doesn't?
Consider what effect each one has on the value in P1OUT, then consider what effect that would have on the port operation - including interrupts...
Andy I understand what you are saying about the oring of the bits. One sets a bit and then clears other bits and the other just sets a bit. My question is why does
P1OUT = LED1 lock out Port 1 ISR, which are inputs, and
P1OUT |= LED1 doesn't. How do I know which one to use at what time? I am going to post my program. The program works OK the way it is written. Put it on a Launchpad with a MSP430G2553 processor and set the UART jumpers to Hardware. When connected to the terminal type the character "a" without the quotes. It will respond by printing three "FIRST". Then ground P1.7. This is my button. It responds with "GO".
In the "Case a" change
P1OUT |= LED1 to
P1OUT = LED1. Go through the same steps and notice "GO" is not printed because Port 1 doesn't fire.
The program does other things but they aren't activated following the above procedures.
Bottom line I'm trying to figure out when to use = VS |=.
#include <msp430g2553.h>////////////////Defines////////////////#define LED1 BIT6#define LED0 BIT0#define DAT BIT0 //P2.0 //input signal port#define BUTTON BIT7#define BUTTON_OUT P1OUT#define BUTTON_DIR P1DIR#define BUTTON_IN P1IN#define BUTTON_IE P1IE#define BUTTON_IES P1IES#define BUTTON_IFG P1IFG#define BUTTON_REN P1RENchar charbuffer[8];int i=0;int j=0;int dis=0;int dissave=0;float mycount=0;unsigned int capture_array[30]; // RAM array for capturesint tick=0;int cap=0;float milesper=1.32/5280;int pre_cap=0;int first_pulse=0;int Start=0;int Start2 = 0;char disbuffer[8];volatile unsigned char butdeb[1];
////////////////Function Protos////////////////void TX(char *tx_message);static char *i2a(unsigned i, char *a, unsigned r);char *itoa(int i, char *a, int r);
static char *i2a(unsigned i, char *a, unsigned r){ if (i/r > 0) a = i2a(i/r,a,r); *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; return a+1;}
char *itoa(int i, char *a, int r){ if ((r < 2) || (r > 36)) r = 10; if (i < 0) { *a = '-'; *i2a(-(unsigned)i,a+1,r) = 0; } else *i2a(i,a,r) = 0; return a;}
void TX(char *tx_message){ unsigned int i=0; //Define end of string loop int char *message; // message variable unsigned int message_num; // define ascii int version variable message = tx_message; // move tx_message into message while(1) { if(message[i]==0) // If end of input string is reached, break loop. {break;} message_num = (int)message[i]; //Cast string char into a int variable UCA0TXBUF = message_num; // write INT to TX buffer i++; // increase string index __delay_cycles(10000); //transmission delay if(i>50) //prevent infinite transmit { P1OUT |= (LED1+LED0); break; } } // End TX Main While Loop} // End TX Functionint main(void){ WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
//setup clock to 1MHZ BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ;
////////////////USCI setup//////////////// butdeb[0] = 0; // Reset button debounce P1SEL = BIT1 + BIT2; // Set P1.1 to RXD and P1.2 to TXD P1SEL2 = BIT1 + BIT2; // UCA0CTL1 |= UCSSEL_2; // Have USCI use SMCLK AKA 1MHz main CLK UCA0BR0 = 104; // Baud: 9600, N= CLK/Baud, N= 10^6 / 9600 UCA0BR1 = 0; // Set upper half of baud select to 0 UCA0MCTL = UCBRS_1; // Modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // Start USCI IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt ////////////////General GPIO Defines////////////////
BUTTON_DIR &= ~BUTTON; BUTTON_OUT |= BUTTON; BUTTON_REN |= BUTTON; BUTTON_IES |= BUTTON; BUTTON_IFG &= ~BUTTON; BUTTON_IE |= BUTTON;
P1DIR |= (LED0 + LED1); //define output ports P1OUT &= ~(LED0 + LED1); //turn ports low P2REN |=(DAT); //enable pullups on respective ports P2IE |= DAT; P2IFG &= ~DAT; P2SEL = DAT; /////////////////SETUP TIMER TA1CCTL0 = CM_2 + SCS + CCIS_0 + CAP + CCIE; // falling edge + CCI0A (P2.0)// + Capture Mode + Interrupt TA1CTL = TASSEL_2 + MC_2; // SMCLK + Continuous Mode __enable_interrupt(); for(;;) { if (dis!=dissave){ TX("D"); itoa(dis, disbuffer,10); TX(disbuffer); TX("\r\n"); TX("S"); itoa(capture_array[5], charbuffer, 10); TX(charbuffer); TX("\r\n"); dissave=dis; } if (Start2==1){ Start2=0; }
}
#pragma vector=USCIAB0RX_VECTOR__interrupt void USCI0RX_ISR(void){ unsigned char c; c = UCA0RXBUF; //SendChar(c); //SendChar( '>' ); switch( c ) { case 'a': // This resets all variables WDTCTL = WDTPW + WDTHOLD;// Stop watchdog timer tick=0; cap=0; mycount=0.0; pre_cap=0; first_pulse=0; i=0; j=0; dis=0; TX("FIRST"); TX("\r\n"); TX("FIRST"); TX("\r\n"); TX("FIRST"); TX("\r\n"); Start=0; BUTTON_IFG &=~BUTTON; BUTTON_IE |= BUTTON; butdeb[0] = 0; // Reset button debounce P1DIR |= 0x01; P1OUT |= LED0;// Set P1.0 to output direction __delay_cycles(10000); break; // main(); }}
// Timer1 interrupt service routine#pragma vector=TIMER1_A0_VECTOR__interrupt void TIMER1(void){ dis+=1; if (first_pulse==0) { pre_cap=TA1CCR0; first_pulse=1; goto here; //break from interrupt service routine }tick = TA1CCR0;cap = tick- pre_cap;mycount=cap;mycount=mycount/10000000;mycount=mycount/3600;mycount=milesper/mycount;cap=mycount;capture_array[i]=cap;i++;if (i ==10){ P1OUT^=LED0;//toggle led first_pulse=0; i=0; mycount=0; }butdeb[0]?butdeb[0]--:1;if (!butdeb[0]){ BUTTON_IFG &=~BUTTON; BUTTON_IE |= BUTTON;}pre_cap = tick; // store this capture valuehere:P1OUT^=LED1;}
#pragma vector=PORT1_VECTOR__interrupt void P1_ISR(void) {
if ((BUTTON_IN & BUTTON) && !butdeb[0]) {
if(Start==0){ butdeb[0] = 8; //start timer // TA1CCTL0 |= CM_2; // TA1CTL = TASSEL_2 + MC_2; // SMCLK + Continuous Mode TX("GO"); TX("\r\n"); Start = 1; } else{ butdeb[0] = 8; TX("HALT"); TX("\r\n"); Start = 0; } }
Donald Varela My question is why does P1OUT = LED1 lock out Port 1 ISR, which are inputs, and P1OUT |= LED1 doesn't.
My question is why does
P1OUT |= LED1 doesn't.
Again, consider what value each one causes to be written into P1OUT, and then consider what effect each value has.
You will have to look in the Datasheet to see the effects of writing to P1OUT.
Donald VarelaHow do I know which one to use at what time?
You use whichever will give the value that you require!
I have a very similar problem.
I have an application program which did not work at all. Finally I realized that if I change the statement: x = y + 5; into x = y - 5 ; then it works fine.
My question is, why "-" makes it work and "+" makes it not work? When should I use "+"? When should I use "-"?
Andy NeilYou will have to look in the Datasheet to see the effects of writing to P1OUT.
It may also depend on the external circuitry...
Andy thanks for pointing me in the right direction on the oring. I did some more research and found this article. http://www.glitovsky.com/Tutorialv0_3.pdf. It explain what you were trying to tell me about P1OUT= and P1OUT |=.
Still not absolutely sure of the details of why it turns the LED on but locks up the PORT 1 ISR function but I understand more about the effects of the = verses |=. Thanks again!!!
Donald VarelaStill not absolutely sure of the details of why it turns the LED on but locks up the PORT 1 ISR function
Think about it: rather than just writing one bit (the one with the LED connected), you are writing all bits - so you have to consider all the effects of writing all those bits...
Donald VarelaAndy thanks for pointing me in the right direction on the oring
Don't forget that it was by Mark Green who explained it to you first
I want to thank everyone. I wrote a previous program using a WDT ISR and could never get it to fire. Yes I had "P1OUT=" instead of "P1OUT |=". Went back and changed it and it works perfectly. Now that I understand oring better I won't make that mistake any more, MAYBE!!!
Donald VarelaNow that I understand oring better...
Consider where you might need ANDing;
Consider where you might need XORing...