Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.
Pokazywanie postów oznaczonych etykietą Drzaśkowy pamiętnik - Kurs AVR. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Drzaśkowy pamiętnik - Kurs AVR. Pokaż wszystkie posty

wtorek, 29 marca 2011

RS-232: Komunikacja ATmega8 z komputerem

Autor: Dondu

Interfejs RS-232 na USART.
Jednym z najbardziej popularnych interfejsów komunikacji jest RS-232. Większość mikrokontrolerów wyposażona jest w co najmniej jeden taki moduł.

Podstawową zaletą RS-232 jest możliwość komunikacji na duże odległości nawet ponad jednego kilometra. Wadą natomiast radykalnie zmniejszająca się przepustowość łącza, wraz ze wzrostem odległości. Coś, za coś :-)

Nie będę tutaj omawiał dokładnie zasad komunikacji pokażę jedynie jak w praktyce połączyć mikrokontroler z komputerem i jak zrealizować łączność z prędkością 57,6kbps z wykorzystaniem przerwań.

Dowiesz się także jakie błędy popełniane są najczęściej w temacie wykorzystania tego interfejsu.

Przeczytaj także jak wykorzystać interfejs RS-232 za pomocą Bletooth: Bluetooth + mikrokontroler



Krzyżowe połączenie

W przypadku RS-232 (w przeciwieństwie do innych interfejsów) urządzenia łączy się krzyżowo, czyli w taki sposób, by wyjście jednego trafiało na wejście drugiego:

Interfejs RS-232 - Krzyżowanie sygnałów RxD i TxD.


Należy o tym pamiętać w szczególności, że standardowe przewody łączące mogą być dwojakiego rodzaju:

Interfejs RS-232 - Rodzaje przewodów łączących.

Jeżeli więc podwójnie skrzyżujesz sygnały RxD i TxD (raz w urządzeniu i drugi raz w przewodzie łączącym), to de facto krzyżowania nie będzie i komunikacji także :-)







Pinologia

W komputerach znajdziesz gniazda RS-232 w formie wtyku typu D-SUB o 9 pinach w wersji męskiej.

Pinologia złącza RS-232 w wersji D-SUB 9.
Źródło

Każdy pin ma numerek (patrz przez lupę - mogą być słabo widoczne). Numerki są zgodne z wersją damską złącza. Innymi słowy damskie jest lustrzanym odbiciem męskiego, przez co piny o tych samych numerach wzajemnie się łączą.

W starszych urządzeniach można znaleźć gniazda w wersji 25 pinowej.
Warto zerknąć na tę stronę: RS232 Connector Pin Assignment lub w wersji PDF.








Prędkości transmisji

RS-232 oferuje bardzo szeroki zakres możliwych prędkości transmisji. Pozwala to na dobranie odpowiedniej do danych warunków (możliwości obu połączonych urządzeń) oraz odległości i innych warunków zewnętrznych (zakłócenia, rodzaj i jakość przewodów, itp). Zerknijmy na tabelę zawartą w datasheet ATmega8 dla zegara taktującego mikrokontroler od 16MHz wzwyż:

RS-232 - ATmega8 - Prędkości transmisji zależnie od częstotliwości zegara taktującego mikrokontroler.

Baud rate, to jednostka prędkości łącza wyrażona w bitach na sekundę (ang. bits per second). Jak każdą jednostkę także i tę możemy wyrażać za pomocą przedrostków wielokrotności jednostki miary. Stąd:
  • kbps - oznacza kilo bitów na sekundę, 
  • Mbps - mega bitów na sekundę.

Takich tabel jak powyższa w datasheet znajdziesz więcej (także dla niższych częstotliwości zegara mikrokontrolera). Za pomocą nich możesz wybrać i ustawić odpowiednio interfejs USART (UART) mikrokontrolera.

Zauważysz w nich, że w trybie asynchronicznym niektóre częstotliwości taktowania mikrokontrolera pozwalają uzyskać znacznie większe prędkości transmisji danych, niż inne częstotliwości. Na pierwszy rzut oka może dziwić fakt, że dla częstotliwości taktowania mikrokontrolera 8MHz, można osiągnąć 1Mbps, podczas gdy z zegarem 20MHz zaledwie 0,5Mbps.

Wytłumaczenie tego faktu znajdziesz tutaj:



Podczas obliczania wartości jaką należy ustawić w rejestrze UBRR, zamiast tabelek możesz skorzystać ze wzorów, które także w datasheet znajdziesz:


RS-232 - ATmega8 - Wzory obliczania wartości rejestru UBRR.


Efektywna prędkość transmisji

Moduł USART umożliwia wybranie jednej z 30 możliwych kombinacji ramki danych, czyli pakietu przesyłającego jedną daną. Parametry ramki danych zależne są od tego

  • bit startu (jest zawsze jeden),
  • bity danych (może być od 5 do 9),
  • bit parzystości (może lecz nie musi występować),
  • bity stopu (co najmniej jeden lub nawet dwa).

Ramka danych przedstawia się więc następująco:

RS-232 - Ramka danych modułu USART.
Rys. RS-232 - Ramka danych modułu USART.

Bity zaznaczone na czerwono występują zawsze. 
Pozostałe (zaznaczone na zielono) w zależności jak ustawisz parametry transmisji.

Jak widzisz ramka może mieć od 7, aż do 13 bitów.

Skoro ramka może mieć różną długość, a BAUD RATE jest stały np. 9600bps, to efektywna prędkość transmisji danych (Data bits) będzie różna dla różnych ustawień długości ramki.

Obliczeń efektywnej prędkości transmisji danych możesz dokonać za pomocą poniższego kalkulatora:

Kalkulator efektywnej prędkości
transmisji danych (USART)
Baud rate bps
Bit startu
Bitów danych
Bit parzystości
Bit stopu
Długość ramki bitów
Efektywna prędkość transmisji bps
%







Odległości

Odległości uzyskiwane za pomocą tego interfejsu orientacyjnie wynoszą:

Prędkość
[bps]
Odległość
[m]
1920016
9600160
4800320
24001000

Źródło: Tomasz Francuz: Język C dla mikrokontrolerów AVR.
Od podstaw do zaawansowanych aplikacji. str. 369

Faktyczne osiągi zależą oczywiście od wielu czynników jak zastosowane przewody, wersja nadajnika i odbiornika oraz środowiska w jakim pracuje tak zrealizowana linia komunikacyjna.






Niezbędna elektronika

W przypadku wykorzystania RS-232 do komunikacji pomiędzy dwoma mikrokontrolerami na niewielkich odległościach np. w tym samym urządzeniu nie ma potrzeby korzystania z dodatkowych układów i można operować napięciami w standardzie mikrokontrolerów.

Jednakże w przypadku łączenia mikrokontolera z urządzeniem pracującym w standardzie napięć RS-232, musisz wiedzieć o tym, że standard poziomów napięć RS-232 znacząco odbiega od poziomów napięć, którymi operują mikrokontrolery. Właśnie dzięki temu możliwe jest osiąganie znacznych odległości. Ceną takiego rozwiązania jest potrzeba stosowania dodatkowych układów pośredniczących.

Mogą być nimi dedykowane do tych zadań układy scalone lub można zbudować własny za pomocą niewielkiej ilości elementów. Układ ten powinien znajdować się po obu stronach linii, czyli na wejściach i wyjściach obu komunikujących się ze sobą urządzeń.


Dedykowane układy RS-232

Podstawowym, powszechnie stosowanym i tanim układem jest MAX232:


MAX232 - Schemat blokowy.

Biblioteka Eagle: maxim.lbr

Fakt, że mikrokontroler może osiągnąć prędkość np. 1Mbps nie oznacza, że możesz z taką prędkością komunikację prowadzić za pomocą MAX232, czy innych tego typu układów, ponieważ układy te mają swoje górne granice prędkości transmisji. W przypadku MAX232 jest to zaledwie 120kbps.

Ale jest także wiele innych układów, które mają znacznie większe prędkości i/lub inne parametry, które mogą być istotne dla Ciebie, jak na przykład pobór prądu w stanie spoczynku w przypadku urządzeń zasilanych z baterii, czy akumulatora:

Często jak w przypadku MAX232 w jednym układzie zawarte są dwa komplety nadajników i odbiorników. Jeżeli nie wykorzystujesz obu nadajników i odbiorników, warto jest zadbać o wymuszenie stanu niskiego na nieużywanych wejściach, by te części układu nie "łapały" zakłóceń:


MAX232 - Prawidłowe podłączenie układu.


MAX'y vs kondensatory

Częstym problemem początkujących jest sprawa kondensatorów używanych w tej rodzinie układów. Trzeba zwrócić uwagę na dwa ważne aspekty:
  1. kondensator C4 ma z pozoru nieprawidłową polaryzację, ale wynika ona z faktu, że na pinie V- jest napięcie ujemne(!).
  2. wartość i rodzaj kondensatorów zależy od typu zastosowanego układu MAX. Dokładną informację znajdziesz w datasheet danego układu. W przypadku MAX232 kondensatory powinny mieć 1µF i mogą być elektrolityczne, tantalowe, a nawet ceramiczne. W przypadku MAX202 kondensatory mają wartość 0,1µF. Zawsze sprawdzaj w datasheet:
MAX232 - wymagania dot. kondensatorów.
Rys. MAX232 - wymagania dot. kondensatorów.


Nie mam pod ręką MAX'a !

Transmisję z wykorzystaniem RS-232 można także prowadzić za pomocą prostego intrerfejsu zrealizowanego za pomocą dwóch tranzystorów i kilku dodatkowych elementów:

RS-232 - Konwerter napięć na tranzystorach.


Tak wykonany interfejs jest bezpieczną wersją o całkiem dobrych parametrach transmisji danych, chociaż mogą wystąpić problemy przy dłuższych przewodach. Innymi słowy rozwiązanie to należy traktować jako awaryjne, testowe, doświadczalne lub świadomy kompromis.

Dodatkową zaletą jest fakt, iż użyte tranzystory i diody mają wiele zamienników, więc praktycznie zawsze pod ręką jakieś znajdziesz. Także rezystory mogą przybierać różne wartości od 2,2k do 10k.




Przykład "koprocesora matematycznego" :-)

Czas przejść do zadania praktycznego. Zbudujemy taki układ:

ATmega 8 - przykład wykorzystania interfejsu RS-232 do komunikacji z komputerem.


