computer
Programowanie Mikroprocesory Mikrokontrolery Last.fm Programowanie Mikroprocesory Mikrokontrolery Facebook Twitter

Valid XHTML 1.0 Transitional

Poprawny CSS!

Programowanie 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:

#define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr,bit) (_SFR_BYTE(sfr) |= _BV(bit))

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

Najprostszym sposobem odczytania wartości z portu jest przepisanie jego wartości do zmiennej. Należy pamiętać że pojedynczy port mikrokontrolera posiada przynajmniej 3 rejestrty. Rejestr kierunku DDRx, rejestr wyjściowy PORTx oraz rejestr wejściowy PINx. Aby odczytać wartości z pinów portu mikrokontrolera należy zdefiniować sobie jakąś zmienną np. o nazwie "zmienna_y" co zrealizowane zostało w pierwszej linijce kodu.

 

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

Załóżmy że ktoś przycisnął przyciski zwierające do masy piny 0,2,4 portu C mikrokontrolera. W drugiej linijce definiujemy port jako wejściowy. W trzeciej linijce kodu ustawiamy podciągnięcie wyjść portu mikrokontrolera do "1" (ustawiamy wartości rejestru wyjściowego PORTx na 1 na każdym bicie) tak aby wyjście mikrokontrolera w przypadku gdy zewnętrznie na pinie nic nie wymusza stanu niskiego przyjmowało stan "1" a dopiero wymuszenie zewnętrzne może mienić jego wartość na „0” np. przyciśnięty przycisk zwierający wejście mikrokontrolera do masy. W czwartej linijce kodu przypisujemy wartość rejestru PINC do zmiennej zmienna_y dzięki czemu stan wejść mikrokontrolera zostanie wpisany do tej zmiennej. Wartość rejestru PINC jest zgodna z wartościami stanów wymuszanych na portcie (dla pustego pinu wartość wymuszana przez ustawienie PORTC „1” natomiast dla np. przyciśniętego przycisku zwierającego pin portu do masy wartość „0” na pinach zwieranych). Rejestr PINC przyjmuje wartości zgodne z wartościami na pinach mikrokontrolera (rejestr wejściowy). Dla tak przygotowanego przykładu w zmiennej „zmienna_y” zapisana zostanie wartość 0b01010111.

Przykłady:

Należy pamiętać że poniższe przykłady nie korelują z opisem zamieszczonym powyżej i wartości zmiennych zaprezentowane poniżej są przykładem samym w sobie nie odnoszącym się do opisu powyżej.

Odczyt zapis wartości na port mikrokontrolera mikroprocesora

//wystawienie wartości 4F na port B mikrokontrolera
DDRB=0xff; // ustalenie kierunku portu (wyjście)
PORTB=0x4F; // wystawienie wartości 4F na port

//odczytanie wartości z portu C mikrokontrolera
DDRB=0x00; // ustalenie kierunku portu (wejściowy)
PORTC=0xFF; // podciągnięcie portu do 1.
x=PINC; // przepisanie aktualnej wartości portu do zmiennej x

 Program realizujący naprzemienne miganie diodami na porcie mikrokontrolera

/*
Program migania diodą
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

#define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr,bit) (_SFR_BYTE(sfr) |= _BV(bit)))
 
int main(void)
{
 
DDRD=0xff;                              // ustalenie kierunku portu (wyjście)
PORTD=0xAA;                     // wystawienie wartości AAh na port czyli 10101010b
 
while(1)
    {
       
        PORTD=0x55;             // wystawienie wartości 55h na port  czyli 01010101b
        _delay_ms(500);         // opóźnienie czasowe 500ms
        PORTD=0xAA;                     // wystawienie wartości AAh na port czyli 10101010b
        _delay_ms(500);         // opóźnienie czasowe 500ms
       
        }
 
}

 

22.03.2020 (poprawić tekst - jest bełkot)


03-maj-2023 11:12:41 CEST
by Pioter




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