Fórum témák

» Több friss téma
Cikkek » Launchpad: ismerkedés az MSP430 mikrovezérlőkkel IV.
Launchpad: ismerkedés az MSP430 mikrovezérlőkkel IV.
Szerző: icserny, idő: Jan 14, 2013, Olvasva: 16046, Oldal olvasási idő: kb. 12 perc
Lapozás: OK   4 / 8

Egyszerű ADC konverzió

A következőkben néhány mintaprogramot mutatunk be az egyszerű ADC konverzió használatára. Az egyszerű ADC konverzió esetünkben azt jelenti, hogy egy csatornát kiválasztunk és csak egyetlen konverziót végünk. Természetesen a programunkat szervezhetjük úgy, hogy egymás után több csatornára vonatkozóan is végzünk egy egyszerű konverziót. 

Az alábbi programban  a Launchpad kártya kb.3,5 V-os VCC  tápfeszültségét használjuk pozitív referenciaként, a negatív referencia pedig a közös pont (VSS) lesz. A programban három csatorna jelét mérjük meg egymás után, ciklikusan.   Az A5 (Chan 5, P1.5 láb) analóg bemenetre kapcsoljuk valamilyen 0 - 3,5 V közötti jelet,  amit meg akarunk mérni. Emellett megmérjük a fél tápfeszültséget (Chan 11), és a belső hőmérő jelét is (Chan 10).

A mérés eredményeit a 4_uart_soft mintaprogramban bemutatott módszerrel, egyirányú szoftveres UART kezeléssel (csak adatküldés) kiíratjuk. Paraméterek: 9600 baud, 8 adatbit, nincs paritásbit, 2 stopbit.

Megjegyzés: a 2 stop bit küldésének itt nincs különösebb jelentősége, a PC oldalon ne is 2 bites, hanem csak 1 stop bites üzemmódot állítsunk be! A 2 stop bit küldése valójában az 1 stop bit vételének biztonságát szolgálja.

A CPU a gyárilag kalibrált 1 MHz-es DCO órajelet használja, az ADC pedig a saját ADC10OSC oszcillátort.

Hardver követelmények:

  • Launchpad kártya ADC-vel rendelkező MSP430G2xxx mikrovezérlővel (például G2231, G2452, G2553)
  • Az újabb kiadású (v1.5) kártyán az RXD,TXD átkötéseket SW állásba kell helyezni (a többi átkötéssel párhuzamosan álljanak)
  • Kössünk a P1.5 bemenetre 0 - 3,5 V közötti jelet (például egy, a VCC és VSS közé kötött potméter csúszkáját)

