Strona 1 z 2
Powerdown mode w ATmega32A chyba źle robię
: 09 maja 2026, 14:40
autor: Michał6201
Cześć
Chciałem sobie wytestować usypianie atmegi32a za pomocą przerwania INT0
Niby program działa poprawnie, ale co któreś wyzwolenie stanem niskim nie powoduje przejścia do głównej pętli, tak jakby się zawieszał program.
Co może być tego przyczyną?
Uśpienie działa bezbłędnie, ale po wybudzeniu nic się nie da robić oprócz kręcenia się w kółko w głównej pętli.
Próba przejścia do jakiejkolwiek procedury z głównej pętli jest niemożliwe bo cały czas INT0 tak jakby przeszkadzał.
To wygląda na to że to całe POWER MODE do niczego nie jest potrzebne, bo bezużyteczne.
W trakcie normalnej pracy chcę, aby INT0 było cały czas podłączone do GND. A to chyba wyklucza usypiania?
$regfile = "m32adef.dat"
$crystal = 11059200 '11,0592MHz
$hwstack = 64
$swstack = 32
$framesize = 64
Config Int0 = Low Level
Enable Interrupts
On Int0 Int0_isr
Config PortB.0 = Input : PortB.0 = 1 : INT_PCF Alias PinB.0 ' WEJŚCIE SYGNAŁU INT 1Hz
Config PortB.3 = Output : PortB.3 = 1 : LED Alias PortB.3
Config POrTD.2 = Input : PORTD.2 = 1 : SWITCH Alias PIND.2
Dim Mig As Bit
Dim Flaga As Bit
Flaga = 0
Do
'Mig = INT_PCF
'If Mig = 0 Then LED = 0 Else LED = 1
' Wprowadzenie w tryb Power Down
If SWITCH = 1 Then Flaga = 1
If Flaga = 1 Then
'LED = 1
Enable Int0
Config Powermode = Powerdown
end if
Loop
END
Int0_isr:
Enable INT0
SWITCH = 0
Flaga = 0
Return
Przy zasilaniu mikrokontrolera napięciem +5V i taktowaniu zewnętrznym kwarcem 11.0592MHz, po wejściu mikrokontrolera w POWERDOWN MODE pobór prądu spada o 10mA.
Oczywiście miganie ledem wyciąłem, tak jak w załączonym kodzie, aby nic nie przekłamywało pomiaru prądu.
Re: Powerdown mode w ATmega32A chyba źle robię
: 10 maja 2026, 2:09
autor: niveasoft
Taka klasyka gatunku

Dziwne że jeszcze po latach tego nie wiesz, ale napiszę.
Jak stoi w nocie aplikacyjnej stan przerwania LOW LEVEL trwa tak długo jak jest włączone i jak długo utrzymuje sie stan niski na pinie INT jesli ktoś włączyył LOW LEVEl INTERRUPT.
Nie wyjdzie z przerwania dopóki trwa stan niski na pinie, ale to jedyny sposób by wybudzić z POWERDOWN

(może jeszcze asynchroniczny zegar potrafi - nie pamiętam)
Tak więc sekwencja powinna być przynajmniej taka, że po wejściu w przerwanie wyłaczasz je, czekasz na ustabilizowanie stanu pinu/wyłacznika/stycznika i dopiero kasujesz flagi kolejnego przerwania (bo drgania na pewno wymusiły następne) i wychodzisz z przerwania. Najkrótszym kodem przerwania powiino być to:
INT0_isr:
Disable INT0
Bitwait SWITCH , 1 ' poczekaj aż wejście otrzyma stan wysoki
Do
Waitms 10
If SWITCH = 1 Then Exit Do
Loop
GIFR = 255 ' General Interrupt Flag Register - kasujemy flagi INTF1, INTF0, i INTF2 - przez 255 jest szybciej
Return
Wpisywanie do przerwania czegoś takiego jak SWITCH=0 jest metodą życzeniową i na pewno nieskuteczną. To tak jakbyś wyszedł na dwór, spojrzał że pada deszcz i powiedział, nie pada

