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. 6 perc
Lapozás: OK   5 / 8

Az ADC „haladó” funkciói

Az alábbiakban (ezen az oldalon és a következő kettőn is) az ADC összetettebb, mondjuk úgy, hogy "haladó" funkcióival ismerkedünk meg. Ezek közé sorolhatók a következő üzemmódok:

  • Triggerelés a Timer_A kimenőjeleivel
  • Ismételt konverzió
  • Automatikus csatornapásztázás
  • Automatikus adattárolás (DTC=Direct Transfer Control)

A "haladó" funkciókkal kapcsolatos vezérlő bitek szerepe:

CONSEQ0 - egycsatornás (0) vagy többcsatornás (1) mód választása

CONSEQ1 - egyszeri konverzió (0), vagy ismételt konverzió (1) választása

MSC - annak kiválasztása, hogy minden konverzió egyedileg  indítandó, külön triggerjellel (0), vagy egyetlen triggerjel indítsa a teljes szekvenciát (1).

SHS1, SHS0 – A triggerjel forrásának kiválasztása (00: ADC10SC bit, 01: Timer_A.OUT1, 10: Timer_A.OUT0, 11: Timer_A.OUT2)

LED PWM vezérlés  - három felvonásban

Az eddigi mintapéldákban az ADC konverzióját mindig szoftveresen indítottuk. Most megnézzük, hogy hogyan használhatjuk a TimerA modult a mérések időzítésére. A bemutatott mintaprogramok John Davies: MSP430 Microcontroller Basics c. könyvének mintapéldái közül valók, amelyeket a Leunchpad kártyához adaptáltunk.

A feladat: a P1.6 kimentre kötött LED fényerejét PWM módban vezéreljük, a kitöltést a P1.5 lábra kötött analóg jellel szabályozzuk egy potméter segítségével. A kapcsolás lényege az alábbi ábrán látható. A potméter két végét a tápfeszültségre és a földre (VCC, illetve VSS) kötjük, a csúszkáját pedig P1.5-re (A5 bemenet). A LED anódja egy áramkorlátozó ellenálláson keresztül a P1.6 kimentre kapcsolódik, a LED katódja pedig a földre. Megjegyezzük, hogy az MSP430 Launhcpad kártya esetén a LED már be van kötve (a zöld LED).

led_control.png

5_1. ábra: a LED vezérlés kapcsolási vázlata.

A program működési elve

A LED-et a Timer0 időzítő 1. sorszámú (CCR1) Capture/Compare csatornájának kimenőjele vezérl a P1.6 kimeneten. A PWM jel ismétlődési frekvenciája kb. 125 Hz. A kalibrálatlan, kb. 1,1 MHz-es DCO frekvenciát 1:8 arányú leosztás után vezetjük Timer0 időzítő TAR számlálójának bemenetére. A TACCR0 periódus regiszterbe pedig 1024-1-et írunk. A fejléc állományban definiált makrók segítségével ez BITA-1-nek is írható.  A PWM jel kitöltését az ADC-ből kapott értékekkkel fogjuk beállítani. Mivel a 10 bites ADC 0-1023 közötti számokat ad, így a konverzió eredménye közvetlenül, átskálázás nélkül felhasználható.

1. felvonás: Konverzió indítás TimerA megszakításban

Az első példában az ADC konverzió indítása a korábbiakhoz hasonlóan, szoftveresen történik, de a szoftveres parancs időzítése most a Timer0 CCR0 csatornájának periodikus megszakítási jeleivel történik. Ahogy a cikksorozat 2. részében említettük, a PWM kitöltés beállítására a CCR0 megszakítás a legalkalmasabb pillanat. Természetesen, itt, a megszakításban nincs idő egy ADC konverzió kivárására (valószínűleg lekésnénk vele a kitöltési tényező frissítését, ami nemkívánatos kimenőjelehez vezetne). Ezért ahhoz a kegyes csaláshoz folyamodunk, hogy mindig az előző periódusban indított konverzió eredményét használjuk fel. Ez a gyakorlatban az jelenti, hogy a potméter változását 1/125 s késéssel követi a kimenet. Természetesen érzékszervi észleléssel ez a kis "késés" nem vehető észre.

