(6) Mikrokontrolery MSP430: porty I/O, obsługa wejść
Żeby skrócić czas wykonania procedury obsługi przerwania w MSP430FR5739 zastosowano specjalny rejestr PxIV (rejestr tylko do odczytu). W rejestrze zapisywana jest wartość informująca o numerze flagi przerwania o najwyższym priorytecie która jest aktualnie ustawiona. Dla wejścia numer 0 jest to wartość 2, dla wejścia numer 1 jest to wartość 4 – a dalej kolejno – dla wejścia numer 7 jest to wartość 16. Podczas odczytu rejestru PxIV zerowana jest jego wartość. Dodatkowo automatycznie czyszczona jest flaga przerwania o najwyższym priorytecie. Szablon procedury obsługi przerwania dla portów P1, P2 i P3 z wykorzystaniem rejestru PxIV pokazano na listingu 3.
List. 3. Szablon procedury obsługi przerwania dla portów P1, P2 i P3
#pragma vector=PORTX_VECTOR __interrupt void Port_X(void) { switch(__even_in_range(PxIV,16)) { case 2: break; // Px.0 case 4: break; // Px.1 case 6: break; // Px.2 case 8: break; // Px.3 case 10: break; // Px.4 case 12: break; // Px.5 case 14: break; // Px.6 case 16: break; // Px.7 default: break; } }
* w miejsce znaku „X” należy wstawić numer portu mikrokontrolera
Szablony procedury obsługi przerwania dla portu P4 z wykorzystaniem rejestru PxIV pokazano na listingu 4 (port P4 ma 2 linie wejścia/wyjścia).
List. 4. Szablon procedury obsługi przerwania dla portu P4
#pragma vector=PORT4_VECTOR __interrupt void Port_4(void) { switch(__even_in_range(P4IV,4)) { case 2: break; // P4.0 case 4: break; // P4.1 default: break; } }
Korzystając z rejestru PxIV w pierwszej kolejności obsłużymy przerwanie o najwyższym priorytecie. Przykładowo jeśli ustawione są dwie flagi przerwania, jedna dla wejścia numer 0 druga dla wejścia numer 1 to procedura obsługi przerwania wywołana będzie dwukrotnie. Za pierwszym wywołaniem procedury w rejestrze PxIV ustawiona będzie wartość 2. Odczyt rejestru (instrukcja switch) wyzeruje jego wartość, a w rejestrze PxIFG wyzerowana zostanie flagę przerwania dla wejścia numer 0. Ponieważ ciągle pozostaje ustawiona flaga przerwania dla wejścia 1, to procedura obsługi przerwania zostanie wywołana ponownie. Przy drugim wywołaniu procedury obsługi przerwania w rejestrze PxIV ustawiona jest wartość 4. Odczyt rejestru PxIV wyzeruje jego wartość i wyczyści flagę przerwania dla wejścia numer 1.
Na płytce startowej LaunchPad do linii numer 0 portu P4 mikrokontrolera podłączono przycisk S1. W prezentowanym przykładzie linie P4.0 mikrokontrolera konfigurujemy jako wejście z włączonym rezystorem podciągającym pull-up . Wciśnięcie przycisku S1 powoduje pojawienie się stanu niskiego na wejściu. Gdy przycisk nie jest wciśnięty to rezystor podciągający pull-up wymusza stanu wysoki na wejściu. W programie wciśnięcie przycisku S1 sygnalizować będziemy włączeniem diody LED1. Na płytce startowej LaunchPad dioda LED1 podłączona jest do linii numer 0 portu PJ. W programie linię PJ.0 konfigurujemy jako wyjście (stan wysoki na wyjściu włącza diodę LED1, stan niski na wyjściu wyłącza diodę).
Rys. 1. Schemat podłączenia a) przycisku S1 do linii P4.0 b) diody LED1 do linii PJ.0 (połączenia wykonane na płytce zestawu LaunchPad)
Przykład „Obsługa wejścia” został napisany w dwóch wersjach. W pierwszej wersji programu wejście obsługiwane jest w trybie pollingu (cykliczne sprawdzanie stanu wejścia). W drugiej wersji programu wejście obsługiwane jest w trybie przerwań (wykrycie zmiany stanu sygnału na wejściu).
Tryb pollingu
Kod źródłowy programu z obsługą wejścia w trybie pollingu pokazano na listingu 5.
List. 5. Obsługa wejścia. Tryb pollingu
// "MSP430 z pamięcią FRAM" // konfiguracja "MSP-EXP430FR5739": // Zadanie numer 6.1. Obsługa wejścia. Tryb pollingu. // ( ustawienia fabryczne ) // // w programie wykorzystano // ACLK nieaktywny // zainstalowany w module // MCLK = SMCLK = DCOCLK ~1MHz // przycisk S1, oraz diode LED1 // // // MSP430FR5739 // działanie programu: // ----------------- // wciśnięcie przycisku S1 // | | // włącza diodę LED1 // S1 -> | P4.0 PJ.0 | -> LED1 // zwolnienie przycisku S1 // | | Ł.K.'13 // wyłącza diodę LED1 //------------------------------------------------------------------- // // pliki nagłówkowe #include "io430.h" // rejestry procesora // void main( void ) // program główny { // WDTCTL = WDTPW + WDTHOLD; // zatrzymaj układ Watchdog // // konfiguracja linii we/wy P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00; P4OUT = 0x00; // ustaw stan niski na liniach PJOUT = 0x00; // ( wszystkie linie pracują w // trybie we/wy, PxSELx wyzerowane ) P1DIR = 0xff; P2DIR = 0xff; P3DIR = 0xff; P4DIR = 0xff; // ustaw linie w kierunku wyjścia PJDIR = 0xff; // // konfiguracja P4.0 P4OUT |= BIT0; // ( wejście "pull-up" ) P4REN |= BIT0; // włącz rezystor podciągający P4DIR &=~ BIT0; // ustaw linie w kierunku wejścia // // while(1) // pętla główna programu { // if( !(P4IN & BIT0) ) // sprawdź stanu przycisku S1 { // PJOUT |= BIT0; // * gdy przycisk jest wciśnięty } // - włącz diodę LED1 else // { // * gdy przycisk jest zwolniony PJOUT &=~ BIT0; // - wyłącz diodę LED1 } // }; // } //