LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

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

Aplikacja

Kod źródłowy programu pokazano na listingu 5.

List. 5. Funkcja main

//  "MSP430 z pamięcią FRAM"        // konfiguracja "MSP-EXP430FR5739": 
//  Zadanie numer 7.1. Obsługa analogowego wejścia. Termistor.
                                    // (ustawienia fabryczne)
//                                  // w programie wykorzystano
//               ACLK  nieaktywny   // zainstalowany w module 
//               MCLK = SMCLK = DCOCLK ~1MHz      // termistor NTC, 100 kOm
//                                  // do modułu podłączamy wyświetlacz
//              MSP430FR5739        // 
//              -----------------   // działanie programu:
//             |         |          // raz na sekundę wykonywany jest pomiar 
//             |      P1.0 | -> LCD E             // napięcia na wyjściu termistora NTC
//             |      P1.1 | -> LCD RS            // wynik pomiaru konwertowany jest na 
//             |      P2.0 | -> LCD D7            // wartość temperatury w st. Celsjusza
//             |      P2.5 | -> LCD D6            // na ekranie LCD wyświetlane są:
//         A4 -> | P1.4    P2.6 | -> LCD D5       // wynik pomiaru binarnie i w Voltach  
//     NTC on/off <- | P2.7    P2.1 | -> LCD D4   Ł.K.'13 // oraz temperatura w st. Celsjusza   
//------------------------------------------------------------------- // 
                                    // pliki nagłówkowe
#include "io430.h"                  // rejestry procesora 
#include "intrinsics.h"             // instrukcje procesora
#include "LCD_2x16.h"               // procedury LCD 
#include "tlv.h"                    // struktura TLV         
#include                   // funkcje wejścia/wyjścia 
                                    //
                                    // zmienne globalne
unsigned int wPomiaruB;             // wynik pomiaru (binarnie)  
float     wPomiaruV;                // wynik pomiaru (Volty) 
float     wPomiaruC;                // wynik pomiaru (stopnie Celsjusza)
                                    //