4_1. lista: A 4_adc_simple_vcc program listája

  1. #include "io430.h"
  2. #include "stdint.h"
  3.  
  4. #define TXD       BIT1                 // TXD a P1.1 lábon
  5.  
  6. /*-------------------------------------------------------------
  7.  * Egyszeri mérés egy ADC csatornában, VCC a referencia
  8.  *-------------------------------------------------------------
  9.  * chan - csatornaválasztó bitek (a csatorna sorszáma << 12)
  10.  */
  11. uint16_t ADC_single_meas(uint16_t chan) {
  12.   ADC10CTL0 &= ~ENC;                   //Az ADC letiltása újrakonfiguráláshoz
  13.   ADC10CTL0 = ADC10SHT_3               //mintavétel: 64 óraütés
  14.              | ADC10ON                 //Az ADC bekapcsolása
  15.              | SREF_0;                 //VR+ = AVCC és VR- = AVSS
  16.   ADC10CTL1 = ADC10SSEL_0 + chan;      //csatorna = 'chan', ADC10OSC az órajel
  17.   ADC10CTL0 |= ENC + ADC10SC;          //Konverzió engedélyezése és indítása
  18.   while (ADC10CTL1 & BUSY);            //Várakozás a konverzió végére
  19.   return ADC10MEM;                     //Visszatérési érték a konverzió eredménye
  20. }
  21.  
  22. /**------------------------------------------------------------
  23.  *   Késleltető eljárás (1 - 65535 ms)
  24.  *-------------------------------------------------------------
  25.  * delay - a késleltetés ms egységben megadva
  26.  */
  27. void delay_ms(uint16_t delay) {
  28.   uint16_t i;
  29.   for(i=0; i < delay; i++) {
  30.     __delay_cycles(1000);              //1 ms késleltetés
  31.   }
  32. }
  33.  
  34. /**------------------------------------------------------------
  35.  *   Egy karakter kiküldése a soros portra
  36.  *   SW_UART: 9600 bit/s, 8, N, 2 formátum
  37.  *   DCO = 1 MHz (Bitidő = 104.167 usec)
  38.  *-------------------------------------------------------------
  39.  * c - a kiküldeni kívánt karakter kódja
  40.  */
  41. void sw_uart_putc(char c) {
  42.   uint8_t i;
  43.   uint16_t TXData;
  44.   TXData = (uint16_t)c | 0x300;        //Add 2 stop bits (mark)
  45.   TXData = TXData << 1;                //Add 1 start bits (space)
  46.   for(i=0; i < 11; i++) {
  47.     if(TXData & 0x0001) {              //Soron következő bit vizsgálata
  48.       P1OUT |= TXD;                    //Ha '1'
  49.     } else {
  50.       P1OUT &= ~TXD;                   //Ha '0'
  51.     }
  52.     TXData = TXData >> 1;              //Adatregiszter léptetés jobbra
  53.     __delay_cycles(89);                //
  54.   }
  55.   P1OUT |= TXD;                        //Az alaphelyzet: mark
  56. }
  57.  
  58. /**------------------------------------------------------------
  59.  *  Karakterfüzér kiírása a soros portra
  60.  *-------------------------------------------------------------
  61.  * p_str - karakterfüzér mutató (nullával lezárt stringre mutat)
  62.  */
  63. void sw_uart_puts(char* p_str) {
  64.   char c;
  65.   while ((c=*p_str)) {
  66.       sw_uart_putc(c);
  67.       p_str++;
  68.   }
  69. }
  70.  
  71. /**------------------------------------------------------------
  72.  * Előjel nélküli egész szám kiírása hexadecimális formában
  73.  *-------------------------------------------------------------
  74.  * t - a kiírandó szám (uint16_t típusú)
  75.  */
  76. void sw_uart_out4hex(uint16_t t)
  77. {
  78.   char c;
  79.   c=(char)((t>>12) & 0x0F);
  80.   if (c>9) c+=7;
  81.   sw_uart_putc(c+'0');
  82.   c=(char)((t>>8) & 0x0F);
  83.   if (c>9) c+=7;
  84.   sw_uart_putc(c+'0');
  85.   c=(char)((t>>4) & 0x0F);
  86.   if (c>9) c+=7;
  87.   sw_uart_putc(c+'0');
  88.   c=(char)(t & 0x0F);
  89.   if (c>9) c+=7;
  90.   sw_uart_putc(c+'0');
  91. }
  92.  
  93. /**------------------------------------------------------------
  94.  * Decimális kiíratás adott számú tizedesjegyre.
  95.  *-------------------------------------------------------------
  96.  * data - a kiírandó szám (előjelesen)
  97.  * ndigits - a kiírandó tizedesek száma
  98.  */
  99. void sw_uart_outdec(int32_t data, uint8_t ndigits) {
  100.   static char sign, s[12];
  101.   uint8_t i;
  102.   i=0; sign=' ';
  103.   if(data
  104.     do {
  105.       s[i]=data%10 + '0';
  106.       data=data/10;
  107.       i++;
  108.       if(i==ndigits) {s[i]='.'; i++;}
  109.     } while(data > 0 || i < ndigits+2);
  110.     sw_uart_putc(sign);
  111.     do {
  112.       sw_uart_putc(s[--i]);
  113.     } while(i);
  114. }
  115.  
  116. void main(void) {
  117. uint16_t data;
  118. int32_t temp;
  119.   WDTCTL = WDTPW + WDTHOLD;            //Letiltjuk a watchdog időzítőt
  120.   DCOCTL = CALDCO_1MHZ;                // DCO beállítása a gyárilag kalibrált
  121.   BCSCTL1 = CALBC1_1MHZ;               // 1 MHz-es frekvenciára
  122.   P1DIR |= TXD;                        //TXD legyen digitális kimenet
  123.   P1OUT |= TXD;                        //TXD alaphelyzete: mark
  124. //--- P1.3 belső felhúzás engedélyezése -----------------------
  125.   P1DIR &= ~BIT3;                      //P1.3 legyen digitális bemenet
  126.   P1OUT |= BIT3;                       //Felfelé húzzuk, nem lefelé
  127.   P1REN |= BIT3;                       //Belső felhúzás engedélyezése  
  128. //--- Analóg csatornák engedélyezése --------------------------
  129.   ADC10AE0 |= BIT5;                    //P1.5 legyen analóg bemenet
  130.  
  131.   while(1) {
  132.     delay_ms(2000);                    //2 s várakozás
  133. //--- Az A5 bemenőjelének mérése és kiíratása ------------------
  134.     data = ADC_single_meas(INCH_5);  
  135.     sw_uart_puts("\r\nchan 5 = ");
  136.     sw_uart_out4hex(data);
  137.     temp = (int32_t)data*3500L/1023;   //A mV-okban mért feszültség
  138.     sw_uart_outdec(temp,3);            //kiírás 3 tizedesre
  139.     sw_uart_puts("V chan 11 = ");
  140. //--- Az A11 csatorna (VDD/2) mérése és kiíratása --------------    
  141.     data = ADC_single_meas(INCH_11);
  142.     sw_uart_out4hex(data);
  143.     temp = (int32_t)data*3500L/1023;   //VDD/2 mV-okban mérve
  144.     sw_uart_outdec(temp,3);            //kiírás 3 tizedesre
  145.     sw_uart_puts("V chan 10 = ");
  146. //--- Az A10 csatorna (hőmérő) mérése és kiíratása -------------  
  147.     data = ADC_single_meas(INCH_10);
  148.     sw_uart_out4hex(data);  
  149.     temp = ((uint32_t)data*2467L - 711030L) >> 8; //tizedfok egységben
  150.     sw_uart_puts(" temp = ");
  151.     sw_uart_outdec(temp,1);            //kiíratás egy tizedesjegyre
  152.     sw_uart_puts(" C");    
  153.   }
  154. }

A program ismertetését a függvények bemutatásával kezdjük, annál is inkább, mert az ADC inicializálása és az egycsatornás mérés lebonyolítása egyetlen függvényben található, a főprogram csak a mérés és a kiíratás szervezését és az átszámításokat végzi.

ADC_single_meas()

Ez a függvény beállítja az ADC üzemmódját,  kiválasztja a bemenő paraméter által megadott anaalóg csatorná, elindít egy konverziót és megvárja annak végét, majd visszatér a konverzió eredményével.

Az ADC inicializálása előtt előbb törölnünk kell az ENC bitet. Az ADC10CTL0 regiszterben ezután csak a mintavételezési időt (itt most nem sietünk, ezért a maximumra állthatjuk), és a feszültségreferencia módot (esetünkben VCC és VSS a pozitív és a negatív referencia) állítjuk be, illetve az ADC10ON bit '1'-be állításával bekapcsoljuk az ADC-t.

Az ADC10CTL1 regiszterben az ADC10SSELx bitmezőt nullára állítjuk (az ADC saját oszcillátora, ADC10OSC adja az órajelet), s az INCHx bitmezőben beállítjuk a kiválasztani kívánt csatorna sorszámát.

Megjegyzés: Vigyázzunk arra, hogy az INCHx bitmező a 212 helyiértéken kezdődik, ezért a függvény paraméterének megadásához vagy a mikrovezérlő leíró állományában található makrókat használjuk (például INCH_5, INCH_10, INCH_11), vagy pedig a csatorna sorszámot 12 bináris helyiértékkel léptessük balra (például AN5 kiválasztásához: 5<<12).

A beállítások után újraengedélyezzük az ADC konverziót az ENC bit '1'-be állításával, és elindítjuk a konverziót az ADC10SC bit '1'-be állításával. A konverzió végét a foglaltságot jelző BUSY bit vagy a megszakításkérő bit figyelésével oldhatjuk meg. A konverzió eredményét az ADC10MEM regiszterből olvashatjuk ki.

sw_uart_putc() - egy karakter kiküldése. Lényegében ugyanaz, amit az első oldalon bemutatott  soros kommunikációnál használtunk, csak most 2 stop bitet küldünk.

sw_uart_puts() - egy nullával lezárt karaktersorozat kiküldése.

sw_uart_out4hex() - egy előjel nélküli 16 bites szám kiíratása négy hexadecimális számjeggyel. Ezt a konverzió nyers eredményének kiíratására használjuk, ellenőrzés céljából.

sw_uart_outdec() - egy előjeles 32 bites szám kiíratása, adott számú tizedesjegy levágásával.  Feltételezzük, hogy a kiírandó szám a levágott tizedesjegyek számának megfelelően 10-zel, 100-zal, ezerrel, stb-vel fel van szorozva. Például ha a hőmérsékletet egy tizedesjeggyel akarjuk kiíratni, akkor a kiírandó számot tizedfokokban kell megadni. Ha a feszültséget V-ban három tizedesjeggyel akarjuk kiíratni, akkor a kiírandó számot millivoltokban kell megadni.

A főprogram

A főprogram inicializáló részében letiltjuk az őrkutyát, beállítjuk a gyárilag kalibrált 1 MHz-es DCO frekcenciát, kimenetre állítjuk a P1.1 portlábat (soros kommunikáció TX kimenet). A P1.3 bemeneten beállítjuk a belső felhúzást, végül a P1.5 bemeneten (AN5 analóg csatorna) engedélyezzük az analóg funkciót.

A főprogram végtelen ciklusában 2 másodperces késleltetés után végzünk egy mérést az AN5 csatornában (a kívülről bevezet analóg jel mérése), az AN11 csatornában (ebben a belső analóg csatornában a tápfeszültség fele mérhető), és az AN10 csatornában (ebben a belső hőmérő jele mérhető).

Feszültség és hőmérséklet meghatározása

A fenti példában VR+ = 3,5 V, illetve ezredvoltokban kifejezve 3500 mV, VR- = 0 V, a 10 bites ADC "végkitérése" pedig 1023. A konverzió NADC eredményéből tehát a millivoltokban kifejezett feszültség az alábbi képlettel számítható ki:

VIN = NADC * 3500 mV/1023

Megjegyzés: A mért feszültséget azért millivoltokban fejezzük ki, mert így tudjuk az egész ábrázolás ellenére három tizedesjeggyel kiíratni a voltban mért feszültséget.

A hőmérséklet meghatározása egy kicsit bonyolultabb. Itt a VIN = NADC * 3500 mV/1023 és a VIN = T * 3,55 mV/°C + 986 mV képletekből kell kiindulni (az utóbbi formula a mikrovezérlő adatlapjában található ), ahol T a Celsius skálán mért hőmérséklet. Ezekből kifejezve a hőmérsékletet, a következő kifejezést kapjuk:

T = NADC * 3500/(1023 * 3,55) - 986/3,55

Ha hőmértsékletet tizedfokokban akarjuk meghatározni, akkor 3500 helyett 35000-et, 986 helyett pedig 9860-at  kell írnunk. Ha a törteket például 256-tal bővítjük, akkor egészaritmetikával is kényelmesen kezelhető képletet kapunk:

T = (NADC * 2467 - 711030)/256

A 256-tal történő osztást természetesen jobbraléptetéssel is meg tudjuk oldani.

Futási eredmény

A program futási eredménye az alábbi ábrán látható. A putty.exe programot használtuk terminálként, s esetünkben a Launchpad kártya a COM3 virtuális soros porton volt elérhető. Sárga nyílakkal megjelöltük azokat a helyeket, amikor a bemenő adatokat megváltoztattuk. AN5 (chan 5) esetében az eredetileg végkitérésbe állított potmétert eltekertük, a beépített hőmérő (chan 10) esetében pedig a mikrovezérlő tokját melegítettük.

4_adc_simple_vcc.png

4_1. ábra: A 4_adc_simple_vcc program futásának eredménye

A 2,5 V-os belső referencia használata

A következő példaprogramban  a mikrovezérlő 2,5 V-os beépített referencia forrását használjuk pozitív referenciaként, a negatív referencia pedig most is a közös pont (VSS) lesz. A program minden másban megegyezik az előző mintapéldával, tehát ugyanúgy három csatorna jelét mérjük meg egymás után, ciklikusan.  Arra azonban ügyelnünk kell, hogy az alacsonyabb referencia feszültség miatt a bemeneti tartomány lecsökken. Így az A5 (Chan 5, P1.5 láb) analóg bemenetre most csak 0 - 2,5 V közötti jelet adhatunk,  ebben a tartományban tudunk csak mérni. Most is megmérjük  a fél tápfeszültséget (Chan 11), és a belső hőmérő jelét is (Chan 10). Mindkét belső jel belefér a 0 - 2,5 V közötti tartományba.

Mivel az 4_adc_simple_ref2 program csak néhány részletben különbözik az előző programtól, itt most csak azokat a függvényeket mutatjuk be, amelyeket megváltoztattunk.

4_2. lista: Részletek a 4_adc_simple_ref programból

 (Az itt nem listázott programrészek megegyeznek a 4_adc_simple_vcc mintapéldával)

  1. #include "io430.h"
  2. #include "stdint.h"
  3.  
  4. uint16_t ADC_single_meas_REF2_5V(uint16_t chan) {
  5.   ADC10CTL0 &= ~ENC;                   //Az ADC letiltása újrakonfiguráláshoz
  6.   ADC10CTL0 = ADC10SHT_3               //mintavétel: 64 óraütés
  7.              | ADC10ON                 //Az ADC bekapcsolása
  8.              | SREF_1                  //VR+ = VREF+ és VR- = AVSS
  9.              | REFON                   //Belső referencia bekapcsolása
  10.              | REF2_5V;                //2,5 V-os referencia kiválasztása
  11.   ADC10CTL1 = ADC10SSEL_0 + chan;      //csatorna = 'chan', ADC10OSC az órajel
  12.   ADC10CTL0 |= ENC + ADC10SC;          //Konverzió engedélyezése és indítása
  13.   while (ADC10CTL1 & BUSY);            //Várakozás a konverzió végére
  14.   return ADC10MEM;                     //Visszatérési érték a konverzió eredménye
  15. }
  16. ...
  17. void main(void) {
  18. uint16_t data;
  19. int32_t temp;
  20. ...
  21. //--- Analóg csatornák engedélyezése --------------------------
  22.   ADC10AE0 |= BIT5;                    //P1.5 legyen analóg bemenet
  23.   while(1) {
  24.     delay_ms(1000);
  25. //--- Az A5 csatorna (P1.5) bemenő feszültségének mérése ------  
  26.     data = ADC_single_meas_REF2_5V(INCH_5);
  27.     sw_uart_puts("\r\nchan 5 = ");
  28.     sw_uart_out4hex(data);
  29.     temp = (int32_t)data*2500L/1023;   //A mV-okban mért feszültség
  30.     sw_uart_outdec(temp,3);            //kiírás 3 tizedesre
  31.     sw_uart_puts("V chan 11 = ");  
  32. //--- Chan 11 = VDD/2 mérése ----------------------------------  
  33.     data = ADC_single_meas_REF2_5V(INCH_11);
  34.     sw_uart_out4hex(data);
  35.     temp = (int32_t)data*5000L/1023;   //VDD mV-okban mérve
  36.     sw_uart_outdec(temp,3);            //kiírás 3 tizedesre
  37.     sw_uart_puts("V chan 10 = ");
  38. //--- Chan 10 a belső hőmérő ----------------------------------  
  39.     data = ADC_single_meas_REF2_5V(INCH_10);
  40.     sw_uart_out4hex(data);  
  41.     temp = ((uint32_t)data*1762L - 711030L) >> 8;  
  42.     sw_uart_puts(" temp = ");
  43.     sw_uart_outdec(temp,1);            //Kiírás 1 tizedesre
  44.     sw_uart_puts(" C");  
  45.     delay_ms(1000);  
  46.   }
  47. }

Az ADC beállítása és a konverzió indítása, valamint az eredmény kiolvasás most is egyetlen függvényben lett begvalósítva, az ADC_single_meas_REF2_5V() függvényben. Az ADC beállításánál annyi a különbség, hogy az ADC10CTL0 regiszter beállításánál most az SREFx bitmezőbe 1-et írunk (a pozitív referencia most VCC helyett Vref+ lesz), valamint bekapcsoljuk a belső referenciát és a 2,5 V-os referencia értéket választjuk ki (tehát Vref+ = 2,5 V lesz).

A főprogramban az a fő különbség, hogy a mért feszültségek meghatározásánál 3500 mV helyett most 2500 mV-ot írtunk. A fél tápfeszültség mérésénél nem tévedésből írtunk 5000 mV-ot, hanem azért, hogy a fél tápfeszültség helyett annak kétszeresét, vagyis a magát a tápfeszültséget írassuk ki (hogy ne kelljen fejben szorozgatnunk).

A hőmérséklet meghatározásánál nem kell a képletet újra levezetni, elegendő a szorzót átskálázni a referencia feszültségek arányában: szorzó = 2467 *2500/3500 = 1762. Az additív tag értéke természetesen nem változik.

A program futási eredménye az alábbi ábrán látható. Sárga nyílakkal megjelöltük azokat a helyeket, amikor a bemenő adatokat megváltoztattuk. AN5 (chan 5) esetében az eredetileg 1 V körüli értékre állított potmétert eltekertük, a beépített hőmérő (chan 10) esetében pedig a mikrovezérlő tokját melegítettük.

4_adc_simple_ref2.png

4_2. ábra: A 4_adc_simple_ref2 program futásának eredménye

Ebben a programban a chan 11 csatorna mérése is hasznos információt adott, hiszen segítségével meghatározhattuk a tápfeszültség pillanatnyi értékét. Különösen fontos ez az információ akkor, amikor 6 MHz-nél magasabb frekvencián járatjuk a mikrovezérlőt, hiszen ebben az esetben a tápfeszültség függvénye, hogy mekkor frekvencia engedhető meg. Ha nem figyelünk rá, hogy mekkora a tápfeszültség, akkor a mikrovezérlő működése megbízhatatlanná válhat.

Az 1,5 V-os belső referencia használata

Harmadik példánkban (4_adc_simple_ref1) a mikrovezérlő 1,5 V-os beépített referencia forrását használjuk pozitív referenciaként, a negatív referencia pedig most is a közös pont (VSS) lesz. Ügyeljünk arra, hogy az alacsonyabb referencia feszültség miatt a bemeneti tartomány lecsökken. Így az AN5 (Chan 5, P1.5 láb) analóg bemenetre most csak 0 - 1,5 V közötti jelet adhatunk,  ebben a tartományban tudunk csak mérni. Emiatt most nem tudjuk megmérni a fél tápfeszültséget (Chan 11), mert az meghaladja a mérési tartomány felső határát. Ezért a most az AN5 csatorna mellett csak a belső hőmérő jelét (Chan 10) mérjük, ami belefér a 0 - 1,5 V közötti tartományba.

Mivel az 4_adc_simple_ref1 program csak néhány részletben különbözik az előző programoktól, itt is csak azokat a függvényeket mutatjuk be, amelyeket megváltoztattunk.

4_3. lista: Részletek a 4_adc_simple_ref1 programból

 (Az itt nem listázott programrészek megegyeznek a 4_adc_simple_vcc mintapéldával)

  1. #include "io430.h"
  2. #include "stdint.h"
  3. /*-------------------------------------------------------------
  4.  * Egyszeri mérés egy ADC csatornában, 1,5 V a belső referencia
  5.  *-------------------------------------------------------------
  6.  * chan - csatornaválasztó bitek (a csatorna sorszáma << 12)
  7.  */
  8. uint16_t ADC_single_meas_REF1_5V(uint16_t chan) {
  9.   ADC10CTL0 &= ~ENC;                   //Az ADC letiltása újrakonfiguráláshoz
  10.   ADC10CTL0 = ADC10SHT_3               //mintavétel: 64 óraütés
  11.              | ADC10ON                 //Az ADC bekapcsolása
  12.              | SREF_1                  //VR+ = VREF+ és VR- = AVSS
  13.              | REFON;                  //Belső referencia bekapcsolása
  14.                                        //1,5 V-os referencia kiválasztása
  15.   ADC10CTL1 = ADC10SSEL_0 + chan;      //csatorna = 'chan', ADC10OSC az órajel
  16.   ADC10CTL0 |= ENC + ADC10SC;          //Konverzió engedélyezése és indítása
  17.   while (ADC10CTL1 & BUSY);            //Várakozás a konverzió végére
  18.   return ADC10MEM;                     //Visszatérés a konverzió eredményével
  19. }
  20.  
  21. ...
  22. void main(void) {
  23. ...
  24. //--- Analóg csatornák engedélyezése --------------------------
  25.   ADC10AE0 |= BIT5;                    //P1.5 legyen analóg bemenet
  26.   while(1) {
  27.     delay_ms(1000);
  28.     data = ADC_single_meas_REF1_5V(INCH_5);
  29.     sw_uart_puts("chan 5 = ");
  30.     sw_uart_out4hex(data);
  31.     temp = (int32_t)data*1500L/1023;   //A mV-okban mért feszültség
  32.     sw_uart_outdec(temp,3);            //kiírás 3 tizedesre
  33.     sw_uart_puts("V chan 10 = ");    
  34.     data = ADC_single_meas_REF1_5V(INCH_10);
  35.     sw_uart_out4hex(data);  
  36.     temp = ((int32_t)data*270687L - 182023932L) >> 16;
  37.     sw_uart_puts(" temp = ");
  38.     sw_uart_outdec(temp,1);      
  39.     sw_uart_puts(" C\r\n");  
  40.     delay_ms(1000);  
  41.   }
  42. }

Az ADC beállítását és a konverzió indítását, valamint az eredmény kiolvasását végző ADC_single_meas_REF1_5V() függvényben az előző példához képest csupán annyi a különbség, hogy A REF2_5V bitet nem állítjuk '1'-be, így Vref+ = 1,5 V lesz.

A főprogramban az a fő különbség, hogy a mért feszültségek meghatározásánál a referencia feszültség helyébe 1500 mV-ot írtunk. A fél tápfeszültség mérése most nem végezhető el, ezért a főprogram végtelen ciklusában csak két csatorna mérése ismétlődik.

A hőmérséklet meghatározásánál most 256 helyett 65536-tal (216) szoroztuk fel a képletben szereplő konstansokat, emiatt most osztás gyanánt 16 helyiértékkel kell jobbraléptetni az eredményt.

A program futási eredménye az alábbi ábrán látható. Sárga nyílakkal megjelöltük azokat a helyeket, amikor a bemenő adatokat megváltoztattuk. AN5 (chan 5) esetében az eredetileg 1 V-ra  állított potmétert eltekertük, a beépített hőmérő (chan 10) esetében pedig a mikrovezérlő tokját melegítettük.

4_adc_simple_ref1.png

4_3. ábra: A 4_adc_simple_ref1 program futásának eredménye


Az ADC megszakítások használata

A fenti programokban egy várakozó ciklusban időzött a program, amíg a konverzió eredményére vártunk. Energiatakarékosság szempontjából ez pazarlás, hiszen a CPU-ra nincs szükség. Az MSP430G2231 mikrovezérlő gyári mintapéldái között található msp430g2x31_adc10_01.c programon keresztül bemutatjuk, hogy a program LPM0 módban is várakozhat a konverzió végére, a felébresztést pedig az ADC programmegszakítási kérelmét kiszolgáló eljárásban valósíthatjuk meg.

Ez a program az A1 analóg bemenetre (P1.1 portláb) bevezetett analóg feszültséget méri. Ha a bejövő feszültság nagyobb, mint a referenciaként használt VCC tápfeszültség fele, akkor a P1.0 kimenetre kötött LED (a Launchpad kártya piros LED-je) világítani fog, a 0.5 Vcc-nél alacsonyabb feszültségek esetén pedig kialszik. Az alábbi lista a program magyar megjegyzésekkel ellátott változatát mutatja be (4_adc1_interrupt.c).

4_4. lista: A 4_adc_interrupt program listája

  1. #include "msp430.h"
  2.  
  3. void main(void)
  4. {
  5.   WDTCTL = WDTPW + WDTHOLD;                 // Letiltjuk a watchdog időzítőt
  6.   ADC10CTL0 = ADC10SHT_3                    // mintavétel: 64 óraütés
  7.              | ADC10ON                      // Az ADC bekapcsolása
  8.              | SREF_0                       // VR+ = AVCC és VR- = AVSS
  9.              | ADC10IE;                     // ADC10 megszakítás engedélyezése  
  10.   ADC10CTL1 = ADC10SSEL_0 | INCH_1;         // ADC10OSC az órajel, A1 a bemenet
  11.   ADC10AE0 |= BIT1;                         // P1.1 analóg funkció engedélyezése
  12.   P1DIR |= BIT0;                            // P1.0 kimenet legyen (LED1)
  13.  
  14.   while(1)
  15.   {
  16.     ADC10CTL0 |= ENC + ADC10SC;             // Konverzió engedélyezése és indítása
  17.     __low_power_mode_0();                   // Alvás a konverzió végéig
  18.     if (ADC10MEM < 0x1FF)                   // Ha A1 < 0.5*Vcc
  19.       P1OUT &= ~0x01;                       // P1.0 LED1-et kikapcsoljuk
  20.     else
  21.       P1OUT |= 0x01;                        // P1.0 LED1-et bekapcsoljuk
  22.   }
  23. }
  24.  
  25. //--- ADC10 megszakításkiszolgáló eljárás -----
  26. #pragma vector=ADC10_VECTOR
  27. __interrupt void ADC10_ISR(void)
  28. {
  29.   __low_power_mode_off_on_exit();           // Felébresztjük az alvó CPU-t
  30. }


A cikk még nem ért véget, lapozz!
Következő: »»   4 / 8
Értékeléshez bejelentkezés szükséges!
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem