Programowanie mikroprocesorów ( mikrokontrolerów )

Sterowanie portami

Komunikacja mikroprocesora mikrokontrolera ze światem zewnętrznym odbywa się za pomocą portów wejść / wyjść. Podstawowymi operacjami na jakich nam zależy są wystawienie jakiejśc wartości na port mikroprocesora mikrokontrolera oraz odczytanie jakiejś wartości z portu. Aby dokonać odczytu wartości z portu mikrokontrolera mikroprocesora należy skonfigurować go jako port wyjściowy czyli wpisać do rejestru DDRx wartości "1" dla odpowiednich nóżek portu które nas interesują bądź też dla całego portu. Możemy zrealizować to na kilka sposobów.

Należy pamiętać że podczas programowanie mikroprocesorów mikrokontrolerów możemy posługiwać się różnymi systemami liczbowymi. Najpopularniejszymi są system dziesiętny, binarny oraz szesnastkowy. Dobrze jest mieć wyobrażenie o zasadzie tworzenia takich systemów liczbowych i sposobach szybkiego przeliczania ich z jednego na drugi gdyż jest to przydatną rzeczą podczas programowania oraz w niektórych przypadkach poprawia jego czytelność używanie różnych systemów liczbowych.

Wystawienie wartości na port mikroprocesora mikrokontrolera

Jednym ze sposobów wystawienia wartości na port jest wpisanie do rejestru wyjściowego PORTx odpowiedniej wartości liczbowej. Następuje wówczas nadanie wartości wzystkim 8 nóżkom na zadeklarowaną jak w poniższym przykładzie: 

Przykład. Wystawienie wartości na cały port na przykładzie portu C:


DDRC=0b11111111;
PORTC=0b01010101;
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
0
1
0
1
0
1
0

W powyższych komendach wykorzystaliśmy deklarowanie wartości rejestrów w sposób binarny. W pierwszej linijce kodu do rejestru określającego kierunek transmisji danych portu C mikroprocesora mikrokontrolera wpisaliśmy jedynki co jest jednoznaczne z ustawieniem portu w tryb portu wyjściowego mikroprocesora mikrokontrolera. W drugiej linijce kodu do rejestru zawierającego wartość portu C wpisaliśmy naprzemiennie jedynki i zera. Stan uzyskany po wykonaniu tych dwóch komend obrazuje rysunek wyprowadzeń mikroprocesora mikrokontrolera obok kodu. Widzimy że na nóżkach mikroprocesora pojawiają sie naprzemian zera i jedynki. Należy pamiętać że dla zapisu 0b01010101 ostatnia wartość z prawej strony jest to najmłodszy bit ( bit o najmniejszej wadze ) natomiast z prawej strony zaraz po literce b występuje najstarszy bit ( bit o największej wadze ).

Programując w języku C++ mamy możliwość w atwy sposób zmieniać wartości poszczególnych bitów w rejestrach. Do tego celu musimy posłużyć się dosyć skomplikowaną  i mało czytelną ( moim zdaniem) komendą. Komenda ustawiająca bit rejestru wygląda następująco "_SFR_BYTE(sfr) |= _BV(bit)" natomiast kasująca bit rejestru "_SFR_BYTE(sfr) &= ~_BV(bit)". Jest jednak proste wyjście z sytuacji. W celu ułatwienia posługiwania się tymi dwoma komendami możemy stworzyć sobie definicje procedury tzn. zastąpić powyższe komendy prostrzymi i bardziej czytelnymi. Do tego celu posłużymy się dwiema definicjami. Jedna będzie ustawiała bit rejestru na jedynkę, natomiast druga będzie kasowała bit rejestru ustawiając go na zero. Omawiane definicje będą wyglądały następująco:

Definicje sterujące pojedynczymi bitami portu mikrokontrolera mikroprocesora
  1.  
  2. //ustawieni jednego z bitów rejestru
  3. #define sbi(sfr,bit) (_SFR_BYTE(sfr) |= _BV(bit))
  4.  
  5. //skasowanie jednego z bitów rejestru
  6. #define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  7.  
  8.  

Powyższe linie w programie wstawiamy zaraz po definicjach #include. Użycie powyższych komend jest następujące:

sbi(sfr,bit)

  • sbi - Jest to komenda i oznacza "set bit" tzn. ustaw bit na jedynkę.
  • sfr - jest to nazwa rejestru mikroprocesora mikrokontrolera z którego bit chcemy ustawić na jedynkę. Wpisujemy zamiast sfr nazwę rejestru np "PORTC"
  • bit - jest to numer bitu z rejestru wpiasnego wcześniej przed przecinkiem tzn zamiast słowa bit wstawiamy cyfrę od 0 do 7 (rejestry są ośmiobitowe).