5_1. lista: A 4_adc_pwm1 program listája

  1. #include "io430.h"
  2.  
  3. void main (void) {
  4.     WDTCTL = WDTPW | WDTHOLD;          // Letiltjuk a watchdog időzítőt
  5.     P1OUT = 0;                         // A nem használt kimeneteket lehúzzuk
  6.     P1DIR = ~(BIT2+BIT3+BIT5);         // Csak RXD, SW2 és AN5 legyen bemenet
  7.     P1SEL |= BIT6;                     // P1.6 legyen TA0.1 kimenet
  8. //-- P1.3 belső felhúzás bekapcsolása ------
  9.     P1OUT |= BIT3;                     // Felfelé húzzuk, nem lefelé
  10.     P1REN |= BIT3;                     // Belső felhúzás bekapcsolása P1.3-ra
  11. //-- Analóg bemenet engedélyezése ----------  
  12.     ADC10AE0 = BIT5;                   // Enable analog input on AN5/P1.5
  13. //-- Timer_A PWM 125Hz, OUT1 kimeneten, SMCLK/8 órajellel, "Felfelé számlálás"
  14.     TACCR0 = BITA - 1;                 // A periódus ADC10-hez illeszkedő (1023)
  15.     TACCTL0 = CCIE;                    // CCR0 megszakítás engedélyezése
  16.     TACCR1 = BIT9;                     // CCR1 induláskor 50%-ra (512)
  17.     TACCTL1 = OUTMOD_7;                // Reset/set PWM mód beállítása
  18.     TACTL = TASSEL_2 |                 // SMCLK az órajel forrása
  19.                 ID_3 |                 // 1:8 osztás bekapcsolása
  20.                 MC_1 |                 // Felfelé számláló mód
  21.                 TACLR;                 // TAR törlése
  22. //-- ADC  konfigurálás ---------------------
  23.   ADC10CTL0 = ADC10SHT_0               // mintavétel: 4 óraütés
  24.              | ADC10ON                 // Az ADC bekapcsolása
  25.              | SREF_0;                 // VR+ = AVCC és VR- = AVSS
  26.     ADC10CTL1 = INCH_5                 // A5 csatorna kiválasztása
  27.                | SHS_0                 // Szoftveres triggerelés (ADC10SC)    
  28.                | ADC10SSEL_0           // ADC10OSC adja az órajelet (~5 MHz)
  29.                | CONSEQ_0;             // Egyszeri, egycsatornás konverzió
  30.     ADC10CTL0 |= ENC;                  // A konverzió engedélyezése
  31.         __low_power_mode_0();          // A további tevékenység megszakításban
  32. }
  33. //---------------------------------------------------------------------------
  34. // CCIFG0 megszakítás PWM ciklusonként: kitöltés beállítás, ADC újraindítás
  35. //---------------------------------------------------------------------------
  36. #pragma vector = TIMER0_A0_VECTOR
  37. __interrupt void TIMERA0_ISR (void)    // A jelzőbit automatikusan törlődik
  38. {
  39.     TACCR1 = ADC10MEM;                 // PWM kitöltés = az előző ADC mérés
  40.     ADC10CTL0 |= ADC10SC;              // Új ADC konverzió indítása
  41. }

 

2. felvonás: Konverzió indítás TACCR0 kimenőjelével

A második példában az ADC konverzió indítása hardveresen történik, a Timer0 CCR0 csatornájának kimenőjelével. Az ADC triggereléséhez azonban csak a Capture/Compare csatornák OUT0, OUT1, OUT2 jeleit használhatjuk, tehát a 0. Compare csatornán kimenő jelet kell produlni. A CCR0 csatorna üzemmódjai azonban korlátozottak, gyakorlatilag csak a toggle módot tudjuk felhasználni periodikus jelek keltésére (OUTMOD_4). Ezzel azonban a PWM frissítési frekvenciát megfelezzük (az OUT0 jelnek csak a felfutó éle triggereli az ADC, a lefutó él nem), így minden beállítás két PWM periódusig marad érvényben.

A PWM kitöltés beállítása most az ADC megszakítást kiszolgáló eljárásban történik. Ezek a megszakítások azonban a konverzió kivárása miatt már a TAR számláló túlcsordulása utánra is eshetnek, ezért nagyon kis kitöltési értékeknél fals kimenőjel keletkezhet (kis kitöltés helyett egy egész periódusra bekapcsolva maradhat a LED). Ez a gyakorlatban azt jelenti, hogy a potmétert nem célszerű teljesen letekerni.