Poniżej program pokazujący transmisję danych z wykorzystaniem przerwań, by nie blokować mikrokontrolera. Program ma za zadanie:
  • odebrać liczbę wysłaną z komputera za pomocą RS-232,
  • dokonać obliczeń funkcji kwadratowej podstawiając odebraną liczbę za X,
  • wysłać za pomocą RS-232 do komputera ciąg znaków reprezentujących obliczony wynik funkcji.
Czyli będzie to prosty koprocesor.


Rezultat działania programu, możesz zobaczyć na filmie umieszczonym pod koniec artykułu.

/* 

Program realizujący obliczanie i wysłanie przez RS-232 wyniku funkcji 
kwadratowej y = 0.3187x^2 + 2x - 7 na podstawie x odebranego 
wcześniej także za pomocą RS-232.

Szczegóły: http://mikrokontrolery.blogspot.com/2011/03/rs-232-atmega8-komputer-terminal.html

Mikrokontroler: Atmega8
Autor: Dondu
Data: 2012.11.30

*/

//#include <stddef.h>
#include <avr\io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>

//zmienne dot. odbioru danych
volatile unsigned char odb_x;       //odebrana liczba X
volatile unsigned char odb_flaga =0;//flaga informująca main o odebraniu liczby

//bufor znaków ze wzorem funkcji, który wysyłamy po starcie programu
volatile unsigned int usart_bufor_ind;           //indeks bufora nadawania
char usart_bufor[30] = "y = 0.3187x^2 + 2x - 7"; //bufor nadawania

void usart_inicjuj(void)
{
 //definiowanie parametrów transmisji za pomocą makr zawartych w pliku
 //nagłówkowym setbaud.h. Jeżeli wybierzesz prędkość, która nie będzie 
 //możliwa do realizacji otrzymasz ostrzeżenie: 
 //#warning "Baud rate achieved is higher than allowed"

 #define BAUD 57600        //tutaj podaj żądaną prędkość transmisji
 #include <util/setbaud.h> //linkowanie tego pliku musi być 
                           //po zdefiniowaniu BAUD
 
 //ustaw obliczone przez makro wartości
 UBRRH = UBRRH_VALUE;  
 UBRRL = UBRRL_VALUE;
 #if USE_2X
   UCSRA |=  (1<<U2X);
 #else
   UCSRA &= ~(1<<U2X);
 #endif


 //Ustawiamy pozostałe parametry moduł USART
 //U W A G A !!!
 //W ATmega8, aby zapisać do rejestru UCSRC należy ustawiać bit URSEL
 //zobacz także: http://mikrokontrolery.blogspot.com/2011/04/avr-czyhajace-pulapki.html#avr_pulapka_2 
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);  //bitów danych: 8
                                                //bity stopu:  1
                                                //parzystość:  brak
 //włącz nadajnik i odbiornik oraz ich przerwania odbiornika
 //przerwania nadajnika włączamy w funkcji wyslij_wynik()
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE); 
}


//--------------------------------------------------------------


ISR(USART_RXC_vect)
{
 //przerwanie generowane po odebraniu bajtu
 odb_x = UDR;   //zapamiętaj odebraną liczbę
 odb_flaga = 1; //ustaw flagę odbioru liczby dla main()
}


//--------------------------------------------------------------

ISR(USART_UDRE_vect){

 //przerwanie generowane, gdy bufor nadawania jest już pusty, 
 //odpowiedzialne za wysłanie wszystkich znaków z tablicy usart_bufor[]

 //sprawdzamy, czy bajt do wysłania jest znakiem końca tekstu, czyli zerem
 if(usart_bufor[usart_bufor_ind]!= 0){

  //załaduj znak do rejestru wysyłki i ustaw indeks na następny znak
  UDR = usart_bufor[usart_bufor_ind++]; 

 }else{

  //osiągnięto koniec napisu w tablicy usart_bufor[]
  UCSRB &= ~(1<<UDRIE); //wyłącz przerwania pustego bufora nadawania
 }
}


//--------------------------------------------------------------


void wyslij_wynik(void){

 //funkcja rozpoczyna wysyłanie, wysyłając pierwszy znak znajdujący się
 //w tablicy usart_bufor[]. Pozostałe wyśle funkcja przerwania, 
 //która zostanie wywołana automatycznie po wysłaniu każdego znaku.

 //dodaj do tekstu wyniku znaki końca linii (CR+LF), by na 
 //ekranie terminala wyniki pojawiały się w nowych liniach
 unsigned char z;
 for(z=0; z<30; z++){
  if(usart_bufor[z]==0){   //czy to koniec takstu w tablicy
   //tak znaleziono koniec tekstu, dodajemy znak CR
   usart_bufor[z]   = 13;  //znak powrotu karetki CR (Carrige Return)
   usart_bufor[z+1]  = 10; //znak nowej linii LF (Line Feed)
   usart_bufor[z+2]  = 0;  //znak końca ciągu tekstu w tablicy
   break;
  }
 }


 //Zaczekaj, aż bufor nadawania będzie pusty
 while (!(UCSRA & (1<<UDRE))); 

 //bufor jest pusty można wysłać

 //następny znak do wysyłki to znak nr 1
 usart_bufor_ind = 0;

 //włącz przerwania pustego bufora UDR, co rozpocznie transmisję
 //aktualnej zawartości bufora 
 UCSRB |= (1<<UDRIE);

}

//--------------------------------------------------------------


