Buduję pilota podczerwieni i mam problem z trybem powerdown.A wiec po włączeniu tego trybu pilot nadal pobiera 0,5mA prądu. Dla Ciekawości chciałem spróbować napisać usypianie pilota w ASM (to moje pierwsze spotkanie z ASM),ale niestety nie działa Czy ktoś mógłby zerknąć na tą procedurę w ASM (jest jako komentarz,bo badałem równolegle działanie mojej wstawki z poleceniem Powerdown bascoma).
Do wywoływania jest "sleep". Dawno w asm nie pisałem, ale to powinno wystarczyć
Małe podpowiedzi:
-przyciski możesz ułożyć w matrix - nie pamiętam jak to po polsku jest, ale oszczędza sporo pinów (http://www.atmel.org/dyn/resources/prod_documents/doc2532.pdf)
-używając mikrokontrolera z przerwaniem PinChange zaoszczędzisz energii. Ewentualnie zrób wybudzanie sygnałem - diody półprzewodnikowe do wejścia przerwania, aby wybudzały podczas nacisnięcia.
Wzbudzenie działa w ten sposób,że przed położenie Uc spać zmieniam wszystkie linie od przycisków na wyjściowe i wystawiam na nie zero. Natomiast na PD2 (int0) jest stan wysoki i to zmiana poziomu na nim budzi proca,po czym znowu zmieniam kierunki portów (nie wiem czy to jest własnie PinChange?)
Niestety to też nie działa. Nie wiem dlaczego bascomowe powerdown działa, a to w asm nie. 0x70 to jest st-by ,ale akurat teraz nie ma to znaczenia bo i tak nie chula:\
PinChange to przerwanie wewnętrzne - bez takich operacji jakie wykonujesz, ale przyznam, że nawet sprytne).
0x70 to wg. mojej dokumentacji PowerDown, ale może mam starą z błędem bo dawno je ściągałem. Wieczorem napiszę program i zobaczę co jest nie tak ... odpisze wieczorem do czego doszedłem...
mialem ten sam problem
https://www.elektroda.pl/rtvforum/topic1172302.html w tym przypadku dzialal kod, ale pozniej jak go dodalem calej reszcie juz nie dzialalo.
wydaje mi sie ze przerwania w bascomie sa troche zrabane (moze sie myle i tylko ja sobie nie potrafie z nimi poradzic)
Przerwania i powerdown w bascomie działają mi bez problemu (trzeba tylko pamiętać żeby w przerwaniu szybko wyłączać globalną obsługę przerwań lub przerwanie o INT). Ale chciałbym to zrobić w ASM i właśnie tu problem że nie chce ruszyć.
Według mojego kalkulatora 0x70 to 0b01110000 czyli według noty st-by
Przerwania i powerdown w bascomie działają mi bez problemu (trzeba tylko pamiętać żeby w przerwaniu szybko wyłączać globalną obsługę przerwań lub przerwanie o INT)
czyli czegos zapomnialem w moim kodzie?
sorry ze sie tak podpinam pod temat
2: Idle
+0000002C: B785 IN R24,0x35 In from I/O location
+0000002D: 7F8E ANDI R24,0xFE Logical AND with immediate
2: Idle
+0000002E: 6280 ORI R24,0x20 Logical OR with immediate
+0000002F: BF85 OUT 0x35,R24 Out to I/O location
2: Idle
+00000030: 9588 SLEEP Sleep
3: Powersave
+00000031: B785 IN R24,0x35 In from I/O location
+00000032: 6780 ORI R24,0x70 Logical OR with immediate
3: Powersave
+00000033: BF85 OUT 0x35,R24 Out to I/O location
+00000034: 9588 SLEEP Sleep
4: Powerdown
+00000035: B785 IN R24,0x35 In from I/O location
+00000036: 6281 ORI R24,0x21 Logical OR with immediate
4: Powerdown
+00000037: BF85 OUT 0x35,R24 Out to I/O location
+00000038: 9588 SLEEP Sleep
5: Stop
+00000039: CFFF RJMP PC-0x0000 Relative jump
Nie pasuje mi za bardzo, do dokumentacji.
magik128 wrote:
...(trzeba tylko pamiętać żeby w przerwaniu szybko wyłączać globalną obsługę przerwań lub przerwanie o INT)
I tu się mylisz - patrz dokumentacja AVR-ów.
Nie globalną, tylko INT, bo globalna sama się "wyłącza"
Teraz nie rozumie juz nic. Z tego co bascom robi w powerdown.Wygląda jakby tylko włączał zezwolenie na tryby uśpienia. Czy ja coś źle odczytuje? Czy kolega Zumek mógłby napisać w ASM przejście do ST-BY dla tego Attiny? Bo według mnie było by to tak:
Co do kolega Wader to nie rozumie tego kawałka ,a mianowicie działania zmienne przerwanie.Nie można odrazu w przerwaniu wyłączyć reakcje na to przerwanie?Zgodnie z tym co pisał kolega Zumek podczas obsługi przerwania globalne zezw jest wyłączone,ale u Ciebie po wyjściu z przerwania zezw globalne znowu jest włączone (o ile dobrze pamietam,zezwolenie włącza sie po wyjściu z przerwania), a INT reaguje na stan niski,dlatego pewnie znowu dostaje przerwanie,zanim zablokujesz INT0. Tak mi się przynajmniej wydaje.
Z tego co pamiętam to musisz jeszcze wyłączyć chyba watchdoga w fusebitach, też miałem z tym problem ale dawno, ale zeszło do tych parunastu uA Poszukaj w nocie.
O watchdogu wiedziałem ,ale on i tak jest fabrycznie wyłączony w fusebitach,wyłączyłem także komparator analogowy,ale ten program w ASM dalej nic nie zmienia:\ ,a bascomowe powerdown chodzi.Zaczynam podejrzewać że jest błąd w pliku attiny2313.dat ,a dokładnie z nazwą symboliczna rejestru MCUCR.
Zamień "in r24, MCUCR" na "in r24, 0x35" ... to wskazanie na adres w pamięci rejestru MCUCR. Wyeliminuje ewentualną pomyłkę w pliku deklaracji mikrokontrolera
Niestety ostatnio od kilku miesięcy mam bardzo mało czasu na swoje hobby i zabawę z prockami więc teraz tak z marszu ciężko mi sobie przypomnieć jak dokładnie działałem z tym PowerDown w swoim pilocie ale wkleję poniżej swój kod taki jaki działa do dzisiaj w tym moim pilociku i to bardzo dobrze działa - moż coś to pomoże. Niestety kod jest w C ale postaram się też wkleić to co jest później w asm po kompilacji:
// wyłączenie komparatora analogowego
// nie jest to zbyt konieczne jeśli nie są używane te piny w procesorze
// szczególnie jako wejścia analogowe (tu mogłoby to być pominięte)
ACSR SET (1<<ACD);
// WYŁĄCZENIE WATCHDOG'a - też konieczne tak naprawdę tylko wtedy
// gdy jest on używany (tu mogłoby to być pominięte)
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Turn off WDT
WDTCSR = 0x00;
// ustawienie trybu POWER-DOWN
MCUCR SET ((1<<SM0)|(1<<SM1));
// ustawienie pinu PORTD.2 (INT0) jako wejście
DDRD RESET (1<<2);
// podciągnięcie do 1
PORTD SET (1<<2);
// zezwolenie na przerwania INT0
GIMSK SET (1<<INT0);
// skasowanie flagi wystąpienia przerwania INT0
EIFR SET (1<<INTF0);
while (1)
{
// globalne zezwolenie na przerwania
sei();
// wprowadzenie procesora w tryb POWER-DOWN
sleep_mode();
}
dodane są komentarze więc może one coś wyjaśnią - jak należy postępować przed wprowadzeniem procka w stan śpiączki klinicznej
// wyłączenie komparatora analogowego
// nie jest to zbyt konieczne jeśli nie są używane te piny w procesorze
// szczególnie jako wejścia analogowe (tu mogłoby to być pominięte)
ACSR SET (1<<ACD);
254: 47 9a sbi 0x08, 7 ; 8
// WYŁĄCZENIE WATCHDOG'a - też konieczne tak naprawdę tylko wtedy
// gdy jest on używany (tu mogłoby to być pominięte)
WDTCSR |= (1<<WDCE) | (1<<WDE);
256: 81 b5 in r24, 0x21 ; 33
258: 88 61 ori r24, 0x18 ; 24
25a: 81 bd out 0x21, r24 ; 33
// Turn off WDT
WDTCSR = 0x00;
25c: 11 bc out 0x21, r1 ; 33
// ustawienie trybu POWER-DOWN
MCUCR SET ((1<<SM0)|(1<<SM1));
25e: 85 b7 in r24, 0x35 ; 53
260: 80 65 ori r24, 0x50 ; 80
262: 85 bf out 0x35, r24 ; 53
// ustawienie pinu PORTD.2 (INT0) jako wejście
DDRD RESET (1<<2);
264: 8a 98 cbi 0x11, 2 ; 17
// podciągnięcie do 1
PORTD SET (1<<2);
266: 92 9a sbi 0x12, 2 ; 18
// zezwolenie na przerwania INT0
GIMSK SET (1<<INT0);
268: 8b b7 in r24, 0x3b ; 59
26a: 80 64 ori r24, 0x40 ; 64
26c: 8b bf out 0x3b, r24 ; 59
// skasowanie flagi wystąpienia przerwania INT0
EIFR SET (1<<INTF0);
26e: 8a b7 in r24, 0x3a ; 58
270: 80 64 ori r24, 0x40 ; 64
272: 8a bf out 0x3a, r24 ; 58
while (1)
{
// globalne zezwolenie na przerwania
sei();
274: 78 94 sei
// wprowadzenie procesora w tryb POWER-DOWN
sleep_mode();
276: 85 b7 in r24, 0x35 ; 53
278: 80 62 ori r24, 0x20 ; 32
27a: 85 bf out 0x35, r24 ; 53
27c: 88 95 sleep
27e: 85 b7 in r24, 0x35 ; 53
280: 8f 7d andi r24, 0xDF ; 223
282: 85 bf out 0x35, r24 ; 53
284: f7 cf rjmp .-18 ; 0x274 <main+0x60>
jak pisałem wcześniej wszystko w tym kodzie działa idealnie a pobór prądu spada do - 6uA !!!! więc jest super
potem jeszcze sama procedura przerwania INT1, w której następuje u mnie akurat obsługa klawiszy - i to właśnie też to przerwanie wybudza procka ze śpiączki
SIGNAL(SIG_INT0)
{
// wyłączenie obsługi przerwań
cli();
//
// tylko na czas przerwania INT0 - przestawiony zostaje
// kierunek portów klawiszy. Zostają ustawione jako wejścia
// natomiast pin PORTD.2 (INT0) jako wyjście ze stanem niskim
// dzięki temu działa obsługa klawiszy
//
// ******* KLAWISZE
//
// ustawienie PORTD.2 , 3 , 4 i 5 jako wejścia
K_DDR RESET (KEY1|KEY2|KEY3|KEY4|KEY5);
// podciągnięcie wejść do 1
K_PORT SET (KEY1|KEY2|KEY3|KEY4|KEY5);
// przestawienie PORTD.2 jako wyjście
DDRD SET (1<<2);
// ustawienie stanu niskiego - do obsługi klawiszy
PORTD RESET (1<<2);
********************************************
...... tutaj kod do obeługi klawiszy ...........
********************************************
// przywracamy ustawienia
// ustawienie pinu PORTD.2 (INT0) jako wejście
DDRD RESET (1<<2);
// podciągnięcie do 1
PORTD SET (1<<2);
// ******* KLAWISZE
//
//
// ustawienie PORTD.2 , 3 , 4 i 5 jako wyjścia
K_DDR SET (KEY1|KEY2|KEY3|KEY4|KEY5);
// ustawienie stanu niskiego
K_PORT RESET (KEY1|KEY2|KEY3|KEY4|KEY5);
}
tak na marginesie to jak piszesz czy w asemblerze czy w każdym innym języku to polecem korzystać z nazw bitów i wyraźne ich włączanie / wyłączanie w kodzie - tak jak widać to u mnie - a wtedy o wiele trudniej o dokonanie jakiejś pomyłki czy pomyłek
Przetestuje to wszystko w poniedziałek bo mam egzamin z fizy:) Co do stosowania nazw bitów, to zachodziło podejrzenie że bascom ma błąd w bibliotece,dlatego pisałem normalnie adresy.