void main(void)                     // program główny   
{                                   //
 WDTCTL = WDTPW + WDTHOLD;          // zatrzymaj układ Watchdog 
                                    // 
 unsigned char tekst[16 + 1];       // zmienna lokalna 
                                    // bufor, tekst ekranu LCD
                                    // 
                                    // konfiguracja linii we/wy 
 P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00; P4OUT = 0x00;       // stan niski na liniach 
 PJOUT = 0x00;                      // linie w kierunku wyjścia    
 P1DIR = 0xff; P2DIR = 0xff; P3DIR = 0xff; P4DIR = 0xff;       // wszystkie linie to:  
 PJDIR = 0xff;                      // wyjścia w stanie niskim 
                                    //
                                    // konfiguracja LCD 
 LcdPiny();                         // linie we/wy 
 LcdSekwencjaStartowa4b3V();        // sekwencja startowa 
 LcdInicjalizacja();                // inicjalizacja LCD
                                    //
                                    // konfiguracja generatora REF
 while(REFCTL0 & REFGENBUSY);       // czekaj dopóki gen. jest zajęty
 REFCTL0 = REFVSEL_0 + REFTCOFF;    // ustaw napięcie VREF = 1.5V 
                                    // wyłącz czujnik temperatury 
                                    //
 P1SELC |= BIT4;                    // konfiguracja 
 P1SEL1 |= BIT4;                    // wejścia analogowego A4 
 P1SEL0 |= BIT4;                    // ustaw trzeci funkcyjny tryb pracy 
                                    //
                                    // konfiguracja przetwornika ADC
 ADC10CTL0 &=~ ADC10ENC;            // wyzeruj bit zezwolenia na konwersję
                                    // próbkowanie 32 takty ADC10CLK
 ADC10CTL0 = ADC10SHT_3;            // ustaw tryb pojedynczego pomiaru
 ADC10CTL1 = ADC10SHP + ADC10SHS_0 + ADC10SSEL_0 + ADC10CONSEQ_0;  // taktowanie pomiaru z wew. osc. 5MHz
 ADC10CTL2 = ADC10RES;              // rozdzielczość pomiaru 10 bitów
 ADC10MCTL0 = ADC10SREF_1 + ADC10INCH_4;    // potencjały referencyjne: 
                                    // V(R+) = VREF, V(R-) = AVSS
                                    // obsługa zew. kanału pomiarowego nr. 4
                                    //
 ADC10IFG &=~ ADC10IFG0;            // wyzeruj flagę przerwania 
 ADC10IE  |= ADC10IE0;              // włącz obsługę przerwań 
                                    // od zakończenia pomiaru napięcia 
                                    //
 __bis_SR_register(GIE);            // odblokuj obsługę 
                                    // przerwań maskowalnych
                                    //
 while(1)                           // pętla główna programu 
 {                                  //
   while(REFCTL0 & REFGENBUSY);     // czekaj dopóki gen. REF jest zajęty
   REFCTL0  |= REFON;               // włącz generator 
   P2OUT   |= BIT7;                 // włącz zasilanie termistora NTC
   ADC10CTL0 |= ADC10ON;            // włącz przetwornik ADC10
                                    // 
   __delay_cycles(100);             // czekaj 100us  
                                    // 
   ADC10CTL0 |= ADC10ENC;           // ustaw bit zezwolenia na konwersję
   ADC10CTL0 |= ADC10SC;            // rozpocznij pomiar napięcia
                                    // (programowe wyzwalanie pomiaru)
                                    //
   __bis_SR_register(CPUOFF);       // przejdź w tryb uśpienia LPM0
                                    // koniec pomiaru, wyjście z uśpienia
                                    // 
   P2OUT   &=~ BIT7;                // wyłącz zasilanie termistora NTC
   ADC10CTL0 &=~ ADC10ENC;          // wyzeruj bit zezwolenia na konwersję 
   ADC10CTL0 &=~ ADC10ON;           // wyłącz przetwornik ADC10
   while(REFCTL0 & REFGENBUSY);     // czekaj dopóki gen. REF jest zajęty
   REFCTL0  &=~ REFON;              // wyłącz generator nap. referencyjnego
                                    //
                                    // kalibracja binarnej wartości pomiaru
   wPomiaruB = (unsigned int)(wPomiaruB * (float)(sTlvRef.CAL_ADC_15VREF_FACTOR / 32768)); // (wzór 7.9) 
   wPomiaruB = (unsigned int)(wPomiaruB * (float)(sTlvAdc10.CAL_ADC_GAIN_FACTOR / 32768)) + sTlvAdc10.CAL_ADC_OFFSET;
                                    //
   wPomiaruV = (float)(wPomiaruB * 1.5) / 1023;     // obliczenie wartości w Voltach (wzór 7.4)
   wPomiaruC = (float)(0.4542 - wPomiaruV)/0.0088;  // obliczenie wartości w st. Celsjusza (wzór 7.16)
                                    //
                                    // prezentacja wyniku
                                    // 
   LcdWyczyscEkran();               // wyczyść ekran LCD
   LcdUstawKursorWK(0,0);           // ustaw kursor na początku 1 linii
   snprintf((char*)tekst,17,"B: %.4d A: %.2fV",wPomiaruB,wPomiaruV);// wypisz wynik pomiaru prezentowany 
   LcdPiszTekst(tekst);             // binarnej oraz w Voltach 
                                    // następnie 
   LcdUstawKursorWK(1,0);           // ustaw kursor na początku 2 linii
   snprintf((char*)tekst,17,"Temp: %.1f%cC",wPomiaruC,223);        // wypisz wynik pomiaru prezentowany 
   LcdPiszTekst(tekst);             // w stopniach Celsjusza
                                    //
   __delay_cycles(1000000);         // czekaj 1 sekundę
 };                                 // 
}                                   //  
                                    //
#pragma vector=ADC10_VECTOR         // procedura obsługi przerwania 
__interrupt void ADC10_ISR(void)    // przetwornika A/C, moduł ADC10
{                                   // 
 switch(__even_in_range(ADC10IV,12))// odczytaj rejestr ADC10IV
 {                                  // 
  case 0: break;                    // brak przerwań
  case 2: break;                    // nadpisanie sekwencji pomiarowej
  case 4: break;                    // nadpisanie wyniku pomiaru
  case 6: break;                    // komparator analogowy, próg w górę
  case 8: break;                    // komparator analogowy, próg w dół
  case 10: break;                   // komparator analogowy, próg pomiędzy
                                    // 
  case 12:                          // zakończenia pomiaru
       wPomiaruB = ADC10MEM0;       // odczytaj wynik pomiaru   
       __bic_SR_register_on_exit(CPUOFF);  // wyjdź z trybu uśpienia 
       break;                       //  
  default: break;                   // brak obsługi
 }                                  //
}                                   //

W programie głównym zatrzymywana jest pracy układu Watchdog:

WDTCTL = WDTPW + WDTHOLD;

Następnie konfigurowane są linie wejścia/wyjścia mikrokontrolera. Wszystkie linie wejścia/wyjścia ustawiane są jako wyjścia w stanie niskim. Najpierw ustawiany jest stan niski na liniach, następnie zmieniany jest kierunek linii z wejścia na wyjście:

P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00; P4OUT = 0x00; PJOUT = 0x00;
P1DIR = 0xff; P2DIR = 0xff; P3DIR = 0xff; P4DIR = 0xff; PJDIR = 0xff;