LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

(8) Mikrokontrolery MSP430: obsługa ADC – przykładowa aplikacja: cyfrowy termometr

W kolejnych instrukcjach konfigurowane są parametry pracy wyświetlacza LCD. Konfigurowane są linie sterujące pracą wyświetlacza. Realizowane jest sekwencja startowa (interfejs 4 bitowy, znaki 5×8, obsługa dwóch linii po 16 znaków każda). Inicjowane jest praca wyświetlacza. Procedury do obsługi alfanumerycznego wyświetlacza LCD ze sterownikiem Hitachi HD44780 umieszczono w pliku „LCD_2x16.c”:

LcdPiny();
LcdSekwencjaStartowa4b3V();
LcdInicjalizacja();

W prezentowanym przykładzie podczas pomiarów analogowych będziemy używać wewnętrznego napięcia referencyjnego wytwarzanego przez moduł REF. Dlatego też w następnych instrukcjach programu konfigurujemy parametry pracy modułu REF. Przed rozpoczęciem pracy z rejestrem konfiguracyjnym REFCTL0 sprawdzany jest stan modułu. Jeśli moduł jest zajęty, to należy czekać do czasu aż nie będzie używany.

while(REFCTL0 & REFGENBUSY);

Kiedy moduł REF nie wykonuje żadnych zadań, można rozpocząć konfigurację modułu. Podczas konfiguracji wartość napięcia referencyjnego VREF ustawiana jest na 1,5 V (bit REFVSEL_0). Wyłączany jest wewnętrzny czujnik temperatury (bit REFVSEL_0), a moduł generatora napięcia jest wyłączony (instrukcja przypisania wartości do rejestru REFCTL0 zeruje bit REFON).

REFCTL0 = REFVSEL_0 + REFTCOFF;

Następnie konfigurowane są parametry pracy modułu przetwornika ADC10_B. Najpierw konfigurowane jest wejście pomiarowe (linia P1.4 mikrokontrolera, wejście analogowe A4). Żeby linia P1.4 zaczęła pracować jako wejście analogowe należy linie ustawić w trzeci funkcyjny tryb pracy. Konfigurację linii realizują poniższe instrukcje.

P1SELC |= BIT4;
P1SEL1 |= BIT4;
P1SEL0 |= BIT4;

Następnie konfigurowane są rejestry sterujące pracą przetwornika ADC10. Ustawiany jest tryb pracy przetwornika, rozdzielczość pomiarów, potencjały referencyjne, źródło i częstotliwość sygnału taktującego pomiary. Konfigurowany jest sposób wyzwalania pomiarów, czas oraz tryb próbkowania sygnału. Włączana jest obsługę przerwań. Przed rozpoczęciem konfiguracji zerowany jest bit zezwolenia na konwersję.

ADC10CTL0 &=~ ADC10ENC;

Następnie ustawiany jest czas próbkowania sygnału analogowego na 32 takty zegara ADC10CLK (bit ADC10SHT_3), oraz włączana jest obsługa przetwornika (wyzerowany bit ADC10ON).

ADC10CTL0 = ADC10SHT_3;

W ramce poniżejpokazano w jakiś sposób obliczyć czas próbkowania sygnału.

Czas próbkowania sygnału analogowego – obliczenia

Sygnał ADC10CLK taktowany jest z wewnętrznego oscylatora MODOSC.

Częstotliwość sygnału ADC10CLK wynosi około 5 MHz.

Czas próbkowania sygnału t Sample obliczamy ze wzoru 7.2

t Sample =  7,62 · (RE + RI) * CI

Rezystancja wewnętrzna RI = 1 k?. Pojemność wewnętrzna CI = 6 pF.

Pojemność zewnętrzną RE musimy obliczyć. Przy rozmieszczeniu elementów jak na rysunku 7, rezystancja RE = (100*470 / 100+470) = 82.46 k?

Podstawiając obliczone wartości do wzoru 7.2 otrzymujemy.

t Sample =  7,62 · (82,46 k? + 1 k?) · 6 pF = 7,62 · 500 ns =  3,8 us

Liczbę taktów sygnału ADC10CLK o czasie trwania t Sample obliczamy ze wzoru 7.3

x Sample = t Sample · fADC10CLK = 3,8 us · 5 MHz = 19

Bit ADC10SHTx pozwala na ustawienie wybranych wartości w zakresie 4…1024 takty sygnału ADC10CLK. Wybieramy pierwszą wyższą wartość od obliczonej. Wartość bitu którą należy ustawić to: ADC10SHT_3 = 32 · ADC10CLK

