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
Seltsam. Interessant wäre zu wissen, an welcher Stelle der Reset passiert. Grob ins Blaue spekuliert: vielleicht mag es der USCI ja nicht, wenn du die Ports zwischendrin auf GPIO schaltest. Ich würde wie folgt vorgehen: * In der Deaktivierungsroutine die P1SEL (was ist denn P1SEL2?) rauswerfen und nur die Richtung mit P1DIR umschalten. Ggf. noch über P1OUT den Pullup ausschalten. * Wenn das nicht hilft, step-by-step schauen, ob wirklich ein Reset kommt und wenn ja, an welcher Stelle. Kann es ein Watchdog-Problem sein? * Dritter Schritt: bei e2e.ti.com nachfragen. Jens-Michael Gross hat sicher eine Idee :-) Max
Max G. schrieb: > Seltsam. Interessant wäre zu wissen, an welcher Stelle der Reset > passiert. Grob ins Blaue spekuliert: vielleicht mag es der USCI ja > nicht, wenn du die Ports zwischendrin auf GPIO schaltest. Hmm, mögen ist gut...ich setze das Teil ja simpel zurück. und die besser ausgebaute Schwester USCIA verträgt das scheinbar problemlos. > > Ich würde wie folgt vorgehen: > * In der Deaktivierungsroutine die P1SEL (was ist denn P1SEL2?) "Function Select Registers PxSEL and PxSEL2" nach slau144j.pdf S 329 MSP430x2xx Family Users Guide... msp430g2553.h: #define P1SEL2_ 0x0041 /* Port 1 Selection 2 */ > rauswerfen und nur die Richtung mit P1DIR umschalten. Ggf. noch über > P1OUT den Pullup ausschalten. Ich werde das mal probieren, dauert aber noch ein Bisschen. > * Wenn das nicht hilft, step-by-step schauen, ob wirklich ein Reset > kommt und wenn ja, an welcher Stelle. Das geht wegen LPM3 eher nicht. Ich merke es daran, dass greeting() gerufen wird, das Ding aber im case 0 - Zweig aufwachen sollte, ohne das greeting(). int main(void) { char stVal[17]; char * s; ioinit(); aftersleep(); greeting(); PGMState=1; while(1) { switch(PGMState) { // 0: sleep, waiting for an button press case 0: { print("S0\r\n"); beforesleep(); LPM3; if(PGMState==0) PGMState=1; break; } // 1: init rf12, goto state 2 case 1: { aftersleep(); rf12_init(); PGMState=2; > Kann es ein Watchdog-Problem sein? > * Dritter Schritt: bei e2e.ti.com nachfragen. Jens-Michael Gross hat > sicher eine Idee :-) > > Max Watchdog ist zu diesem Zeitpunkt abgeschaltet und läuft sonst mit 1,9ms Interrupt als Zeitgeber.. Gruß, Holm
Bist du sicher, dass der Reset direkt nach dem Aufwachen kommt? Oder passiert dazwischen noch was? Steht in den Errata was dazu? Ansonsten wie gesagt: e2e.ti.com ist für MSP430-Themen hilfreicher als das Forum hier. Sorry. Max
Nein, natürlich nicht sicher. Ich merke nur das, wenn ich die USCIB nicht zurücksetzte, dass dann kein Reset passiert. das hier mit MSP430 nicht so dermaßen viel lost ist, weiß ich.. Gruß, Holm
Vielleicht erstmal schaun ob da wirklich ein Reset kommt: - Spannungsteiler von + nach GND aus 2 gleichen Widerständen an den Portpin hängen. - Bei einem echten Reset wird das Pin Tri-State. Dann sollte da die 1/2 Betriebsspannung auf dem Oszi zu sehen sein.
Auflösung des Rätsels: Die Sache funktioniert schon wie programmiert, der Reset wurde im Prinzip nur durch das Zuschalten der Betriebsspannung für den RFM12 und eine externe China-Digitalmeßuhr verursacht. Etwas mehr Abblocken der Betriebsspannung am MSP430 (10µ) hat den Effekt dann beseitigt. Eigentlich hatte ich gedacht der der relativ kurz a nder Testschaltung angelötete olle Lithium-Handyakku von Siemens niederohmig genug sei und hatte nur mit 680n geblockt. Verstärkt wurde der Effekt noch durch eine Diode in Reihe zur Betriebsspannung, der ich einen Strommesser parallel geschaltet hatte, ich wollte ja wissen wieviel das Ding im Schlafmodus so zieht und auch eine Überlastung des Strommessers vermeiden (Uni 11e, bis runter zu 3µA Vollausschlag, FET-Voltmeter). Im Endeffekt erwies sich die 1N4148 in Durchlassrichtung auch als zu hochohmig, die Meßuhr startete nicht mehr richtig ohne parallel geschalteten Strommesser mit minimal 100mA Bereich. Evtl. Probiere ich nochmal irgend eine Schottky. Die Sache funktioniert nun schon ein paar Tage wie sie soll. Gruß, Holm
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.