5_2. lista: A 4_adc_pwm2 program listája

  1. #include "io430.h"
  2.  
  3. void main (void) {
  4.     WDTCTL = WDTPW | WDTHOLD;          // Letiltjuk a watchdog időzítőt
  5.     P1OUT = 0;                         // A nem használt kimeneteket lehúzzuk
  6.     P1DIR = ~(BIT2+BIT3+BIT5);         // Csak RXD, SW2 és AN5 legyen bemenet
  7.     P1SEL |= BIT6;                     // P1.6 legyen TA0.1 kimenet
  8. //-- P1.3 belső felhúzás bekapcsolása ------
  9.     P1OUT |= BIT3;                     // Felfelé húzzuk, nem lefelé
  10.     P1REN |= BIT3;                     // Belső felhúzás bekapcsolása P1.3-ra
  11. //-- Analóg bemenet engedélyezése ----------  
  12.     ADC10AE0 = BIT5;                   // Enable analog input on AN5/P1.5
  13. //-- Timer_A PWM 125Hz, OUT1 kimeneten, SMCLK/8 órajellel, "Felfelé számlálás"
  14.     TACCR0 = BITA - 1;                 // A periódus ADC10-hez illeszkedő (1023)
  15.     TACCTL0 = OUTMOD_4;                // Toggle mód (OUT0 indítja az ADC-t)
  16.     TACCR1 = BIT9;                     // CCR1 induláskor 50%-ra (512)
  17.     TACCTL1 = OUTMOD_7;                // Reset/set PWM mód beállítása
  18.     TACTL = TASSEL_2 |                 // SMCLK az órajel forrása
  19.                 ID_3 |                 // 1:8 osztás bekapcsolása
  20.                 MC_1 |                 // Felfelé számláló mód
  21.                 TACLR;                 // TAR törlése
  22. //-- ADC  konfigurálás ---------------------
  23.     ADC10CTL0 = ADC10SHT_0             // mintavétel: 4 óraütés
  24.                | ADC10ON               // Az ADC bekapcsolása
  25.                | SREF_0                // VR+ = AVCC és VR- = AVSS
  26.                | ADC10IE;              // Programmegszakítás engedélyezése
  27.     ADC10CTL1 = INCH_5                 // A5 csatorna kiválasztása
  28.                | SHS_2                 // Hatdveres triggerelés (TA0.0)    
  29.                | ADC10SSEL_0           // ADC10OSC adja az órajelet (~5 MHz)
  30.                | CONSEQ_2;             // Ismételt egycsatornás konverzió
  31.     ADC10CTL0 |= ENC;                  // A konverzió engedélyezése
  32.         __low_power_mode_0();          // A további tevékenység megszakításban
  33. }
  34.  
  35. //----------------------------------------------------------------------
  36. // ADC10 megszakítás kiszolgálása: PWM kitöltés aktualizálása
  37. //----------------------------------------------------------------------
  38. #pragma vector = ADC10_VECTOR
  39. __interrupt void ADC10_ISR (void)      // A jelzőbit automatikusan törlődik
  40. {
  41.     TACCR1 = ADC10MEM;                 // PWM kitöltés = ADC konverzió eredménye
  42. }

 Amint látható, ez a program alig különbözik az előzőtől. Az eltérések röviden így összegezhetők:

  • TACCTL0 beállításánál OUTMOD_4 üzemmódot állítunk be, s nem egedélyezünk megszakítást.
  • ADC10CTL0 beállításánál engedélyeztük az ADC megszakításokat (ADC10IE=1)
  • ADC10CTL1 beállításánál most SHSx=2 (OUT0 legyen a triggerjel), valamint CONSEQx=2 (ismételt egycsatornás konverzió ) kell.
  • Különbség az is, hogy a TCCR0 megszakítás (TIMER0_A0_VECTOR) helyett most az ADC konverziók végén aktiválódó ADC10_VECTOR megszakítást szolgáljuk ki.

3. felvonás: Közvetlen adatmozgatás (DTC)

Az előző példában az ADC konverzió végén szoftveresen pakoltuk át az adatot az ADC10MEM regsizterből a TACCR1 regiszterbe. Miért ne csinálnánk ezt is hardveres módon? Akkor megtakaríthatjuk a fölösleges időhúzást a CPU feléledésére várva, illetve a program legfontosabb állapotjelzőinak (visszatérési cím, Státusz Regiszeter) elmentésével bíbelődve? Az ADC10 közvetlen adatmozgatási képességgel rendelkezik (Direct Transfer Control, DMA), ami leveszi a vállunkról az adatmozgatás terhét.