W kolejnych instrukcjach ustawiany jest tryb pracy przetwornika (bit ADC10CONSEQ_0 pojedynczy pomiar jednego kanału). Włączane jest programowe wyzwalanie pomiarów (bit ADC10SHS_0). Ustawiany jest tryb próbkowania sygnału (bit ADC10SHP). W prezentowanym przykładzie włączane jest próbkowanie sygnału w trybie wyzwalania w którym sygnał próbkowany jest przez czas zdefiniowany za pomocą bitu ADC10SHT z rejestru ADC10CTL0. Następnie definiowane jest źródło sygnału ADC10CLK taktującego konwersję (bit ADC10SSEL_0). W prezentowanym przykładzie sygnał ADC10CLK taktowany jest z wewnętrznego oscylatora MODOSC wytwarzającego sygnał zegarowy o częstotliwości 5 MHz:

ADC10CTL1 = ADC10SHP + ADC10SHS_0 + ADC10SSEL_0 + ADC10CONSEQ_0;

W kolejnym rejestrze konfiguracyjnym ustawiana jest rozdzielczość pomiarów na10 bitów (bit ADC10RES), włączana jest prezentację wyniku pomiaru w formie binarnej (wyzerowany bit ADC10DF) oraz ustawiany jest tryb szybkiej konwersji (wyzerowany bit ADC10SR):

ADC10CTL2 = ADC10RES;

Następnie konfigurowane są potencjały referencyjne V(R+), V(R-) (bit ADC10SREF_1). Źródłem potencjału V(R+) jest napięcie referencyjne VREF o wartości 1,5 V (napięcie generowane przez wewnętrzny moduł REF). Źródłem potencjału V(R–) jest masa analogowa AVSS mikrokontrolera o wartości 0 Volta. Multiplekser analogowy ustawiany jest na obsługę czwartego kanału pomiarowego (bit ADC10INCH_4, kanał A4):

ADC10MCTL0 = ADC10SREF_1 + ADC10INCH_4;

Na zakończenie konfigurowana jest obsługa przerwań. Zerowana jest flaga przerwania ADC10IFG0, oraz włączana jest obsługa przerwań od zakończenia pomiaru (flaga ustawiana w momencie zakończenia pomiaru i wypisania wyniku pomiaru do rejestru ADC10MEM0):

ADC10IFG &=~ ADC10IFG0;
ADC10IE  |= ADC10IE0;

Dodatkowo odblokowywana jest obsługa przerwań maskowalnych:

__bis_SR_register(GIE);

Podsumowując: moduł przetwornika ADC10_B pracuje w trybie pojedynczego pomiaru jednego kanału. Pomiary realizowane są na zewnętrznym czwartym kanale pomiarowy. Rozdzielczość pomiarów to 10 bitów. Potencjałem referencyjnym V(R+) jest wewnętrzne napięcie VREF o wartości 1,5 V. Czas próbkowania sygnału został ustawiony na 32 takty zegara ADC10CLK. Pomiary wyzwalane są w sposób programowy przy pomocy bitu ADC10SC. Sygnał taktujący konwersję ADC10CLK taktowany jest w zewnętrznego oscylatora MODOSC. Częstotliwość sygnału wynosi 5 MHz (brak podziału częstotliwości sygnału, preskalery częstotliwości sygnału są ustawione na wartość 1, wyzerowane bity ADC10DIVx, ADC10PDIVx). Włączona jest obsługa przerwań od zakończenia pomiaru.

W pętli głównej programu włączany jest generator napięcia referencyjnego (bit REFON):

while(REFCTL0 & REFGENBUSY);
REFCTL0  |= REFON;

Włączane jest zasilanie termistora NTC (stan wysoki na wyjściu P2.7):

P2OUT   |= BIT7; 

Włączany jest przetwornik ADC10 (bit ADC10ON):

ADC10CTL0 |= ADC10ON; 

Ponieważ od włączenia generatora REF do pojawienia się napięcia VREF musi minąć co najmniej 30 ms, to wprowadzane jest programowe opóźnienie. Czas opóźnienia to 100 ms:

__delay_cycles(100);

Następnie ustawiany jest bit zezwolenia na konwersję (bit ADC10ENC) i uruchamiany jest pomiar napięcia (bit ADC10SC, programowe wyzwalanie pomiaru):

ADC10CTL0 |= ADC10ENC;
ADC10CTL0 |= ADC10SC;

Mikrokontroler wprowadzany jest w tryb uśpienia LPM0 (w trybie tym wyłączona jest CPU mikrokontrolera):

__bis_SR_register(CPUOFF);

Ustawienie bitu ADC10SC w rejestrze ADC10CTL0 rozpoczyna pomiar napięcia na wejściu analogowym A4. Uruchamiany jest proces próbkowania sygnału analogowego, który trwa 32 takty zegara ADC10CLK. Następnie rozpoczyna się konwersja wyniku z postaci analogowej na cyfrową. Wynik pomiaru w formie binarnej o rozdzielczości10 bitów zapisywany jest w rejestrze wyniku ADC10MEM0. Wpisanie wyniku do rejestru ADC10MEM0 powoduje ustawienie w rejestrze ADCD10IFG flagi przerwania ADCD10IFG0. Mikrokontroler jest budzony z uśpienia i rozpoczyna się wykonanie procedury obsługi przerwania:

