Technika Mikroprocesorowa Technika Mikroprocesorowa laboratorium


Technika mikroprocesorowa
materiały do laboratorium
Autor: Dorota Rabczuk
Architektura mikrokontrolera
AT90S8515
1. Jednostka arytmetyczno-logiczna ALU posiada dostęp do 32-ch
rejestrów 8-bitowych, na których wykonuje obliczenia.
2. Pamięć programu Flash 8 kbajtów, licznik instrukcji, dekoder instrukcji.
3. Pamięć ulotna danych RAM 512 bajtów.
4. Pamięć nieulotna danych EEPROM 512 bajtów.
5. UrzÄ…dzenia peryferyjne: liczniki/timery 8-bitowe i 16-bitowe, timer z
trybem PWM, timer watchdog, moduł przerwań zewnętrznych,
interfejsy: SPI i UART, komparator analogowy
Architektura mikrokontrolera
AT90S8515
Pamięci wewnętrzne mikrokontrolera
1. Pamięć programu Flash  programowalna elektrycznie równolegle lub
szeregowo. Programowanie szeregowe może się odbywać w układzie
przez interfejsy: SPI lub JTAG lub UART (RS-232)  ten ostatni sposób
wymaga wcześniejszego wgrania programu ładującego tzn. bootloader a
2. Pamięć danych RAM (SRAM)  o dostępie nanosekundowym, ulotna,
tryby adresowania: bezpośredni i wskaznikowy.
3. Pamięć danych EEPROM o dostępie milisekundowym, nieulotna.
Zapis liczb
Zapis liczb:
0b11011100  zapis binarny
0xdc lub $dc  zapis szesnastkowy
220 zapis dziesiętny
0b11011100 = 0xdc = $dc = 220
Makro _BV(x) jest liczbą, która ma jedną binarną 1 na pozycji x
_BV(6) = 0b01000000 = 0x40 = 64
Suma i iloczyn binarny
Suma binarna |
Suma binarna jest wykonywana bit z bitem. Operacja ta służy do ustawienia w
wyjściowym rejestrze wybranych bitów pozostawiając pozostałe bez zmian.
0b???????? | 0b10101010 = 0b1?1?1?1?
Bity nieparzyste tj. 1,3,5 i 7 zostajÄ… ustawione, natomiast bity parzyste
tj. 6,4,2,0 nie ulegnÄ… zmianie.
Iloczyn binarny &
Iloczyn binarny jest wykonywany bit z bitem. Operacja ta służy do wyzerowania w
wyjściowym rejestrze wybranych bitów pozostawiając pozostałe bez zmian.
0b???????? & 0b10101010 = 0b?0?0?0?0
Bity nieparzyste tj. 1,3,5 i 7pozostaja bez zmian, natomiast bity parzyste
tj. 6,4,2,0ulegajÄ… wyzerowaniu.
Przesunięcie binarne
Przesunięcie binarne w lewo <<
Operacja (1<<0) powoduje utworzenie liczby 0b00000001
(1<<0) = 0x01
Operacja (1<<4) powoduje przesunięcie binarnej 1 o 4 pozycje w lewo i
utworzenie liczby (1<<4) = 0b00010000
Liczba (1<<4) | (1<<0) = 0b00010001 ma 2-ie jedynki binarne
Przesunięcie binarne w prawo >>
Operacja (a>>8) powoduje przesunięcie wszystkich bitów liczby o 8 pozycji w prawo
i jest przydatna do wykonywania operacji na młodszym i starszym bajcie liczby 16-sto
bitowej w 8-mio bitowych mikrokontrolerach
char b, c; //liczby 8-mio bitowe
int a=0x3456; //liczba 16-sto bitowa
b = a; //młodszy bajt liczby a tj. b=0x56;
c = (a>>8); //starszy bajt liczby a tj. b=0x34;
Przesunięcie binarne
Przesunięcie binarne w lewo << jest równoznaczne z pomnożeniem przez 2
B =A << 1; //B=A*2
C =A << 2; //C=A*4
Przesunięcie binarne w prawo >> jest równoznaczne z podzieleniem przez 2
B =A >> 1; //B = A/2
C= A >> 3; //C = A/8
Negacja binarna
Operacja ~(1<<0) powoduje zanegowanie wszystkich bitów w liczbie
0b00000001 i tym samym utworzenie liczby 0b11111110
~(1<<0) = 0xFE
Operacja ~(1<<4) powoduje zanegowanie wszystkich bitów liczby (1<<4)
~(1<<4) = 0b11101111
Liczba (1<<4) | (1<<0) = 0b00010001 ma 2-ie jedynki binarne
Liczba ~((1<<4) | (1<<0) ) = 0b11101110 ma 2 binarne zera
~(_BV(6)) = ~(0b01000000) = 0b10111111 = 0xBF = 191
Operacje binarne - przykłady
Po zdefiniowaniu # define bit5 5
Operacja A | = (1<Operacja A & = ~(1<Operacja A &= (1<wyjÄ…tkiem bitu 5 i ma sens selekcji bitu 5 zmiennej A.
Aby się dowiedzieć, czy bit 5 jest wyzerowany dokonuję selekcji i porównania.
if (A & (1<; //jest wyzerowany
else
; //nie jest wyzerowany
Operacje logiczne
Suma logiczna ||
Jeśli którakolwiek z liczb jest różna od zera, to wynik jest prawdą
Iloczyn logiczny &&
Jeśli obie liczby są niezerowe, to wynik iloczynu jest prawdą
Negacja logiczna !
Zaprzeczeniem 1 jest 0
Pętle
switch (zmienna)
for
{
for ( i=1; i<11; i++)
case 1: //gdy zmienna = 1
{ Rozkaz; }
rozkaz;
break;
case 2: //gdy zmienna = 2
rozkaz;
break;
}
Wykorzystywana np. do rozróżniania
naciśniętych klawiszy
Pętla while
while
Pętla while jest często wykorzystywana w programie głównym, jeśli potrzebne jest
ciągłe wykonywanie procedur wątku głównego
do
{ ;rozkazy }
while (1); //wykonuj zawsze
Pętla while jest też wykorzystywana do oczekiwania na ustawienie lub wyzerowanie bitu.
Np. dopóki nie ustawi się bit 5 w rejestrze A czekaj
while(! (A & (1<W pętli tej nie umieszczono żadnych rozkazów, co oznacza, że program stoi oczekując
na spełnienie warunku
Projekt w środowisku AVR Studio
Każdy projekt należy założyć w oddzielnym katalogu.
Projekt zawiera następujące pliki:
.c pliki z kodem zródłowym napisanym w języku C
.h opcjonalnie pliki nagłówkowe z deklaracjami, definicjami i wybranymi
procedurami kodu zródłowego
.aps zawiera informacje o tym, które pliki należą do projektu i będą podlegały
kompilacji
.aws przechowuje informacje bieżące o ostatnio używanej przestrzeni roboczej
(nieistotny dla projektu)
Makefile Plik Makefile w katalogu default zawiera reguły kompilacji
czyli przekształcania wyrażeń z języka wysokiego poziomu (tu: C)
na wyrażenia niskopoziomowe
.eep, .elf. , .hex, .o pliki wyjściowe w katalogu default powstałe podczas kompilacji.
Plik .hex w formacie Intel Hex należy wgrać do pamięci
Flash mikrokontrolera AVR
Podstawowe opcje kompilacji
Podstawowe opcje kompilacji należy ustawić na zakładce
Project Configuration Options:
Typ procesora, dla którego jest wykonywana kompilacja
Częstotliwość zegara procesora (tu: kwarcu)
Poziom optymalizacji
Należy zaznaczyć pole  Create Hex File
Uwaga!!
Jeśli pętla programu nie obiega prawidłowo (może się to zdarzyć zarówno w czasie
symulacji środowiskowych, jak i po uruchomieniu programu w mikrokontrolerze),
wówczas należy zmniejszyć poziom optymalizacji do O0.
Struktura programu
Na początku programu należy wczytać potrzebne pliki nagłówkowe z funkcjami bibiotecznymi.
#include //biblioteka procesora
#include //biblioteka przerwań
#include //procedury z opóznieniem czasowym
Następnie umieszcza się definicje potrzebnych procedur dodatkowych (w tym procedur
przerwań), a na samym dole procedurę główna (main)
Nazwy procedur dodatkowych mogą być dowolne , natomiast nazwy procedur przerwań są
zarejestrowane i można je znalezć w pliku procesora.
W bibliotece delay.h zdefiniowno procedury odliczajÄ…ce czas w ms oraz µs o definicjach:
_delay_us (x);
_delay_ms (x);
Definicje procedur
char Procedura1 (int m, bool n)
{
rozkazy;
return k;
}
Procedura1 pobiera zmienne: m typu int i n typu bool, a zwraca zmiennÄ… k typu char.
Jeśli procedura nie pobiera lub nie zwraca zmiennych, to w stosowne pola wpisujemy  void
Procedura przerwania zewnętrznego ma zarejestrowana nazwę
ISR (INT0_vect )
{
rozkazy;
}
Procedura main
int main (void)
{
char t;
bool a=true;
int b = 20;
t= Procedura1 (20, true);
return 0:
}
Program main wywołuje procedurę Procedura1 od parametrów: 20, main i odbiera wynik na
zmiennÄ… t.
Procedur przerwań nie wywołuje się programowo, procedury te są wykonywane samoczynnie,
jeśli zajdą określone warunki sprzętowe lub programowe pod warunkiem wcześniejszego zdjęcia
maski danego przerwania.
Kolejność procedur
Jeśli w programie umieścimy (oprócz definicji) również deklaracje procedur,
to kolejność procedur nie jest istotna i wszystkie procedury widzą się wzajemnie.
Deklaracja przykładowej procedury:
char Procedura1 (int, bool);
W prostym programie można pominąć deklaracje procedur, jednak należy
wówczas zadbać o takie uporządkowanie procedur, aby procedura umieszczona
niżej odwoływała się wyłącznie do procedur umieszczonych nad nią.
W takim układzie procedura main musi być ostatnia.
Plik nagłówkowy
Deklaracje procedur, deklaracje zmiennych oraz definicje wybranych procedur
można przenieść do samodzielnie utworzonego pliku nagłówkowego z rozszerzeniem .h.
Pliki nagłówkowe przeważnie tworzy się tematycznie np. dla umieszczenia wszystkich
procedur związanych z wyświetlaczem LCD.
Przykład wczytania pliku nagłówkowego
#include
Porty input/output
Mikrokontroler AT90S8515 posiada 4 uniwersalne porty dwukierunkowe
(Input/Output): A, B, C, D, z których każdy ma 8 linii z możliwością
podwieszenia każdej linii przez rezystor do zasilania.
Każdy z portów jest obsługiwany przez 3 rejestry:
Rejestr kierunkowy DDR (A, B, C lub D)
Rejestr wyjściowy PORT (A, B, C lub D)
Rejestr wejściowy PIN (A, B, C lub D)
Mikrokontroler ATMega128 posiada 6 uniwersalnych portów (Input/Output):
A, B, C, D, E i F.
Linie portów (na przykładzie portu D)
Rejestr kierunkowy portu D - DDRD
Bit 7 6 5 4 3 2 1 0
Nazwa DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr danych portu D - PORTD
Bit 7 6 5 4 3 2 1 0
Nazwa PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr wejściowy portu D - PIND
Bit 7 6 5 4 3 2 1 0
Nazwa PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0
Odczyt/zapis R R R R R R R R
Wartość początkowa N/A N/A N/A N/A N/A N/A N/A N/A
N/A  wartość nieustalona
Konfiguracja linii portów
Konfiguracja rejestru kierunkowego DDR (A, B, C lub D):
1  linia staje się wyjściem
0  linia staje się wejściem
Gdy linia jest wyjściem, to rejestr PORT (A, B, C lub D) ustawia:
1  wyjście w stanie wysokim
0  wyjście w stanie niskim
Gdy linia jest wejściem, to rejestr PORT (A, B, C lub D) ustawia:
1  podwieszenie wejścia pod zasilanie
0  wejście w stanie wysokiej impedancji
Gdy linia jest wejściem, to rejestr PIN (A, B, C lub D) służy do odczytu
stanu linii (czy zwarta od zewnÄ…trz).
Konfiguracja linii portów -wyjście
Linia 2 portu B jako wyjście (przykładowe sposoby zapisu):
DDRB = DDRB | 0b00000100;
lub
DDRB = DDRB | 0x04;
lub
DDRB = DDRB | _BV(2);
lub
DDRB | = _BV(2);
gdzie makro _BV(x) jest liczbą, która ma jedną 1 binarną jedynkę na
pozycji x np. _BV(2) = 0b00000100
Konfiguracja linii portów -wejście
Linia 2 portu B jako wejście (przykładowe sposoby zapisu):
DDRB = DDRB & 0b11111011;
lub
DDRB = DDRB & 0xFB;
lub
DDRB = DDRB & ~_BV(2);
lub
DDRB & = ~_BV(2);
gdzie makro ~_BV(x) jest liczbą, która ma jedną 1 binarne zero na pozycji
x np. ~_BV(2) = 0b11111011
Konfiguracja linii portów 
przykład 1 (założenia)
Na linii 0 portu D umieszczono przycisk.
Na linii 0 portu B umieszczono diodÄ™.
Należy sprawdzać w sposób ciągły stan przycisku i odzwierciedlać
zapalaniem/gaszeniem diody.
Elementy programu:
- pętla wykonywana zawsze do {;} while(1);
- selekcja linii 0 za pomocÄ… iloczynu binarnego: PIND & 0x01
jest warunkiem wykonania rozkazu
Konfiguracja linii portów  przykład 1
int main(void)
{
DDRD &= ~_BV(0); //linia 0 portu D jako wejście
PORTD |= _BV(0); //podwieszenie wejścia
DDRB |= _BV(0); // linia 0 portu B jako wyjście
PORTB |=_BV(0); //wyjście w stanie high
do
{
if (PIND & 0x01) //sprawdz stan na linii 0 portu D
PORTB &= ~_BV(0); //wyjście w stanie low
else
PORTB |=_BV(0); //wyjście w stanie high
}
while(1);
return 0;
}
Konfiguracja linii portów  przykład 2
Na linii 0 portu D umieszczono przycisk.
Na linii 0 portu B umieszczono diodÄ™.
Należy sprawdzać w sposób ciągły stan przycisku i jego zwarcie zasygnalizować
trwałym świeceniem diody.
Elementy programu:
- selekcja linii 0 za pomocÄ… iloczynu binarnego: PIND & 0x01
- wyliczenie iloczynu logicznego (PIND & 0x01), który jest warunkiem
wykonania rozkazu
- wykorzystanie pętli while o logice:  dopóki nie zwarto przycisku czekaj
while (! (PIND & 0x01) );
Konfiguracja linii portów 
przykład 2 (założenia)
int main(void)
{
DDRD &= ~_BV(0); //linia 0 portu D jako wejście
PORTD |= _BV(0); //podwieszenie wejścia
DDRB |= _BV(0); // linia 0 portu B jako wyjście
PORTB |=_BV(0); //wyjście w stanie high
while (PIND & 0x01); //dopóki nie zwarto przycisku stój
PORTB &= ~_BV(0); //wyjście w stanie low
return 0;
}
Porty  przykład 3
Założenia: Wykorzystując pętlę do{;} while(1); mrugaj diodą 4 na porcie B
Szkic programu:
int main(void)
{
//konfiguracja linii diody
do
{ //zapal diodÄ™
//czekaj 500ms
//zgaÅ› diodÄ™
//czekaj 500ms
}
while(1);
}
Porty  przykład 4
Założenia: Wykorzystując pętlę for (i=0; & .) o 8 obejściach i operację obrotu zmiennej
(char a) w lewo zrób linijkę, w której (po każdym obejściu pętli for) przybywa 1 światełko.
Po 8-mym obejściu pętli palą się wszystkie diody, ponieważ zmienna obracana w lewo jest z
prawej uzupełniana zerami.
Szkic programu:
Int main(void)
{
char i, A=0xff;;
//konfiguracja linii 8-miu diod
PORTB = A; //zgaszenie wszystkich diod
for (i=0; & & & & & )
{
//czekaj 500ms
//obróć zmienną A o 1 pozycję w lewo
//wystaw liczbÄ™ A na PORTB
}
return 0;
}
Porty  przykład 5
Założenia: Wykorzystując pętlę for (i=0; & .) o 8 obejściach zrób linijkę z jednym
zapalonym, przemieszczającym się światełkiem.
W tym celu wykorzystaj zmiennÄ…  i oraz makro _BV(x).
Szkic programu:
Int main(void)
{
char i;
//konfiguracja linii 8-miu diod
for (i=0; & & & & & )
{
//czekaj 500ms
PORTB = & & & ..
}
return 0;
}
Zmodyfikuj działający program tak, aby zapalone światełko  chodziło bez końca.
Wektory przerwań
W najniższej części pamięci Flash są lokowane wektory przerwań
(wątków bocznych). Są to adresy procedur wykonywanych pod
warunkiem zaistnienia określonego zdarzenia (wewnętrznego lub
zewnętrznego).
Zaistnienie zdarzenia jest sygnalizowane ustawieniem binarnej flagi
przerwania.
Warunkiem wykonania procedury przerwania jest zdjęcie (w wątku
głównym) maski przerwania.
Wektory są ustawione w hierarchii pierwszeństwa  im niższy adres,
tym wyższa hierarchia. Najwyżej w hierarchii stoi wektor Reset, który
ma adres 0.
Wektory przerwań procesora
AT90S8515
Adres przerwania symbol przerwania yródło
przerwania
$000 RESET Spadek napięcia zasilania, impuls ujemny na linii RESET, układ watchdog
$001 INT0 Przerwanie zewnętrzne 0
$002 INT1 Przerwanie zewnętrzne 1
$003 TIMER1 CAPT TIMER 1 w trybie przechwytu
$004 TIMER1 COMPA TIMER 1 w trybie porównawczym z rejestrem A
$005 TIMER1 COMPB TIMER 1 w trybie porównawczym z rejestrem B
$006 TIMER1 OVF TIMER 1 w trybie przepełnienia
$007 TIMER0 OVF TIMER 0 w trybie przepełnienia
$008 SPI, STC ukończenie transmisji szeregowej SPI
$009 UART, RX zakończenie odbioru UART
$00A UART, UDRE pusty rejestr danych UART
$00B UART, TX zakończenie nadawania UART
$00C ANA_KOMP komparator analogowy
Przerwania zewnętrzne INT0, INT1
AT90S8515
Przerwania zewnętrzne INT0 i INT1 są wywoływane przez stan niski,
zbocze narastające lub zbocze opadające na określonych liniach
zewnętrznych mikrokontrolera. W mikrokontrolerze AT90S8515
przerwanie INT0 reaguje na stany na linii 2 portu D, a przerwanie INT1
na linii 3 portu D.
Przerwania zewnętrzne INT0 i INT1 wywoływane poziomem niskim nie
posiadają flag. W związku z tym, przerwania te są wywoływane tylko w
czasie rzeczywistym.
Bity konfigurujące zródło przerwania INT0 oraz INT1 znajdują się w
rejestrze kontrolnym MCUCR.
Przerwania zewnętrzne  wybór zródła
przerwania
Rejestr kontrolny - MCUCR
Bit 7 6 5 4 3 2 1 0
Nazwa SRE SRW SE SM ISC11 ISC10 ISC01 ISC00
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
ISC01 ISC00 yródło przerwania
0 0 Poziom niski na linii INT0
0 1 Zarezerwowane
1 0 Zbocze opadajÄ…ce na linii INT0
1 1 Zbocze narastajÄ…ce na linii INT0
ISC11 ISC10 yródło przerwania
0 0 Poziom niski na linii INT1
0 1 Zarezerwowane
1 0 Zbocze opadajÄ…ce na linii INT1
1 1 Zbocze narastajÄ…ce na linii INT1
Maska i flaga przerwania
zewnętrznego
Rejestr masek przerwań - GIMSK
Bit 7 6 5 4 3 2 1 0
Nazwa INT1 INT0 - - - - - -
Odczyt/zapis R/W R/W R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr flag przerwań - GIFR
Bit 7 6 5 4 3 2 1 0
Nazwa INTF1 INTF0 - - - - - -
Odczyt/zapis R/W R/W R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
Przerwania zewnętrzne  przykład
W programie głównym skonfigurowano linię 2 portu D, na której
umieszczono przycisk oraz linię 2 portu B, an której umieszczono diodę.
W rejestrze MCUCR wybrano zródło przerwania: poziom niski na linii
przycisku.
Zdjęto maskę przerwania i włączono przerwania, tym samym moduł
przerwań podjął ciągłą obserwację linii INT0 (2-ga linia portu D).
Gdy linia jest rozwarta wykonywana jest pętla główna programu, w której
dioda jest gaszona.
Gdy linia zostanie zwarta program wykonuje procedurÄ™ przerwania
ISR (INT0_vect), w której umieszczono rozkaz zapalenia diody.
Nazwa procedury przerwania jest zarejestrowania i można ją znalezć w
pliku z danymi procesora.
Przerwania zewnętrzne  przykład
ISR (INT0_vect) //procedura przerwania INT0
{ PORTB &= ~_BV(2); //zapalenie diody 2
}
int main(void) //procedura główna
{
DDRD &= ~_BV(2); //linia 2 portu D jako wejście
PORTD |= _BV(2); //podwieszenie wejścia
DDRB |= _BV(2); // linia 2 portu B jako wyjście
PORTB |=_BV(2); //wyjście high
MCUCR = 0x00; //przerwanie poziomem niskim
GIMSK = 0x40; //zdjęcie maski INT0
sei(); // Odblokowanie przerwań
do
{PORTB |= _BV(2); } //zgaszenie diody 2
while (1);
}
Przerwania zewnętrzne  polecenia
1. Wzorując się na przykładzie przygotuj projekt, w którym aktywne będą 2
przerwania zewnętrzne INT0 oraz INT1 (sprawdzające 2-gą i 3-cią linię portu D).
W odpowiedzi na naciśnięcie przycisków należy zapalać odpowiednio 2-gą i 3-cią
diodÄ™ na porcie B.
2. Zwróć uwagę, że w przykładzie na poprzedniej stronie na wszystkie 8 bitów
rejestru MCUCR wpisywane są stany 0 rozkazem MCUCR = 0x00. Zmień rozkaz
tak, zerowane były tylko 4 młodsze bity odpowiedzialne za konfigurację przerwań
zewnętrznych, natomiast 4 starsze odpowiedzialne za aktywację zewnętrznej
przestrzeni adresowej (w tym za prace LCD) pozostały bez zmian.
3. Podobnie w rejestrze masek ustaw tylko 2 najstarsze bity pozostawiając pozostałe
bez zmian.
Liczniki/timery
Moduły liczników/timerów są przeznaczone do zliczania impulsów
zegarowych mikrokontrolera lub impulsów na liniach zewnętrznych
mikrokontrolera.
Przy zliczaniu impulsów zegarowych można wykorzystać dzielnik
wstępny impulsów przez N (prescaler) tym samym wydłużając N-krotnie
zliczony czas.
W najprostszym trybie zliczanie następuje od 0 do 28 w przypadku timera
8-bitowego, oraz od 0 do 216 w przypadku timera 16-bitowego. Po
przepełnieniu rejestr liczący zapełnia się zerami, a timer zlicza nadal.
Timer 8-bitowy  prescaler
Rejestr kontrolny TIMER a 0  TCCR0
Bit 7 6 5 4 3 2 1 0
Nazwa - - - - - CS02 CS01 CS00
Odczyt/zapis R R R R R R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Prescaler TIMER a 0 [1]
CS02 CS01 CS00 Impulsy zliczane
0 0 0 Zatrzymanie TIMER a 0
0 0 1 CK
0 1 0 CK/8
0 1 1 CK/64
1 0 0 CK/256
1 0 1 CK/1024
1 1 0 Zbocza opadajÄ…ce na linii 0 portu B
1 1 1 Zbocza narastajÄ…ce na linii 0 portu B
Timer 8-bitowy  wybor prescalera
Rejestr kontrolny TIMER a 0  TCCR0
Bit 7 6 5 4 3 2 1 0
Nazwa - - - - - CS02 CS01 CS00
Odczyt/zapis R R R R R R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Przykład: wybór prescalera 1024
TCCR0 = 0b00000101;
TCCR0 = 0x05;
TCCR0 = (1<TCCR0 = _BV(CS02)|_BV(CS00);
Wyrażenia (1<binarną jedynkę na pozycji x.
Timer 8-bitowy  rejestry
Rejestr zliczania TIMER a 0  TCNT0
Bit 7 6 5 4 3 2 1 0
Nazwa MSB - - - - - - LSB
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr flagowy timerów  TIFR
Bit 7 6 5 4 3 2 1 0
Nazwa TOV1 OCF1A OCF1B - ICF1 - TOV0 -
Odczyt/zapis R/W R/W R/W R R/W R R/W R
Wartość początkowa 0 0 0 0 0 0 0 0
W rejestrze TCNT0 następuje zliczanie kroków od 0 do 256.
Ustawienie flagi TOV0 (bit 2) sygnalizuje przepełnienie. Po przepełnieniu
rejestr TCNT0 zapełnia się zerami, a timer kontynuuje zliczanie.
Timer 8-bitowy  maska przerwania
Zdjęcie maski TOIE0 (ustawienie bitu 2) włącza przerwanie wywołane
przepełnieniem Timera 0.
Po każdym przepełnieniu program główny pobiera adres procedury przerwania z
wektora przerwań i wykonuje procedurę przerwania (watek boczny), po czym
wraca do wątku głównego i kontynuuje jego wykonywanie.
Rejestr masek timerów  TIMSK
Bit 7 6 5 4 3 2 1 0
Nazwa TOIE1 OCIE1A OCIE1 - TICIE1 - TOIE0 -
Odczyt/zapis R/W R/W R/W R R/W R R/W R
Wartość początkowa 0 0 0 0 0 0 0 0
Timer 8-bitowy  obsługa programowa
Obsługa programowa polega na sprawdzaniu w pętli, czy ustawiła się flaga
sygnalizująca przepełnienie.
int main(void)
{
TCCR0 = (1<while (! (TIFR & (1<//flaga TOV0 stój
TIFR |=(1<TCCR0 = 0x00; //wyłącz timer
return 0;
}
Timer 8-bitowy  obsługa sprzętowa
Obsługa sprzętowa polega na zdjęciu maski i zleceniu modułowi timerów
sprawdzanie, czy doszło do przepełnienia oraz wykonanie procedury przerwania.
ISR (TIMER0_OVF_vect) //procedura przerwania
{
asm( nop ); //asemblerowy rozkaz pusty
}
int main(void)
{
TCCR0 = (1<TIMSK |= (1<sei(); //włączenie przerwań
do
{
asm( nop ); //asemblerowy rozkaz pusty
while(1); //nic nie rób czekaj na przerwania
return 0;
}
Timer 8-bitowy  zadania
1. Napisz program, który zlicza przerwania timera 0 (czyli zlicza, ile razy
licznik się  przekręcił ) i wartość tą pokazuje na 8-miu diodach.
2. Napisz program, który po kolejnych przerwaniach timera na przemian
zapala i gasi wybranÄ… diodÄ™.
Magistrala równoległa
Mikrokontroler może zaadresować 64 kbajty komórek w zewnętrznej
przestrzeni adresowej. Adresowanie odbywa się równolegle na 16-stu
liniach portów A (8 linii) oraz C (8 linii). Dane są przesyłane na 8 liniach
portu A. Podwójne wykorzystanie linii portu A (do adresowania i przesyłu
danych) jest możliwe dzięki zastosowaniu zatrzasku adresowego.
W układzie EVB-503 na magistrali równoległej podłączono pamięć
zewnętrzną RAM o pojemności 32kbajty.
Dwa z pozostałych wolnych adresów zostały wykorzystane do podłączenia
wyświetlacza LCD.
Podłączenie wyświetlacza LCD
W układzie EVB-503 wyświetlacz LCD został umieszczony w zewnętrznej
przestrzeni adresowej pod adresem ustalonym przez konfiguracjÄ™
wyprowadzeń dekodera adresowego. Dostęp do danych w tym układzie
znajduje się pod adresem $1F91, a dostęp do instrukcji sterujących
wyświetlaczem pod adresem $1F90.
W programie adresy te należy zdefiniować jako stałe typu wskaznikowego:
#define LCD_rozkaz (*(unsigned char *) (0x1F90))
#define LCD_dane (*(unsigned char *) (0x1F91))
Procedury wyświetlacza LCD
void LCD_rozkaz (int rozkaz) //rozkaz sterujÄ…cy
{
LCD_rozkaz = rozkaz;
_delay_ms(5);
}
void wyswietl_znak (char zn) //wyświetlenie danej
{
LCD_dane = zn;
_delay_ms(1);
}
void LCD_ini (void)
{
// wpisz rozkazy ze slajdu  Konfiguracja wyświetlacza LCD
}
int main(void) { return 0; }
Procedura sterowania wyświetlaczem
Pod adres przeznaczony do sterowania wyświetlaczem wpisz rozkaz sterujący
void LCD_rozkaz (int rozkaz)
{
LCD_rozkaz = rozkaz;
_delay_ms(5);
}
Procedura wyświetlenia znaku
Pod adres przeznaczony dla danych wyświetlanych (adres pamięci DDRAM
wyświetlacza) wpisz daną ASCII do wyświetlenia
void wyswietl_znak (char zn)
{
LCD_dane = zn;
_delay_ms(1);
}
Procedura inicjacji wyświetlacza
Procedura inicjacji wyświetlacza jest wykonywana tylko raz, na początku
programu głównego
void LCD_ini (void)
{
// wpisz rozkazy ze slajdu  Konfiguracja wyświetlacza LCD
}
Konfiguracja wyświetlacza LCD
Procedura konfiguracji wyświetlacza LCD składa się z następujących
rozkazów:
Aktywacja przestrzeni adresowej zewnętrznej
Opóznienie strobu (impulsu) zapisu np. o 1 cykl
Komenda trybu sterowania (8-mio bitowy - 0x38) wydana 3x
Komenda przesuwania napisu i kursora (bez zmiany zawartości DDRAM)
Komenda włączenia wyświetlacza
Komenda przesuwania napisu i kursora (ze zmianą zawartości DDRAM)
Komenda czyszczenia wyświetlacza
Komenda poczÄ…tkowego ustawienia kursora (adres DDRAM)
Dostęp do zewnętrznej przestrzeni
adresowej
Rejestr kontrolny  MCUCR (mikrokontroler AT90S8515)
Bit 7 6 5 4 3 2 1 0
Nazwa SRE SRW SE SM ISC11 ISC10 ISC01 ISC00
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Aktywacja zewnętrznej przestrzeni adresowej odbywa się
przez ustawienie bitu 7 (SRE) rejestru MCUCR.
Wymagane opóznienie impulsu zapisu/odczytu o 1 cykl maszynowy uzyskuje
siÄ™ przez ustawienie bitu 7 (SRW) rejestru MCUCR.
Komenda trybu sterowania
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 1 D/L N F * *
D/L liczba bitów danych interfejsu sterującego: D/L=1 interfejs 8-
bitowy, D/L=0 interfejs 4-bitowy,
N liczba wyświetlanych linii: N=1 dwie linie, N=0 jedna linia
F format znaku: F=1 znak 5×10 punktów, F=0 znak 5×7 punktów
* Wartość nieistotna
(czas wykonania komendy 5ms)
Komenda przesuwania napisu/kursora
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 0 1 S/C R/L * *
S/C S/C=1 przesuwanie napisu bez zmiany zawartości pamięci danych
DDRAM sterownika LCD, S/C=0 przesuwanie kursora bez zmiany
zawartości pamięci danych DDRAM sterownika LCD
(pamięć DDRAM przechowuje znaki wyświetlone na matrycy LCD),
R/L R/L=1 przesuwanie w prawo, R/L=0 przesuwanie w lewo
* Wartość nieważna
(czas wykonania komendy 120 us)
Komenda włączania wyświetlacza
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 0 0 1 D C B
D włącza/wyłącza wyświetlacz)
C włącza/wyłącza kursor
B włącza/wyłącza funkcję mrugania kursora
(czas wykonania komendy 120 us)
Komenda przesuwania napisu/kursora
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 0 0 0 1 I/D S
I/D ustala kierunek przesuwu kursora: I/D = 1 w prawo,
I/D = 0 w lewo
S włącza (S = 1) i wyłącza (S = 0) funkcję przesuwu napisu z
równoczesnym przesuwaniem znaków w pamięci danych DDRAM
sterownika
(czas wykonania komendy 120 us)
Komenda powrotu kursora
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 0 0 0 0 1 *
Ustawia kursor na pozycji poczÄ…tkowej (adres=0).
Jeśli napis był przesunięty, ustawia go w pozycji oryginalnej.
Pamięć danych DRRAM nie ulega zmianie.
(czas wykonania komendy 5ms)
Komenda czyszczenia wyświetlacza
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 0 0 0 0 0 0 0 1
Czyści wyświetlacz i ustawia kursor na adresie 0 pamięci danych DRAM.
Komenda ta jest używana tylko podczas konfiguracji wyświetlacza.
W trakcie pracy wyświetlacza znaki na LCD należy nadpisywać bez
czyszczenia.
(czas wykonania komendy 5ms)
Adres DDRAM-u
Bit 7 6 5 4 3 2 1 0
Nazwa/Wartość 1 DD DD DD DD DD DD DD
Ustawia adres pamięci danych DDRAM odpowiadający pozycji
znaku na wyświetlaczu.
Adres należy ustawić na 7-miu bitach oznaczonych DD
pozostawiając 1 na najstarszym bicie. Adresy 1-szej linii leżą w
zakresie od 0 do 63, a 2-giej linii od 64 do 127.
Na matrycach LCD o liczbie znaków mniejszej niż 64 dalsze znaki
każdej linii pozostaną niewidoczne.
(czas wykonania komendy 120 us)
Przykłady wyświetlania znaków
LCD_ini( ); //inicjuj wyświetlacz
LCD_steruj (128); //ustawia kursor w górnej linii na lewym skraju
pisz_znak (66); //wyświetla literę B
LCD_steruj (???); // kursor w górnej linii na prawym skraju
pisz_znak (???); //wyświetla cyfrę 2
LCD_steruj (???); //ustawia kursor w dolnej linii na lewym skraju
pisz_znak ( A ); // wyświetla literę A
LCD_steruj (???); // kursor w dolnej linii na prawym skraju
pisz_znak (0x33); // wyświetla cyfrę 3
Przykłady wyświetlania - polecenia
1. Wyświetl litery A, B, C w dolnej linii rozpoczynając od 3-
ciej pozycji.
2. Wyświetl w jednej linii tekst składający się z 50-ciu znaków
(większość z nich będzie niewidoczna). Następnie obracaj
powoli napis w lewo, aby można było zobaczyć wszystkie
znaki.
3. Napisz program, który zlicza przerwania timera 0 (czyli
zlicza, ile razy licznik się  przekręcił ) wyświetla liczbę
 przekręceń na LCD.
Zamiana liczby binarnej na ascii
Liczba  przekręceń timera 0 z poprzedniego
przykładu jest zapisana w rejestrze 8-
bitowym w postaci binarnej i przed
wyświetleniem na LCD wymaga zamiany na
ascii.
Tablica kodów ASCII
Znak Kod Znak Kod Znak Kod Znak Kod Znak Kod
32 ! 33 " 34 # 35 $ 36
% 37 & 38 ' 39 ( 40 ) 41
* 42 + 43 , 44 - 45 . 46
/ 47 0 48 1 49 2 50 3 51
4 52 5 53 6 54 7 55 8 56
9 57 : 58 ; 59 < 60 = 61
> 62 ? 63 @ 64 A 65 B 66
C 67 D 68 E 69 F 70 G 71
H 72 I 73 J 74 K 75 L 76
M 77 N 78 O 79 P 80 Q 81
R 82 S 83 T 84 U 85 V 86
W 87 X 88 Y 89 Z 90 [ 91
\ 92 ] 93 ^ 94 _ 95 ` 96
A 97 B 98 C 99 D 100 E 101
F 102 G 103 H 104 I 105 J 106
K 107 L 108 M 109 N 110 O 111
P 112 Q 113 R 114 S 115 T 116
U 117 V 118 W 119 X 120 Y 121
Z 122 { 123 | 124 } 125 ~ 126
Wskazniki do pamięci RAM i FLASH
Do zapisu i odczytu pamięci RAM wykorzystujemy typowe zmienne wskaznikowe języka C
char* str; //deklaracja wskaznika typu char w pamięci RAM
char zn; //deklaracja zmiennej typu char w pamięci RAM
zn = * (str); //pobranie znaku spod wskaznika str i przepisanie
//na zmiennÄ… zn
Do zapisu i odczytu pamięci FLASH środowisko ma zdefiniowany własny zestaw wskazników
i procedur zdefiniowanych w pliku nagłówkowym
#include
PGM_P str_P; //deklaracja wskaznika typu char w pamięci FLASH
char zn; //deklaracja zmiennej typu char w pamięci RAM
zn = pgm_read_byte(str_P); // pobranie znaku z pamięci FLASH spod wskaznika str_P
// i przepisanie go na zmienną zn w pamięci RAM
Procedury wyświetlania tekstów z
pamięci RAM i FLASH
Procedura pisz_string pobiera kolejne znaki spod wskaznika str do tablicy i wyświetla je na LCD
dopóki nie napotka na NULL
void pisz_string (char* str)
{ char zn;
while(0 != (zn = * (str++)))
pisz_znak(zn);
}
Procedura pisz_string_P pobiera kolejne znaki spod wskaznika str_P do pamięci FLASH
i wyświetla je na LCD dopóki nie napotka na NULL
void pisz_string_P (PGM_P str_P)
{ char zn;
while(0 != (zn = pgm_read_byte(str_P ++)))
pisz_znak(zn);
}
Deklaracje tablic w pamięciach RAM i
FLASH
//dane w pamięci RAM
char napis[ ] = "witaj!";
char tablica[ ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9};
char *str;
Dane przechowywane w pamięci FLASH muszą mieć charakter globalny
//dane w pamięci FLASH
const char napis_P[ ] PROGMEM=  hello!";
char tablica_P[ ] PROGMEM= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3};
PGM_P str_P;
Przykłady wyświetlania tekstów
RAM FLASH
pisz_znak(tablica[5]); str_P= & tablica_P[5];
char zn;
zn = pgm_read_byte (str_P);
pisz_znak(zn);
pisz_string(napis); pisz_string_P(napis_P);
pisz_string_P(PSTR( Hurra ! ));
pisz_string("HaHa ! ");
Pamięć EEPROM  rejestr adresowy
Elektrycznie programowalna, nieulotna pamięć EEPROM mikrokontrolera
AT90S8515 ma 512 bajtów adresowanych od 0 do 511.
Adres zapisu/odczytu danej należy umieścić w 16-sto bitowym rejestrze
EEAR (EEARH+EEARL).
Rejestr adresowy pamięci EEPROM - EEAR (część starsza  EEARH, część młodsza EEARL)
Bit 15 14 13 12 11 10 9 8
Nazwa MSB
Nazwa LSB
7 6 5 4 3 2 1 0
Odczyt/zapis R R R R R R R R/W
R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Pamięć EEPROM  rejestr danych
Daną przeznaczoną dla pamięci EEPROM należy wstawić do rejestru EEDR.
Zapisanie jednego bajtu w pamięci EEPROM trwa od 2.5  4ms.
W procesie odczytu dana spod adresu umieszczonego w rejestrze EEAR jest
przepisywana do rejestru EEDR. Odczyt jednego bajtu trwa 4 cykle zegarowe.
Rejestr danych pamięci EEPROM  EEDR
Bit 7 6 5 4 3 2 1 0
Nazwa MSB LSB
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Pamięć EEPROM - procedury
Dla zapisania i odczytania pamięci EEPROM najlepiej posłużyć się gotowymi procedurami
zawartymi w pliku nagłówkowym eeprom.h.
W pliku eeprom.h można zapoznać się z deklaracjami procedur dla EEPROM-u:
void eeprom_write_word (unsigned int *adres, unsigned int *dana);
unsigned int eeprom_read_word (unsigned int *adres);
Przykład wykorzystania w programie:
#include
unsignad int *l;
eeprom_write_word (l+8, 'b');
eeprom_busy_wait();
char c;
c= eeprom_read_word (l+8);
pisz_znak(c);
Samodzielne tworzenie procedur dla EEPROM-u jest nieskuteczne ze względu na wymagania
czasowe (kolejność impulsów musi następować z dokładnością do 4 cykli zegarowych) 
język C nie daje możliwości takiego panowania nad czasem.
Przetwornik analogowo-cyfrowy
Ćwiczenie jest wykonywane na mikrokontrolerze ATMega8, który jest
wyposażony w 8-mio kanałowy przetwornik analogowo-cyfrowy o
rozdzielczości 10-cio bitowej wyprowadzony na 8 linii portu C. Kanały
można skonfigurować jako niesymetryczne lub symetryczne (różnicowe).
Kanałom różnicowym można przyporządkować określone wartości
wzmocnienia. Typowa częstotliwość przetwarzania mieści się między 50 a
200kHz.
Rejestr konfiguracji przetwornika
Rejestr konfiguracji przetwornika ADC  ADMUX
Bit 7 6 5 4 3 2 1 0
Nazwa REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
REFS1, REFS0  wybór zakresu przetwarzania
ADLAR  bit decydujący o sposobie wyrównania wyniku konwersji w rejestrze ADC
(ADCH+ADCL), gdy ADLAR = 0 wyrównanie do prawej, gdy ADLAR = 1
wyrównanie do lewej
MUX4  MUX0  wybór kombinacji wejść analogowych podłączonych do
przetwornika oraz wzmocnień dla tych wejść. Dla MUX4  MUX0 = 0 wybrane jest
wejście niesymetryczne 0 na porcie F ze wzmocnieniem równym 1
Zakres przetwarzania
Napięcie odniesienia dla przetwornika
REFS1 REFS0 Napięcie odniesienia
0 0 Zewnętrzne zródło podłączone do pinu AREF
0 1 Wewnętrzne 5V z kondensatorem podłączonym na pinie AREF
1 0 zarezerwowane
1 1 Wewnętrzne 2.56V z kondensatorem podłączonym do pinu AREF
Zakres napięcia przetwarzanego może być podawany wewnętrznie lub zewnętrznie
na pin AREF. Przy wyborze zródła wewnętrznego minimalne napięcie
przetwarzania wynosi 0V, a maksymalne 5V-1LSB lub 2.56V-1LSB.
Rozdzielczość przetwarzania jest 10-bitowa.
Wyrównanie wyniku konwersji w
rejestrze danych
Rejestr danych ADCH i ADCL (dla bitu ADLAR = 0)
Bit 15 14 13 12 11 10 9 8
ADCH - - - - - - ADC9 ADC8
ADCL ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0
Bit 7 6 5 4 3 2 1 0
Odczyt/zapis R R R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr danych ADCH i ADCL (dla bitu ADLAR = 1)
Bit 15 14 13 12 11 10 9 8
ADCH ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2
ADCL ADC1 ADC0 - - - - - -
Bit 7 6 5 4 3 2 1 0
Odczyt/zapis R R R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr statusowy przetwornika
Rejestr statusowy przetwornika ADC  ADCSR
Bit 7 6 5 4 3 2 1 0
Nazwa ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
ADEN  włączenie przetwornika
ADSC  rozpoczęcie przetwarzania ADC. Konwersja trwa 14 cykli zegara przetwornika,
przy czym 1-sza konwersja po włączeniu przetwornika trwa 25 cykli zegara
przetwornika.
ADFR - włączenie ciągłego przetwarzania, rejestr wyniku przetwarzania jest
aktualizowany w sposób ciągły
ADIF  flaga sygnalizująca zakończenie pojedynczego przetwarzania
ADIE  maska przerwania przetwornika
ADPS2, ADPS1, ADPS0  preskaler zegara przetwornika, im większy współczynnik
preskalera tym powolniejszy zegar przetwornika i dokładniejszy wynik konwersji
Czas konwersji
Czas konwersji jest wyrażony w cyklach zegara przetwornika
Warunki Czas uśredniania Czas konwersji
(w cyklach zegara (w cyklach zegara
przetwornika) przetwornika)
1-sza konwersja 14.5 25
Konwersja na wejściu 1.5 13
niesymetrycznym
Konwersja na wejściu 1.5/2.5 13/14
różnicowym
Prescaler zegara przetwornika
ADPS2 ADPS1 ADPS0 Współczynnik
podziału
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
Założenia programowe
% wejście niesymetryczne 0-we przetwornika (linia 0 portu C) - wybór
wejścia 0 wymaga wyzerowania bitów MUX4-MUX0 w rejestrze
ADMUX,
% zakres przetwarzania 5V-owy ze zródłem wewnętrznym,
% przetwarzanie ciągłe - ustawiony bit ADFR w rejestrze ADCSR,
% ograniczenie rozdzielczości do 8-mio bitowej (wyrównanie do lewej na
bicie ADLAR i odczyt wyłącznie starszej części rejestru ADC),
% uśrednianie wyniku przetwarzania co 5 pomiarów,
% Wyrażenie wyniku pomiaru w mV (wynik pomiaru wyrażony w mV
leży w zakresie 0  5000mV i musi być przechowany na zmiennej int
% Wyrażenie wyniku pomiaru w kodzie ASCII
% Wysłanie w UART poszczególnych cyfr wyniku pomiaru w ASCII
Uzupełnienie programu main
int main (void)
{
int wynik;
% Skonfiguruj rejestry ADMUX i ADCSR wg założeń
% Skonfiguruj interfejs UART (9600, 8n1)
do
{
for (wykonaj 5 razy)
{
% Poczekaj na zakończenie przetwarzania (sygnalizacja flagą ADIF),
% Odczytaj wynik przetwarzania
}
% Uśrednij wynik przetwarzania z 5-ciu pomiarów,
% Uśredniony wynik przetwarzania wyraz w mV (pomnoż przez krok przetwornika),
% Uśredniony wynik przetwarzania w mV przekształć na kod ASCII
% Wyślij w UART kolejne cyfry ASCII wyniku pomiaru (wzoruj się na slajdzie 89)
}
while (1);
return 0;
}
Bin_to_ASCII
Założenie: liczba jest typu int MAX 216 = 65536
(wynik pomiaru wyrażony w mV leży w zakresie 0  5000mV) .
Przekształcenie liczby binarnej na kod ASCII należy wykonać w
następującego wzoru:
% Oblicz kolumnę dziesiątek tysięcy:
dz_tys = liczba/10000;
% Oblicz kolumnę tysięcy (procent oznacza resztę z dzielenia):
tys = (liczba%10000)/1000;
% Oblicz resztÄ™ z dzielenia przez tysiÄ…c:
reszta = (liczba%10000)%1000;
% & & & & & & & & ..kontunuuj
Transmisja szeregowa UART
Moduł UART (Universal Asynchronous Receiver and Transmiter) obsługuje
dupleksową, asynchroniczna transmisję danych między procesorem a
urządzeniem zewnętrznym.
Dane są nadawane (i odbierane) w formacie start-stopowym tzn., każdy znak
składa się z:
1 bitu startu: logiczne 0
8 lub 9 bitów danych
1 bitu stopu: logiczna 1.
9-ty bit danych może zostać wykorzystany jako bit parzystości lub jako
dodatkowy bit stopu.
Transmisja szeregowa UART  rejestr
danych
Rejestr danych transmisji UART  UDR
Bit 7 6 5 4 3 2 1 0
Nazwa MSB LSB
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
Rejestr danych jest wykorzystywany do nadawania i odbioru danych.
Fizycznie istniejÄ… 2 rejestry danych (transmisja jest dupleksowa), ale
występują pod ta samą nazwą.
Transmisja szeregowa UART  rejestr
danych
Rejestr statusowy UART  USR
Bit 7 6 5 4 3 2 1 0
Nazwa RXC TXC UDRE FE OR - - -
Odczyt/zapis R R/W R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
RXC  flaga zakończenia odbioru znaku
TXC  flaga zakończenia nadawania znaku
UDRE  flaga pustego bufora nadawczego (bufor mieści 2 znaki)
FE  flaga błędu synchronizacji ramki
OR  flaga nadpisania znaku
Transmisja szeregowa UART 
rejestr kontrolny
Rejestr kontrolny UART  UCR
Bit 7 6 5 4 3 2 1 0
Nazwa RXCIE TXCIE UDRIE RXEN TXEN CHR9 RXB8 TXB8
Odczyt/zapis R/W R/W R/W R/W R/W R/W R W
Wartość początkowa 0 0 0 0 0 0 1 0
RXCIE  maska przerwania odbiorczego
TXCIE  maska przerwania nadawczego
UDRIE  maska przerwania pustego bufora nadawczego
RXEN  włączenie odbiornika
TXEN  włączenie nadajnika
CHR9  włączenie transmisji 9-tego bitu
RXB8  9-ty bit odebrany
TXB8  9-ty bit gotowy do nadania
Transmisja szeregowa UART 
prędkość transmisji
Rejestr prędkości transmisji UART  UBRR
Bit 7 6 5 4 3 2 1 0
Nazwa MSB - - - - - - LSB
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
fCK
BAUD =
16(UBRR +1)
BAUD  prędkość w bitach/sek typowe wartości: 1200, 2400, 4800, 9600, 19200
fck  częstotliwość zegara mikrokontrolera
UBRR  wartość obliczona, którą po zaokrągleniu należy wstawić do rejestru UBRR
Transmisja szeregowa UART 
nadawanie z obserwacjÄ… flagi
Program główny:
//konfiguracja interfejsu UART
UBRR =38; //ustalenie prędkości transmisji
UCR = (1<//wysłanie liczby ASCII a
UDR =  a ;
while(! (USR & (1<USR |= (1<//wysłanie  b
UDR =  b ;
while(! (USR & (1<USR |= (1< Transmisja szeregowa UART 
przykład nadawania z przerwaniem
W programie głównym dokonuje się konfiguracji parametrów transmisji, odblokowania przerwań
i wysłania 1-szego znaku. Kolejne znaki są wysyłane, gdy moduł przerwań zgłosi zakończenie
wysyłania poprzedniego znaku.
//zmienna globalna
char a;
procedura przerwania:
ISR (UART_TX_vect)
{UDR = a++; } //wysłanie kolejnej liczby
program główny:
UBRR =38; //ustalenie prędkości transmisji
UCR = (1<a =  a ;
UDR = a; //wysłanie liczby ASCII a
sei(); //włączenie przerwań
while (1) ; //nic więcej nie rób
Transmisja szeregowa UART 
odbiór z obserwacją flagi
Program główny:
//konfiguracja interfejsu UART
UBRR =& .; //ustalenie prędkości transmisji
UCR = (& ..); //włączenie odbiornika
do
{
while(! (USR & (& ..))); //oczekiwanie na ustawienie flagi
& & & & & .. //odbiór z rejestru UDR
& & & & & & //wyświetlenie znaku na LCD
}
while(1);
Transmisja szeregowa UART 
przykład odbioru z przerwaniem
W programie głównym dokonuje się konfiguracji parametrów transmisji i odblokowania przerwań
Kolejne znaki są odbierane i wyświetlane na LCD, gdy moduł przerwań zgłosi zakończenie
odbioru znaku.
procedura przerwania:
ISR (& & & & & ..)
{//odbiór znaku
//wyświetlenie znaku}
program główny:
//inicjacja LCD
UBRR =38; //ustalenie prędkości transmisji
UCR = (& & ..) | (& & ..); //włączenie odbiornika , zdjęcie maski odbiorczej
sei(); //włączenie przerwań
while (1) ; //nic więcej nie rób
Magistrala 1-wire
Magistrala 1-wire składa się z pojedynczej linii. Na magistrali 1-wire
jedno urządzenie MASTER nadzoruje pracę jednego lub wielu urządzeń
SLAVE. Urządzenie MASTER oraz wszystkie SLAVE są podłączone
do magistrali wyjściem tranzystora  otwarty dren lub bramką
trójstanową. Takie podłączenie umożliwia  zwolnienie linii przez
każde z urządzeń po zakończeniu transmisji. Magistrala 1-wire wymaga
zewnętrznego rezystora podciągającego do zasilania o wartości około
5k&!. Stanem bezczynnym magistrali jest stan wysoki.
Impuls Resetu i obecności
Każdy transfer po magistrali rozpoczyna się od impulsu Resetu nadawanego przez
urządzenie MASTER i impulsu obecności, który jest odpowiedzią urządzenia SLAVE. W
czasie impulsu Resetu MASTER zwiera magistralÄ™ do masy na czas co najmniej 480 µs.
Po tym czasie MASTER zwalnia magistralę, która wskutek podciągnięcia rezystorem 5k
przechodzi w stan wysoki. SLAVE dokonuje detekcji zbocza narastajÄ…cego, czeka 15  60
µs, po czym nadaje impuls obecnoÅ›ci zwierajÄ…c magistralÄ™ do masy na czas 60 240 µs.
Impuls Resetu i obecności
Mikrokontrolery nie posiadajÄ… interfejsu do magistrali 1-wire. W zwiÄ…zku z tym magistralÄ™ 1-wire
można umieścić na dowolnej linii mikrokontrolera np. 5 linia portu B.
Wówczas na liniach portu D można umieścić 8 diod pomocniczych w uruchamianiu programu.
Definicja impulsu resetu zawiera opis kształtu impulsu przedstawiony na rysunku
(w przykładzie pomijamy odczyt impulsu obecności)
void reset (void)
{
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
//odczekaj 5us
//magistrala w stan niski
//odczekaj 500us
//magistrala w stan wysoki
//odczekaj 500us  pomijamy odczyt impulsu obecności
}
Impuls Resetu i obecności
W tym rozwiniętym przykładzie MASTER nadaje impuls reset i odczytuje impuls obecności
void reset (void)
{
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
//odczekaj 5us  czas nie restrykcyjny
//magistrala w stan niski
//odczekaj 500us
//magistrala w stan wysoki
//odczekaj 60us
//magistrala jako wejście
//podwieszenie wejścia (magistrali) pod zasilanie (wewnetrzne)
//odczyt stanu magistrali
//if( stan magistrali == HIGH)
//SLAVE nieobecny (wyświetl tekst)
//else
// SLAVE obecny (wyświetl tekst)
//odczekaj 500us
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
}
Ramka nadawcza
Stany logiczne: 0 i 1 są nadawane w ramkach czasowych. Każda ramka
czasowa trwa co najmniej 60 µs, z odstÄ™pem miÄ™dzy ramkami co najmniej 1µs.
Rysunek przedstawia ramki obu stanów logicznych  obie ramki rozpoczynają
siÄ™ od zbocza opadajÄ…cego.
Impulsy stanów logicznych
Definicja impulsu stanu logicznego  0 (lewa połowa rysunku z poprzedniego slajdu)
void impuls0 (void)
{
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
//odczekaj 5us
//magistrala w stan niski
//odczekaj 80us
//magistrala w stan wysoki
//odczekaj 10us
}
Definicja impulsu stanu logicznego  1 (prawa połowa rysunku z poprzedniego slajdu)
void impuls1 (void)
{//do samodzielnego wypełnienia wg. rysunku
}
Procedura nadania 1 bajtu
Bajt nadajemy bit po bicie rozpoczynając od najmłodszego bitu, czyli przez
obrót bajtu w prawo
void nadaj (char A)
{
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
for (& & & ..) //8 obrotów pętli dla 8-miu bitów
{
if (selekcja najmłodszego bitu zmiennej A) //sprawdzenie wartości najmłodszego bitu
) impuls1(); //impuls logicznej
else
impuls0(); //impuls logicznego 0
}
A=A>>1; //obrót bajtu w prawo
}
Ramka odbiorcza
MASTER generuje zbocze opadajÄ…ce i podtrzymuje stan niski co najmniej przez 1 µs,
po czym zwalnia magistralę, która wskutek powieszenia przechodzi w stan wysoki.
Teraz SLAVE może zewrzeć magistralę do masy (gdy nadaje logiczne 0 ) lub pozostawić
jÄ… w stanie wysokim (gdy nadaje logicznÄ… 1). MASTER odczytuje stan magistrali przed
upÅ‚ywem 15 µs od rozpoczÄ™cia ramki.
Procedura odbioru 1 bajtu
Bajt odbieramy bit po bicie wsuwajÄ…c bity przychodzÄ…ce po magistrali na najstarszÄ… (7-mÄ…)
pozycjÄ™ zmiennej B i obracajÄ…c zmiennÄ… B w prawo
char odbierz (void)
{
for ( & & & & .) //8 obrotów pętli dla 8-miu bitów
{
B=B>>1; //obrót bajtu w prawo
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
//5us
//magistrala 1-wire w stan niski
//5us
//magistrala 1-wire jako input
//magistrala 1-wire podwieszona do zasilania (wewnętrznie)
//10us
if (& & & & .) //odczyt stanu magistrali
B |= 0b10000000; //odebrano stan 1
else
& & & & & . //odebrano stan 0
}
//magistrala 1-wire jako output
//magistrala 1-wire w stan wysoki
}
Termometr cyfrowy DS18B20
Układ DS18B20 zawiera czujnik temperatury i przetwornik A/C o rozdzielczości
12-sto bitowej, co odpowiada pomiarowi temperatury z krokiem 0.0625°C.
Pamięć układu DS18B20 składa się z 8-miu rejestrów, temperatura jest
zapisywana na dwóch pierwszych rejestrach: 0-wy rejestr zawiera młodszy bajt
pomiaru temperatury, 1-szy rejestr zawiera starszy bajt pomiaru temperatury.
Podczas transmisji na magistrali dane są nadawane począwszy od najmłodszego
bitu.
Rejestr 0-wy jest wysyłany przez DS18B20 jako pierwszy.
Sesja komunikacyjna po magistrali
1-wire z termometrem DS18B20
TRYB DANE KOMENTARZ
URZDZENIA (NAMAODSZY BIT
MASTER JAKO 1-SZY)
TX Impuls resetu Master generuje impuls resetu
RX Impuls obecności DS18B20 odpowiada impulsem obecności
TX $CC Master wydaje rozkaz pominięcia odczytu
pamięci ROM
TX $44 Master wydaje rozkaz pomiaru temperatury
TX Podciągnięcie linii Master utrzymuje magistralę w stanie wysokim
czas pomiaru = 1000ms
TX Impuls resetu Master generuje impuls resetu
RX Impuls obecności DS18B20 odpowiada impulsem obecności
TX $CC Master wydaje rozkaz pominięcia odczytu
pamięci ROM
TX $BE Master wydaje rozkaz odczytu pamięci RAM
urzÄ…dzenia
RX Odczyt 2-ch słów Master odczytuje wynik pomiaru temperatury
Uzupełnienie programu main
W programie głównym należy:
% skonfigurować linię magistrali 1-wire (kierunek linii: output, stan linii: high),
% skonfigurować 8 diod na porcie D (kierunek linii: output stan linii: high),
% w nieskończonej pętli wywoływać procedury 1-wire wg. kolejności pokazanej w tabeli na
poprzednim slajdzie
int main (void)
{
& & & & & ..//konfiguracje
do
{
& & & & .//procedury z tabeli
//odbierz bajt LS
//odbierz bajt MS
//wyświetl bajt LS na diodach
}
while (1);
return 0;
}
Rejestr temperatury
Rejestr temperatury (LS byte)
Bit 7 6 5 4 3 2 1 0
Nazwa 23 22 21 20 2-1 2-2 2-3 2-4
Rejestr temperatury (MS byte)
Bit 15 14 13 12 11 10 9 8
Nazwa S S S S S 26 25 24
S  bity znaku
Wynik pomiaru temperatury na LCD
Wynik pomiaru temperatury w rozdzielczości 12-sto bitowej odbieramy od termometru
w 2-ch bajtach LS i MS.
W celu ułatwienia zadania rozdzielność należy ograniczyć do 8-mio bitowej
(1-stopniowej).
W tym celu bajt LS należy obrócić o 4 pozycje binarne w prawo, aby usunąć bity:
2-4, 2-3, 2-2, 2-1.
Bajt MS również należy obrócić, po czym zsumować je binarnie, aby w bajcie
wynikowym uzyskać następujący układ bitów:
0 26 25 24 23 22 21 20
Bajt wynikowy zawiera temperaturę w zapisie binarnym o rozdzielczości 8-bitowej.
Bajt ten należy przetworzyć na kod ascii, a następnie wyświetlić na LCD.
Zadania do wykonania
1. Stwórz procedury
1. Resetu i obecności
2. Impulsu logicznej 1
3. Impulsu logicznego 0
4. Zapisu bajtu (8-miu bitów)
5. Odczytu bajtu (8-miu bitów)
2. Przy wykorzystaniu procedur napisz program główny do pomiaru temperatury w
nieskończonej pętli
Dla uproszczenia można pominąć:
Impuls obecności,
Bit znaku, zakładając że temperatura jest dodatnia
Bity wyniku o rozdzielczości większej niż 8 (wynik można wówczas zapisać na
1 bajcie)
Magistrala SPI
Magistrala SPI składa się z linii:
% MOSI Master output Slave input
% MISO Master input Slave Output
% SCK Clock
% SS Slave select (CS  Chip Select lub CE  Chip Enable)
Sygnał taktujący transmisję SCK oraz sygnał wyboru urządzenia Slave
jest zawsze wystawiany przez urzÄ…dzenie Master.
Linie MOSI i MISO są wspólne dla wszystkich urządzeń na magistrali,
linia SS jest prowadzona do każdego Slave oddzielnie.
Magistrala SPI
Transmisja po magistrali jest dookólna  każdemu nadawaniu po linii
MOSI towarzyszy odbiór po linii MISO. Nie wszystkie transfery niosą
informacje, niekiedy mogą być nadawanie dane  puste np. same zera.
Fazowanie magistrali SPI
Faza sygnału taktującego definiuje zależność pomiędzy zboczami sygnału
taktującego , a momentami odbioru (próbkowania) danych wejściowych i
nadawania (przesuwania w rejestrze) danych wyjściowych.
% CPHA=0 pierwsze zbocze sygnału taktującego próbkuje dane
wejściowe, drugie zbocze przesuwa dane w rejestrze (dane są próbkowane, a
następnie przesuwane i wysyłane)
% CPHA=1 pierwsze zbocze sygnału taktującego przesuwa dane w
rejestrze  wyprowadza je z rejestru, drugie zbocze próbkuje dane wejściowe
(dane są przesuwane i wysyłane, a następnie próbkowane i wpisywane do
rejestru)
Polaryzacja i fazowanie przebiegów na magistrali dla bitu CPHA =0
i różnych wartości bitu CPOL.
Fazowanie magistrali SPI
Polaryzacja i fazowanie przebiegów na magistrali dla bitu CPHA =1
i różnych wartości bitu CPOL.
Tryby pracy interfejsu SPI
Wartości bitów CPOL i CPHA decydują o wyborze jednego z 4-ch trybów pracy interfejsu
SPI, oznaczonych jako 0, 1, 2 lub 3.
W zakresie polaryzacji i fazowania urządzenie Master musi się dostosować do
wymagań Slave podanych w nocie katalogowej tego urządzenia.
Zegar czasu rzeczywistego DS1305 pracuje w trybie 1.
Tryby pracy interfejsu SPI [1]
Zbocze narastajÄ…ce Zbocze opadajÄ…ce Tryb pracy SPI
CPOL = 0, CPHA = 0 Próbkowanie Zmiana danych 0
CPOL = 0, CPHA = 1 Zmiana danych Próbkowanie 1
CPOL = 1, CPHA = 0 Zmiana danych Próbkowanie 2
CPOL = 1, CPHA = 1 Próbkowanie Zmiana danych 3
Rejestry interfejsu SPI
Rejestr kontrolny interfejsu SPI - SPCR
Bit 7 6 5 4 3 2 1 0
Nazwa SPIE SPE DODR MSTR CPOL CPHA SPR1 SPR0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa 0 0 0 0 0 0 0 0
% Bit 7  SPIE: maska przerwania interfejsu SPI
% Bit 6  SPE: włączenie interfejsu
% Bit 5  DODR: kolejność przesyłu danych: 0  MSB pierwszy, 1  LSB pierwszy
% Bit 4  MSTR: wybór trybu master/slave
% Bit 3  CPOL: wybór polaryzacji sygnału taktującego
% Bit 2  CPHA: wybór fazy próbkowania
% Bit 1  SPR1, bit 0  SPR0: wybór częstotliwości taktującej (patrz tabela)
Wybór częstotliwości taktującej
Należy wybrać dzielnik między częstotliwością interfejsu SPI, a zegarem
systemowym.
Rejestry interfejsu SPI
Rejestr statusowy interfejsu SPI - SPSR
Bit 7 6 5 4 3 2 1 0
Nazwa SPIF WCOL - - - - - -
Odczyt/zapis R R R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
% Bit 7  SPIF: flaga zakończenia transferu 1-go bajtu danych
% Bit 6  WCOL: flaga kolizji
Rejestry interfejsu SPI
Rejestr danych interfejsu SPI - SPDR
Bit 7 6 5 4 3 2 1 0
Nazwa MSB - - - - - - LSB
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
Wartość początkowa X X X X X X X X
Służy do bajtów danych między jednostką CPU a interfejsem SPI.
Interfejs mikrokontrolera
Interfejs SPI mikrokontrolera AT90S8515 leży na liniach:
% MOSI PORTB, 5
% MISO PORTB, 6
% SCK PORTB, 7
Linie SS oraz wejście alarmu budzika nie należą do interfejsu i można
je połączyć dowolnie np. tak, jak proponuje tabela.
Połączenie linii zegara DS1305 i linii mikrokontrolera wyprowadzonych na złącze AUX3
płytki EVB-503 [5]
Linie zegara DS1305 Linie złącza AUX3 (połączone z Linie
liniami zegara DS1305) mikro-
kontrolera
CE  linia wyboru Chip Enable ER (SS) Chip Select (Slave Select) PORTB, 4
SDI  wejście danych Serial Data Input SI (MOSI) Master Output Slave Input PORTB, 5
SDO  wyjście danych Serial Data Output SO (MISO)  Master Input Slave Output PORTB, 6
SCLK  linia taktujÄ…ca Serial Lock SCK  Serial Lock PORTB, 7
INT0  linia przerwania Interrupt 0 /IR (INT0)  Interrupt 0 PORTD, 2
Rejestry zegara DS1305
Rejestry czasu i daty
Adres
Zakres
szesnastkowy Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
(BCD)
Odczyt Zapis
$00 $80 0 dziesiÄ…tki sekund sekundy 00-59
$01 $81 0 dziesiÄ…tki minut minuty 00-59
P 01-12 +
12
dziesiÄ…tki
godziny P/A
$02 $82 0
A
godzin
24 10tki 00-23
$03 $83 0 0 0 0 dni tygodnia 1-7
dziesiÄ…tki dni
$04 $84 0 0 dni miesiÄ…ca 1-31
miesiÄ…ca
DziesiÄ…tki
$05 $85 0 0 MiesiÄ…ce 01-12
miesięcy
$06 $86 dziesiÄ…tki lat Lata 00-99
Tryb 24h  bit 6 =0, tryb 12h  bit 6=1,
Dla trybu 12h: P  po południu (bit 5 =1), A  przed południem (bit5 = 0)
Rejestry zegara DS1305
Rejestry alarmów
Adres Zakres
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
szesnastkowy (BCD)
ALARM 0
$07 $87 M* 10 sekund alarmu sekundy alarmu 00-59
$08 $88 M 10 minut alarmu minuty alarmu 00-59
P*
01-
12
10-tki
12+P/A
$09 $89 M godzina alarmu
A*
godzin
24 10tki 00-23
$0A $8A M 0 0 0 dzień alarmu 01-07
ALARM 1
$0B $8B M 10 sekund alarmu sekundy alarmu 00-59
$0C $8C M 10 minut alarmu minuty alarmu 00-59
P
01-
12
10-tki
12+P/A
$0D $8D M godzina alarmu
A
godzin
24 10tki 00-23
$0E $8E M 0 0 0 dzień alarmu 01-07
* M  bit maski, P  po południu, A  przed południem
Rejestry zegara DS1305
Rejestry specjalne
Adres
Zakres
szesnastkowy
(BCD)
Odczyt Zapis
$0F $8F Rejestr kontrolny -
$10 $90 Rejestr statusowy -
$11 $91 Rejestr układu ładującego baterię -
$12  $92 
Zarezerwowane -
$1F $9F
$20  $A0 
96 bajtów pamięci RAM 00-FF
$7F $FF
BCD_to_ASCII
W rejestrach zegara dane są zapisywane w formacie BCD (tj. cyfra na każdym
półbajcie). Jest to zapis identyczny z szesnastkowym, ale tylko w zakresie cyfr
od 0 do 9.
Etapy przetwarzania BCD to ASCII:
% Wydzielenie półbajtów liczby 8-bitowej
% Obrót starszego pół-bajtu o 4 pozycje binarne w prawo
% Dodanie wartości 48 do każdego pół-bajtu
char st, ml, a;
st = a & & & & & ; //wydzielenie 4-ch starszych bitów (cyfra BCD)
st = st >>4; //cyfra w postaci BIN
st = st +48; //zamiana BIN to ASCII
ml = a & & & & & .. // wydzielenie 4-ch młodszych bitów (cyfra BCD)
& & & & & & .. //zamiana BIN to ASCII
Rejestry zegara DS1305
Rejestr kontrolny  adres odczytu $0F, adres zapisu $8F
Bit 7 6 5 4 3 2 1 0
Nazwa EOSC WP 0 0 0 INTCN AIE1 AIE0
Odczyt/zapis R/W R/W R/W R/W R/W R/W R/W R/W
% Bit 7  EOSC: włączenie/wyłączenie oscylatora
Wyzerowanie bitu EOSC rozpoczyna pracÄ™ oscylatora. Ustawienie bitu EOSC
zatrzymuje pracę oscylatora i DS1305 wchodzi w tryb pracy energooszczędnej.
% Bit 6  WP: zabezpieczenie przed nieuprawnionym zapisem
Przed każdą operacją zapisu do rejestru zegara lub RAM-u bit WP musi zostać
wyzerowany. Ustawiony w stan logicznej 1 bit WP zapobiega operacji zapisania do
rejestrów, w tym również na pozycje 1, 2 i 7 rejestru kontrolnego. Po resecie stan bitu
WP jest nieustalony, dlatego przed operacją zapisu bit WP musi zostać wyzerowany.
% Bit 2  INTCN: bit kontrolny przerwania alarmu
Gdy INTCN=1 działa alarm 0 (sygnalizacja stanem niskim na linii INT0) oraz alarm 1
(sygnalizacja stanem niskim na linii INT1), gdy INTCN=0 działa tylko alarm 0
% Bit 1  AIE1: maska alarmu 1
% Bit 0  AIE0: maska alarmu 0
Rejestry zegara DS1305
Rejestr statusowy  adres odczytu $10
Bit 7 6 5 4 3 2 1 0
Nazwa 0 0 0 0 0 0 IRQF1 IRQF0
Odczyt/zapis R R R R R R R R
Wartość początkowa 0 0 0 0 0 0 0 0
% Bit 1  IRQF1: flaga przerwania 1
Flaga IRQF1 sygnalizujÄ…ca alarm 1
% Bit 0  IRQF0: flaga przerwania 0
Flaga IRQF0 sygnalizujÄ…ca alarm 0
Transfer po magistrali  zapis słowa
Stanem bezczynnym linii wyboru (CE lub SS lub CS) jest logiczne 0 i taką wartością
należy wysterować tę linie po resecie urządzenia.
Master rozpoczyna transfer danych od wybrania urzÄ…dzenia Slave (podniesienie linii
wyboru (CE lub SS lub CS) w stan logicznej 1.
Następnie Master generuje 16 impulsów zegarowych. W takt 1-szych 8-miu impulsów
Master wysyła na magistrale adres rejestru zegara, dla którego są przeznaczone dane.
W takt kolejnych 8-miu impulsów zegara Master wysyła na magistrale 8-mio bitowa daną
dla rejestru zegara.
Transfer kończy się wyzerowaniem linii wyboru.
Transfer po magistrali  odczyt słowa
Master rozpoczyna transfer danych od wybrania urzÄ…dzenia Slave (podniesienie linii
wyboru (CE lub SS lub CS) w stan logicznej 1.
Następnie Master generuje 16 impulsów zegarowych. W takt 1-szych 8-miu impulsów
Master wysyła na magistrale adres rejestru zegara, od którego będzie czytał dane.
W takt kolejnych 8-miu impulsów zegara Slave nadaje, a Master odbiera 8-mio bitową
danÄ… z rejestru zegara.
Transfer kończy się wyzerowaniem linii wyboru.
Transfer po magistrali  procedura
Ze względu na dookólną transmisję po magistrali jedna procedura obsługuje równocześnie
nadawanie i odbiór. Procedura pobiera 1 bajt (typ char) oraz zwraca bajt odczytany.
Jeśli celem jest zapis ważny jest bajt pobierany przez procedurę (można zaniechać
odczytu). Jeśli celem jest odczyt ważny jest bajt zwracany przez procedurę (bajt pobierany
może przenosić same zera). Rozróżnienie między zapisem a odczytem następuje na
najstarszym bicie adresu.
char transfer (char adres, char dana)
{
char odebrany;
//ustaw liniÄ™ wyboru urzÄ…dzenia Slave
//podaj do rejestru danych interfejsu adres rejestru zegara
//poczekaj, aż interfejs skończy transfer adresu (sygnalizacja flagą SPIF)
//podaj do rejestru danych interfejsu danÄ… do zapisania w rejestrze zegara
//poczekaj, aż interfejs skończy transfer danej (sygnalizacja flagą SPIF)
//wyzeruj liniÄ™ wyboru
//odbierz danÄ… z rejestru danych interfejsu
return odebrany;
}
Program main  wersja podstawowa
W programie głównym należy:
% skonfigurować linię wyboru (kierunek linii: output, stan linii: low),
% linie interfejsu (MOSI i SCK: output/high, MISO input/podwieszony)
% skonfigurować 8 diod na porcie D (kierunek linii: output stan linii: high),
% skonfigurować rejestr kontrolny interfejsu SPI SPCR,
% skonfigurować rejestr kontrolny zegara (zapisywany pod adresem $8F)
% w nieskończonej pętli odczytywać rejestr sekund i wyświetlać stan rejestru na diodach
int main (void)
{
& & & & & ..//konfiguracje
do
{
//odczyt rejestru sekund
//wyświetlenie stanu rejestru na diodach
}
while (1);
return 0;
}
Konfiguracja interfejsu SPI
Bity konfiguracji interfejsu znajdują się w rejestrze SPCR. Należy:
% Włączyć interfejs,
% Wybrać tryb MASTER,
% Wybrać prędkość po magistrali SPI.
Kierunek przesyłu danych oraz fazowanie i polaryzacja musza być zgodne z wymaganiami
urządzenia SLAVE na magistrali. Zegar DS1305 wymaga następujących ustawień:
% Kierunek przesyłu danych: od MSB do LSB,
% Tryb pracy magistrali: 1.
int main (void)
{
% Konfiguracje linii portów
% Konfiguracja rejestru SPCR
% Konfiguracja rejestru kontrolnego zegara DS05
do {& & & .} while (1);
return 0;
}
Rozwinięcie programu main -1
Wyświetlenie daty i czasu
int main (void)
{
& & & & & ..//konfiguracje w tym inicjacja LCD
do
{
//odczyt rejestru minut
//przetworzenie danej BCD to ASCII
//wyświetlenie na LCD
//odczyt rejestru sekund
//przetworzenie danej BCD to ASCII
//wyświetlenie na LCD
}
while (1);
return 0;
}
Rozwinięcie programu main - 2
Wymuszenie wartości początkowych rejestrów daty i czasu
Wstaw wartości początkowe do rejestrów zegara.
Zegar powinien startować od aktualnej daty i czasu.
int main (void)
{
& & & & & ..//konfiguracje
//zapis wartości początkowej do rejestru lat (procedura pobiera daną w BCD)
//zapis wartości początkowej do rejestru& & & & & & & ..
do
{
//odczyt rejestru & & & & .
//przetworzenie danej BCD to ASCII
//wyświetlenie na LCD
}
while (1);
return 0;
}
ASCII_to_BCD
W rejestrach zegara dane są zapisywane w formacie BCD (tj. cyfra na każdym półbajcie).
Jest to zapis identyczny z szesnastkowym, ale tylko w zakresie cyfr od 0 do 9.
Z każdych 2-ch cyfr w kodzie ASCII można utworzyć 1-ną cyfrę w kodzie BCD.
Etapy przetwarzania ASCII to BCD:
% Odjęcie 48 odpowiednio od 2-ch cyfr ASCII
% Obrót bitów jednej z cyfr o 4 pozycje binarne w lewo
% Dodanie binarne cyfr
Zamiast odejmować 48 można binarnie wyzerować starszy półbajt cyfry w zapisie ASCII,
ponieważ wszystkie niezerowe bity liczby 48 leżą na starszym półbajcie.
48 = 0b00110000
Rozwinięcie programu main - 3
Wartości początkowe w kodzie ASCII
Napisz procedurę asciitobcd(), która dane pobiera liczby w kodzie ASCII, zamienia na BCD
i zapisuje rejestrach zegara.
char asciitobcd (char dzies, char jedn)
{
char danabcd;
& & & & .....
return danabcd;
}
int main (void)
{
& & & & & .
danax = asciitobcd (& & & & .);
transfer (adres, danax);
& & & & & & & & & & & .
do {& & & & & ..} while (1);
return 0;
}
Magistrala I2C
Magistrala I2C składa się z dwóch linii:
% linią SCL przesyłane są impulsy zegarowe synchronizujące transmisję,
% linia SDA transmituje dane w dwóch kierunkach.
Stanem  idle (bezczynnym) obu linii jest stan wysoki.
Przebieg zegarowy jest generowany przez urzÄ…dzenie MASTER magistrali.
Adresowanie na magistrali I2C
Master adresuje urządzenie Slave na magistrali podając programowo dwie części jego
adresu:
% adres software owy urządzenia Slave a identyfikujący typ urządzenia np. pamięć
% adres sprzętowy Slave a  ustawiony na liniach adresowych urządzenia, adres
sprzętowy daje możliwość rozróżnienia kilku urządzeń Slave jednakowego typu
podłączonych na magistrali np. jednakowych pamięci
Stabilność i zmiana danych
Dane na magistrali sÄ… stabilne w stanie wysokim impulsu zegarowego.
Dane sÄ… zmieniane przez urzÄ…dzenie nadajÄ…ce w stanie niskim impulsu zegarowego.
Sekwencja startu i stopu
SekwencjÄ… startu jest zbocze opadajÄ…ce na linii danych SDA nadane w stanie wysokim
linii zegarowej SCL.
SekwencjÄ… stopu jest zbocze narastajÄ…ce na linii danych SDA nadane w stanie wysokim
linii zegarowej SCL.
Transmisja bajtu danych
Dane sÄ… nadawane w jednostkach 8-mio bitowych (bajtach).
Urządzenie odbierające, po odebraniu 8-miu bitów danej na linii SDA, przełącza
siÄ™ na nadawanie i w czasie 9-tego impulsu zegarowego nadaje na linii SDA
impuls ujemny w roli potwierdzenia odebrania bajtu danych.
Urządzenie nadające, po nadaniu 8-miu bitów danej na linii SDA, przełącza się
na odbiór i w czasie 9-tego impulsu zegarowego sprawdza, czy na linii SDA
pojawił się ujemny impuls potwierdzający.
Pamięć EEPROM AT24CXX - wyprowadzenia
Linia Funkcja
wyprowadzenia Linii
A0-A2 Wejścia adresowe
SCL Wejście zegarowe
SDA Linia danych
WP Zabezpieczenie przed
nieuprawnionym zapisem
Pamięć EEPROM AT24CXX  linie adresowe
Liczba pamięci jednego typu możliwa do podłączenia w systemie
Typ pamięci Linie adresowe Liczba pamięci
jednego typu w
systemie
AT24C01 A2, A1, A0 8
AT24C02 A2, A1, A0 8
AT24C04 A2, A1 4
AT24C08 A2 2
AT24C16 Brak 1
Pamięć EEPROM AT24CXX  stronicowanie
Układ danych w pamięciach AT24CXX
Typ pamięci Liczba stron Liczba bajtów Długość słowa
pamięci na stronę adresowego w
bitach
AT24C01 16 8 7
AT24C02 32 8 8
AT24C04 32 16 9
AT24C08 64 16 10
AT24C16 128 16 11
Pamięć EEPROM AT24CXX  adresowanie
komórki pamięci
Bity adresowe komórki pamięci są rozłożone w dwóch sąsiednich bajtach adresowych:
% najstarsze bity P2, P1, P0 są składową adresu urządzenia
% bity pozostałe są zapisywane w adresie danej
Adresowanie komórki pamięci
Typ pamięci Słowo Długość adresu
adresu [bitów]
AT24C01 *XXXXXXX 7
AT24C02 XXXXXXXX 8
AT24C04 P0XXXXXXXX 9
AT24C08 P1P0XXXXXXXX 10
AT24C16 P2P1P0XXXXXXXX 11
Pamięć EEPROM AT24CXX  adres urządzenia
Składowe adresu urządzenia:
% 4-ro bitowy adres rodziny urządzeń (bity 7-4) dla rodziny pamięci EEPROM:1010
% adres sprzętowy A2, A1, A0 (bity 3-1)
% starsze bity adresu strony (lub komórki) pamięci P2, P1, P0 (bity 3-1),
% tryb (1: Read / 0: Write).
Bit 7 6 5 4 3 2 1 0
AT24C01/02 1 0 1 0 A2 A1 A0 R/W
AT24C04 1 0 1 0 A2 A1 P0 R/W
AT24C08 1 0 1 0 A2 P1 P0 R/W
AT24C16 1 0 1 0 P2 P1 P0 R/W
Zapis pojedynczego bajtu danych
Nadanie bajtu danych po magistrali przebiega w następującej kolejności:
% nadanie sekwencji startu
% nadanie adresu urzÄ…dzenia w trybie do zapisu (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% nadanie adresu danej (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% nadanie danej (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% nadanie sekwencji stopu.
Podany adres powinien wskazywać na komórkę pamięci. Dana zostanie zapisana w
pamięci. Czas zapisu wewnętrznego  około 10ms.
Zapis strony danych
Nadanie strony danych po magistrali przebiega identycznie jak nadanie
pojedynczego bajtu z tym, że po 1-szym bajcie danych można jeszcze nadać nie
więcej niż stronę danych odbierając potwierdzenie po każdym bajcie. Proces kończy
siÄ™ nadaniem sekwencji stopu.
Nadanie liczby bajtów większej niż strona spowoduje zawinięcie się adresu i
nadpisanie poczÄ…tku tej samej strony.
W trybie nadawczym adres jest inkrementowany automatycznie modulo wielkość
strony.
Odbiór bajtu danych z podaniem adresu
Odbiór pojedynczego bajtu danych po magistrali przebiega w następującej kolejności:
% nadanie sekwencji startu
% nadanie adresu urzÄ…dzenia w trybie do zapisu (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% nadanie adresu danej (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% powtórne nadanie sekwencji startu
% nadanie adresu urzÄ…dzenia w trybie do odczytu (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% odebranie danej (1 bajt),
% przeczekanie 9-tego impulsu (nie nadajemy ujemnego impulsu potwierdzenia)
% nadanie sekwencji stopu.
Odbiór bajtu danych spod adresu domyślnego
Jeśli adres komórki pamięci został ustawiony w toku poprzedniej łączności, to w
kolejno realizowanym odczycie można pominąć ustawienie adresu komórki pamięci.
Wówczas odbiór pojedynczego bajtu danych przebiega w następującej kolejności:
% nadanie sekwencji startu
% nadanie adresu urzÄ…dzenia w trybie do odczytu (1 bajt),
% odebranie potwierdzenia (1 bit  impuls ujemny),
% odebranie danej (1 bajt),
% przeczekanie 9-tego impulsu (nie nadajemy ujemnego impulsu potwierdzenia)
% nadanie sekwencji stopu.
Odczyt dowolnej liczby bajtów danych
Odbiór wielu bajtów przebiega identycznie jak odbiór pojedynczego bajtu z tym, że po
odebraniu 1-szego bajtu należy potwierdzić odbiór impulsem ujemnym na 9-tym
impulsie zegarowym, po czym można jeszcze odebrać dowolną liczbę bajtów
potwierdzając odbiór każdego. Nie potwierdza się tylko odbioru ostatniego bajtu 
zamiast tego należy nadać sekwencję stopu.
Po dojściu do adresu końcowego adres zawinie się automatycznie i rozpocznie się
odczyt pamięci od początku. W trybie odbiorczym adres jest automatycznie
inkrementowany modulo rozmiar pamięci.
Definicje
Programowa obsługa magistrali I2C wymaga napisania odpowiednich procedur
komunikacyjnych. Dla ułatwienia i przejrzystości proste procesy dobrze jest zamknąć
w definicjach (makrach)
Zdefiniuj zmienne i wyrażenia
#define SDA 2
#define SCL 3
/#define ustawbit(port,bit) (port |= (1</#define wyzerujbit(port,bit) (port &= ~(1< Kształtowanie impulsu
Kształtując programowo impuls zegarowy między kolejnymi stanami na linii SCL
należy wstawić opóznienie, które będzie decydować o prędkości transmisji po
magistrali. Dla opóznienia 5us otrzymamy prędkość: 4 opóznienia w procedurze
imp_SCL = 20us / odwrotność 50kHz.
void imp_SCL()
{
_delay_us(5);
wyzerujbit (PORTB, SCL);
_delay_us(5);
ustawbit (PORTB, SCL);
_delay_us(5);
wyzerujbit (PORTB, SCL);
_delay_us(5);
}
Procedura startu i stopu
void I2C_start(void) void I2C_stop(void)
{ {
_delay_us(5); _delay_us(5);
ustawbit (PORTB, SDA); wyzerujbit (PORTB, SDA);
ustawbit (PORTB, SCL); wyzerujbit (PORTB, SCL);
_delay_us(5); _delay_us(5);
wyzerujbit(& & ); ustawbit(& & );
_delay_us(5); _delay_us(5);
wyzerujbit(& ..); ustawbit(& ..);
_delay_us(5); _delay_us(5);
} }
Nadawanie bajtu na magistralÄ™
W pętli o ośmiu obejściach należy:
% nadawać na linię danych SDA bity pobranego słowa od MSB do LSB
(bajt musi być obracany w lewo),
% każdemu bitowi musi towarzyszyć 1 impuls zegarowy (przejście low/high/low na linii SCL)
Wartość bitu na linii danych SDA:
% musi być stabilna w stanie wysokim impulsu zegarowego na linii SCL,
% będzie programowo zmieniana w stanie niskim impulsu zegarowego na linii SCL.
Po nadaniu 8-miu bitów danej:
% zmień kierunek na linii SDA na odbiór (input podwieszony)
% w stanie wysokim 9-tego impulsu zegarowego odczytaj impuls potwierdzenia z linii SDA
% stosownie ustaw/wyzeruj zmiennÄ… globalnÄ…  blad
% wyzeruj liniÄ™ zegarowÄ… SCL
% zmień kierunek na linii SDA na nadawanie (output high)
Procedura nadawania bajtu
void I2C_nadajbajt (char data)
{
//upewnij się, że linia SCL startuje od stanu output low
for ( i=0; i<8; i++)
{
//wyślij najstarszy bit zmiennej data na linię SDA
//nadaj 1 impuls zegarowy dodatni na liniÄ™ SCL (low/high/low)
//obróć zmienną data w lewo
}
//zmień kierunek na linii SDA na INPUT podwieszony
//ustaw liniÄ™ zegarowÄ… w stan high (9-ty impuls) + delay
if (odczytaj liniÄ™ danych SDA)
{blad = 1;}
else
{blad = 0;}
//wyzeruj liniÄ™ zegarowa SCL + delay
//ustaw liniÄ™ danych SDA w stan output high
}
Odbiór bajtu z magistrali
Zmień kierunek na linii danych na input i podwieś linie programowo pod zasilanie.
W pętli o ośmiu obejściach w stanie wysokim impulsu SCL:
% Odbierz z linii danych SDA bit słowa wsuwając bit z prawej z obrotem bajtu w lewo
% każdemu bitowi musi towarzyszyć 1 impuls zegarowy (przejście low/high/low na linii SCL),
przy czym odbiór następuje w stanie high impulsu zegarowego
Po nadaniu 8-miu bitów danej:
% zmień kierunek na linii SDA na output
% jeśli chcesz potwierdzić odbiór bajtu wysteruj linię SDA stanem low, w przeciwnym wypadku
wysteruj liniÄ™ SDA stanem high
% podaj 9-ty impuls zegarowy na liniÄ™ SCL (low/high/low  w stanie high impulsu dane na linii
SDA będą stabilne)
Procedura odbioru bajtu
Procedurę należy przygotować w 2-ch wariantach: z potwierdzeniem na 9-tym impulsie
zegarowym i bez potwierdzenia.
char I2C_odbierzbajt_ack (void) // char I2C_odbierzbajt_noack (void)
{
//kierunek linii danych SDA input, linia podwieszona pod zasilanie
for (i=0; i<8; i++)
{
odb=odb<<1;
//linia zegarowa w stan wysoki + delay
if (odczyt linii danych SDA)
//zapis na najmłodszą pozycję zmiennej odb;
else
//zapis na najmłodsza pozycję zmiennej odb;
//linia SCL w stan niski + delay
}
//kierunek linii danych SDA output,
//sterowanie liniÄ… SDA: high  brak potwierdzenia + delay, low  potwierdzenie + delay
//impuls na linii SCL (9-ty impuls: low/high/low)
return odb;
}
Program main  nadawanie i odbiór 1-go bajtu
int main (void)
{
//konfiguracje: linie SDA i SCL kierunek output stan high
//inicjacja LCD
//Postępuj wg slajdu 144:
// - Nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do zapisu + odczytaj potwierdzenie
// - Nadaj adres danej (wybierz komórkę pamięci) + odczytaj potwierdzenie
// - Nadaj danÄ… (liczba ascii) + odczytaj potwierdzenie
// - Nadaj sekwencjÄ™ stopu
// Odczekaj 20ms (zapis wewnętrzny)
//Postępuj wg slajdu 146:
// - Nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do zapisu + odczytaj potwierdzenie
// - Nadaj adres danej (wybierz komórkę pamięci) + odczytaj potwierdzenie
// - Ponownie nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do odczytu + odczytaj potwierdzenie
// - Odbierz daną z komórki pamięci + nie nadawaj potwierdzenia na 9-tym impulsie
// - Nadaj sekwencjÄ™ stopu
//Odebraną daną wyświetl na LCD
Nadawanie i odbiór strony danych
int main (void)
{
//& & & & & & & & & //konfiguracje
//Postępuj wg slajdu 146:
// - Nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do zapisu + odczytaj potwierdzenie
// - Nadaj adres danej (wybierz początek strony pamięci) + odczytaj potwierdzenie
// - Nadaj danÄ… (liczba ascii) + odczytaj potwierdzenie
// - Nadawaj kolejne dane do końca strony + odczytuj potwierdzenia
// - Nadaj sekwencjÄ™ stopu
// Odczekaj 20ms (zapis wewnętrzny)
//Postępuj wg slajdu 148:
// - Nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do zapisu + odczytaj potwierdzenie
// - Nadaj adres danej (wybierz początek strony pamięci) + odczytaj potwierdzenie
// - Ponownie nadaj sekwencjÄ™ startowÄ…
// - Nadaj adres urzÄ…dzenia w trybie do odczytu + odczytaj potwierdzenie
// - Odbierz daną z komórki pamięci + nadaj potwierdzenie na 9-tym impulsie
// - Odbieraj kolejne dane do końca strony, potwierdzaj wszystkie za wyjątkiem ostatniej
// - Nadaj sekwencjÄ™ stopu
// Odebrane dane umieszczaj kolejno w tablicy
// Wyświetl na LCD dane z tablicy


Wyszukiwarka

Podobne podstrony:
6 Programowanie mikroprocesorów laboratorium
4 Programowanie mikroprocesorów laboratorium
6 Programowanie mikroprocesorów laboratorium
2 Programowanie mikroprocesorów laboratorium
3 Programowanie mikroprocesorów laboratorium
Cwiczenie nr 02 Sprzet i technika pracy laboratoryjnej
5 Programowanie mikroprocesorów laboratorium
1g zastosowania techniki mikroprocesorowej
7 Zastosowanie techniki mikroprocesorowej II
Technika mikroprocesorowa test
Technika mikroprocesorowa
7 Technika mikroprocesorowa test
Podzial na grupy Technika Mikroprocesorowa ?zNazwy1
Materiałoznawstwo i Techniki Wytwarzania Plan Laboratoriów

więcej podobnych podstron