Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Attiny2313][Bascom i ASM] tryb powerdown

magik128 10 Jan 2009 12:26 3992 16
  • #1
    magik128
    Level 22  
    Witam


    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).

    
    Enable Interrupts
    Set Portd.2
    Enable Int0
    Set Portd.2
    Powerdown
    '$asm
      'in  r17,mcucr
      'ldi r16,0B00100000
      '!and r16,r17
      '!Out Mcucr , R16
    
      'in  r17,mcucr
      'ldi r16,0B01000000
      '!and r16,r17
      '!Out Mcucr , R16
    
      'sleep
    '$END ASM
    


    [Attiny2313][Bascom i ASM] tryb powerdown
  • #2
    marenc
    Level 24  
    Jeżeli chcesz zrobić PowerDown(piszę z pamięci i mam nadzieję, że bez błędów):
    in r16, MCUCR
    ori r16, 0x70
    out MCUCR, r16

    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.
  • #3
    magik128
    Level 22  
    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:\
  • #4
    marenc
    Level 24  
    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...
  • #5
    wader_669
    Level 28  
    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)

    jeszcze troche poprawilem kod:
    
    $regfile = "m32def.dat"
    $crystal = 8000000
    
    Config Pind.5 = Output                                      ' dioda 1
    Config Pind.6 = Output                                      ' dioda2
    
    Config Int0 = Low Level
    On Int0 Przerwanie
    Enable Interrupts
    dim przerwanie_x as bit
    Config Pina.7 = Input                                       ' przycisk
    Config Pina.6 = Input                                       ' przycisk
    Config Pind.2 = Output                                      ' przycisk int0
    
    Portd.2 = 0
    Set Porta.7
    Set Porta.6
    
    Disable Int0
    
    Do
    Reset Portd.5
    Reset Portd.6
    
    If Pina.7 = 0 Then
    Waitms 25
    Bitwait Pina.7 , Set
    
       Set Portd.5
    
    End If
    
    If Pina.6 = 0 Then
    Waitms 25
    Bitwait Pina.6 , Set
    
       Set Portd.6
    
    End If
    
    
    Config Pina.7 = Output                                  
    Config Pina.6 = Output 
    Porta.7 = 0
    Porta.6 = 0                                     
    Config Pind.2 = Input
    Set Portd.2
    
    
    Enable Int0
    
    Powerdown
    
    if przerwanie_x=1 then
    Disable Int0
    
    Config Pina.7 = Input                                       ' przycisk
    Config Pina.6 = Input                                       ' przycisk
    set porta.7
    set porta.6
    
    Config Pind.2 = Output                                      ' przycisk int0
    Portd.2 = 0
    
    przerwanie_x=0
    end if
    Loop
    End
    
    Przerwanie:
    przerwanie_x=1
    Return
    


    przerabialem kod z glowy, wiec jak sa bledy to sorry
  • #6
    magik128
    Level 22  
    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

    [Attiny2313][Bascom i ASM] tryb powerdown
  • #7
    wader_669
    Level 28  
    magik128 wrote:
    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
  • #8
    zumek
    Level 39  
    magik128 wrote:
    ...Według mojego kalkulatora 0x70 to 0b01110000 czyli według noty st-by

    Twój kalkulator działa dobrze, ale Bascom-owy(v.1.11.9.3) nie bardzo :(
    Bascom Basic
    
    $regfile = "attiny2313.dat"
    Idle
    Powersave
    Powerdown
    Stop
    
    


    Efekt w ASM
    
    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"
    :D
  • #9
    marenc
    Level 24  
    Według Twojej dokumentacji powinno działać:
    in r16, MCUCR
    andi r16, 0x8f
    ori r16, 0x30 //Lub ori r16, 0x60
    out MCUCR, r16

    Ten przekład z bascom'a na asm faktycznie niekoniecznie dobry :P Nie znam bascom'a ale patrząc na polecenie w nim, to asm tego nie wykonuje ;)
  • #10
    magik128
    Level 22  
    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:

    
    $asm
    !IN        R24,mcucr
    !ORI       R24,0x20
    
    !Out mcucr , R24
    
    
    !IN        R24,mcucr
    !ORI       R24,0x50
    
    !Out mcucr , R24
    SLEEP
    $end Asm
    


    Ale nie daje to żadnej reakcji:\



    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.

    
    Powerdown 
    
    if przerwanie_x=1 then 
    Disable Int0 
    
    Config Pina.7 = Input                                       ' przycisk 
    Config Pina.6 = Input                                       ' przycisk 
    set porta.7 
    set porta.6 
    
    Config Pind.2 = Output                                      ' przycisk int0 
    Portd.2 = 0 
    
    przerwanie_x=0 
    end if 
    Loop 
    End 
    
    Przerwanie: 
    przerwanie_x=1 
    Return 
  • #11
    madart
    Level 26  
    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.
  • #12
    marenc
    Level 24  
    magik128 - teoretycznie dobrze ...
  • #13
    magik128
    Level 22  
    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.
  • #14
    marenc
    Level 24  
    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 ;)
  • #15
    magik128
    Level 22  
    Dalej nic, już nie mam pojęcia jak do tego podejść.
  • #16
    mirekk36
    Level 42  
    Witam,

    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

    pozdrawiam i powodzenia
  • #17
    magik128
    Level 22  
    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.

    Pozdrawiam i dziękuje