int main(void)
{
 usart_inicjuj(); //inicjuj moduł USART (RS-232)
 sei();           //włącz przerwania globalne

 wyslij_wynik();  //na początku wysyłamy text wzoru, który po 
                  //resecie jest w tablicy usart_bufor[]

 while(1){

  //tutaj Twój program ....

  //czekamy na informację o odebraniu danej nie blokując mikrokontrolera
  if(odb_flaga){

   odb_flaga = 0; //zgaś flagę

   //wykonaj obliczenia i wynik przekształć na znaki ładując do 
   //bufora usart_bufor[]
   sprintf(usart_bufor, "%f", 0.3187 * odb_x * odb_x + 2 * odb_x - 7);

   wyslij_wynik();  //rozpocznij wysyłanie wyniku przez RS-232
  }

  //w tym czasie można wykonywać dowolny program
  //umieść go tutaj lub przed if() powyżej
 }
}


Do pobrania: Kompletny projekt AVR Studio 4 + plik HEX dla 16MHz




Testujemy programem terminala

Do kontroli komunikacji oraz wysyłania i odbierania danych na komputerze wykorzystamy program Realterm. To bardzo rozbudowany w porównaniu z zawartym w systemie Windows Hyper Terminal'u.
Możesz oczywiście wykorzystać dowolny inny program terminala.

Po uruchomieniu programu musisz ustawić parę opcji. Zaczniemy od zakładki Display:

RealTerm - Ustawienia w zakładce Display.

Następnie w zakładce Port ustawiamy takie same parametry transmisji jakie ustawiliśmy w programie mikrokontrolera:

RealTerm - Ustawienia w zakładce Port.

Włączamy nasz mikrokontroler i naszym oczom powinien ukazać się przesłany przez niego tekst wzoru:

RealTerm - Odbiór danych z mikrokontrolera.

Jeżeli napis się nie ukazał, powinieneś sprawdzić swój projekt dokładnie. Poniżej opisałem najczęściej występujące problemy.

Zanim zaczniemy testować dalej włączymy opcję Display as: Ansi w zakładce Display, po to by nie było widać znaków sterujących.

Czas wypróbować jak działa nasza projekt. W tym celu za pomocą zakładki Send wyślemy liczbę z zakresu od 0 do 255. Mikrokontroler odbierze liczbę, obliczy wartość funkcji i zwróci wynik:

RealTerm - Wysłanie danej do mikrokontrolera.

Za każdym razem, gdy wyślesz liczbę, natychmiast otrzymasz wynik funkcji. Oznacza to, że komunikacja przebiega prawidłowo.

Działanie układu możesz zobaczyć na poniższym filmie (ustaw sobie najwyższą rozdzielczość z możliwych):





Pozostałe tryby pracy USART

Moduł USART ma spore możliwości i wiele różnych ustawień, nie będę się na ten temat rozpisywał, bo musiałbym napisać książkę, a ponieważ jest już sporo literatury na ten temat więc pozwolicie, że swój czas poświęcę na inne ważniejsze artykuły. Bardzo dokładnie opisał to Tomek Francuz w swojej książce. Można także posiłkować się dokumentacją mikrokontrolera.




Najczęściej występujące problemy

W trakcie projektowania i testów, możesz się natknąć na kilka problemów.

Brak lub niepoprawna komunikacja

Z tym interfejsem wieże się spora ilość miejsc, w których można popełnić błąd skutkujący brakiem komunikacji. Oto najważniejsze z nich:
  1. zapominanie o tym, iż w niektórych mikrokontrolerach dwa różne rejestry mogą być pod tym samym adresem, patrz: Pułapki AVR'ów,
  2. ustawienie różnych parametrów transmisji w obu urządzeniach,
  3. stosowanie niestabilnego (niedokładnego) źródła zegara taktującego mikrokontroler, szczególnie w przypadku pracy USART w trybie asynchronicznym,
  4. błędne połączenie urządzeń w zależności od posiadanego przewodu (prosty lub krzyżowy),
  5. zbyt długi przewód łączący oba urządzenia w stosunku do wybranej prędkości transmisji,
  6. kiepskiej jakości przewody,
  7. zbyt duże zakłócenia zewnętrzne.
Pomocne w rozwiązywaniu problemów komunikacji jest okienko Status:

RealTerm - Okienko statusu linni RS-232.

Jeżeli coś będzie sygnalizowane na czerwono powinieneś się nad tym zastanowić.

Problem liczb i znaku zapytania w terminalu

Jeżeli wysyłasz do terminala liczby w postaci kodów ASCII, możesz się natknąć na problem pojawiającego się w zamian jedynie znaku zapytania. Rozwiązanie problemu znajdziesz tutaj: Problem znaku zapytania podczas konwersji float do znaków ASCII

Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

Podłączenie karty pamięci SD

Autor: drzasiek
Redakcja: dondu

Drzaśkowy pamiętnik: Spis treści


Budując system z mikrokontrolerem, często zachodzi potrzeba magazynowania większej ilości informacji, które mogą być odczytywane i/lub zapisywane w czasie działania programu, i nie są gubione w czasie gdy odłączymy zasilanie,

Niekiedy wystarcza do tego wbudowana pamięć EEPROM, ale nie zawsze. Małe mikrokontrolery posiadają zwykle od kilkuset bajtów do kilku/kilkunastu KB pamięci EEPROM lub jej nie posiadają wcale.