cbi(sfr,bit)

  • cbi - Jest to komenda i oznacza "clear bit" tzn. ustaww bit na zero.
  • sfr - jest to nazwa rejestru mikroprocesora mikrokontrolera z którego bit chcemy ustawić na jedynkę. Wpisujemy zamiast sfr nazwę rejestru np "PORTC"
  • bit - jest to numer bitu z rejestru wpiasnego wcześniej przed przecinkiem tzn zamiast słowa bit wstawiamy cyfrę od 0 do 7 (rejestry są ośmiobitowe).

Przykład. Wystawienie wartości pojedynczych bitów na port na przykładzie portu C:


DDRC=0b11111111;
PORTC=0b11111111;
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
1
1
1
1
1
1
1

cbi (PORTC,3);
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
1
1
0
1
1
1
1

cbi (PORTC,6);
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
1
1
0
1
1
0
1

sbi (PORTC,3);
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
1
1
1
1
1
0
1

sbi (PORTC,6);
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
1
1
1
1
1
1
1

W powyższym przykładzie przedstawione zostało zastosowanie poznanych komend. W pierwszym kroku wystawione zostają jedynki na cały port C mikroprocesora mikrokontrolera. W drugim kroku wyzerowany zostaje czwarty bit portu C (numerowany jest jako 3 ponieważ notacja bitów portu zaczyna się od zera), następnie zerowany zostaje siódmy bit portu C mikroprocesora mikrokontrolera. W dwóch ostatnich krokach kolejno zostaje wysterowany czwarty bit portu C na jedynkę i następnie wysterowany zostaje siódmy bit na jedynkę przywracając port C do stanu pierwotnego.

Odczyt wartości z portu mikroprocesora mikrokontrolera

Najprostrzym sposobem odczytania wartości z portu jest wpisanie jego wartości do zmiennej. Aby tego dokonać należy zdefiniować sobie jakąś zmienną np o nazwie "zmienna_y" co zrealizowane zostało w pierwszej linijce.


char zmienna_y;
DDRC = 0b00000000;
PORTC = 0b11111111 ;
zmienna_y = PINC;
Atmega8
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
1
0
1
0
1
0
1
0

W drugiej linijce definiujemy port jako wejściowy i w trzeciej linijce kodu usawiamy podciągnięcie wyjść do "1" tak aby nie podłączone nigdzie wyjście przyjmowało stan "1" a dopiero wymuszenie zewnętrzne może mienić jego wartość na 0 np zwierając wejście mikrokontrolera do masy. W czwartej linijce kodu przypisujemy wartość portu C do zmiennej zmienna_y dzięki czemu stan wejść mikrkokontrolera zostanie wpisany do tej zmiennej.

Przykłady:

Odczyt zapis wartości na port mikrokontrolera mikroprocesora
  1. //wystawienie wartości 4F na port B mikrokontrolera
  2. DDRB=0xff; // ustalenie kierunku portu (wyjście)
  3. PORTB=0x4F; // wystawienie wartości 4F na port
  4.  
  5. //odczytanie wartości z portu C mikrokontrolera
  6. DDRB=0x00; // ustalenie kierunku portu (wyjście)
  7. PORTC=0xFF; // podciągnięcie portu do 1.
  8. x=PINC; // przepisanie aktualnej wartości portu do zmiennej x
  9.  

Program realizujący naprzemienne miganie diodami na porcie mikrokontrolera
  1.  
  2. /*
  3. Program migania diodą
  4. */
  5.  
  6. #include <avr/io.h>
  7. #include <util/delay.h>
  8.  
  9. #define F_CPU 8000000UL
  10. #define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  11. #define sbi(sfr,bit) (_SFR_BYTE(sfr) |= _BV(bit)))
  12.  
  13. int main(void)
  14. {
  15.  
  16. DDRD=0xff;                              // ustalenie kierunku portu (wyjście)
  17. PORTD=0xAA;                     // wystawienie wartości AAh na port czyli 10101010b
  18.  
  19. while(1)
  20.     {
  21.        
  22.         PORTD=0x55;             // wystawienie wartości 55h na port  czyli 01010101b
  23.         _delay_ms(500);         // opóźnienie czasowe 500ms
  24.         PORTD=0xAA;                     // wystawienie wartości AAh na port czyli 10101010b
  25.         _delay_ms(500);         // opóźnienie czasowe 500ms
  26.        
  27.         }
  28.  
  29. }
  30.  
  31.  





 
Wszelkie prawa zastrzeżone! Kopiowanie, powielanie i wykorzystywanie zdjęć, treści oraz jej fragmentów bez zgody autora zabronione.
© mikroprocesory.info.pl@gmail.com 2013.