Jeśli przycisk ma zwarty pin do masy to procesor nic z tym zrobić nie może. Po prostu jest zwarty do masy. Może to tylko odczytywać.
Re: Powerdown mode w ATmega32A chyba źle robię
: 10 maja 2026, 10:45
autor: Michał6201
Dziękuję Ci za podpowiedź.
Przy tym zapisie pokazuje się błąd i nie pozwala skompilować.
Bitwait SWITCH , set 1 ' poczekaj aż wejście otrzyma stan wysoki
Ale i tak raczej w takiej sytuacji nic z tego usypiania nie będzie, bo płytkę mam już od dawna zrobioną, pin INT (PD2) w czasie działania programu jest zwarty na stałe do GND, a tylko podczas braku aktywności jest podciągnięty do VCC. Więc zwarcie INT do GND na stałe musiałoby aż do odwołania wybudzić jednorazowo mikrokontroler z powerdown, aby mógł program normalnie wykonywać się.
W ogóle nie przewidywałem używania przerwań. Teraz wpadłem na taki pomysł chcąc obniżyć pobór prądu w czasie bezczynności. Ale jak widać nie da się.
To kompiluje się, ale nie działa. Tzn program wykonuje się w głównej pętli dopóki INT0 nie zostanie podciągnięty do VCC. I na tym kończy się działanie programu. Pomaga tylko reset.
Zmieniłem też zapis po Bitwait na RESET zamiast SET, bo PD2 ma być w czasie działania układu cały czas podciągnięty do GND, ale też zawiesza się procek. GIFR = 255 też zawiesza procka.
$regfile = "m32adef.dat"
$crystal = 11059200 '11,0592MHz
$hwstack = 64
$swstack = 32
$framesize = 64
Config Int0 = Low Level
Enable Interrupts
On Int0 Int0_isr
Config PortB.0 = Input : PortB.0 = 1 : INT_PCF Alias PinB.0 ' WEJŚCIE SYGNAŁU INT 1Hz
Config PortB.3 = Output : PortB.3 = 1 : LED Alias PortB.3
Config PortC.7 = Output : PortC.7 = 0 : BUZ Alias PortC.7
Config POrTD.2 = Input : PORTD.2 = 1 : SWITCH Alias PIND.2
Config POrTC.6 = Input : PORTC.6 = 1 : SW Alias PINC.6
Dim Mig As Bit
Dim Flaga As Bit
Flaga = 0
Dim Bip As Bit
Bip = 0
Do
Flaga = 0
Mig = INT_PCF
If Mig = 0 Then LED = 0 Else LED = 1
' Wprowadzenie w tryb Power Down
If SWITCH = 1 Then Flaga = 1
If Flaga = 1 Then
Led = 1
Enable INT0
Config Powermode = Powerdown
end if
Loop
END
INT0_isr:
Disable INT0
'SWITCH = 1
Bitwait SWITCH , Set ' poczekaj aż wejście otrzyma stan wysoki
Do
Waitms 10
If SWITCH = 1 Then Exit Do
Loop
GIFR = 255 ' General Interrupt Flag Register - kasujemy flagi INTF1, INTF0, i INTF2 - przez 255 jest szybciej
Return
Ten kod działa, ale co jakiś czas zawiesza się program, więc wygląda na to, że te przerwania i usypiania to nic pewnego. Nie powinien wieszać się program przy próbie wybudzenia.
$regfile = "m32adef.dat"
$crystal = 11059200 '11,0592MHz
$hwstack = 64
$swstack = 32
$framesize = 64
Config Int0 = Low Level
Enable Interrupts
On Int0 Int0_isr
Config PortB.0 = Input : PortB.0 = 1 : INT_PCF Alias PinB.0 ' WEJŚCIE SYGNAŁU INT 1Hz
Config PortB.3 = Output : PortB.3 = 1 : LED Alias PortB.3
Config PortC.7 = Output : PortC.7 = 0 : BUZ Alias PortC.7
Config POrTD.2 = Input : PORTD.2 = 1 : SWITCH Alias PIND.2
Config POrTC.6 = Input : PORTC.6 = 1 : A Alias PINC.6
Dim Mig As Bit
Dim Flaga As Bit
Flaga = 0
Dim Bip As Bit
Bip = 0
Do
Flaga = 0
Mig = INT_PCF
If Mig = 0 Then LED = 0 Else LED = 1
If A = 0 then gosub Beep
' Wprowadzenie w tryb Power Down
If SWITCH = 1 Then Flaga = 1
If Flaga = 1 Then
Led = 1
Enable INT0
Config Powermode = Powerdown
end if
Loop
END
INT0_isr:
Disable INT0
SWITCH = 0
'Bitwait SWITCH , RESET ' poczekaj aż wejście otrzyma stan wysoki
Do
SWITCH = 0
Waitms 500
If SWITCH = 0 Then Exit Do
Loop
GIFR = 255 ' General Interrupt Flag Register - kasujemy flagi INTF1, INTF0, i INTF2 - przez 255 jest szybciej
Return
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 12:01
autor: niveasoft
Proponuję nie kopać się z koniem i wymienić procesor na nowszy.
Na przykład jeśli masz to nawet w obudowie DIL64 to możesz sobie tam wsadzić Mega324P, Mega644P, Mega1284P.
Program ktory już masz będzie pasował jeden do jednego a będziesz mógł wybudzić procesor przerwaniem PCINT.
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 20:02
autor: Michał6201
ATMEGA324P odpada, bo inaczej ma piny zasilania wyprowadzone, a tak jak już pisałem płytka jest złożona.
Natomiast pasować będzie ATMEGA644P, ATMEGA324A z tych mniejszych. Konicznie obudowa TQFP44.
Zaraz wytestuję na mojej płytce testowej program na ATMEGA644, bo mam taką w obudowie DIL.
Czy w ATMEGA644P dla pinu PCINT26/INT0 (PD2) zmienić musi się kod służący do uśpienia i wybudzenia?
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 20:27
autor: niveasoft
Oczywiscie z iloscią tych pinów się machnąłem bo pisałem "z głowy. DIP ma 40 pinów a TQFP 44.
Jednak co do tych 324P że nie pasują to bym jeszcze sprawdził. U mnie one mają jedną wspólna notę katalogową (164/324/644) a literki na końcu to były dla minimalnych napięc przy jakich pracują stabilnie. V działa z najniższymi napięciami. P z trochę wyższymi. Kiedyś chyba gdzieś dawno słyszałem żę P to "Pico Power". Te A były najstarsze chyba.
W programie może być tylko delikatna różnica w Timerach bo stare mają czasem tylko "Compare" a nowsze moga mieć "Compare_a", "Compare_b" itd...
Nie będę drążył tematu tych 324A/P/V bo ta Atmega644P jest popularna i najtańsza chyba.
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 20:32
autor: Michał6201
A czy kod odpowiedzialny za usypianie i wybudzanie zmienia się jakoś przy ATMEGA644p?
Chodzi o pin PCINT26/INT0 (PD2) bo to na nim mam usypianie/wybudzanie
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 20:56
autor: niveasoft
Raczej tak. Spróbuj tego. Pisałem tak na szybciora z głowy, ale to ma pokazać koncept.
W PCINT on reaguje na zmiany na pinie wiec przerwanie masz i jak dostanie stan wysoki i jak zmieni na niski. Jeden trzeba wtedy przy usypianiu zignorować.
Pewnie tu dużo mozna dopieścić.
Teraz powinno migać LED`em jak na PD2 jest masa a jak nie to LED powinien zgasnąć
$regfile = "m644pdef.dat"
$crystal = 11059200 '11,0592MHz
$hwstack = 64
$swstack = 32
$framesize = 64
PCMSK3 = &B0000_0100 'aktywny tylko PD2
Enable PCINT3 : On PCINT3 Pcint3_isr
Int_pin alias pind.2 : set portd.2
Config PortB.3 = Output : PortB.3 = 1 : LED Alias PortB.3
Dim sleep_request as byte
Enable interrupts
do
Waitms 500 : toggle LED
if sleep_request = 1 then 'jesli nie bylo masy i ustawiono flage
sleep_request = 0 'kasuj i idz spac
Set LED 'nie zapomnij zgasic LED`a
Config powermode = powerdown
end if
'tu program bedzie jak sie obudzi
'zatoczy kolo i bedzie normalnie migac LED`em
loop
end
Pcint3_isr: 'zmiana stanu na pinie
If int_pin = 0 then 'jesli pokazała się masa to nic nie rob
return
else
sleep_request = 1 'jesli masa zanikla to ustaw flage i wracaj
end if
Return
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 21:24
autor: Michał6201
Jeśli INT0 jest podciągnięty do VCC i na chwilę zniknie zasilanie mikrokontrolera, to program startuje, tak jakby INT0 było ściągnięte do GND.
Czyli chwilowy zanik napięcia spowoduje włączenie układu i wykonywanie programu w głównej pętli.
Re: Powerdown mode w ATmega32A chyba źle robię
: 11 maja 2026, 21:33
autor: niveasoft
Na próbę dodaj sobie jakieś opóźnienie przed włączeniem przerwań. Na przykład przed Enable Interrupts:
Dim sleep_request as byte
Waitms 500
'kasowanie wywolania przerwania jesli juz jakies procesor zauwazyl
PCIFR = PCIFR 'jesli gdzies jest flaga 1 to ja tam wpisze przez co ją skasuje
sleep_request = 1 'jesli ma spac z zalozenia
Enable Interrupts
Możesz też na bezczelnego w pętli dać warunek że jak stan wysoki to ma iśc spać bo Tobie potrzebny jest tylko stan niski do wybudzenia:
sleep_request = Int_pin 'jesli stan wysoki w petli to idz spac
If sleep_request = 1 Then ' ..... itd...