Dlatego szukamy taniego i łatwo dostępnego nośnika o dużej pojemności.

Świetnym rozwiązaniem okazują się wszechobecne karty pamięci SD, które oferują bardzo duże pojemności, małe wymiary, niską cenę oraz łatwą obsługę przez interfejs SPI.

Garść wiedzy o kartach SD, dokumentację standardu oraz jak kartę podłączyć do płytki stykowej znajdziesz w artykule: Karta SD


Karta SD z systemem FAT

Obsługa systemu plików na karcie pamięci nie jest wcale taka prosta. Nie należy się jednak tym zrażać. No bo po co wyważać otwarte drzwi?

W sieci można znaleźć kilka wersji darmowych bibliotek do obsługi kart pamięci z systemem FAT/FAT32.
Jedną z najlepszych, prostych w obsłudze oraz co najważniejsze ciągle rozwijanych jest biblioteka FatFS oraz jej okrojony odpowiednik przeznaczony na mikrokontrolery, czyli Petit FatFs.

W artykule tym przedstawię proste sposoby podłączenia karty pamięci do mikrokontrolera Atmega8 oraz sposób implementacji Petit FatFs.



Magistrale (interfejsy)


Karty SD posiadają dwie magistrale:
  • SDBus - szybsza, 4 bitowa magistrala,
  • SPI - wolniejsza, ale za to bardzo popularna.
W niniejszym artykule pokazuję sposób wykorzystania karty poprzez interfejs SPI.



Zasilanie

Zasilanie karty SD może mieścić się w pewnych przedziałach:
  • 2V - 3,6V dla komend inicjalizacji, 
  • 2,7V - 3,6V podczas przesyłania danych oraz pozostałych komend.
Dla niniejszego artykułu wykorzystuję najczęściej stosowany poziom napięcia jakim jest 3,3V. To poziom napięcia, który zapewnia bezpieczne użytkowanie karty, a znaczna część mikorkontrolerów może z nim także pracować.




Pinologia

Karta SD posiada wyprowadzeń:
  • 9  - w wersji SD
  • 11 - w wersji mini SD,
  • 8  - w wersji micro SD.


Pinologia (wyprowadzenia) karty SD.

Pinologia (wyprowadzenia) karty mini SD.   Pinologia (wyprowadzenia) karty mikro SD.


Nas interesują oznaczenia w drugiej kolumnie na powyższych rysunkach, czyli dla interfejsu SPI:


VDDZasilanie karty pamięci (+)
VSS1 i VSS2GND (masa)
DIData Input (szeregowe wejście danych)
DOData Output (szeregowe wyjście danych)
SCLKsygnał taktujący transmisję (sygnal zegarowy)
CSChip Select (w stanie niskim uruchamia bufory I/O karty)





Podłączamy kartę SD do mikrokontrolera

Czas więc podłączyć kartę pamięci do mikrokontrolera.

Trzeba jednak pamiętać o poziomach napięć sygnałów i ich ewentualnego dopasowania (konwersji).

Najprostszym rozwiązaniem jest zasilanie zarówno mikrokontrolera jak i karty pamięci takim samym napięciem, np. 3,3V.

Jednak nie zawsze mikrokontroler może być zasilany takim napięciem, a to ze względu na:
  • własne ograniczenia (brak możliwości pracy z takim napięciem),
  • potrzebę zasilania mikrokontrolera napięciem większym od 3,6V (maksymalne dla karty SD) np. 5V z powodu ustawionej dużej prędkości mikrokontrolera lub wymogów dot. napięcia zasilania  podłączonych do niego innych układów peryferyjnych..

Zobaczmy więc jakie mamy ograniczenia dla mikrokontrolera ATmega8 w wersji podstawowej oraz wersjach A i L:

  • ATmega8 oraz ATmega8L:


ATmega8, ATmega8L - zakresy napięć zasilania.
Rys. ATmega8, ATmega8L - zakresy napięć zasilania.


  • ATmega8A jest podobnie jak w ATmega8L:


ATmega8A - zakresy napięć zasilania.
Rys. ATmega8A - zakresy napięć zasilania.

ale niestety zależy także od prędkości zegara jakim taktujemy ATmega8A:


ATmega8A - zakresy napięć zasilania w zależności od częstotliwości zegara (F_CPU).
Rys. ATmega8A - zakresy napięć zasilania
w zależności od częstotliwości zegara (F_CPU).

Jaki widzisz wiele czynników trzeba brać pod uwagę ustalając napięcie zasilania mikrokontrolera, przez co często trzeba mocno kombinować.



Mikrokontroler 3,3V - karta SD 3,3V

Rozważmy na początek najprostszy przypadek, czyli zasilanie zarówno karty pamięci jak i mikrokontrolera napięciem 3,3V.


Schemat podłączenia karty pamięci SD do mikrokontrolera Atmega8 - wspólne napięcie zasilania  3,3V.
Rys. Schemat podłączenia karty pamięci SD do mikrokontrolera Atmega8
(wspólne napięcie zasilania  3,3V).


Powyższy schemat przedstawia najprostszy sposób połączenia mikrokontrolera i karty.

