Gast
#3254096
Moin, Ich habe hier ein Projekt mit einem MSP430 und einem RFM12, bei dem der Prozessor nach einem Timeout dem RFM12 über einen PNP Transistor den Saft klaut und sich mit LPM3 schlafen legen soll. Damit in der Zwischenzeit keine parasitären Ströme über die SPI zum RFM12 fließen, muß ich die USCIB an der der RFM12 liegt deinitialisieren, also die entsprechenden Portpins (P1.5,P1.6 und P1.7) auf Ausgang mit Low Potential schalten (oder auf Eingang floatend). Die Applikation funktioniert nach dem Aufwachen wieder, nur sind meine Variablen weg, weil der Prozessor offensichtlich einen Reset an dieser Stelle macht. Für die Initialisierung und die Reinitialisierung nach dem LPM3 verwende ich die selben Routinen (USCIAset() und USCIBset()). Das ist die Funktion zur initialisierung der USCIB: void USCIBset() // Restore IO after LPM3 // Setup the USCIB to RF12 Communication { __disable_interrupt(); P1SEL |= BIT5 | BIT6 | BIT7; // P1.5 UCB0CLK, P1.6 UCB0SOMI, P1.7 UCB0SIMO P1SEL2 |= BIT5 | BIT6 | BIT7; // P1.5 UCB0CLK, P1.6 UCB0SOMI P1.7 UCB0SIMO P1DIR |= BIT4; P1SEL &= ~BIT4; // P1.4 Output RFM12 Enable P1SEL2 &= ~BIT4; P1OUT |=BIT4; // P1.4 High RFM12 inactive // USCI Channel B, 2 Wire SPI UCB0CTL1 |= UCSWRST; // Reset USCI B /* * Control Register 0 * * ~UCCKPH -- Data is changed on the first UCLK edge and captured on the following edge * UCCKPL -- Inactive state is high * UCMSB -- MSB first * ~UC7BIT -- 8-bit * UCMST -- Master mode * UCMODE_0 -- 3-Pin SPI * UCSYNC -- Synchronous Mode * */ UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCMODE_0 | UCSYNC; //mode(0,0) /* * Control Register 1 * * UCSSEL_2 -- SMCLK * UCSWRST -- Enabled. USCI logic held in reset state */ UCB0CTL1 = UCSSEL_2 | UCSWRST; // SMCLK /* Bit Rate Control Register 0 */ UCB0BR0 = 16; // SMCLK/16 = 921600hz //UCB0BR0 = 1; // SMCLK/1 = 1MHz /* Enable USCI */ UCB0CTL1 &= ~UCSWRST; __enable_interrupt(); } und hier die zur "Deinitialisierung" void USCIBunset() // To be called before LPM3 to lower current consumtion // Reset USCIB to make the Processor signals input to // prevent the RF12 to draw current { __disable_interrupt(); // P1.5 |P1.6 |P1.7 |P1.4 //UCB0CLK|UCB0SOMI|UCB0SIMO|RF12SEL UCB0CTL1 = UCSWRST; // Reset USCI B P1OUT &= ~(BIT7|BIT6|BIT5|BIT4); // pull to low P1DIR &= ~(BIT7|BIT6|BIT5); // Inputs P1SEL &= ~(BIT7|BIT6|BIT5); // IO Function P1SEL2 &=~(BIT7|BIT6|BIT5); // IO Function __enable_interrupt(); } An und für sich sollte das disablen der Interrupts nicht notwendig sein, weil ich an dieser Stelle schon Alles "den Schlaf" störende ausgeschaltet habe. Der einzige freigegebene Int ist einer an P1.3 der den Prozessor aufwachen läßt und weitere Ints von dem Ding werden schon in der ISR abgeschaltet. P1.4 das oben mit angesteuert wird, ist des Select Signal für den RFM12, deswegen sollte das auch nach Abschalten der Betriebsspannung des RFM auf GND gezogen werden, sonst versorgt sich auch von da der RFM12. Gerufen wird die Abschalterei von hier: void beforesleep() { GAUGEPOWER_OFF; USCIAunset(); // deactivate RS232 USCIBunset(); // make P1.5..P1.7 high impedance LED_ERR_OFF; // switch off LEDs LED_RX_OFF; // switch off LEDs LED_TX_OFF; // switch off LEDs fiveminto=TIMEOUT; // reload timeout value TA0CTL = TACLR; // Reset Timer A0 TACCTL0 &= ~CCIE; // TACCR0 Int disable P1IFG &=~BIT3; // P1.3 Reset Int FLG P1IE |=BIT3; // P1.3 Interrupt Enable P2IE &= ~BIT0; // P2.0 Interrupt disable (SCK) WDTCTL = WDTPW|WDTHOLD; // stop watchdog IE1 &= ~WDTIE; // disarm WDT int } wobei ich mit der Reihenfolge auch schon experimentiert habe. Wenn ich den RFM12 aus der Fassung ziehe und auf die Deinitialisierung verzichte, wacht der Prozessor wieder so auf, wie er sollte, USCIA macht nur eine RS232 zu Debug Zwecken und außer das ich "Glitches" auf der TxD Leitung offensichtlich nicht vermeiden kann, funktioniert das dort mit USCIAUnset problemlos. Interrupts benutzen beide USCIs nicht. Der Vollständigkeit halber noch die zur RS232 gehörenden Routinen: void USCIAset() // Initialize USCI Channel A, async UART { /* * Control Register 1 */ UCA0CTL0 = 0; // ASYNC, 8 Bit, No Parity, 1Stopbit, UART Mode /* * Control Register 1 * * ~UCSSEL_1 * UCSSEL_0 BRCLK = ACLK * ~UCRXEIE Errornous Character disabled * ~UCBRKIE Received BREAK Charakters do not set UCA0RXIFG * ~UCDORM Not dormant. All received characters will set UCA0RXIFG * ~UCTXADDR Next received character is data * ~UCTXBRK Next frame transmitted is not BREAK * UCSWRST Enables. USCI logic held in RESET * * Note: ~<BIT> indicates that <BIT> has value zero */ UCA0CTL1 = 0; UCA0CTL1 |= UCSWRST; // RESET UCA0CTL1 |= UCSSEL0; // USCI use ACLK 32768Hz UCA0BR0 = 3; // 9600 UCA0BR1 = 0; // UCA0MCTL = (UCBRS0 | UCBRS1) & ~UCOS16; // Modulation 3 P1SEL |= RXD |TXD; // P1.1 RXD, P1.2 TXD P1SEL2 |= RXD | TXD; // P1.1 RXD, P1.2 TXD UCA0CTL1 &= ~UCSWRST; // Start USCI state machine } //---------------------------------------------------------------------- ---- void USCIAunset() // Reset USCIA before LPM3 { // from sending garbadge // still a glitch.. fixable? UCA0CTL1 |= UCSWRST; // Reset UCSIA P1SEL &= ~(RXD|TXD); P1SEL2 &= ~(RXD|TXD); // Make Pins standard IO P1OUT |= TXD; P1DIR |= TXD; // set to high to prevent TXD } Hat Jemand eine Idee wer mit da in die Suppe spucken könnte? Der MSP430 nimmt in Ruhe erwartungsgemäß 0,8µA an 3,6V auf (Lithiumzelle). Gruß, Holm