Redakcja: dondu
Drzaśkowy pamiętnik: Spis treści
Na końcu poprzedniej części artykułu pisałem o szybko zmontowanym i zaprogramowanym układzie. Zanim jednak to zrobiłem, zasięgnąłem nieco teorii, żeby nie zrobić jakiegoś głupiego błędu przy podłączeniu.
Korzystając z tej specjalistycznej wyszukiwarki, wpisując nazwę mikrokontrolera ATmega8 znalazłem jego dokumentację czyli datasheet (j.ang).
Nie miałem wcześniej „przyjemności” czytać tego typu dokumentacji, więc zanim połapałem gdzie, co szukać, to minęło trochę czasu. Pierwszą rzeczą jaką uważałem za konieczną do prawidłowego podłączenia było znalezienie rozmieszczenia pinów mikrokontrolera.
To akurat poszło szybko ponieważ stosowny rysunek znajduje się na samym początku :-)
No dobrze. Wiem już gdzie co jest, ale jak i co tutaj podłączyć?
Skorzystanie z gotowego schematu przedstawionego w kursie jest proste, ale trzeba jeszcze zrozumieć co gdzie i dlaczego? W dokumentacji znalazłem więc odpowiedni rozdział, gdzie można znaleźć interesujące mnie wartości napięć i prądów, itd., a więc Electrical Characteristics:
Najbardziej istotna okazała się pierwsza tabelka w tym rozdziale, wraz z adnotacja obok. Zawiera ona maksymalne możliwe parametry zasilania, obciążenia prądowego oraz temperatury, jakie może wytrzymać ten mikrokontroler. Ich przekroczenie może doprowadzić do jego uszkodzenia.
Rys. Atmega8 - Najważniejsze parametry. |
Wiedząc na czym stoję i korzystając nieco z dokumentacji stabilizatora 7805 wykonałem zasilacz 5V:
Teraz to wszystko można znaleźć też tutaj: Zasilanie mikrokontrolera
Zegar taktujący
Z dokumentacji mikrokontrolera dowiedziałem się, że fabrycznie jest on ustawiony za pomocą bitów konfiguracyjnych (j.ang: fuse bits) tak, że jest taktowany przez wewnętrzny zegar RC o częstotliwości 1MHz. Nie musiałem więc stosować zewnętrznego kwarcu.
Bity konfiguracyjne opisałem na mojej stronie: Fuse Bits
Projektuję schemat
Pozostało już tylko prawidłowo podłączyć zasilanie, programator, diody oraz przycisk a więc standardowy układ do ćwiczeń dla początkującego:
Pobierz schemat Eagle: schemat_uc.rar
Jak policzyłem rezystor przy diodach LED? Użyłem kalkulatora: Kalkulatory elektronika
Skąd te dodatkowe elementy (kondensatory i rezystory) po lewej stronie schematu?
Wszystkiego możesz dowiedzieć się tutaj: Minimalne podłączanie pinów
Pierwszy program
Przyszedł więc czas na napisanie programu. Przykładowy program z kursu niewiele mi mówił, napisałem więc bardzo prosty program mrugający naprzemiennie dwoma diodami.
//częstotliwość zegara #define F_CPU 1000000L #include <avr/io.h> #include <util/delay.h> //definicja LED1 (do którego pinu podłączony LED1) #define LED1 PB0 //definicja LED2 (do którego pinu podłączony LED2) #define LED2 PB1 // Pętla główna void main(void) { //########### I/O ########### DDRB |= (1<<LED1) | (1<<LED2); //Ustawienie pinów sterujących diodami //jako wyjścia PORTB |= (1<<LED1); //Ustawienie stanu wysokiego na wyjściu //sterującym LED1 (stan początkowy) //########################## while (1) //Pętla główna { PORTB ^=(1<<LED1); //suma modulo 2 (XOR) stanu poprzedniego na porcie //pinu LED1 (zmiana stanu na przeciwny) PORTB ^=(1<<LED2); //suma modulo 2 (XOR) stanu poprzedniego na porcie //pinu LED2 (zmiana stanu na przeciwny) _delay_ms(1000); //opóźnienie 1000ms czyli 1s } }Pobierz projekt w AVR Studio: main1.rar
Oczywiście wyżej pokazany program jest to już wersja po kilkukrotnym poprawianiu, jak na początek przystało :-) , aż do otrzymania komunikatu:
Programowanie wg instrukcji z kursu, podłączenie prawidłowe a więc wszystko przebiegło pomyślnie, a dwie mrugające diody chyba nigdy wcześniej nie dawały mi tyle satysfakcji :-)
Następnie postanowiłem wykorzystać podłączony do atmegi przycisk do sterowania w jakiś sposób diodami. I tak na przykład powstał programik, który reagując na wciśnięty przycisk zatrzymywał mrugające diody:
//częstotliwość zegara #define F_CPU 1000000L #include <avr/io.h> #include <util/delay.h> //definicja LED1 (do którego pinu podłączony LED1) #define LED1 PB0 //definicja LED2 (do którego pinu podłączony LED2) #define LED2 PB1 //definicja KLAWISZ (do którego pinu podłączony KLAWISZ) #define KLAWISZ PC0 void main(void) { //########### I/O ########### DDRB |= (1<<LED1) | (1<<LED2); //Ustawienie pinów sterujących diodami // jako wyjścia PORTB |= (1<<LED1); //Ustawienie stanu wysokiego na wyjściu sterującym LED1 //(stan początkowy) DDRC &=~ (1<<KLAWISZ); //Ustawienie pinu klawisza jako wejście PORTC |= (1<<KLAWISZ); //włączenie rezystora podciągającego tzw. Pull_up //########################## while (1) //Pętla główna { if(PINC & (1<<KLAWISZ))//jeśli klawisz nie wciśniety { PORTB ^=(1<<LED1); //suma modulo 2 (XOR) stanu poprzedniego //na porcie i pinu LED1 (zmiana stanu na przeciwny) PORTB ^=(1<<LED2); //suma modulo 2 (XOR) stanu poprzedniego na porcie //pinu LED2 (zmiana stanu na przeciwny) _delay_ms(1000); //opóźnienie 1 s } } }
Pobierz projekt w AVR Studio: main2.rar
Takich programików powstało kilka, trudno je wszystkie tutaj przytaczać. Ale trzeba się rozwijać, więc poszedłem dalej, wykorzystując Timer do mrugania diodami. Ale o tym w kolejnej części mojego pamiętnika.
Drzaśkowy pamiętnik: Spis treści
Mam pytanie. Czemu za diodą led jest rezystor 1k omowy? Po pierwsze, to chciałbym zaznaczyć, że nie ogarniam tak 99% ; q. Patrzę w data sheety atmegi8, napięcie wychodzące - 5V, natężenie - 20mA. Liczę, liczę, prawo Ohma, Kirchhoffa - no wychodzi rezystor 100 omowy jak ulał. A proponujecie tysiąc. Wrzucam dane w circuit simulator - no 1k nie pasuje, dioda (3V) się nie świeci. Pomocy ; ).
OdpowiedzUsuńZanim Drzasiek odpowie zaglądnij do menu KALKULATORY ELEKTRONIKA. Znajdziesz tam kalkulator LEDów.
OdpowiedzUsuńByć może Drzasiek wykorzystywał LEDy o wysokiej jasności świecenia, które przy znacznie mniejszych prądach świecą bardzo jasno.
Szanowny Anonimowy
OdpowiedzUsuńTo, co policzyłeś zależy przede wszystkim od tego co i jak liczyłeś :) Rezystor w szeregu z diodą daje się po to, by ograniczyć prąd diody. Jednak dioda w szeregu z rezystorem to nie to samo co sam rezystor, więc nie możesz liczyć rezystora do diody podstawiając do wzoru z prawa Ohma jedynie napięcie zasilania oraz oczekiwany prąd. Ważnym parametrem jest spadek napięcia na diodzie oraz maksymalny prąd diody. Parametry te musisz odnaleźć w dokumentacji do diody, lub jeśli jej nie masz to przyjąć jakieś bezpieczne wartości. Spadek napięcia zależy od materiału, a więc od koloru świecenia diody. Można to sprawdzić nieco googlując, jaki kolor to jaki spadek napięcia. Przyjmuje się, że 20 mA jest prądem bezpiecznym dla większości diod, nie znaczy to jednak, że należy na siłę starać się aby płynął prąd 20 mA, gdyż większość LEDów świeci się już przy kilku mA. Wszystko zależy od wymagań projektu, do testów nie ma sensu jechać na maksymalnych obrotach.
A więc znając spadek napięcia na diodzie, odejmujesz go od napięcia zasilania.
Np:
U = Ucc - Ud
U = 5 V - 2.3V
U = 2.7V
Następnie otrzymaną wartość dzielisz przez oczekiwany prąd który ma popłynąć przez diodę (do obliczenia podajemy w amperach) i otrzymujesz wartość rezystancji, którą należy wpiąć w szereg z diodą LED.
Np:
R = U / Id
R = 2.7 V / 0.005 A
R = 540 [Omów]
Aaaa! Teraz już wszystko jasne i zupełnie inne liczenie ; ). Dzięki wielkie za pomoc!
OdpowiedzUsuńWitam! Jako początkujący mam parę pytań, wiem może ,,gópie'', ale chciałbym się dowiedzieć:
OdpowiedzUsuń1. Zamiast Atmegi8 mam pod ręką Atmege8A - dobrze widzę, że w Dokumentacji pobór prądu wynosi 3.6mA? Myślałem, że taki procek pobiera więcej.
2. Czy zasilacz od starego Siemensa ok 7,75V i 150mA starczy bezproblemu na zasilenie tego układu, a w przyszłości trochę bardziej rozbudowanych? Wiem, że LED pobiera ok 20mA co daje nam 40mA + procek, czy się mylę?
3. Czy Programując płytkę odłączyć zasilacz, mam programator USBasp?
Witaj!
OdpowiedzUsuńAd. 1
Nie podałeś dla jakiego napięcia zasilania, częstotliwości zegara i trybu pracy tę wartość odczytałeś, więc trudno odpowiedzieć jednoznacznie, ale prawdopodobnie nie pomyliłeś się.
Ad.2
Kombinujesz prawidłowo, czyli wystarczy. Dodam tylko, że LED wcale nie musi być zasilany 20mA. Przy 10mA może świecić niewiele gorzej niż przy 20mA. Wszystko zależy od zastosowanego LED. Są takie, które mają bardzo dużą jasność przy prądzie rzędu 2mA.
Ad. 3
Jeżeli masz osobne zasilanie i nie wykorzystujesz zasilania z USBasp, to nie musisz odłączać. Ważne jest, by masy były połączone. Innymi słowy nie powinno się łączyć równolegle dwóch źródeł zasilania.
Witam
OdpowiedzUsuńMam pytanie o 2 miejsca w kodzie:
1. DDRB |= (1<<LED1) | (1<<LED2)
DDRB to rejestr 8 bitowy w którym się ustawia czy porty PB0 do PB7 mają być wyjściami czy wejściami, natomiast LED1 i LED2 wskazująna konkretne wyprowadzenia PB0 i PB1 czyli przedstawiają raczej po 1 bicie. W związku z tym zastanawiam się czy w trakcie funkcji OR nie jest LED1 i LED2 przedstawiane jako 8 bitów z ustawianymi wartościami tylko na pozycjach odpowiadającymi wyprowadzeniom PB0 i PB1.
2. if(PINC & (1<<KLAWISZ))
Jest to warunek na klawisz nie wciśnięty, jak ma wyglądać warunek na wciśnięty przycisk??
1. Nie wiem, czy jest już późno i nie rozumiem pytania, albo po prostu je mało sprecyzowałeś.
OdpowiedzUsuńAle spróbuje zgadnąć o co mogło Ci chodzić. Rejestr DDRB jest 8 bitowy, każdy bit odpowiada za kierunek pracy danego pinu w porcie. Jeśli chcesz, aby rejestr/zmienna została załadowana tylko nową wartością, dajesz po jej nazwie znak = , np:
DDRB = 4;
lub analogiczny zapis:
DDRB = (1<<2);
Ale jeśli chcesz, aby wartość, która była w rejestrze/zmiennej zapisana nie uległa skasowaniu, a jedynie chcesz ustawić/skasować dany bit to możesz zapisać to w takiej postaci:
DDRB = DDRB | (1<<2);
Wtedy wartość rejestru będzie równa DDRB "lub" 00000100.
Język C umożliwia skrócony zapis takiego typu, czyli np. zapis w postaci:
DDRB = DDRB | 1;
można zapisać tak:
DDRB |= 1;
Podobnie z innymi operacjami, np jeśli do zmiennej licznik chcemy dodać wartość 2, możemy napisać to w taki sposób:
liczkik = licznik + 2;
lub w sposób skrócony:
licznik += 2;
2. Zaprzeczenie tego, co jest w nawiasie, czyli:
if(!(PINC & (1<<KLAWISZ)))
lub sposób bardziej jasny:
if((PINC & (1<<KLAWISZ))==0)
Ten komentarz został usunięty przez autora.
OdpowiedzUsuńWitam, jaka wersja AVR studio jest wykorzystywana do kompilowania programów ? Jak należy zmodyfikować program by ruszył pod attiny13 ? Czy problem może leżeć w rejestrze i/o ? Błąd jaki mi wyrzuca to ../Asd.c:15:10: warning: return type of 'main' is not 'int'
OdpowiedzUsuńTo moje pierwsze kroki w tym języku, dziękuję za wyrozumiałość.
To nie jest błąd tylko ostrzeżenie. main ma prototyp int main(), nie void main(). Często, tak jak w powyższych przykładach pisze się void, bo main w AVR nigdy się nie kończy, więc zwracanie wyniku nie ma sensu. To ostrzeżenie można zignorować, lub napisać dla spokoju int main. Powyższe przykłądy skompilujesz w czymkolwiek, musisz tylko dostosować nazwy rejestrów do tych, które są dostępne w użytym procku.
OdpowiedzUsuńWitam
OdpowiedzUsuńNa początek przedstawię swój fragment:
#define LED1 0x02
#define LED2 0x04
#define PRZ2 0x08
int main(void)
{
// Ustawianie wyjść
DDRB |= LED1;
DDRB |= LED2;
// Włączanie wyjść
PORTB |= LED1;
//Rezystory podciągające
PORTB |= PRZ2;
while (1) {
if ((PINB&PRZ2)) PORTB^=LED1|LED2;
}
Jako, że dopiero raczkuję z AVR (m.in. dzięki Wam idzie to całkiem przyjemnie) mam kilka pytań:
1) DDRB |= (1<<LED1) | (1<<LED2);
podzieliłem to na dwie instrukcje, wynik: objętość kodu wynikowego zmniejszona o 2 bajty (1 rozkaz?) - jakie są tego konsekwencje? Chodzi mi o to, czy zmniejszając kod nie dałem procesorowi więcej obliczeń (dwa polecenia), gdzie wg. poradnika jest to w jednym poleceniu - a dokładnie: jaka jest różnica w ASM pomiędzy tymi dwoma sposobami?
2) if(PINC & (1<<KLAWISZ))
zmieniłem to ze względu na stosowanie liczb hex - jednak aby to działało musiałem zastosować podwójny nawias - dlaczego? Czyżby operacja AND zwracała jakiś wynik (który jest brany pod uwagę przy pojedynczym nawiasie)?
Stosuję AtmelStudio + wbudowany symulator na ATTiny 13. Ze względu właśnie na wbudowany symulator nie zastosowałem delay.
Dzięki za poradniki - nie tylko ja, ale pewnie wiele osób z tego skorzysta :)
Pozdrawiam
codedigger
Witaj,
OdpowiedzUsuńCieszymy się, że artykuły są przydatne :-)
PYTANIE 1
----------
W Atmel Studio możesz podglądać kod assemblera generowany przez kompilator stąd możesz samemu sprawdzić, różnicę w wygenerowanym kodzie.
W pierwszym przypadku:
// Ustawianie wyjść
DDRB |= LED1;
DDRB |= LED2;
realizujesz osobno dwie operacje ustawiania bitów dlatego wygenerowany kod wygląda dla tego fragmentu tak:
SBI 0x17,1 Set bit in I/O register
SBI 0x17,2 Set bit in I/O register
W drugim przypadku w jednym rozkazie ustawiasz oba piny na raz:
DDRB |= (1<<LED1) | (1<<LED2);
dlatego kod wygląda tak:
IN R24,0x17 In from I/O location
ORI R24,0x14 Logical OR with immediate
OUT 0x17,R24 Out to I/O location
Za to działanie odpowiadają preprocesor i kompilator. Najpierw preprocesor na etapie przed kompilacją oblicza wartość wyrażenia:
(1<<LED1) | (1<<LED2)
i otrzymuje wynik:
0x14
a następnie kompilator realizuje algorytm dodania logicznego tej wartości do rejestru DDRB (kod wynikowy podałem wyżej).
Teraz widzisz skąd różnica w ilości kodu, a w konsekwencji czasu jego realizacji.
Czy w tym zakresie wszystko jasne?
Pytanie drugie wyjaśnię w następnym komentarzu.
PYTANIE 2
OdpowiedzUsuńNa początek dobra rada - nie stosuj liczb hex, tylko definicje pinów. To kolosalna zaleta, z kilku powodów:
- nie pomylisz bitów,
- kod łatwiej analizować po czasie, gdy się do niego wraca,
- osoba sprawdzająca ma ułatwione zadanie.
W Twoim przypadku podwójne nawiasy nie mają znaczenia. kod wygenerowany dla
if ((PINB&PRZ2)) PORTB^=LED1|LED2;
jest taki
LDI R25,0x06 Load immediate
SBIS 0x16,3 Skip if bit in I/O register set
RJMP PC-0x0001 Relative jump
IN R24,0x18 In from I/O location
EOR R24,R25 Exclusive OR
OUT 0x18,R24 Out to I/O location
RJMP PC-0x0005 Relative jump
a dla:
if (PINB&PRZ2) PORTB^=LED1|LED2;
jest dokładnie taki sam:
LDI R25,0x06 Load immediate
SBIS 0x16,3 Skip if bit in I/O register set
RJMP PC-0x0001 Relative jump
IN R24,0x18 In from I/O location
EOR R24,R25 Exclusive OR
OUT 0x18,R24 Out to I/O location
RJMP PC-0x0005 Relative jump
Proponuję potestować w kompilatorze CManiak na następującym kodzie:
#include <stdio.h>
int main(void){
#define PB3 3
#define KLAWISZ PB3
//symulujemy, że pin PB3 ma stan wysoki
unsigned char PINB = 0x08;
printf( "PINB = %d \n", PINB);
printf( "KLAWISZ = %d \n", KLAWISZ);
printf( "(PINB & KLAWISZ) = %d \n", (PINB & KLAWISZ));
printf( "(1<<KLAWISZ) = %d \n", (1<<KLAWISZ));
printf( "(PINB & (1<<KLAWISZ)) = %d \n\n", (PINB & (1<<KLAWISZ)));
if(PINB & KLAWISZ) printf("Warunek 1 spełniony. \n");
if(PINB & (1<<KLAWISZ)) printf("Warunek 2 spełniony. \n");
return 0;
}
Podsumowując oba pytania:
1. Poczytaj o preprocesorze.
2. Warto poczytać manual kompilatora GCC, chociażby pobieżnie, ale po to by mieć pojęcie, co w nim można znaleźć.
Mam pytanie odnośnie tego zapisu:
OdpowiedzUsuń1. DDRB |= (1<<LED1) | (1<<LED2)
Jak mam rozumieć "<<" bo to raczej nie jest przesunięcie w lewo. Gdzie znajdę przystępne informacje na temat definicji pinów? Na razie rozumiem ustawianie pinów za pomocą liczb hex. Z góry dziękuje za odpowiedź.
<< to przesunięcie w lewo: Przesuwanie bitow w lewo
OdpowiedzUsuńDefinicje znajdziesz w datasheet, ponieważ odpowiadają one nazwom pinów, rejestrów i ich bitów. Możesz także szukać w plikach kompilatora np. pliku iom8.h który zawiera definicja dla ATmega8.
Witam!
OdpowiedzUsuńSkoro << to przesunięcie w lewo to czemu (1<>LED1) daje wartość logiczną zero? Mógłbym prosić o dokładniejsze napisanie jak to działa?
Witam,
OdpowiedzUsuńPotrzebuję pomocy odnośnie ustawianie portów:
DDRB |= (1<<LED1)
Wcześniej używałem przypisanie heksadecymalnie DDRB = 0x03
Rozumiem przesuniecie bitowe jak i dodawanie OR | ale razem
kompletnie nie rozumiem. Zmienna LED1 jest konkretnym portem,
załóżmy że np PD0 czyli przesuwamy PD0 o 1 bit w lewo?.?.?.
I co tam robi dodawanie bitowe | ?
Donu Why? ;]
Pozdrawiam
Witaj,
UsuńBrakuje Ci wiedzy co kryje się pod zdefiniowanym PD0. Aby to sprawdzić sięgasz do pliku nagłówkowego z definicjami dla Twojego mikrokontrolera. W przypadku ATmega8 jest to plik iom8.h.
Znajdujesz w nim:
/* PORTD */
#define PD7 7
#define PD6 6
#define PD5 5
#define PD4 4
#define PD3 3
#define PD2 2
#define PD1 1
#define PD0 0
czyli w czasie kompilacji pod PD0 podstawiane jest zero, czyli de facto otrzymujesz:
DDRB |= (1<<0)
a to oznacza, że przesuniemy jedynkę o zero pozycji w lewo, czyli nadal otrzymamy jedynkę, a w zapisie binarnym 0b00000001
Spróbuj teraz pokazać jak to będzie w przypadku PD5.
Gdy odpowiesz, to ja dodam program do wypróbowania w CManiaku i obserwowania wyniku.
Czyli tak,
UsuńMamy 8 bitowy rejestr DDRD 0b00000000
z całej siły chcę ustawić kierunek wyjściowy na PD5
DDRB |= (1<<5) czyli tak 0b00010000 lub 0b00100000 ???
wiem że przesuwam ...... o 5 bitów w lewo
lecz problem polega na tym że nie wiem co.
Są 2 opcje :
1. to po prosty bit '1'.
2. Jest to 8 bitowy PD1 0b00000010
no i nie wiem po co to dodawanie |
Musisz mi wybaczyć mój brak wiedzy ale wybrałem złą książkę
"AVR & ARM7..." z góry dziękuję za Zainteresowanie i bezinteresowną Pomoc ;]
Pozdrawiam
Czytaj wolniej lub kilka razy ponieważ napisałem cyt.
Usuń"DDRB |= (1<<0)
a to oznacza, że przesuniemy jedynkę o zero pozycji w lewo ..."
Czyli w Twoim przypadku:
(1<<5) daje wynik 0b00100000
Poniżej obiecany program do sprawdzenia i próbowania w CManiaku:
unsigned char DDRD; //symulujemy rejestr DDRD
/* PORTD */
#define PD7 7
#define PD6 6
#define PD5 5
#define PD4 4
#define PD3 3
#define PD2 2
#define PD1 1
#define PD0 0
//funkcja konwersji liczby na ciąg znaków reprezentacji binarnej
const char *byte_to_binary(int x){
//wykorzystuje nagłówek string.h
int z; static char b[9]; b[0] = '\0'; for (z = 128; z > 0; z >>= 1){strcat(b, ((x & z) == z) ? "1" : "0");}; return b;
}
int main(void) {
//ustaw w DDRD bit PD0
DDRD |= (1<<PD0);
printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD
//ustaw dodatkowo bit PD5
DDRD |= (1<<PD5);
printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD
//podmień nową zawartość DDRD ustawiając od razu bity PD3, PD4 i PD7
DDRD = (1<<PD7) | (1<<PD4) | (1<<PD3);
printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD
return 0;
}
Dzięki Dondu!!!
UsuńTeraz ogarnąłem... takie banalne a zepsuło mi parę dobrych litrów krwi ;)
Jeszcze raz Dziękuję!
Hej,
OdpowiedzUsuńna schemacie z układem do podłączenia przy pinie 1, PC6(/RESET), widoczne kółko to oznaczenie negacji sygnału? Trzeba jakis dodatkowy układ negujący zastosować czy połączenie VCC przez R10k jest jakby negacją sygnału? a moze to oznaceznie czegos zupelnie innego?
Nie wiem jak to rozumieć, z góry dzięki
Przemek
Witaj.
UsuńTak, kółko oznacza negację. Pin RESET jest wejściem. Jeżeli nie byłoby negacji, oznaczało by to, że podanie jedynki (stan wysoki, zwarcie do Vcc, np. 5V) na ten pin spowodowałoby zresetowanie mikrokontrolera.
Ponieważ jednak jest negacja na tym pinie oznacza to, że zresetowanie mikrokontrolera następuje przy podaniu zera (stan niski, czyli zwarcie do masy).
Dlatego też normalnie pin ten jest podłączony przez rezystor do Vcc, by nie nastąpiło przypadkowe zresetowanie mikrokontrolera.
u mnie w Atmel Studio 6 (ver.: 6.1.2730)
OdpowiedzUsuńtrzeba było zamienić void main(void)
na int main(void)
i dodać na końcu return 0; bo inaczej program się nie budował.
Witam, gdybym chciał aby 3 LED mrugały jedna po drugiej? Męczę się z tym dłuższy czas i już nie mam pomysłów.Zadeklarowałem 3 diodę na PB2 dodałem instrukcję do pętli i mrugają raz jedna raz dwie... Pozdrawiam
OdpowiedzUsuń#define F_CPU 1000000L
#include
#include
#define LED1 PB0
#define LED2 PB1
#define LED3 PB2
void main(void)
{
//########### I/O ###########
DDRB |= (1<<LED1) | (1<<LED2) (1<<LED3);
PORTB |= (1<<LED1);
//##########################
while (1)
{
PORTB ^=(1<<LED1);
PORTB ^=(1<<LED2);
PORTB ^=(1<<LED3);
_delay_ms(1000);
}
}
Musimy jednak przejść na forum, bo system ucina znaki i kod staje się nieczytelny. Utwórz proszę więc nowy temat w dziale: Mikrokontrolery AVR
Usuńi wklej tutaj link do tematu na forum, gdy już go utworzysz.
http://www.elektroda.pl/rtvforum/viewtopic.php?p=13219331#13219331
UsuńPozdrawiam
Dodam tylko klikalny link, gdzie rozwiązaliśmy Twój problem: Atmega8 - Mruganie 3 LED
UsuńSiemka dlaczego pobrany od cb program "main2" po wgraniu na atmega8 zajmuje tylko 112 bajtów a po skopiowaniu tego co napisałeś i kompilacji w programie Code Blocks to samo zajmuje 3218 bajtów
OdpowiedzUsuńCodeBlocks - to już prehistoria :D
UsuńMoże w programie używasz liczb zmiennoprzecinkowydh (typy Double lub float)?
Poza tym musisz mieć włączoną optymalizację - masz?