W praktyce (choć nie jest to konieczny warunek) powinno się stosować podciągnięcia do zasilania (wszystkich linii odpowiedzialnych za komunikację) za pomocą zewnętrznych rezystorów, aby zapobiegać stanom nieustalonym na liniach transmisyjnych np. tuż po włożeniu karty do złącza, ale zanim jeszcze układ nadrzędny (MASTER) rozpocznie komunikację z kartą.

Należy więc schemat wzbogacić następująco:


Schemat podłączenia karty pamięci SD do mikrokontrolera (wspólne napięcie zasilania  3,3V) wraz z rezystorami podciągającymi.
Rys. Schemat podłączenia karty pamięci SD do mikrokontrolera(wspólne napięcie zasilania  3,3V) wraz z rezystorami podciągającymi.



Wartości rezystorów podciągających można dobrać typowo z zakresu 4.7-10k.

Pełne podłączenie karty pamięci do mikrokontrolera ATmega8A zasilanego napięciem 3,3V.


Kompletny schemat ATmega8A + karta SD + rezystory podciągające (wspólne zasilanie 3,3V).
Rys. Kompletny schemat ATmega8A + karta SD + rezystory podciągające
(wspólne zasilanie 3,3V).






Mikrokontroler 5V - karta SD 3,3V


Co zrobić, gdy z jakichś względów mikrokontroler musi być zasilany napięciem wyższym, np. 5V?

Karta SD na wejściach akceptuje poziomy z zakresu od Vss-0,3V do Vdd+0,3V zatem można przy zasilaniu karty napięciem 3,3V wysyłać do niej sygnały napięciowe z zakresu od -0,3V do 3,6V.

Stan wysoki będzie rozpoznawany od ok. 0,625Vdd, czyli w tym przypadku od 2V do 3,6V, zaś stan niski będzie rozpoznawany od 0,25Vdd w dół, czyli od -0,3V do 0,82V.


Rozwiązanie 1: rezystor

Oto najprostsze (chociaż nie zalecane) rozwiązanie. Bardziej można je stosować jako rozwiązanie awaryjne/testowe:

Mikrokontroler zasilany 5V, karta SD zasilana 3,3V+ rezystory (szeregowo) dostosowujace poziom sygnałów.
Rys. Mikrokontroler zasilany 5V, karta SD zasilana 3,3V
+ rezystory (szeregowo) dostosowujace poziom sygnałów.


Układ działa na zasadzie stabilizatora parametrycznego na diodzie zenera:

Schemat stabilizatora parametrycznego.
Rys. Schemat stabilizatora parametrycznego.


Literatura:

Zaraz, zaraz! Ale diod nie widać na wcześniejszym schemacie!
Owszem - wykorzystuje się tutaj wbudowane na wejściach karty pamięci diody zabezpieczające.

Taki układ działa na liniach MOSI, CLK oraz CS.


Ale po co rezystor na linii Miso?

Przecież jest to wejście danych dla mikrokontrolera, a więc wyjście karty pamięci. Skoro karta zasilana jest napięciem 3,3V, będą tam sygnały z przedziału 0V do 3,3VDlatego rezystor ten nie jest konieczny jednakże pod warunkiem, że nie będziemy programować mikrokontrolera, gdy podłączona jest karta pamięci.

Odłączanie karty pamięci podczas każdego programowania jest kłopotliwe, stąd potrzebny jest rezystor zabezpieczający linię DO karty, ponieważ w trakcie programowania na linii MISO mikrokontrolera wystąpią napięcia z przedziału 0V-5V.


Jak dobrać rezystory?

Tutaj byłbym ostrożny. Ja użyłem rezystorów 470R. Takie rozwiązanie nadaje się raczej dla wolniejszych prędkości transmisji.

Poniżej przebiegi CLK dla częstotliwości 1, 2, 4 i 8 MHz na wyprowadzeniach karty pamięci podłączonej według powyższego schematu:


Przebiegi na linii CLK dla częstotliwości 1MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 1MHz.



Przebiegi na linii CLK dla częstotliwości 2MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 2MHz.


Przebiegi na linii CLK dla częstotliwości 4MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 4MHz.


Dla 4MHz transmisja już się posypała.

Ale dlaczego? Jak widać na powyższym oscylogramie poziom niski wypada na granicy ok. 0,9V. Jak podawałem na początku, stan niski dla zasilania karty napięciem 3,3V jest rozpoznawany z przedziału -0,3V do ok. 0,82V, zatem nic dziwnego, że przy prędkości transmisji 4MHz taki układ już się nie działa prawidłowo.



Przebiegi na linii CLK dla częstotliwości 8MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 8MHz.

Dla 8MHz, czyli maksymalnej częstotliwości zegara SPI ATmega8 jak widać wygląda to jeszcze gorzej.
Dolny offset (przesunięcie w górę względem 0V) sięga już ok. 1,5V  (strasznie dużo!), zatem nie ma szans na prawidłowe rozpoznawanie poziomów napięć przez kartę SD.


Wnioski:
  1. Sposób ten jest dość ryzykowny i w łatwy sposób można uszkodzić kartę pamięci.
  2. Diody zenera na wejściu karty to diody o napięciu zenera ok. 3,6V (wynika to z max napięcia zasilania karty) stąd też przy zasilaniu karty napięciem 3,3V mieścimy się na styk w granicy napięcia VCC+0.3V jakie można podać na wejście karty.


Rozwiązanie 2: rezystor + dioda