A DTC beállításához három regisztert kell feltöltenünk:

ADC10DTC0 - ebben állíthatjuk be az üzemmódot (esetünkben most az egyblokkos, folyamatos átviteli módot kell kiválasztani)

ADC10DTC1 - ez adja meg az átviendő adatok számát(esetünkben egyetlen adatot kell átvinni)

ADC10SA - a cél helyének kezdőcíme (esetünkben a TACCR1 regiszter címe a 64 kilobájtos memória címtartományban)

5_3. lista: A 4_adc_pwm3 program listája

  1. #include "io430.h"
  2. #include "io430.h"
  3.  
  4. void main (void) {
  5.     WDTCTL = WDTPW | WDTHOLD;          // Letiltjuk a watchdog időzítőt
  6.     P1OUT = 0;                         // A nem használt kimeneteket lehúzzuk
  7.     P1DIR = ~(BIT2+BIT3+BIT5);         // Csak RXD, SW2 és AN5 legyen bemenet
  8.     P1SEL |= BIT6;                     // P1.6 legyen TA0.1 kimenet
  9. //-- P1.3 belső felhúzás bekapcsolása ------
  10.     P1OUT |= BIT3;                     // Felfelé húzzuk, nem lefelé
  11.     P1REN |= BIT3;                     // Belső felhúzás bekapcsolása P1.3-ra
  12. //-- Analóg bemenet engedélyezése ----------  
  13.     ADC10AE0 = BIT5;                   // Enable analog input on AN5/P1.5
  14. //-- Timer_A PWM 125Hz, OUT1 kimeneten, SMCLK/8 órajellel, "Felfelé számlálás"
  15.     TACCR0 = BITA - 1;                 // A periódus ADC10-hez illeszkedő (1023)
  16.     TACCTL0 = OUTMOD_4;                // Toggle mód (OUT0 indítja az ADC-t)
  17.     TACCR1 = BIT9;                     // CCR1 induláskor 50%-ra (512)
  18.     TACCTL1 = OUTMOD_7;                // Reset/set PWM mód beállítása
  19.     TACTL = TASSEL_2 |                 // SMCLK az órajel forrása
  20.                 ID_3 |                 // 1:8 osztás bekapcsolása
  21.                 MC_1 |                 // Felfelé számláló mód
  22.                 TACLR;                 // TAR törlése
  23. //-- ADC  konfigurálás ---------------------
  24.     ADC10CTL0 = ADC10SHT_0             // mintavétel: 4 óraütés
  25.               | ADC10ON                // Az ADC bekapcsolása
  26.               | SREF_0;                // VR+ = AVCC és VR- = AVSS
  27.     ADC10CTL1 = INCH_5                 // A5 csatorna kiválasztása
  28.               | SHS_2                  // Hatdveres triggerelés (TA0.0)    
  29.               | ADC10SSEL_0            // ADC10OSC adja az órajelet (~5 MHz)
  30.               | CONSEQ_2;              // Ismételt egycsatornás konverzió
  31.     ADC10DTC0 = ADC10CT;               // Folyamatos adatátvitel, egy blokk
  32.     ADC10DTC1 = 1;                     // Egyetlen target cím a memóriában
  33.     ADC10SA = (unsigned short) &TACCR1;// A target cím
  34.     ADC10CTL0 |= ENC;                  // A konverzió engedélyezése
  35.     __low_power_mode_0();              // Sem CPU, sem interrupt nem kell már!
  36.  }

Ez a program szinte szóról szóra megegyezik az előzővel. Az eltérések röviden így összegezhetők:

  • ADC10CTL0 beállításánál most nem engedélyeztük az ADC megszakításokat, nincs rá szükség. Az ADC10IFG jelzőbit bebillnése most a DTC-t aktiválja.
  • ADC10DTC0, ADC10DTC1 és ADC10SA beállításával  konfiguráljuk a DTC átvitelt a fentebb ismertetett módon.
  • Nincs, nem kell egyetlen megszakítás kiszolgáló eljárás sem! A beállítások után a hardver CPU nélkül, önállóan teszi a dolgát.

A cikk még nem ért véget, lapozz!
Következő: »»   5 / 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