#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
 switch(__even_in_range(ADC10IV,12))
 {
   case 0: break;
   case 2: break;
   case 4: break;
   case 6: break;
   case 8: break;
   case 10: break;
   case 12: 
   wPomiaruB = ADC10MEM0;
   __bic_SR_register_on_exit(CPUOFF);
   break;
   default: break;
 }
}

W procedurze obsługi przerwania odczytujemy wartość rejestru ADC10IV (instrukcja switch). W naszym przykładzie obsługiwane są wyłącznie przerwania od zakończenia pomiaru (blok case 12). Z rejestru ADC10MEM0 odczytujemy wynik pomiaru i zapisujemy w zmiennej globalnej wPomiaruB. Odczyt rejestru ADC10MEM0 powoduje wyzerowanie flagi przerwania ADC10IFG0. Na zakończenie procedury obsługi przerwania wykonywana jest instrukcja procesora która modyfikuje sposób powrotu z procedury obsługi przerwania:

__bic_SR_register_on_exit(CPUOFF);

Po powrocie z procedury obsługi przerwania wykonanie programu powraca w miejsce w którym zostało przerwane przez przerwanie. W naszym przypadku jest to tryb uśpienia LPM0. Wywołanie instrukcji __bic_SR_register_on_exit z parametrem CPUOFF powoduje, że po powrocie z procedury obsługi przerwania mikrokontroler nie wróci do trybu uśpienia LPM0. Mikrokontroler zostanie obudzony z uśpienia, a wykonanie pętli głównej programu będzie kontynuowane.

Po powrocie do wykonania pętli głównej programu wyłączane jest zasilanie termistora NTC (stan niski na wyjściu P2.7):

P2OUT   &=~ BIT7;

Wyłączany jest przetwornik ADC10 (zerowanie bitu ADC10ON):

ADC10CTL0 &=~ ADC10ENC;
ADC10CTL0 &=~ ADC10ON;

Wyłączany jest moduł napięć referencyjnych (zerowanie bitu REFON):

while(REFCTL0 & REFGENBUSY);
REFCTL0  &=~ REFON;

Następnie rozpoczyna się obróbka wyniku pomiaru. Wynik pomiaru w formie binarnej jest kalibrowany. Do kalibracji używane są współczynniki zapisane w strukturze TLV mikrokontrolera. Kalibrowana jest wartość napięcia referencyjnego REF oraz przetwornik ADC10 (wzór 7.9):

wPomiaruB = (unsigned int)(wPomiaruB * (float)
            (sTlvRef.CAL_ADC_15VREF_FACTOR / 32768));
wPomiaruB = (unsigned int)(wPomiaruB * (float)
            (sTlvAdc10.CAL_ADC_GAIN_FACTOR / 32768)) + sTlvAdc10.CAL_ADC_OFFSET;

Binarny skalibrowany wynik pomiaru konwertowany jest na wartość w Voltach (wzór 7.4):

wPomiaruV = (float)(wPomiaruB * 1.5) / 1023;

Na podstawie zmierzonego napięcia, obliczana jest wartość temperatury (wzór 7.16)

wPomiaruC = (float)(0.4542 - wPomiaruV)/0.0088;

W zmiennych globalnych wPomiaruB, wPomiaruV, wPomiaruC, są zapisane: skalibrowany wynik pomiaru w formie binarnej, wartość napięcia na wyjściu termistora NTC w Voltach, oraz temperatura w stopniach Celsjusza.

W kolejnych liniach programu wartości te prezentowane są na ekranie wyświetlacza LCD. W pierwszej linii ekranu wyświetlane są wynik pomiaru binarnie oraz w Voltach:

LcdWyczyscEkran();
LcdUstawKursorWK(0,0);
snprintf((char*)tekst,17,"B: %.4d A: %.2fV",wPomiaruB,wPomiaruV);
LcdPiszTekst(tekst);

W drugiej linii ekranu wyświetlana jest temperatura

LcdUstawKursorWK(1,0);
snprintf((char*)tekst,17,"Temp: %.1f%cC",wPomiaruC,223);
LcdPiszTekst(tekst);

Do konwersji zmiennych na napisy użyta została funkcja języka „C” snprintf(). Po wypisaniu wyników pomiarów na ekranie wyświetlacza LCD. Wprowadzane jest programowe opóźnienie o czasie trwania jednej sekundy:

__delay_cycles(1000000);

Następnie pętla główna programu wykonuje się ponownie. Cykl pomiaru napięcia na wyjściu termistora NTC powtarza się.