Napięcie na wejściach można zmniejszyć, stosując zewnętrzną diodę zenera, na napięcie 2,7 - 3,6V.

Najlepiej jednak trzymać się w środku przedziału, ponieważ tak jest najbezpieczniej.

Mając za to podwójne zabezpieczenie, można pokusić się o ciut mniejsze rezystory. Ja zastosowałem rezystory 220Ω oraz diody zenera BZX553 o napięciu zenera 3V.


Mikrokontroler zasilany 5V, karta SD zasilana 3,3V + rezystory i diody dostosowujace poziom sygnałów.
Rys. Mikrokontroler zasilany 5V, karta SD zasilana 3,3V
+ rezystory i diody dostosowujace poziom sygnałów.


Tak wyglądają przebiegi na linii CLK dla następujących szybkości transmisji:


Przebiegi na linii CLK dla częstotliwości 1MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 1MHz.


Przebiegi na linii CLK dla częstotliwości 2MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 2MHz.


Przebiegi na linii CLK dla częstotliwości 4MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 4MHz.

Jak widać dla 4MHz przy tym rozwiązaniu występuje mniejszy offset od dołu niż dla rozwiązania poprzedniego. Dla 4MHz przy tym sposobie podłączenia karty transmisja nadal ma prawo zadziałać.


Przebiegi na linii CLK dla częstotliwości 8MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 8MHz.

Przy 8MHz offset jest już za duży i transmisja się posypała.




Rozwiązanie 3: dzielnik rezystancyjny

Równie proste, ale zdecydowanie lepsze niż rozwiązania poprzednie.

Skoro trzeba zmniejszyć napięcie, to chyba pierwszym sposobem jaki przychodzi do głowy elektronikowi jest zastosowanie dzielnika napięcia.

Ale jak dobrać wartości rezystancji?

Idealny rezystor posiada tylko jeden parametr: rezystancję. W praktyce posiada jeszcze indukcyjność i pojemność pasożytniczą. Zatem układ dzielnika napięcia, który dla rezystora idealnego widziany jest tak:


Dzielnik rezystancyjny idealny.
Rys. Dzielnik rezystancyjny idealny.


w praktyce dla rezystora wygląda tak (tzw. układ zastępczy):


Dzielnik rezystancyjny rzeczywisty.
Rys. Dzielnik rezystancyjny rzeczywisty.


Dodatkowo każde wejście karty posiada swoją pojemność i to wcale nie małą ze względu chociażby na pojemność złączową i pasożytniczą diod na wejściu.

Jak widać może się z tego zrobić filtr LC lub RC lub jakiś inny mutant :-)

Zakładając dolnoprzepustowy filtr RC, częstotliwość graniczna filtru będzie malała wraz ze wzrostem rezystancji.

Stosując zatem rezystory o dużych wartościach zmniejszamy sobie pasmo przepustowości takiego dzielnika napięciowego.

Stąd wniosek: Im mniejsze wartości rezystancji, tym lepsze pasmo.

Ale nie ma nic za darmo:

Stosując rezystory o małych wartościach zwiększamy płynące prądy.

I tutaj powstaje pytanie: Jakie wartości rezystancji użyć, żeby nie uszkodzić wyjść mikrokontrolera, ale mieć możliwie najszybszą transmisję danych?

Jako, że prezentowany przykład dotyczy ATmega8, zaglądamy co mówi dokumentacja:


Nieprzekraczalne wartości najważniejszych parametrów mikrokontrolera ATmega8
Rys. Nieprzekraczalne wartości
najważniejszych parametrów mikrokontrolera ATmega8.

Jak widać maksymalny prąd pojedynczego pinu mikrokontrolera może wynieść 40mA.

Jednakże nie znaczy to, że możemy ustawić pin jako wyjście i pobierać z niego godzinami prąd 40mA i wszystko będzie w porządku. Producent podaje tę wartość w punkcie „Absolute Maximum Ratings”, czyli wartości, których przekroczenie skutkuje uszkodzeniem mikrokontrolera. Dlatego dla bezpieczeństwa przyjmijmy prąd 20mA (0,02A).

Teraz wykonamy proste obliczenie z prawa Ohma:

R = U / I
R = 5V / 0,02A = 250Ω

Czyli przy napięciu wejściowym 5V, aby popłynął prąd nie większy niż 20mA należy użyć rezystory o łącznej rezystancji szeregowej nie mniejszej niż 250Ω.

Teraz należy dobrać rezystory o dostępnych i dość popularnych wartościach. Ja wybrałem:
R1 = 100Ω
R2 = 220Ω

I = U / R
I = 5V / (110Ω + 220Ω) ≈ 0,0156A ≈ 15,6mA 

oraz:

Uwyj = 5V • 220Ω / (110Ω + 220Ω)  ≈  3,44V


Dla takich wartości prąd pobierany z wyjścia mikrokontrolera nie przekroczy 16mA, a napięcie na wyjściu dzielnika wyniesie ok. 3,44V, zatem mieszczę się spokojnie w dopuszczalnych granicach.

Nanosimy wartości elementów na schemat:


Mikrokontroler zasilany 5V, karta SD zasilana 3,3V + dzielniki rezystorowe dostosowujace poziom sygnałów.
Rys. Mikrokontroler zasilany 5V, karta SD zasilana 3,3V
+ dzielniki rezystorowe dostosowujace poziom sygnałów.


