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
Wyprowadzenia 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 wskaźnikowy. 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<<bit5) spowoduje ustawienie bitu 5 w zmiennej A Operacja A & = ~(1<<bit5) spowoduje wyzerowanie bitu 5 zmiennej A Operacja A &= (1<<bit5) spowoduje wyzerowanie wszystkich bitów za 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<<bit5) ) = = 0) ; //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 for for ( i=1; i<11; i++) { Rozkaz; } switch (zmienna) { case 1: //gdy zmienna = 1 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<<bit5))); 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 źródłowym napisanym w języku C.h opcjonalnie pliki nagłówkowe z deklaracjami, definicjami i wybranymi procedurami kodu źró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 <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> //biblioteka procesora //biblioteka przerwań //procedury z opóźnieniem czasowym Następnie umieszcza się definicje potrzebnych procedur/funkcji 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 znaleźć w pliku procesora. Przykładowy program main wywołuje procedurę funkcja 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. Biblioteka delay.h zawiera funkcje: _delay_us (x);_delay_ms (x);
Kolejność procedur Jeśli w programie umieścimy (oprócz definicji) również deklaracje procedur, to kolejność procedur jest nieistotna i wszystkie procedury widzą się wzajemnie. Deklaracja przykładowej procedury (funkcji): char funkcja (int); W prostym programie można pominąć deklaracje procedur, jednak należy wówczas zadbać o takie uporządkowanie procedur, aby procedura (funkcja) umieszczona niżej odwoływała się wyłącznie do procedur umieszczonych nad nią. W takim układzie procedura main musi być ostatnia.
Struktura prostego programu bez deklaracji funkcji char funkcja (int m) { char k; k=m+1; return k; } ISR (INT0_vect ) { _delay_us (50); _delay_ms (10); } //definicja funkcji //definicja procedury przerwania int main (void) { char t; t= funkcja (20); //wywołanie funkcji return 0: }
Struktura programu z deklaracjami funkcji char funkcja (int); ISR (INT0_vect ) { _delay_us (50); _delay_ms (10); } //deklaracja funkcji //definicja procedury przerwania int main (void) { char t; t= funkcja (20); //wywołanie funkcji return 0: } char funkcja (int m) { char k; k=m+1; return k; } //definicja funkcji
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 <pliklcd.h>
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); PORTD = _BV(0); DDRB = _BV(0); PORTB =_BV(0); //linia 0 portu D jako wejście //podwieszenie wejścia // linia 0 portu B jako wyjście //wyjście w stanie high do { } while(1); return 0; } if (PIND & 0x01) PORTB &= ~_BV(0); else PORTB =_BV(0); //sprawdź stan na linii 0 portu D //wyjście w stanie low //wyjście w stanie high
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); PORTD = _BV(0); DDRB = _BV(0); PORTB =_BV(0); //linia 0 portu D jako wejście //podwieszenie wejścia // linia 0 portu B jako wyjście //wyjście w stanie high while (PIND & 0x01); PORTB &= ~_BV(0); return 0; } //dopóki nie zwarto przycisku stój //wyjście w stanie low
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; for (i=0; ) { } return 0; } //zgaszenie wszystkich diod //czekaj 500ms //obróć zmienną A o 1 pozycję w lewo //wystaw liczbę A na PORTB
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 Źró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 źródło przerwania INT0 oraz INT1 znajdują się w rejestrze kontrolnym MCUCR.
Przerwania zewnętrzne wybór źró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 Źró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 Źró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 założenia przykładu 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 źró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ą znaleźć 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 2 8 w przypadku Timera 8-bitowego, oraz od 0 do 2 16 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 wybór 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<<CS02) (1<<CS00); TCCR0 = _BV(CS02) _BV(CS00); Wyrażenia (1<<x) oraz _BV(x) są identycznymi liczbami, które mają jedną 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<<CS00); //włącz Timer, prescaler = 1 while (! (TIFR & (1<<TOV0))); //dopóki nie ustawi się //flaga TOV0 stój TIFR =(1<<TOV0); //wyzeruj flagę 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) { asm( nop ); } //procedura przerwania //asemblerowy rozkaz pusty int main(void) { TCCR0 = (1<<CS00); //włącz Timer, prescaler = 1 TIMSK = (1<<TOIE0); //zdejmij maskę TOIE0 sei(); //włączenie przerwań do { asm( nop ); //asemblerowy rozkaz pusty while(1); //nic nie rób czekaj na przerwania return 0; }
Timer 8-bitowy polecenia 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 wskaźnikowego: #define LCD_rozkaz (*(unsigned char *) (0x1F90)) #define LCD_dane (*(unsigned char *) (0x1F91))
Procedury wyświetlacza LCD Do sterowania wyświetlaczem należy zdefiniować 3 procedury (funkcje): void LCD_sterowanie (int rozkaz) przesyła rozkaz pod adres 0x1F90, gdzie jest on interpretowany przez sterownik LCD jako rozkaz sterujący (przestaw kursor, przesuń napis itd..) void wyswietl_znak (int zn) przesyła rozkaz pod adres 0x1F91, gdzie jest on interpretowany przez sterownik LCD jako dana dla DDRAM-u (DATA RAM) i zostanie wyświetlony na LCD od pozycji bieżącej kursora. Sterownik LCD zapewnia automatyczną post-inkrementację pozycji na LCD, dlatego przy wyświetlaniu ciągu znaków ustala się pozycję tylko 1- szego znaku w ciągu void LCD_ini (void) zestaw komend aktywujących wyświetlacz wg wymagań sterownika HD44780
Zestaw procedur wyświetlacza LCD void LCD_steruj (int rozkaz) { LCD_rozkaz = rozkaz; _delay_ms(5); } void wyswietl_znak (char zn) { LCD_dane = zn; _delay_ms(1); } //rozkaz sterujący //wyświetlenie danej void LCD_ini (void) { // wpisz rozkazy ze slajdu Konfiguracja wyświetlacza LCD } int main(void) { return 0; }
Konfiguracja wyświetlacza LCD Procedura konfiguracji/aktywacji wyświetlacza LCD składa się z następujących rozkazów: Włączenie interfejsu przestrzeni adresowej zewnętrznej bit SRE Opóźnienie strobu (impulsu) zapisu np. o 1 cykl bit SRW 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)
Aktywacja wyświetlacza LCD Przykładowa procedura aktywacji wyświetlacza LCD: void LCD_ini (void) { MCUCR = (1<<SRE) (1<<SRW); LCD_steruj(0b00111000); LCD_steruj(0b00111000); LCD_steruj(0b00111000); LCD_steruj(0b00011000); LCD_steruj(0b00001100); LCD_steruj(0b00000110); LCD_steruj(0b00000001); LCD_steruj(0b10000000); }
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óźnienie 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 F liczba wyświetlanych linii: N=1 dwie linie, N=0 jedna linia 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 bez zmiany zawartości DDRAM-u Bit 7 6 5 4 3 2 1 0 Nazwa/Wartość 0 0 0 1 S/C R/L * * S/C R/L 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=1 przesuwanie w prawo, R/L=0 przesuwanie w lewo * Wartość nieistotna (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 ze zmianą zawartości DDRAM-u Bit 7 6 5 4 3 2 1 0 Nazwa/Wartość 0 0 0 0 0 1 I/D S I/D S ustala kierunek przesuwu kursora: I/D = 1 w prawo, I/D = 0 w lewo 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)
Komenda ustawiania adresu 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 wyswietl_znak (66); //wyświetla literę B LCD_steruj (???); // kursor w górnej linii na prawym skraju wyswietl_znak (???); //wyświetla cyfrę 2 LCD_steruj (???); //ustawia kursor w dolnej linii na lewym skraju wyswietl_znak ( A ); // wyświetla literę A LCD_steruj (???); // kursor w dolnej linii na prawym skraju wyswietl_znak (0x33); // wyświetla cyfrę 3
Wyświetlanie znaków - 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 30-ciu znaków (większość z nich będzie niewidoczna). Następnie obracaj powoli napis w lewo, aby można było zobaczyć ukryte znaki. Uwaga! Nie zmieniaj rozkazów w funkcji LCD_ini. Obrót rozpocznij po wyświetleniu napisu. 1. Napisz program, który zlicza przerwania Timera 0 i wyświetla na LCD liczbę przepełnień Timera (liczba przepełnień jest zapisana w rejestrze Timera w postaci binarnej i przed wyświetleniem 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
Wskaźniki do pamięci RAM i FLASH Do zapisu i odczytu pamięci RAM wykorzystujemy typowe zmienne wskaźnikowe języka C char* str; char zn; zn = * (str); //deklaracja wskaźnika typu char w pamięci RAM //deklaracja zmiennej typu char w pamięci RAM //pobranie znaku spod wskaźnika str i przepisanie //na zmienną zn Do zapisu i odczytu pamięci FLASH środowisko ma zdefiniowany własny zestaw wskaźników i procedur zdefiniowanych w pliku nagłówkowym #include <avr/pgmspace.h> PGM_P str_p; char zn; zn = pgm_read_byte(str_p); //deklaracja wskaźnika typu char w pamięci FLASH //deklaracja zmiennej typu char w pamięci RAM // pobranie znaku z pamięci FLASH spod wskaźnika 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 wskaźnika 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++))) wyswietl_znak(zn); } Procedura pisz_string_p pobiera kolejne znaki spod wskaźnika 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 ++))) wyswietl_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 z pamięci RAM i FLASH RAM wyswietl_znak(tablica[5]); pisz_string(napis); pisz_string("haha! "); FLASH str_p= & tablica_p[5]; char zn; zn = pgm_read_byte (str_p); wyswietl_znak(zn); pisz_string_p(napis_p); pisz_string_p(pstr( Hurra! ));
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 Odczyt/zapis 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 R/W Wartość początkowa R/W 0 R/W 0 R/W 0 R/W 0 R/W 0 R/W 0 R/W 0 R/W 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 <avr/eeprom.h> unsignad int *l; eeprom_write_word (l+8, 'b'); eeprom_busy_wait(); char c; c= eeprom_read_word (l+8); wyswietl_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 źró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 źró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 (w cyklach zegara przetwornika) Czas konwersji (w cyklach zegara przetwornika) 1-sza konwersja 14.5 25 Konwersja na wejściu niesymetrycznym Konwersja na wejściu różnicowym 1.5 13 1.5/2.5 13/14
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 programu przetwarzania A/C 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 źró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
Szkic programu przetwarzania A/C 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 wyraź 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 } while (1); return 0; }
Zamiana zapisu binarnego na ASCII Założenie: liczba jest typu int MAX 2 16 = 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
Arduino Uno board
Memories: Flash memory 32kB SRAM 2kB EEPROM 1kB
ISP programming
The bootloader is basically a.hex file that runs when you turn on the board. It is very similar to the BIOS that runs on your PC. It does two things. First, it looks around to see if the computer is trying to program it. If it is, it grabs the program from the computer and uploads it into the ICs memory (in a specific location so as not to overwrite the bootloader). That is why when you try to upload code, the Arduino IDE resets the chip. This basically turns the IC off and back on again so the bootloader can start running again. If the computer isn t trying to upload code, it tells the chip to run the code that s already stored in memory. Once it locates and runs your program, the Arduino continuously loops through the program and does so as long as the board has power.
USART Interface and USART connection to PC COM MAX 232 converts signals from an RS-232 serial port to signals suitable for use in TTL Asynchronous transmission
USART to USB adapter
The Uno differs from all preceding boards in that it does not use the FTDI USB-toserial driver chip. Instead, it features the Atmega16U2 (Atmega8U2 up to version R2) programmed as a USB-to-serial converter.
Default Clock Source The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in 1.0MHz system clock. The startup time is set to maximum and time-out period enabled. (CKSEL = "0010", SUT = "10", CKDIV8 = "0"). The default setting ensures that all users can make their desired clock source setting using any available programming interface. Other clock sources Low power crystal oscillator crystal External oscillator Low frequency crystal oscillator Used for real time clock
Clock systems
Linia DTR umożliwia resetowanie mikrokontrolera z komputera PC konieczne przed ładowaniem programu przez bootloader
General purpose input/output schematic
Tryby uśpienia i sposób wybudzania
Controlling sleep modes register description
Interrupt vectors
Bitwise operators: & AND OR ~ NOT << SHIFT LEFT >> SHIFT RIGHT Example: Bitwise AND PORTD = 0b???????? Number= 0b11111011???????? unknown bits & 11111011 =?????0?? result: one bit cleared Binary and hex numbers are best suited to address ports Examples: 0b00000001 = 0x01 0b00000010 = 0x02 0b00000100 = 0x04 0b00001000 = 0x08 0b00001100 = 0x0C 0b11110001 = 0xF1 0b10001000 = 0x88
Example: Bitwise OR PORTD = 0b???????? Number= 0b00000100???????? unknown bits 00000100 =?????1?? result: one bit set Example: Bitwise NOT PORTD = 0b10101010 ~PORTD = 0b01010101 Example: Bitwise SHIFT PORTD = 0b10101010 PORTD<<1 = 0b01010100
Pin 2 as input internally pulled up pin 2 = PORTD, 2 DDRD = DDRD & 0xFB; (input) pinmode(2, INPUT_PULLUP); PORTD = PORTD 0x04; (pullup) pinmode(2, INPUT_PULLUP); Pin 2 as input floating (high Z) pin 2 = PORTD, 2 DDRD = DDRD & 0xFB; (input) pinmode(2, INPUT); PORTD = PORTD & 0xFB; (floating) pinmode(2, INPUT); Pin 13 as output pin 13 = PORTB, 5 DDRB = DDRB 0x20; PORTB = PORTB 0x20; PORTB = PORTB & 0xDF; pinmode(13, OUTPUT); digitalwrite(13, HIGH); digitalwrite(13, LOW);
Cod in AtmelStudio: int main(void) { setup(); while (1) loop(); return 0; } Cod in Arduino setup(); loop(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup (void) { // the setup function runs once when you press reset or power the board //funkcja setup jest wykonywana 1x po resecie lub podaniu zasilania } void loop(void) { // the loop function runs over and over again forever //funkcja loop() jest wykonywana w kółko w nieskończonej pętli }
Example: blinking LED Using Arduino library void setup() { pinmode(13, OUTPUT); } void loop() { digitalwrite(13, HIGH); delay(1000); // wait for a second digitalwrite(13, LOW); delay(1000); } Using PORT manes void setup() { DDRB = DDRB 0x20; } void loop() { PORTB = PORTB 0x20; delay(1000); // wait for a second PORTB = PORTB & 0xDF; delay(1000); }
Serial monitor is an application on PC connected to USART via USB Serial.begin(9600); //9600 bits per second Serial.print(variable); Serial.print( string ); #include <util/delay.h> includes _delay_us(80); _delay_ms(80); delaymicroseconds(480);
Types of variables
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 statusowy 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 BAUD f CK 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 połączenia Asynchroniczny interfejs UART mikrokontrolera ma dwie linie: nadawczą TXD i odbiorczą RXD. W mikrokontrolerze AT90S8515 linie te znajdują się na porcie D: RXD = PORTD0, TXD = PORTD1. Na liniach mikrokontrolera występują poziomy TTL (5V/0V). Podłączenie interfejsu UART do portu COM komputera PC, gdzie występują poziomy standardu RS-232 (-15V/0V) wymaga zastosowania konwertera zmiany poziomów. Z tego względu na płytce EVB-503 konwerter poziomów napięć został włączony przed wyjściami DB9, na których występują już napięcia standardu RS-232. Połącz wyprowadzenie RXD1 złącza AUX2 z linia PORTD0, a wyprowadzenie TXD1 złącza AUX2 z linia PORTD1.
Transmisja szeregowa UART nadawanie z obserwacją flagi Program główny: //konfiguracja interfejsu UART UBRR =38; UCR = (1<<TXEN); //wysłanie liczby ASCII a UDR = a ; while(! (USR & (1<<TXC))); USR = (1<<TXC); //wysłanie b UDR = b ; while(! (USR & (1<<TXC))); USR = (1<<TXC); //ustalenie prędkości transmisji //włączenie nadajnika //oczekiwanie na ustawienie bitu TXC //wyzerowanie flagi TXC //oczekiwanie na ustawienie bitu TXC //wyzerowanie flagi TXC
Transmisja szeregowa UART nadawanie 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++; } program główny: UBRR =38; UCR = (1<<TXCIE) (1<<TXEN); a = a ; UDR = a; sei(); while (1) ; //wysłanie kolejnej liczby //ustalenie prędkości transmisji //włączenie nadajnika, zdjęcie maski nadawczej //wysłanie liczby ASCII a //włączenie przerwań //nic więcej nie rób
Transmisja szeregowa UART odbiór z obserwacją flagi Program główny: //konfiguracja interfejsu UART UBRR =.; UCR = (..); do { while(! (USR & (..)));.. } while(1); //ustalenie prędkości transmisji //włączenie odbiornika //oczekiwanie na ustawienie flagi //odbiór z rejestru UDR //wyświetlenie znaku na LCD
Transmisja szeregowa UART odbiór 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; UCR = (..) (..); sei(); while (1) ; //ustalenie prędkości transmisji //włączenie odbiornika, zdjęcie maski odbiorczej //włączenie przerwań //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 procedura uproszczona 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 bajtu (8 bitów) 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) ) impuls1(); //impuls logicznej else impuls0(); //impuls logicznego 0. //obrót bajtu w prawo } //sprawdzenie wartości najmłodszego bitu }
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 bajtu (8 bitów) 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 //delay. us } //magistrala 1-wire jako output //magistrala 1-wire w stan wysoki return..; }
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 URZĄDZENIA MASTER DANE (NAMŁODSZY BIT JAKO 1-SZY) KOMENTARZ 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 2 3 2 2 2 1 2 0 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 2 6 2 5 2 4 S bity znaku
Odczyt temperatury w rozdzielczości 8-bitowej Wynik pomiaru temperatury jest przekazywany przez termometr w rozdzielczości 12- bitowej na bajtach LS i MS. Ograniczenie rozdzielczości do 8-bitowej (Δ=1 ) polega na usunięciu bitów: 2-1, 2-2, 2-3, 2-4. W tym celu bajty LS i MS należy odpowiednio obrócić, po czym zsumować je binarnie i uzyskać na bajcie wynikowym następujący układ bitów: 0 2 6 2 5 2 4 2 3 2 2 2 1 2 0 Bajt wynikowy zawiera temperaturę w zapisie binarnym o rozdzielczości 8-bitowej. Przed wyświetleniem na LCD liczbę binarną należy rozłożyć na kolumny (setki, dziesiątki, jedności) i zapisać każdą kolumnę w kodzie ASCII.
Odczyt temperatury w rozdzielczości 12-bitowej Usunięte poprzednio bity części ułamkowych temperatury 2-1, 2-2, 2-3, 2-4 należy zapisać na oddzielnej zmiennej. Rozdzielczość 12-bitowa jest równa 1/16 = 0,0625. Z porównania kolumn liczb w zapisie dwójkowym i dziesiętnym a 16 a 8 a2 4 a1 2 b4 b3 b2 1 10000 1000 100 10 4 3 b 625 10000 1 ( a4 2a3 4a2 8a1 ) (1000b1 100b2 10b3 b 10000 wynika, że kolumnę części dziesiętnych b 1 można obliczyć mnożąc liczbę przez 625, a następnie wyznaczając część całkowitą z podziału przez 1000. Wyznacz kolumny części dziesiętnych, setnych, tysiącznych i dziesięciotysięcznych, każdą z nich przedstaw w kodzie ASCII i wyświetl na LCD. 4 )
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)
1-wire IButton
Termometr cyfrowy DS18B20 - cechy
DS18B20 obudowy i wyprowadzenia
DS18B20 zasilanie pasożytnicze
DS18B20 zasilanie pasożytnicze
DS18B20 zasilanie zewnętrzne
DS18B20 port 3-stanowy
DS18B20 zasilanie In digital circuits, a high impedance (also known as hi-z, tri-stated, or floating) output is not being driven to any defined logic level by the output circuit. The signal is neither driven to a logical high nor low level; this third condition leads to the description "tri-stated". Such a signal can be seen as an open circuit (or "floating" wire) because connecting it to a low impedance circuit will not affect that circuit; it will instead itself be pulled to the same voltage as the actively driven output.
DS18B20 - schemat
DS18B20 pamięć ROM Transmisja następuje od LSB do MSB ( od prawej do lewej)
DS18B20 pamięci RAM i EEPROM
DS18B20 rejestr konfiguracyjny
DS2430 256-bit 1wire EEPROM Główne sekcje pamięci: - 64-bitowa pamięć ROM (laserowo wypalona) - 256-bitowa pamięć danych EEPROM - 256-bitowy pamięć tymczasowa (pośredniczy przy zapisie i odczycie z EEPROM) - 64-bitowy rejestr aplikacji jednokrotnie programowalny - 64-bitowa pamięć tymczasowa (pośredniczy przy zapisie rejestru aplikacji) - 8-bitowy rejestr statusowy (status rejestru aplikacji: zapisany/nie zapisany) Main memory sections: - 64-bit lasered ROM - 256-bit data memory - 256-bit scratchpad - 64-bit OTP application register (OTP- One Time Programmable) - 64-bit scratchpad - 8-bit status memory
Schemat blokowy
Mapa pamięci
Master musi najpierw wysłać jedną z komend adresowanych do pamięci ROM (Read ROM, Match ROM, Search ROM lub Skip ROM). Po wykonaniu komendy ROM Master może wydawać komendy adresowane do innych pamięci
Pamięć ROM
Komendy adresowane do pamięci ROM
Search ROM Command (F0H) Odczyt numerów identyfikacyjnych urządzeń na magistrali (przy założeniu, że na magistrali jest więcej niż jedno urządzenie) Wszystkie urządzenia ma magistrali mają wyjścia typu otwarty kolektor. Po podłączeniu tych urządzeń do jednej linii (1-wire) stan magistrali jest wynikiem hardwarowej operacji logicznej AND (koniunkcja hardwarowa). Proces rozpoczyna się następująco: - master odczytuje wynik koniunkcji bitów LSB wszystkich urządzeń - master odczytuje negację wyniku koniunkcji bitów LSB wszystkich urządzeń - master zapisuje na magistrali pożądaną wartość bitu LSB tym samym wydaje rozkaz przejścia w stan high-z urządzeniom o niezgodnym bicie LSB itd. do bitu 63 (MSB). W takim procesie master odczytuje numer jednego urządzenia. Następnie urządzenie już odczytane przechodzi w stan high-z, a proces zaczyna się ponownie dla urządzeń o numerach jeszcze nie odczytanych. All devices are open drain and connected to one wire produce a wired AND result. Master issues a 0FH command. Then master: read a bit, reads the complement to the bit, writes the desired value of the bit. All devices that do not match turn to state high-z.
Algorytm zapisu i odczytu pamięci EEPROM
Zapis i odczyt pamięci
CRC Cyclic Redundancy Code - reszta z dzielenia wielomianów Dzielnik i dzielna są traktowane jako ciągi (liczby) binarne, dzielenia następuje wg. zasad arytmetyki binarnej modulo 2, wynik dzielenia jest nieistotny (pomijany), reszta z dzielenia (CRC) jest dopisywana do ciągu przesyłanych danych Odbiornik dzieli otrzymany ciąg z dołączonym CRC przez ten sam wielomian, jeśli wynik dzielenia jest różny od zera, to w transmisji wystąpił błąd. Obliczenia CRC mogą być: stablicowane lub wykonywane na bazie procedur.
Dodawanie i odejmowanie w arytmetyce binarnej modulo dwa (bez przeniesienia) suma różnica 10011011 10011011 +11001010 11001010 01010001 01010001 0 0 = 0 0 1 = 1 1 0 = 1 1 1 = 0 W arytmetyce binarnej modulo 2 suma i różnica są dają identyczny rezultat. Z tego powodu nie można tradycyjnie porównywać liczb pod względem relacji większa/mniejsza. Liczba X jest większa lub równa liczbie Y jeżeli pozycja najstarszego bitu liczby X jest taka sama lub większa niż pozycja najstarszego bitu Y. np. 101 jest mniejsze niż 1010
Dzielenie w arytmetyce binarnej modulo dwa (bez przeniesienia)
DS18B20 wielomian CRC Ciąg danych: 1010101010101010101010 Dzielimy przez wielomian 100110001 W tym celu ciąg danych uzupełniamy o 8 zer 101010101010101010101000000000 100110001 liczymy sumę modulo 2 001100100010101010101000000000 100110001 liczymy sumę modulo 2 11111100110101010101000000000 100110001 liczymy sumę modulo 2 itd. aż do uzyskania 8-bitowej reszty z dzielenia
Nadajnik transmituje bity danych uzupełnione o bity reszty z dzielenia wielomianów CRC8 lub CRC16 CRC 8 =x 8 +x 5 +x 4 +1 100110001 = 0x31 CRC 16 =x 16 +x 15 +x 2 +1 11000000000000101=0x8005 Wybiera się takie wielomiany, dla których rozkład 0 i 1 wielomianu oraz wielokrotności wielomianu nie przypomina rozkładu szumu (równomiernego) Odbiornik dzieli otrzymany ciąg łącznie z bitami reszty CRC przez ten sam wielomian CRC 8 (lub CRC 16 ). Jeżeli reszta z dzielenia =0, ciąg nie został przekłamany.
Generator hardwarowy CRC16 i CRC8
//Polynomial: x^8 + x^5 + x^4 + 1 (0x8C) uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data) { uint8_t i; crc = crc ^ data; for (i = 0; i < 8; i++) { if (crc & 0x01) crc = (crc >> 1) ^ 0x8C; else crc >>= 1; } } return crc; uint8_t i, crc; crc = 0x00; p = &(tab[0]); for (i=0; i<7; i++) crc = _crc_ibutton_update(crc, *p++); if(??????) Serial.println( crc zgodne");
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.
Magistrala SPI Linie MOSI i MISO są wspólne dla wszystkich urządzeń na magistrali, linia SS jest prowadzona do każdego Slave oddzielnie.
Magistrala SPI
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.
Tryby pracy interfejsu SPI Bity konfiguracyjne CPOL i CPHA decydują o tym, na którym zboczu impulsu dane na magistrali są stabilne (moment próbkowania danych sample), a na którym następuje ich zmiana setup. Możliwe są 4 kombinacje związane z fazą i polaryzacją impulsu zegarowego Przednie zbocze Impulsu leading edge Tylne zbocze Impulsu trailing edge 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. Master musi dostosować tryb pracy do wymagań Slave podanych w nocie katalogowej tego urządzenia.
Fazowanie magistrali SPI CPHA=0
Fazowanie magistrali SPI CPHA=1
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)
Prędkość transmisji na magistrali SPI
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 leży na liniach: SS PORTB, 4 MOSI PORTB, 5 MISO PORTB, 6 SCK PORTB, 7
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; }
Real-time clock DS1305 Zegar czasu rzeczywistego
Typowy schemat operacyjny układu DS1305
Schemat blokowy układu DS1305
Źródła zasilania Backup supply is a non-rechargeable lithium battery Backup supply is a rechargeable battery Battery operate mode
Tricle charger Trckle charger to układ podładowywania baterii podłączonej do punktu Vcc2 ze źródła Vcc1 przez diodę (lub dwie diody) i rezystor ograniczający prąd ładowania. W tym układzie bateria jest stale naładowana do optymalnej wartości energii
Zestawienie rejestrów układu DS1305
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
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 SPI: 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; }
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; }
Zamiana kodu BCD na kod 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 & ; st = st >>4; st = st +48; ml = a &.... //wydzielenie 4-ch starszych bitów (cyfra BCD) //cyfra w postaci BIN //zamiana BIN to ASCII // wydzielenie 4-ch młodszych bitów (cyfra BCD) //zamiana BIN to ASCII
Zamiana kodu ASCII na kod 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
Potencjometr cyfrowy MCP4131-103 Podstawowe parametry: - Rezystancja 10kΩ ± 20% - Rozdzielczość 7-bitowa (129 kroków) Wyprowadzenia: - CS linia wyboru (w stanie niskim podczas transmisji danych) - SCK linia zegara taktującego transmisję - SDI/SDO multipleksowana linia danych dla obu kierunków transmisji - V SS linia łączona z masą - V DD linia łączona z zasilaniem - POB terminal B potencjometru skojarzony z wartością parametru sterującego 0 (rezystancja =0), nie ma z góry przypisanej polaryzacji względem suwaka (wipera), może być łączony zarówno z V SS jak i z V DD - POA terminal B potencjometru skojarzony z wartością parametru sterującego 128 (rezystancja =MAX), nie ma z góry przypisanej polaryzacji względem suwaka (wipera), może być łączony zarówno z V SS jak i z V DD - POW suwak, nie ma z góry przypisanej polaryzacji względem POA i POB, może być łączony zarówno z V SS jak i z V DD
Schemat blokowy MCP41XX Bloki funkcjonalne: Kontrola zasilania (power up/ brown out) Mapa pamięci Interfejs SPI Układ rezystorowy Brak w MCP4131 Brak w MCP4131
Drabinka rezystancyjna Odłączanie terminali od układu Odłączanie terminali od układu
Funkcje MCP41XX Wartości defaultowe wipera (suwaka) Po resecie: Rejestr wipera jest ładowany wartością defaultową Rejestr TCON jest ładowany wartością defaultową MCP4131 Zakres zmian wartości wipera Obliczanie rezystancji od wipera do punktu B MCP4131-103: rezystancja R AB = 10kΩ ± 20% Rezystancja wipera R W = 75 Ω
Mapa pamięci MCP41XX Mapa pamięci ulotnej RAM urządzenia zawiera 16 pozycji szerokich na 9 bitów (16x9): Rejestr wipera potencjometru 0 Rejestr wipera potencjometru 1 (brak w MCP4131) Rejestr TCON Rejestr STATUS (nie używany w MCP4131) Bity rejestr TCON R0A podłącza (1) lub odłącza (0) terminal A rezystora od układu R0W podłącza (1) lub odłącza (0) terminal W rezystora od układu R0B podłącza (1) lub odłącza (0) terminal B rezystora od układu R0HW wprowadza (0) rezystor w hardwarowy stan shutdown : Terminal A jest odłączony Suwak jest połączony z terminalem B Interfejs działa Hardware shutdown
Prędkość transmisji po interfejsie SPI: 250kHz z wewnętrznym podwieszeniem linii SDO/SDI 4MHz z zewnętrznym podwieszeniem linii SDO/SDI Podwieszenie wewnętrzne
16-bitowy rozkaz zapisu z równoczesnym odczytem odczytu (tryb 0) Podczas ładowania bitów komendy (bity AD3, AD2, AD1, AD0, C1, C0) odczyt linii SDI/DSO wyprowadza same jedynki. Siódmy odczytany bit CMDERR informuje, czy odebrana 6-bitowa komenda jest zrozumiała (1) /niezrozumiała (0).
16-bitowy rozkaz odczytu (tryb 0) Bity adresu AD3-AD0 Bity błędu CMDERR Bity danych D8-D0 Bity komendy C1, C0
Format komendy
8-bitowy rozkaz zapisu (tryb 0) dotyczy inkrementacji/dekrementacji wartości rezystancji Inkrementacja: Adres: 0x00 Komenda: 0x01 Dane: brak Odczyt CMDERR: 1 - OK 0 - błąd Dekrementacja: Adres: 0x00 Komenda: 0x10 Dane: brak Odczyt CMDERR: 1 - OK 0 - błąd
Dekrementacja powtarzana Sygnał CS wraca do stanu idle między kolejnymi dekrementacjami
Połączenie układu laboratoryjnego Interfejs SPI
#include <SPI.h> SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setClockDivider(SPI_CLOCK_DIV128); SPCR = (1<<SPE) (1<<MSTR); SPCR &= ~((1<<CPHA) (1<<CPOL)); SPCR = (1<<SPR1); SPI.begin(); SPI.setDataMode() SPI.setClockDivider 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 //static const uint8_t SS = 10; //static const uint8_t MOSI = 11; //static const uint8_t MISO = 12; //static const uint8_t SCK = 13; linia poza interfejsem linia interfejsu linia interfejsu linia interfejsu //konfiguracja programowa linii znajdującej się poza interfejsem pinmode (SS, OUTPUT); digitalwrite(ss,high);
uint8_t spi_transfer(uint8_t address, uint8_t data) { uint8_t o; digitalwrite(ss, HIGH); SPDR = address; while (!(SPSR && (1<<SPIF))); SPDR = data; while (!(SPSR && (1<<SPIF))); o = SPDR; digitalwrite(ss, LOW); return o; } int digitalspiwrite(int address, int value) { digitalwrite(slaveselectpin,high); SPI.transfer(address); int re = SPI.transfer(value); digitalwrite(slaveselectpin,low); return re; }
Podstawowe funkcje biblioteczne (makra) 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 #define cbi(reg, bitmask) *reg &= ~bitmask #define sbi(reg, bitmask) *reg = bitmask Przykłady: cbi (PORTD, (1<<6)); PORTD &= ~(1<<6); cbi (PORTD, PORTD6); PORTD &= ~(1<< PORTD6); cbi (PORTD, _BV(6)); PORTD &= ~(1<<_BV(6)); sbi (PORTB, (1<<6)); PORTD = (1<<6); sbi (PORTD, PORTD6); PORTD = (1<< PORTD6); sbi (PORTD, _BV(6)); PORTD = (1<<_BV(6));
Podstawowe funkcje biblioteczne (makra) sfr = special function register Rejestr wejściowy portu D - PIND #define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit)) while(bit_is_set(pind, PIND5)) { } while(pind & (1<< PIND5)) { } #define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit))) while(bit_is_clear(pind, PIND5)) { } while(!(pind & (1<< PIND5))) { } #define loop_until_bit_is_set(sfr, bit) loop_until_bit_is_set(pind, PIND5); do { } while (bit_is_clear(pind, PIND5)); #define loop_until_bit_is_clear(sfr, bit) loop_until_bit_is_clear(pind, PIND5) ; do { } while (bit_is_set(pind, PIND5)); 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
Funkcja biblioteczna Arduino int analogread(uint8_t pin) { uint8_t low, high; ref= 1; pin -= 14; ADMUX = (ref<< 6) (pin & 0x07); sbi(adcsra, ADEN); sbi(adcsra, ADSC); while (bit_is_set(adcsra, ADSC)); low = ADCL; high = ADCH; return (high << 8) low; } int mojadc() //zał. MUX0-MUX3=0 { char l, h; ADMUX = ((1<<REFS0)); ADCSRA = ((1<<ADEN) (1<<ADSC)); ADCSRA = ((1<<ADPS2) (1<<ADPS1)); while (! (ADCSRA & (1<<ADIF))); ADCSRA = (1<<ADIF); //zerowanie flagi adif l = ADCL; hh = ADCH; return (h << 8) l; }
Expandera I/O MCP23S17 SPI Expandera I/O MCP20S17 I2C
Budowa blokowa expanderów I/O: MCP23S17 SPI oraz MCP23017 I2C
Rejestry expandera MCP23S17 SPI I/O parami dla portów A i B IODIR odpowiedzialne za kierunek linii GPIO GPPUB podwieszanie wewnętrzne linii wejściowych) IPOL odwrócenie polaryzacji bitu sterującego skojarzoną linią (wpisanie zera do rejestru IPOL powoduje sterowanie skojarzonego pinu logiczną jedynką) GPINTEN maska przerwania dla zmiany stanu na skojarzonej linii (1 zdjęta) DEFVAL rejestr wartości defaultowych (startowych) dla porównania, stwierdzenie wartości przeciwnej na skojarzonej linii wywoła przerwanie INTCON kontroluje z czym porównywany jest aktualny stan na pinie w celu stwierdzenia zmiany na pinie ( 1: porównanie z korespondująca wartością w rejestrze DEFVAL, 0: porównanie z poprzednim stanem na pinie) IOCON rejestr konfiguracyjny (wybór banku, sposobu adresowania, polaryzacji na linii przerwania itp.) INTF rejestr flagowy przerwań, jedynka logiczna sygnalizuje przerwanie wywołane zmianą stanu na skojarzonej linii. Rejestr tylko do odczytu ignored. INTCAP rejestr przechwytujący stan na skojarzonym pinie w chwili przerwania read only, kolejna zmiana stanu na tej samej linii nie wywoła przerwania GPIO odzwierciedla stan na pinie wejściowym (odczyt) oraz wpisuje stan do pinu wyjściowego (zapis) OAT dla wyjść: wpis do przerzutnika wyjściowego (równoznaczny z wpisem do pinu wyjściowego), dla wejść odczyt ostatniego wpisu do przerzutnika (nie jest to odczyt pinu)
Rejestr konfiguracyjny IOCON W rejestrze IOCON należy wybrać bank 0, wybrać prace sekwencyjną (ustawić bit SEQOP w stan logicznej jedynki), aktywować adresowanie (ustawić bit HAEN)
Konfiguracja startowa (setup) expandera I/O MCP23S17 SPI Dwa porty GPIOA oraz GPIOB po 8 linii. Po resecie (np. po podaniu napięcia zasilającego) wszystkie linie portów są skonfigurowane jako wejścia (input). Kierunek linii można zmienić w rejestrach IODIRA oraz IODIRB (wpisanie zera konfiguruje wyjście, a jedynki wejście (w mikrokontrolerze jest odwrotnie: wpisanie 0 konfiguruje wejście, a jedynki wyjście) Na liniach wejściowych aktywujemy rezystory podciągające (przez wpisanie jedynek do rejestru GPPUA lub GPPUB Uaktywnienie trybu adresowania wymaga wpisania logicznej jedynki do bitu HAEN w rejestrze IOCONA lub IOCONB (oba rejestry zawierają ten sam bit)
Arduino Ethernet shield Układ Ethernetowy W5100 zawiera stos TCP/IP do nawiązywania połączeń Ethernetowych TCP oraz UDP. Podtrzymuje jednocześnie do 4-ch gniazd sieciowych. Do połączenia z płytką Arduino Uno wykorzystuje piny: 10, 11, 12, 13 (dodatkowo karta SD korzysta z pinu 4)..
Ethernet shield pinout Serial: 0 (RX) and 1 (TX). Used to receive (RX) and transmit (TX) TTL serial data. External Interrupts: 2 and 3. These pins can be configured to trigger an interrupt on a low value, a rising or falling edge, or a change in value. See the attachinterrupt() function for details. PWM: 3, 5, 6, 9, and 10. Provide 8-bit PWM output with the analogwrite() function. SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). These pins support SPI communication using the SPI library. LED: 9. There is a built-in LED connected to digital pin 9. When the pin is HIGH value, the LED is on, when the pin is LOW, it's off. On most other arduino boards, this LED is found on pin 13. It is on pin 9 on the Ethernet board because pin 13 is used as part of the SPI connection. The Ethernet board has 6 analog inputs, labeled A0 through A5, each of which provide 10 bits of resolution (i.e. 1024 different values). By default they measure from ground to 5 volts, though is it possible to change the upper end of their range using the AREF pin and the analogreference() function. Additionally, some pins have specialized functionality: TWI: A4 (SDA) and A5 (SCL). Support TWI communication using the Wire library. AREF. Reference voltage for the analog inputs. Used with analogreference(). Reset. Bring this line LOW to reset the microcontroller. Typically used to add a reset button to shields which block the one on the board.
Funkcja setup przy tworzeniu serwera HTTP #include <SPI.h> #include <Ethernet.h> byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x13, 0x3A }; IPAddress ip(192,168,0,230); EthernetServer server(80); void setup() { // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); }
void loop() { EthernetClient client = server.available(); Serwer rozpoczyna nasłuch, if (client) odbiera od klienta żądanie HTTP { while (client.connected()) { if (client.available()) { char c = client.read(); if (c == '\n' ) //rozpoznanie końca żądania HTTP (end of HTTP request) { client.println("http/1.1 200 OK"); client.println("content-type: text/html"); client.println("refresh: 1"); // odświeżanie (refresh every second) client.println(); client.println("<html>"); //client.print(..); client.println("<br />"); } client.println("</html>"); break; } } } delay(1); client.stop(); }}
Odbiór łańcucha (stringu) z żądaniem HTTP void loop() { EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); if (dstring.length() < 30) { dstring +=c; if (c == '\n') {
Wyszukiwanie ciągu w żądaniu HTTP String.IndexOf wskazuje na miejsce wystąpienia wskazanych znaków w łańcuchu if(dstring.indexof("l=1")>0) { digitalwrite(ledpin, HIGH); // set the LED on LEDON = true; } if(dstring.indexof("l=0")>0) { digitalwrite(ledpin, LOW); // set the LED on LEDON = false; }
Komponenty w html u Tworzone są: dwa radiobuttony o działaniu alternatywnym komponent submit przekazujący rozkaz dla diod poprzez dopisanie łańcucha do żądania HTTP client.println("</html></body>"); client.println("<form method=get name=led><br>"); { } { } if(ledon == false) client.println("<input type='radio' name='l' value='1'>led ON<br>"); client.println("<input type='radio' name='l' value='0' checked>led OFF<br>"); else if(ledon == true) client.println("<input type='radio' name='l' value='1' checked>led ON<br>"); client.println("<input type='radio' name='l' value='0'>led OFF<br>"); client.println("<input type=submit value=submit></form>"); client.println("<br />"); client.println("</body></html>");
Atrybut href w html u Atrybut href zawiera adres internetowy powiązanej strony The href attribute specifies the URL of the page the link goes to. a /a ograniczają fragment interpretowany jako adres URL w html u nie wszystkie znaki są znakami ascii i niektóre wymagają zamiany na ascii przez poprzedzenie ich backslashem - przykładem jest kombinacja \ client.println("<a href=\"/?lighton\"\">turn On Light</a>"); client.println("<a href=\"/?lightoff\"\">turn Off Light</a><br />");. if(readstring.indexof("?lighton") >0) digitalwrite(2, HIGH); // set pin 6 high else if(readstring.indexof("?lightoff") >0) digitalwrite(2, LOW); // set pin 6 low readstring=""; //clearing string for next read
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 E MASTER SCL R2 10k R1 10k SDA SLAVE 1 SLAVE 2 SLAVE N Linie adresu sprzętowego E lub GND E lub GND E lub GND 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 wyprowadzenia A0-A2 SCL SDA WP Funkcja Linii Wejścia adresowe Wejście zegarowe Linia danych 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 pamięci Liczba bajtów na stronę Długość słowa 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 adresu Długość 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<<bit)) /#define wyzerujbit(port,bit) (port &= ~(1<<bit))
Kształtowanie impulsu Kształtując programowo impuls zegarowy między kolejnymi stanami na linii SCL należy wstawić opóźnienie, które będzie decydować o prędkości transmisji po magistrali. Dla opóźnienia 5us otrzymamy prędkość: 4 opóźnienia 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) { _delay_us(5); ustawbit (PORTB, SDA); ustawbit (PORTB, SCL); _delay_us(5); wyzerujbit( ); _delay_us(5); wyzerujbit(..); _delay_us(5); } void I2C_stop(void) { _delay_us(5); wyzerujbit (PORTB, SDA); wyzerujbit (PORTB, SCL); _delay_us(5); ustawbit( ); _delay_us(5); ustawbit(..); _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 Zapis pojedynczego bajtu danych : // - 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 Odbiór bajtu danych z podaniem adresu : // - 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 Zapis pojedynczego bajtu danych : // - 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 Odbiór bajtu danych z podaniem adresu : // - 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
GPS I/O Odbiornik GPS MiniGMouse podłączony jest na magistrali UART w standardzie TTL, skonfigurowany do prędkości 9600bps, 8n1, korzysta z protokołów standardu MTK: - NMEA 0183 do cyklicznego przesyłania danych w ramkach GGA, GSA, GSV, RMC, VTG, - MTK NMEA Command do odbioru komend konfiguracyjnych i restartu - RTCM do ustalania standardu transmisji poprawek różnicowych i formatu danych
Ramki GPS Ramki z danymi zgodne ze standardem MTK są wysyłane cyklicznie co 1s.
Ramka RMC Ramka RMC zawiera dane o czasie, pozycji, prędkości i kursie. Dane są ważne, jeśli status danych jest literą A. Poniżej zamieszczono przykładową odebraną ramkę RMC, a na kolejnym slajdzie wyjaśnienie układu i formatu danych w ramce. $GPRMC, 064951.000,A,2307.1256,N,12016.4438,E,0.03,165.48,260406,,,A*55
Odbiór ramki RMC Ramka RMC ma zawsze stałą liczbę 12-stu przecinków. Ramka RMC ma zawsze stałą liczbę 12-stu przecinków Rozpoznanie ramki RMC należy oprzeć na rozpoznaniu nagłówka i liczeniu przecinków W tym celu należy: założyć rejestr przesuwny (przesuwany programowo) o rozmiarze 6-ciu znaków służący do rozpoznania nagłówka $GPRMC. Każdy odebrany znak należy wsunąć w rejestr przesuwając równocześnie znaki poprzednie, po czym sprawdzić, czy w rejestrze znajduje się poszukiwany nagłówek, Po rozpoznaniu nagłówka należy odbierane znaki wstawiać do Tablicy, równocześnie licząc przecinki, Po 12-stym przecinku należy zaprzestać wstawiania kolejnych znaków do Tablicy, wybrać potrzebne dane, zmienić format ich prezentacji i wyświetlić na LCD. Czas podawany jest po 1-szym przecinku, szerokość geograficzna po 3- cim, a długość po 5-tym przecinku.
Odbiór z GPS-u struktura programu ISR (UART_RX_vect) //procedura przerwania UART_RX { char rejestr[6], Tablica[100], indeks=0, przecinek=0; char rozpoznano=0; //odbieraj znaki a=udr; wsuwaj do rejestru rejestr[0]=rejestr[1]; rejestr[1]=rejestr[2]; rejestr[5]=a; // rozpoznaj nagłówek if(rejestr[0]== $ ) &&.. //po rozpoznaniu nagłówka (rozpoznano = 1) odbierane znaki wstawiaj do Tablicy if(rozpoznano==1) Tablica[indeks++] =a; //licz przecinki, po 12 zaprzestań uzupełniania Tablicy //pobierz potrzebne dane, zmień ich format i wyświetl na LCD if(przecinki ==12) &&.. //rozpocznij proces od początku (rozpoznano =0) } int main (void) //program główny { //konfiguracja magistrali UART do odbioru znaków w przerwaniu while (1) ; //pętla główna bezczynna }
Procedura przerwania odbiorczego magistrali UART: UART_RX_vect Odbierz znak z UART-a Przesuń znaki w rejestrze o 1 w lewo rejestr[0]=rejestr[1]; rejestr[1]=rejestr[2]; Itd. Wsuń znak odebrany do rejestru z prawej Czy nagłówek został już rozpoznany? Wpisz znak do tablicy [indeks] Indeks++ Tak Nie Czy w rejestrze znajduje się poszukiwany nagłówek $GPRMC? Tak Czy znak jest przecinkiem? Tak Nie Rozpoznano =1 Przecinek =0 Nie Przecinek++ Czy to 12-sty przecinek? Tak Nie Rozpoznano =0 Przecinek =0, indeks=0 Wybierz i wydrukuj znaki z tablicy zawierające dane o pozycji geograficznej Return
Testowanie programu Przygotuj przykładowa ramkę RMC odebraną od GPS-u w formacie.txt. Połącz wyjście szeregowe płytki EVB-503 z wejściem COM komputera PC. Otwórz Hyper-Terminal i skonfiguruj na 9600 8n1. Wysyłaj symulowana ramkę RMC wykorzystując funkcję wklej do hosta Format danych - zamiana części minut na sekundy Długość i szerokość geograficzna są odbierane w formacie ddmm.mmmm, gdzie d degrees (stopnie), m- minutes (minuty), po kropce podawane są części minut. Format należy zamienić na ddmmss, gdzie s seconds (sekundy) np. 0.1234min = 0.1234* 60 sek = 7.404 sek zaokrąglamy do 7sek Procesor nie przetwarza ułamków zatem dla.m1m2m3m4 - każdą z liczb m1, m2, m3, m4 należy zamienić z zapisu ascii na binarny - utworzyć liczbę long int s1=m1bin*1000 + m2bin*100.. - liczbę s1 pomnożyć przez 60 i wybrać odpowiednie kolumny zapisu dziesiętnego
Podział pamięci półprzewodnikowych Pamięci półprzewodnikowe sekwencyjne rejestry przesuwające CCD - ze sprzężeniem ładunkowym ulotne zwykłe statyczne (SRAM) równoległe (bipol.,unipol.) szeregowe (unipol.) dynamiczne (DRAM) klasyczne (unipol.) pseudostatyczne (unipol.) nieulotne ROM PROM EPROM (szereg. i równol.) EEPROM (E 2 PROM) (szereg. i równol.) NVRAM (SRAM+EEPROM) FLASH (3 rodzaje) FRAM bipolarne unipolarne u n i p o l a r n e
Pamięć nieulotnych - ROM Pamięć ROM jest produkowana w formie specjalizowanych układów scalonych. Zawartość komórek jest ustalana już w czasie produkcji przez zastosowanie odpowiedniej struktury logicznej. Raz wyprodukowana, pamięć ROM nie może już zmienić swojej zawartości - w przypadku błędów w zapisanych danych nie ma możliwości ich poprawienia.
Pamięć nieulotnych - EPROM Kasowanie zawartości pamięci wymaga naświetlenia jej struktury światłem ultrafioletowym przez około 10-15 minut. Dlatego w obudowie EPROM umieszczone jest małe okienko kwarcowe przepuszczające ultrafiolet, poprzez które widoczna jest płytka krzemowa zawierająca elementy pamięci. Pamięci EEPROM mogą być kasowane i programowane około 100 razy. Produkuje się również tzw. jednorazowe pamięci EPROM - bez okienka tzw. OTP EPROM (ang. One Time Programmable - programowalne jednorazowo). Układy takie zawierają strukturę EPROM, jednak mogą być zaprogramowane tylko jeden raz.
Pamięć nieulotnych EEPROM Zasada działania opiera się na przechowywaniu informacji w tranzystorach polowych MOSFET. Zwykły tranzystor składa się ze źródła i drenu - półprzewodnika typu N+ (P+) oddzielonego półprzewodnikiem typu P (N) nad którym umieszczona jest elektroda - bramka. Przyłożenie napięci do bramki wywołuje pole elektryczne w półprzewodniku typu P (N) i wytworzenie w nim obszaru o tym samym typie co źródło i dren. Zwróćmy uwagę, że tranzystor tego typu pobiera prąd tylko w momencie przełączania stanu. Jedna komórka pamięci EEPROM składa się tranzystora, który pomiędzy podłożem, a bramką sterującą (Control Gate - CG) posiada odizolowaną bramkę pływającą (Floating Gate - FG). Elektrony raz umieszczone na FG mogą pozostać tam przez lata pamiętając zaprogramowany stan. Liczba programowań 100000, każda komórka kasowana oddzielnie 10ms
Pamięć nieulotnych EEPROM FLASH Pamięć Flash jest rodzajem pamięci EEPROM zorganizowanej w bloki, które mogą być kasowane w całości. Czysta komórka pamięci Flash posiada nienaładowaną FG, co odpowiada zapisanej binarnej jedynce. Przykładając wysokie napięcie (12 V w porównaniu do 3,3 V lub 5 V napięcia zasilania podczas odczytu) elektrony "wskoczą" na FG i zostanie zaprogramowane binarne zero. Przyłożenie wysokiego napięcia o odwrotnej polaryzacji powoduje wyczyszczenie zawartości komórki, impuls prądu o natężeniu blisko 200 A przypomina ten przepływający przez lampę błyskową i stąd nazwa pamięci. Kasowanie jest możliwe tylko blokami po kilka tysięcy bitów. Udało się dzięki temu skrócić czas zapisu komórki do kilkudziesięciu nanosekund. Cykl programowania-zapisywanie (Program/Erase - P/E) może zostać powtórzony maksymalnie od 10 000 do 1000 000 razy. Struktura NOR Struktura NAND
Pamięć nieulotnych EEPROM FLASH Organizacja bloków pamięci EEPROM Flash: 32 strony x 512 B + 16 B na ECC = blok 16 kb 64 strony x 2048 B + 64 B na ECC = blok 128 kb 64 strony x 4096 B + 128 B na ECC = blok 256 kb 128 stron x 4096 B + 128 B na ECC = blok 512 kb ECC Error Correction Code Ciekawym rozwiązaniem wykorzystującym pamięci Flash, zyskującym ostatnio popularność, są dyski Flash SSD stosowane w laptopach.
Pamięć NV-RAM nie jest pamięcią stałą, tylko pamięcią RAM zintegrowaną z EEPROM i/lub baterią, która podtrzymuje działanie pamięci po wyłączeniu zasilania. W komputerach PC pamięć NV-RAM jest często stosowana do zapamiętywania ustawień płyty głównej komputera.
Pamięć ulotna SRAM
Pamięć SRAM na magistrali równoległej SRAM Linie DA7 DA0 są multipleksowane, Najpierw pojawiają się na nich bity adresu, a po zatrzaśnięciu stanów na wyjściach przerzutników D, na te same linie podawane są dane. Zatrzaśnięcie stanów przerzutników następuje na zboczu opadającym ALE.
Pamięć ulotnych DRAM
Pamięć nieulotnych FRAM
rodzaj rozmiar nieulot- zapis odczyt pobór komórki ność czas ilość czas ilość mocy [ns] [ns] SRAM duży - 25-100 nieogr. 25-100 nieogr. niski DRAM średni - 50-100 nieogr. 30-70 nieogr. wysoki EEPROM średni + 10ms 10 5 60-150 nieogr. średni NVRAM duży + 25-45 nieogr. 25-45 nieogr. średni Flash mały + 5-10 s 10 6 70-150 nieogr. średni FRAM średni + 55-200 10 10-10 14 55-200 10 10-10 14 niski
Zalety pamięci FRAM w stosunku do EEPROM (E 2 PROM) - dostęp 30 razy szybszy - liczba zapisów (przeprogramowań) 1milion razy większa - zużycie energii 200 razy mniejsze - wysoka odporność na pola elektromagnetyczne i promieniowanie gamma - przechowywanie danych 10 lat bez baterii - prostsza konstrukcja jedynie mały kondensator podtrzymujący w razie spadku napięcia zasilającego podczas procesu zapisu
Porównanie pamięci SRAM, FRAM
Pamięć FRAM FM25C160B 16kbit zorganizowanych jako 4K x 8 100 trylionów cykli zapis/odczyt 150 lat zachowania zawartości pamięci Magistrala SPI o prędkości do 20 MHz Prędkość zapisu i odczytu równa prędkości na magistrali (bezzwłoczny zapis/odczyt) Podział pamięci na bloki chronione bitem zezwolenia na zapis Podtrzymuje tryb 0 i 3 pracy magistrali SPI Zużycie prądu w stanie aktywnym (zapis/odczyt) 250μA przy 1MHz Zużycie prądu w stanie idle 4μA
Komendy (opcodes) pamięci FRAM FM25C160B Realizacja rozkazu WREN
Zapis danych w pamięci Odczyt danych z pamięci
Zastosowanie pamięci FRAM w systemach wbudowanych: - Authentication chip z szyfrowaniem np. AES do identyfikacji uprawnionego użytkownika - Custom LSI LSI wg. zamówienia - RFID identyfikator drogą radiową
RFID Radio Frequency Identification Układ składa się z czytnika i etykiety (transpondera) Czytnik: nadajnik, odbiornik, dekoder, antena nadawcza i odbiorcza Etykieta: układ scalony bez obudowy z anteną, bez zasilania. Czytnik nadając wytwarza falę elektromagnetyczną. Etykieta po znalezieniu się w polu czytnika gromadzi energię w kondensatorze, po czym wysyła odpowiedź do czytnika. Po wysłaniu odpowiedzi etykieta pozostaje nieczynna przez pewien czas, co umożliwia odczyt wielu transponderów znajdujących się jednocześnie w polu odczytu. częstotliwości pracy: 13,5MHz zasięg około metra 800 900 MHz zasięg kilka metrów
FRAM embedded RFID LSI MB89R112
FRAM embedded RFID LSI MB89R112 budowa blokowa
Budowa akcelerometru elektronicznego Konstrukcja elektromechaniczna MEMS z siliconu przewodzącego w kształcie kondensatora o ruchomej okładce, do której przeczepiony jest silikonowy ciężarek Przyspieszenie ziemskie działając na obciążenie przesuwa okładki względem siebie, co powoduje zmiany pojemności okładki kondensatora Ruchoma okładka kondensatora z obciążeniem
Akcelerometr w roli czujnika przechyłu (Tilt/inclination sensing with accelerometr) Pomiar siły grawitacji pozwala ocenić położenie obiektu w przestrzeni. Akcelerometr dwuosiowy sensor jest najbardziej wrażliwy na zmiany pochylenia, gdy oś pochylenia jest prostopadła do siły grawitacji (pochylenia wzdłuż osi x lub y czułość: 17.45mg/deg), sensor jest najmniej wrażliwy na zmiany pochylenia wzdłuż osi z - czułość 0.15 mg/deg). Akcelerometr dwuosiowy umieszczony poziomo Akcelerometr dwuosiowy umieszczony pionowo
Akcelerometr 3-osiowy w roli czujnika przechyłu Akcelerometr trzyosiowy odczyt zmian przyspieszenia ziemskiego wzdłuż osi x, y, z pozwala na obliczenie odchylenia od trzech osi Akcelerometr na płaszczyźnie poziomej x/y Φ kąt między osią x ρ kąt między osią y a płaszczyzną x/y a płaszczyzną x/y θ kąt między osią z a wektorem grawitacji θ kąt między osią z a wektorem grawitacji Wyznaczanie kątów odchylenia na bazie pomiarów przyspieszenia a x, a y, a z
Akcelerometr 3-osiowy w roli czujnika przechyłu Utrzymanie stałej czułości sensora przy katach pochylenia od 0 do 360 deg Utrzymania stałego poziomu szumów Możliwość rozróżnienia przyspieszenia wzdłuż osi od przechyłu Wykorzystanie pomiarów przyspieszenia grawitacji wzdłuż trzech osi pozwala na utrzymanie stałej czułości sensora przy pochyleniach od 0 do 360 deg
Akcelerometr - rozpoznanie odwrócenia przedmiotu na podstawie znaków przyspieszeń wzdłuż osi x i y oraz z
Akcelerometr - zmiana orientacji ekranu (poprzeczna lub wzdłużna) Zmiana przyspieszenia wzdłuż osi x i y
Akcelerometr - próg zmiany orientacji ekranu (poprzeczna lub wzdłużna) Wartości przyspieszenia wzdłuż osi w 4-ch orientacjach sensora Wartości progowe dla rozpoznania orientacji sensora
Akcelerometr - rozpoznanie klepnięcia (tap detection) Zmiana przyspieszenia w funkcji czasu (wzdłuż wybranej osi) jako efekt klepnięcia w akcelerometr Zasady rozpoznania klepnięcia: Przyspieszenie wzdłuż wybranej osi musi przekroczyć wartość progową i wrócić poniżej tej wartości w czasie ograniczonym z góry (2 parametry rozpoznania)
Akcelerometr - rozpoznanie podwójnego klepnięcia (double tap detection) Zmiana przyspieszenia w funkcji czasu (wzdłuż wybranej osi) jako efekt podwójnego klepnięcia w akcelerometr Zasady rozpoznania podwójnego klepnięcia: każde klepnięcie rozpoznawane indywidualnie wg zasad podanych powyżej drugie klepnięcie musi się nastąpić w czasie Pulse Window ograniczonym w góry
Budowa kompasu elektronicznego Czujnik zbudowany z ferromagnetyku (InSb Ind, Antymon) przez który płynie prąd. Wskutek interakcji pól magnetycznego i elektrycznego (prawo Lorentza) rezystancja materiału jest proporcjonalna do indukcji magnetycznej B (wzór).
Natężenie pola magnetycznego Natężenie pola magnetycznego jest wektorem w przestrzeni o różnym nachyleniu do płaszczyzny poziomej na różnych szerokościach geograficznych Inklinacja magnetyczna - kąt zawarty pomiędzy płaszczyzną poziomą a osią swobodnie zawieszonej igły magnetycznej
Wpływ pochylenia czujnika na pomiary kompasu Jeśli kompas jest utrzymywany w płaszczyźnie poziomej x/y, to kąt zmierzony w tej płaszczyźnie określa azymut α (heading) względem północy magnetycznej Jeśli czujnik zostanie odchylony o kąt w przestrzeni, to trzeba kompensować wskazania czujnika uwzględniając kąty odchylenia względem 3-ch osi Obliczenie współrzędnych nowego położenia na podstawie współrzędnych starego położenia i kątów odchylenia względem 3-ch osi
Wpływ pochylenia czujnika na pomiary kompasu - wzory obliczeniowe Nowe współrzędne pola magnetycznego M x2, M y2, M z2 w funkcji starych współrzędnych pola M x1, M y1, M z1 i kątów pochylenia σ i γ (na płaszczyźnie x/z) Namiar (azymuth) w funkcji nowych współrzędnych
Współpraca kompasu i akcelerometru elektronicznego w zakresie kompensacji inklinacji magnetycznej Kąty nachylenia względem osi x i y na płaszczyźnie są wyznaczane na podstawie przyspieszeń wzdłuż tych osi pomierzonych przez akcelerometr Czułość i dokładność kompasu elektronicznego w znacznym stopniu zależy od parametrów współpracującego z nim akcelerometru. Dokładność wyznaczenia kątów pochylenia ϕ= γ oraz σ przez akcelerometr istotnie wpływa na dokładność określenia namiaru względem północy magnetycznej.
Czułość, szumy i błędy kompasu (z akcelerometrem) Błędy wyznaczenia namiaru względem północy magnetycznej są funkcją kątów pochylenia ϕ oraz σ oraz wartości namiaru Czułość jest stała i zależy głównie od akcelerometru 3-osiowego Poziom szumów jest stały i zależy głównie od akcelerometru 3-osiowego Kalibracja urządzenia dokonywana fabrycznie (można sprawdzić pomiarowo offset) Wbudowana korekcja temperaturowa wskazań akcelerometru Poziom szumów Błędy określenia namiaru
Żyroskop elektroniczny zasada działania Siła Coriolisa w nano-strukturze MEMS skutkuje zmianą pojemności kondensatora Masa poruszająca się w kierunku v i wirująca wokół osi z prędkością kątową Ω podlega sile Coriolisa działającej w kierunku F Dwie masy poruszające się w kierunkach przeciwnych wprawiane w ruch obrotowy doznają przeciwnie skierowanych sił Coriolisa Gdy do mas przyłożymy przyspieszenie liniowe, obie będą poruszać się w tym samym kierunku i nie nastąpi zmiana pojemności czujnika. Żyroskop MEMS jest nieczuły na przyspieszenie liniowe związane np. z pochyleniem
Żyroskop elektroniczny zasada działania Masa jest wytrawiana w polikrzemie i umieszczona na krzemowych sprężynach tak, żeby mogła poruszać się tylko w jednym kierunku. Masa jest wprawiana w ruch (drgania) siłą elektrostatyczną. Gdy masa (czujnik) zostanie wprawiony w ruch obrotowy to zwrot siły Coriolisa zależy od aktualnego kierunku drgania masy. Kierunek siły Coriolisa zależy od kierunku przemieszczania masy
Podłączenie urządzenia na magistrali I2C