i testujemy otrzymując następujące przebiegi na lini CLK:

1MHz:

Przebiegi na linii CLK dla częstotliwości 1MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 1MHz.



2MHz

Przebiegi na linii CLK dla częstotliwości 2MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 2MHz.



4MHz


Przebiegi na linii CLK dla częstotliwości 4MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 4MHz.



8MHz

Przebiegi na linii CLK dla częstotliwości 8MHz.
Rys. Przebiegi na linii CLK dla częstotliwości 8MHz.



Jak widać rozwiązanie to jest najlepszym z wszystkich dotychczas przeze mnie przedstawionych, a transmisja przebiega poprawnie nawet przy 8MHz.



Przyczyny problemów?

Jedną z najczęściej spotykanych przyczyn kłopotów z komunikacją po SPI wraz z konwersją napięć jest nieodpowiednie dobranie układu konwertującego do zastosowanej częstotliwości transmisji danych.

Drugą przyczyną może być błędny odczyt stanu wysokiego na linii MISO przez  mikrokontroler. Zasilając kartę SD napięciem 3,3V, a  mikrokontroler napięciem 5V, poziom 3,3V na wejściu  mikrokontrolera powinien być odczytywany jako wysoki.

3,3V/5V = 0,66

Zdarzyć się jednak może, że napięcie zasilania karty wyniesie nieco mniej, zaś mikrokontrolera nieco więcej i w konsekwencji mogą występować błędy.




Rozwiązanie 4: bufor

Rozwiązaniem wszelkich problemów związanych z poziomami napięć jest zastosowanie buforów na liniach pomiędzy kartą pamięci i mikrokontrolerem, np. popularny bufor SN74LS07. Jest to układ scalony zawierający w sobie 6 buforów z wyjściem typu OC (ang. open collector).


Bufor SN74LS07.
Rys. Bufor SN74LS07.



Open collector (otwarty kolektor) oznacza, że kolektor wyjściowego tranzystora NPN nie posiada wewnętrznego podłączenia do stanu wysokiego. Poniżej schemat wewnętrzny pojedynczej bramki w układzie SN74LS07. Zauważ, że tranzystor ten ma kolektor podłączony jedynie do wyjścia oznaczonego Output:


Wewnętrzna struktura pojedynczego bufora 74LS07.
Rys. Wewnętrzna struktura pojedynczego bufora SN74LS07.


Układ z wyjściem OC może jedynie zewrzeć wyjście do masy (logiczne zero) lub pozostawić je w stanie wysokiej impedancji więc żeby była to logiczna jedynka musimy zastosować zewnętrzny rezystor podciągający.

Podobnie występują również układy OD (open Drain) w przypadku układu zbudowanego na tranzystorach polowych.

Zastosowanie bufora OC (lub OD) daje możliwość elastycznego dostosowania odpowiedniego poziomu napięcia stanu wysokiego na wyjściu bufora, podciągając wyjście przez rezystor zewnętrzny do odpowiedniej szyny napięcia zasilania.

Maksymalny prądy wyjściowy w stanie niskim dla układu SN74LS07 wynosi 40mA. Przy zasilaniu układu napięciem 5V, rezystor podciągający (czyli rezystor obciążenia dla wyjścia OC) może mieć minimalną wartość (liczymy prawem Ohma):

R = U / I

R = 5V / 0,04A = 125Ω

Nie należy jednak stosować tak małych rezystancji, by zbytnio nie obciążać układu, ani źródła zasilania. Dlatego bezpieczną wartością będzie przyjęcie wartości rezystancji z przedziału 470Ω - 1kΩ.


Stosuj bufory gdy musisz mieć absolutną pewność poprawnego działania przy dużych częstotliwościach.




Przykład czytnika kart SD

Poniżej przedstawiono przykładowy schemat podłączenia karty pamięci do mikrokontrolera zasilanego napięciem 5V przy zastosowaniu bufora (translatora napięć) na układzie SN74LS07.


Mikrokontroler zasilany 5V, karta SD zasilana 3,3V + bufor 74LS07 z rezystorami dostosowujacy poziom sygnałów.
Rys. Mikrokontroler zasilany 5V, karta SD zasilana 3,3V
+ bufor 74LS07 z rezystorami dostosowujacy poziom sygnałów.

I na zakończenie artykułu przedstawiam schemat i kod programu do bardzo prostego demonstracyjnego czytnika dokumentów tekstowych z karty pamięci, wykorzystując wyświetlacz 2x16 znaków z kontrolerem HD44780 i bibliotekę obsługi systemu FAT na kartach pamięci – Petit FatFS:


Kompletny schemat czytnika kart SD (mikrokontroler i bufor zasilane 5V, karta SD zasilana 3,3V).
Rys. Kompletny schemat czytnika kart SD
(mikrokontroler i bufor zasilane 5V, karta SD zasilana 3,3V).


Kompletny projekt (program) w Atmel Studio 6: sd_reader.rar

Mikrokontroler Atmega16 ustawiony na wewnętrzny oscylator RC 8MHz. Program otwiera plik tekstowy DOK1.txt znajdujący się w głównym katalogu na karcie pamięci i wyświetla tekst. Klawisz GORA i DOL służą do przewijania tekstu.


Przeczytaj take: Karta SD

Miłej zabawy z Petit FatFS!

Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.