Hallo,
Ich hätt ma ne frage:
Ich möchte anfangen mit assembler zu programmieren, wie fang ich da am besten an (welches programm ist am geignetsten und wo programmieren lernen oder mit was )?
Danke
Druckbare Version
Hallo,
Ich hätt ma ne frage:
Ich möchte anfangen mit assembler zu programmieren, wie fang ich da am besten an (welches programm ist am geignetsten und wo programmieren lernen oder mit was )?
Danke
achso ich habe noch vergessen ich möchte das mit atmel-prozessor machen.
Als Programmierumgebung gibt es AVRStudio und VMLab. Beide nutze ich und finde sie auch gut. Zum 'Brennen' des Atmel nutze ich PonyProg.
Das war es auch schon an Software. Für den Anfang würde man sogar ohne Hardware auskommen, da zB VMLab eine super Testumgebung beinhaltet. Man kann virtuell Displays, Tastenfelder, Analogschieberegler, Oszilloskope und mehr anklemmen.
Ein Buch kann ich dir leider nicht empfehlen, mein erstes Assemblerbuch war auch mein letztes. Zu empfehlen sind die Tutorials auf Mikrocontroller.net.
Also einfach mal reinschauen und loslegen...
hallo pacer1,
ich hab gerade angefangen, mich mit den µc zu befassen und mir dazu des lernpaket von franzis gekauft (gibts bei amazon und conrad).
da ist avr studio 4 enthalten.
und möchte nun ein fertiges, mitgeliefertes lernprogramm (zb. led2.asm) mit dem deguger schritt für schritt durchgehen. leider gelingt mir das nicht.
ich werde auch nirgendwo fündig, wei man das bewerkstelligt, auch nicht in der hilfe des avr studio.
lt. pulldown menü müsste es mit "alt" und "+" der zehnertastatur gehen - nichts. auch nicht, wenn ich auf das icon -> (next step) drücke.
was mache ich hier falsch?
der debugger läuft und stellt einen schönen gelben pfeil neben die erste anweisung (rjmp anfang). das wars dann ... :-((
kann mir hier jemand helfen?
lg heinz
Einzelschritte im Debugger macht man mit der Funktionstaste F11, mit F10 überspringt man eine Befehl. Steht auch im Menue unter DEBUG als "Step into".
Ja, nut den franzispaket hatte ich auch angefangen - und mir dann die neueste Version des AVRStudio geholt. Die gibt es als freie Software HIER. Wenn ich mich richtig erinnere, hatte ich anfangs auch gelegentlich Schwierigkeiten mit dem AVRStudio. Ich weiß nicht, ob nicht der GCC-Compiler WinAVR zum ordnungsgemässen Arbeiten auch noch erforderlich ist. Jedenfalls habe ich beide drauf, (wohl auch in der neuesten Version) und bei mir (XP, Pentium ..) läuft alles gut.Zitat:
Zitat von HeSt
Viel Erfolg
Man braucht GCC/WINAVR nicht zum AVRstudio wenn man in ASM programmieren will. Solange man es nicht braucht, sollte man es auch besser weglassen, denn bei der Kombination WinAvr /AVRstudio funktioniert nicht unbedingt jede Kombination von Versionen.
danke für eure antwort.
hab vergessen zu schreiben: hatte es ja auch mit f10 und f11 probiert - funktionierte nicht.
habe heute den pc neu hochgefahren, avr gestartet, programm neu umgewandelt, debuger gestartet - und siehe da, f10 + f11 funktionieren!
musste wahrscheinlich gestern von lauter herumprobieren in einem status gelandet sein, wo sich das avr studio "geweigert" hat, mit den "F"-tasten zu funktionieren.
danke nochmals !!!!
lg heinz
Hallo HeSt,
Prima, daß Dein Assembler jetzt funktioniert. Ich hatte sehr gerne in Assembler programmiert - nur leider sind eben manche Probleme in Hochsprachen wirklich besser darstellbar. Und ich hatte mich deswegen mühselig in C eingearbeitet und kann mittlerweile einfachere Dinge schon in C schreiben - und die laufen sogar :).
Vermutlich war das dann aber eine der vielen Krankheiten des Betriebssystems. Aber das ist ja auch nicht mehr sooo wichtig. Viel Erfolg weiterhinZitat:
Zitat von HeSt
hallo joe,
das "nicht funktionieren" dürfte daran liegen, dass ich einige male in den "power down mode" gehe (sleep). dann lässt das avr nichts mehr mit sich tun.
und dazu gleich eine frage:
wie erzeuge ich interrupts an den eingängen?
int0 oder pinchange?
die entsprechenden pinb anklicken (aktiv setzen) bringt nichts.
schönen abend
Hi,
? ? ? Reale Interrupts im Programm oder im Simulator? Im Simulator hatte ich das nie hinbekommen; das hatte ich dann aufgegeben und lieber gleich im/mit Controller gemacht.Zitat:
Zitat von HeSt
Im Ablauf: 1) ISR (Interrupt Service Routine) schreiben. 2) Interrupt-Initialisierungsroutine schreiben. 2) Interrupt Vector Tabelle schreiben. 3) Port/Pin richtig initialisieren (noch immer Software). 4) Freuen, dass der Interrupt die richtige Aktion auslöst.
Soweit ich mich noch erinnere war das gar nicht so schwer einen Interrrupt auszulösen. Ist aber doch schon eine ganze Zeit her. Zur Not, wenn sonst nichts geht, könnte man auch die Interrupt flags direkt setzen. Wenn man ein spezielle Signal braucht gibt es noch einen externen Stimulus, ist aber auch nicht ganz einfach.
freunde,
verzeiht einem ungeduldigen alten lehrling!
ich rede immer noch vom avr, also vom simulator.
der interrupt lässt sich übrigens schön auslösen, in dem man - so wie ich ja probiert habe - das pinb port bit auf ein setzt.
allerdings muss man dann 2x die f11 taste drücken!! erst dann greift der interrupt und springt in die i-routine.
so, und nun hab ich ein problem mit meinem programm, das ich nicht verstehe:
1. interrupt routine (irr) wird aufgerufen (das SREG wird gesichert)
2. irr macht ein rcall auf eine subroutine (ist ja normal oder?)
3. in der subr gibts unter anderen befehlen 2 schleifen mit rjmp
4. wenn die subr dann auf das ret(urn) kommt, springt das programm nicht in die aufrufende irr zurück (war ja rcall) sondern auf @$0000 - verhält sich also wie ein reset!!!
wie das ???
kann mir das einer erklären?
was mache ich falsch bzw. wo liegt der hund in meinem gedankengang?
Vorsicht - "der avr" würde für mich eher nach dem realen Controller klingen als nach dem Simulator.Zitat:
Zitat von HeSt
Hmmm, das klingt seltsam, und es klingt nicht gut. Also - ich weiß nicht, ob ein rcall in einer ISR sinnig (oder möglich - oder erlaubt) ist - ich hatte das nie gemacht. Ich lebe unter der Philosophie, dass die ISR so schnell wie möglich abzuarbeiten ist.Zitat:
Zitat von HeSt
Nur nebenbei: die ISR wird mit reti abgeschlossen: Return from Interrupt, aber das wird Dir sicher schon klar sein.
Ich habe mal einen funktionierenden Code hervorgeholt, den ich vor Jahrhunderten in Assembler geschrieben hatte und der noch immer in meinem tiny13 als potentionmeter-getriebener Servotester funktioniert. Vielleicht hilft Dir so ein Anschauungsmaterial. Ich muss dazusagen, dass das kein perfekter Code ist - also er hat nicht direkt Vorbildfunktion. Aber der hex-file läuft.
Vielleicht postest Du mal Deinen code? Auf jeden Fall mal viel Erfolg für Dich.Code:; >>>
; Sicherung vom 21jan08, 13:46 nach Datei servo1_servoplatine-gut.asm
;===================================================================================
;========== Beachte: printout aus AVRStudio geht (nur) bis col 85 ==================
;* Target MCU : ATtiny13
;* Target Hardware : Servotester-Platine, Servo auf PB3, Poti auf PB4
;* Target cpu-frequ. : 9,6 MHz, interner Oszillator
;===================================================================================
;*Versionsgeschichte:
;====================
;x1599 21jan08 12ff Version für die "Servoplatine" adaptiert
; dazu ISR+adc+servo1-x30-gut.asm abgeändert.
;
;* Aufgabenstellung
;* ISR zum Testen von einem Servo mit der Servotester-Platine
; Servo über getrennte Leitung, max. 1 A, vom Labornetzteil versorgt
; Portbelegung, Schaltung auszugsweise (übernomm. v. srv-adc+pwm-x29b.asm)
;
; Vcc(6V LNT) -----------------------------------------Vcc-Servo1
;
; Vcc -----------tiny13-Vcc
; |
; | tiny13-PB3=pin2----------------+---Signal-Servo1
; | |
; | + - - (poti1->ADC) - - +
; | |
; | tiny13-PB4--------+
; | V
; | +--------+
; +-------------------+ 25klin +----+
; +--------+ |
; |
; GND---------------------------------------+----------GND-Servo1
;
;* ===============================================
; ######### Original war: ISR+adc+servo1-x30-gut.asm
;===================================================================================
; Speicherbelegung
;r14 low-Byte der ADC-Wandlung (lsb)
;r15 high-Byte der ADC-Wandlung: Beide ergeben einen Wert zwischen 0...1023
;r16 Mehrzweck, high-Byte in Pausen "pause_an", "pause_aus", "led_ende" u.ä.
;r17 low-Byte in Pausen, s.o.
;
;r18 -- --
;r19 -- --
;r20 -- --
;
;r21 Byte Steuerbyte. Es werden nur Bits ausgewertet
; "Rampe" an-aus, 1=Rampe an, bit 1 = Servo 1 , bit 5 = Servo 2
; Übernahme Rampenwert, 1=Daten wurden noch nicht übernommen vom
; Hauptprogramm in die ISR, 0=ISR hat Daten abgeholt und zwar
; bit 2 = Servo 1 , bit 6 = Servo 2
;r22 1/2 Word lsb Zeitwert Rampe aus auf-ab-Rechnerei im Hauptprogramm
;r23 1/2 Word msb zu r26
;r24 1/2 Word LSB Zeitwert Rampe aus ADC/Poti im Hauptprogramm
;r25 1/2 Word MSB wird vom r14/15 geholt und zurechtgerechnet
;
;r26 1/2 Word LSB GESAMTDAUER Servoimpuls MUSS in r26/27 sein wegen sbiw
;r27 1/2 Word MSB Zeitwert für GESAMTDAUER Servoimpuls, etwa 500 Takte ?
;
;r28 1/2 Word lsb LSB RampenCOUNTER Servo1, wird in ISR runtergezählt
;r29 1/2 Word msb MSB Counter stammt vom ADC
;r30 1/2 Word lsb LSB Auf-ab-COUNTER Servo2, wird in ISR runtergezählt
;r31 1/2 Word msb MSB
;
;===================================================================================
#include "tn13def.inc"
; Interrupthandler-Tabelle (aus ATTiny13_doc2535.pdf, Seite 42)
; Address Code Labels ; Comments
.org 0x0000 rjmp anfang ; Reset Handler
;.org 0x0003 rjmp isr_x13 ;TIMO_OVF = Timer0 Overflow Handler
.org 0x0006 rjmp isr_ctc ; IRS für Timer0 CompareA Handler
;
;===================================================================================
; Deklarationen für den Praeprozessor
; Konstanten ####### evtl. auch keine Konstanten definiert
;
#define a r16 ;Kurzbezeichung für Allzweckregister r16
;
; Anschlussbelegung, vgl. srv-adc+pwm-x29b.asm
#define servo1 3 ;Servo 1 auf Port PB3
#define potiadc 2 ;Poti 1 am Port PB4 geht auf ADC-Kanal 2
;
;Festwerte und div. Daten für adcdat etc ====>
#define adcpsc 7 ; =7 ==> Clock/128, 9,6 MHz werden 75 kHz, vgl. doc, S93
;#define adcdat 3 ;Dummywert vom ADC ###>>> "Nur" 8Bit-Wandlung ! ? !
#define msges 5000 ;Gesamtzeit der Rampe: 5000 ISR-Zyklen sind 20 ms
#define mstest 500 ;Test ergibt mit mstest 500 und tmprs 40: für 2,0 ms
; das heisst: 4 µs Interrupt-Abstand (Fehler +4%)
#define msmin 180 ;Minimalwert für Rampe: 0,5 ms
#define tmrprs 38 ;Preset im Timer-Register (hoffentlich für CTC)
;
;===================================================================================
; Hauptprogramm
;===================================================================================
;
anfang:
rcall mc_init ;Initialisiere den Mikrocontroller
rcall isr_ini ;Initialisiere die ISR
rcall adcinit ;ADC initialisieren
;
sei ; .. Interrupts allgemein zulassen im Hauptprogramm
anfang2:
rcall adc_hol ;Hole Daten vom ADC in Register low=r14 + high=r15
;
rjmp anfang2
;
;===================================================================================
; Prozeduren
;===================================================================================
;
adc_hol: ;=== Hole Daten vom ADC, wird erst NACH der Wandlung verlassen
;Nach Wandlung sind die Werte in; L=r14,H=r15
ldi r16,potiadc ;Poti ist auf ADC-Kanal 2. >> Kanal 0 = Pin1=PB5,
; K1(ADC1)=Pin7=PB2, K2=Pin3=PB4 und K3=Pin2=PB3
rcall rdadc ;ADC auslesen
ret ;=====----->>>>>
;
rdadc: ;=== Hole Daten vom ADC in die Register low=r14 + high=r15
out admux,r16 ;vgl.doc2535, S 79
sbi admux,adlar ;Result left adjusted ==> NUR 8-Bit-Wandlung
sbi adcsra,adsc ;Wandlung starten
adrdy: ;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
sbic adcsra,adsc ;Skip if bit is cleared => dann ADC fertig
rjmp adrdy ; .. wenn nicht fertig, warten
adrdyb:
sbic adcsra,adsc ;Erst zweite Wandlung bringt korrektes Erbebnis,
rjmp adrdyb ; vgl. doc2535, sonst könnte alter Wert da sein.
; Dies dann, ###===>>> nur WENN der Kanal umgeschaltet wurde.
; in r14,adcl ;Daten einlesen, zuerst Low-Byte - nicht bei adlar
in r15,adch ;vgl. oben ADMUX (out 3), ADSC
ret ;=====----->>>>>
;
;===================================================================================
; Initialisierungprozeduren, für µC, ADC und Timer-ISR
;===================================================================================
;
mc_init: ;=== Initialisiere Mikrocontroller
; PB0 (servo1) + PB3 (servo2) = Ausgang, PB4 (poti1) = ADC-Eingang
ldi r16,0b00001000 ;Ausgang (1) auf PB3, Eingang (0) auf PB4
out ddrb,r16 ;Datenrichtungsbits setzen, Port ist Ausgang
ldi r16,0b11100111 ;Datenrichtungsbits setzen
out portb,r16 ; und initialisieren
ret ;=====----->>>>>
;
adcinit: ;=== Initialisiere ADC und hole Daten
ldi a,adcpsc ;Setze adpsc0,1,2 => Clock/128, siehe define
out adcsra,a ;Lade prescaler ==> 75 kHZ, siehe define
sbi admux,potiadc ;Wandlung vom Kanal ADC2 = PB4 = potiadc
sbi admux,adlar ;Result left adjusted ==> NUR 8-Bit-Wandlung
sbi adcsra,aden ;AD en-able einschalten
sbi adcsra,adsc ;Wandlung zum Initialisieren starten
;
adrdy_in1: ;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
sbic adcsra,adsc ;Skip if bit is cleared => dann ADC fertig
rjmp adrdy_in1 ; .. wenn nicht fertig, warten
adrdy_in2: ;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
sbic adcsra,adsc ;Skip if bit is cleared => dann ADC fertig
rjmp adrdy_in2 ; .. wenn nicht fertig, warten
;
ldi r16,0b00000000 ;Dummy-Muster
mov r14,r16 ;Muster nach r14
mov r15,r16 ; .. und nach r15
sbi adcsra,aden ;AD en-able einschalten
sbi adcsra,adsc ;Wandlung zum Initialisieren starten
ret ;=====----->>>>>
;
;
isr_ini: ;=== Initialisierung der ISR (war mal isrinit_x15)
;
;;Timer Register werden belegt
ldi a,(1<<wgm01) ;prescaler ist 1, waveform = CTC
out tccr0a,a ;Register TCCR0 ist für den Prescaler zuständig
ldi a,(1<<cs00) ;prescaler ist 1 => kein Prescaling, Abstand zum
out tccr0b,a ; nächsten Interrupt bestimmt der
; CTC-Prescaler tmrprs
ldi a,(1<<ocie0a) ;Hier Interrupts nach CTC eingeschaltet
out timsk0,a ;Register TIMSK ist dafür zuständig
ldi a,tmrprs ;Hier wird der Timer vorgeladen. Er läuft dann
out TCNT0,a ; .. tmrprs mal durch bevor ein Interrupt auftritt
out ocr0a,a ;Preset tmrprs in OCR0A
; .. Interrupts allgemein zulassen im Hauptprogramm
; ret ;=====----->>>>>
;
;
;===================================================================================
; Interrupt-Service-Routine
;===================================================================================
;
;
isr_ctc: ;=== Immer wieder Veränderungen
;
sbiw r27:r26,1 ;Pointer von 5000 runterzählen
; für EINEN Servoimpuls von 20 ms
breq i_neu ; .. und Spezialfall "null" ==> Daten umschaufeln
; und Rampe einschalten. WENN keine neuen Daten da
; sind, dann alte Daten nehmen :(
;
; Jetzt wird nachgesehen, ob eine der Rampen ausgeschaltet werden muss. Das steht
; im Portbit ddrb
;
isr_nn: ;=== Zähler der ISR steht nicht auf Null
s1_pran: ;=== Servo1: Prüfe, ob Rampe ist an
in r20,portb
sbrs r20,servo1 ;Ist Rampe von servo1 an?
rjmp i_raus ;Wenn Rampe nicht an ist, dann gleich raus
;
sbiw r29:r28,1 ;Decrementiere Rampenwert
brne i_raus ;weiter, wenn noch nicht Null zu servo2
cbi portb,servo1 ; Sonst Lösche Rampe für Servo1
;
rjmp i_raus
sbiw r29:r28,1
breq i_neu
rjmp i_raus
i_neu: ;Daten neu in Register und port servo1 umschalten
ldi r28,low(msmin)
ldi r29,high(msmin)
; mov r17,r15 ;Es ist adlar gesetzt, das ADCLH ist in r15
ldi r18,0
add r28,r15
adc r29,r18
;Und ADC-Wert gleich nochmal draufaddieren
; aber nur die Hälfte
clc ;Clear carry für anschliessende Division /2
ror r15 ;
add r28,r15
adc r29,r18
;
ldi r26,low(msges) ;Loopgrenzen für Gesamtloop 20 msec
ldi r27,high(msges)
sbi portb,servo1 ; Und setze Rampe für Servo1. FERTIG
;
i_raus:
reti ;=====----->>>>>
;
;===================================================================================
; Ende des Quellcodes
;===================================================================================
Das SREG muß man selber retten. In der Regel ist das der Erste befehl nach dem RJMP in der Vektor tabelle.
Es spricht nicht viel gegen rcall in der ISR.
Eine Ursache für das Problem könnte ein nicht initialisierter Stack sein. Wenn der Stack noch irgendwo im Nirwana ist, dann kann der Rücksprung auch schon mal nach 0000 gehen.
danke euch beiden für die antworten!
ich rufe aus der ISR deshalb eine SR auf, weil ich diese auch aus anderen SRs aufrufe - ich sie also mehrfach verwende.
und es sollte kein problem dadurch geben - gibt es auch nicht - siehe weiter unten.
der tip mit dem stack war gut!
ich hatte die initialisierung irgendwo abgekupfert und die dürfte wohl nicht für den tiny 13 gedacht sein ...
nach dem init stand die stapeladresse des SPL auf 0 !!
ich hab die stack initialisierung mal raus genommen und siehe da, zumindest der simulator setzt die richtige größe (endadresse) ein.
habe dann sicherheitshlaber das richtige init eingesetzt.
habe dann weiter getestet - nun läufts richtig!!
also war das SPL das problem.
wie poste ich meinen code?
aber das hat sich ja nun erübrigt oder?
übrigens danke für den deinen!
muss mich erst einlesen und verstehen!
hab meinen servotester mit einem 555er gemacht.
funktioniert auch tadellos.
Code posten:Zitat:
Zitat von HeSt
Button [C ode] drücken ( danach steht dort [C ode*] ) ,
jetzt den Code eingeben (z.B. copy und paste)
Button [C ode*] drücken.
Oder: Code eingeben, markieren und danach den Button [C ode] drücken.
Anmerkung: Zwischen "C" und "o" muss hier im Text ein Zwischenraum stehen, damit die Schaltfunktion für den Code (an dieser Textstelle im Posting) nicht aktiviert wird.
Deinen Code zu lesen hat sich ja nun erübrigt. Obwohl - wär ja mal interessant . . . . .
Ich hatte gerade festgestellt, dass mein Beispiel total schlecht ist. Dieses hier ist vermutlich etwas besser: Stack ist initialisiert, Stackpointer wird in der ISR gesichert und so. Man entwickelt sich halt mit der Zeit *ggggg*.Zitat:
Zitat von HeSt
Code:/* =================================================================================
Sicherung 20dez07 1732 nach Datei ..A1..\minitest\minitest_x10.asm
===================================================================================
..............
===================================================================================
*/
/* ============================================================================== */
; Deklarationen für den Praeprozessor und Konstanten (s.auch oben Speicherbelegung)
#include <m168def.inc>
#define a r16 ;Kurzbezeichung für Allzweckregister r16
#define ac r17 ;Kurzbezeichung für ISR-Allzweckregister r17
;===================================================================================
/* Interrupthandler-Tabelle
Address Code Labels ; Comments */
.org 0x0000 rjmp RESET ;Reset Handler, power-on, brown-out, watchdog
/*.org 0x0001 rjmp xt_int0 ; EXT_INTO IRQO Handler
.org 0x0002 reti ; PCINTO PCINTO Handler
.org 0x0003 reti ; TIMO_OVF ;Timer0 Overflow Handler
.org 0x0004 reti ; EE_RDY ;EEPROM Ready Handler
.org 0x0005 reti ; PITAL_COMP ;Analog Comparator Handler
.org 0x0006 reti ; TIMO_COMPA ;Timer0 CompareA Handler
.org 0x0007 reti ; TIMO_COMPE ;Timer0 CompareE Handler
.org 0x0008 reti ; WATCHDOG ;Watchdog Interrupt Handler
.org 0x0009 reti ; ADC ;ADC Conversion Handler
*/
;===================================================================================
; Hauptprogramm
;===================================================================================
;
RESET: ;=== Generelle Initialisierung
; Zuerst RAMEND und Stack definieren;
ldi a,RAMEND ;Ram Ende des tiny13
out SPL,a ;Stack Pointer tiny13 setzen
anfang: ;=== Nur ein Dummy-Hauptprogramm
rcall init_mc ;Initialisiere den Mikrocontroller
rcall ini_xti0 ;Initialisiere die ISR für external Interrupt
sei ; .. und Interrupts allgemein zulassen
a2:
rcall tiw ;Tu irgend etwas
rjmp a2
;
;===================================================================================
; Prozeduren
;===================================================================================
;
tiw: ;=== tuirgendwas ... ein bisschen code muss ja abgearbeitet werden
push a
in a,SREG
push a
push ac ;AUCH das ISR-Allzweckbyte - auf alle Fälle
tiw_pop:
pop ac
pop a
out SREG,a
pop a
ret ;=====----->>>>>
;
;===================================================================================
; Initialisierungen für µC und ISR
;===================================================================================
;
init_mc: ;=== Initialisiere Mikrocontroller
;ALLE Register initialisieren hier := pull-ups einschalten
ldi a,0b00111100 ;
out ddrb,a ;Datenrichtung "Ausgabe" für alle ports
ldi a,0b00000000
out portb,a ; und alle ports ausschalten = low = sink
ret ;=====----->>>>>
;
ini_xti0: ;=== Initialisiere external Interrupt
;
;(1<<ISC01 | 1<<ISC00)
ldi a,0b00000011 ;Init. extern. Interrupt0 auf rising edge
out MCUCR,a ; d.h. MCUCR ISC00,01 auf 1 (doc2535,S 55)
ldi a,0b01000000 ;(1<<INT0)
out GIMSK,a ; und erlaube diese I´s in GIMSK
ret ;=====----->>>>>
;
;===================================================================================
; Interrupt-Service-Routine #######>>>>>
;===================================================================================
;
xt_int0: ;=== Markiere Arbeit dieser ISR
push a
in a,SREG
push a
ldi a,0b00001000 ;Bit3 (PB3) einschalten
out portb,a
int0_pop:
pop a
out SREG,a
pop a
reti ;=====----->>>>>
;
;===================================================================================
; Ende des Quellcodes
;===================================================================================
hallo joe,
entschuldige, gibts einen "C" oder "C ode" button?
ich hab hier ein kleines fensterchen "Kurz Antwort" mit 4 buttons drunter, aber keiner davon entspricht dem genannten.
auch nicht im header oder unter jeder antwort werde ich fündig.
tut mir leid, da stehe ich auf der leitung!
gib mir nen schubbs zur seite !!
1) Du kannst in das Fenster [Kurze Antwort] schreiben. Da gibts den Button (noch) nicht. Wenn Du dann auf [Vorschau] drückst - ahhhhhhhh :).
2) Wenn Du gleich auf [zitat], rechts oben, oder [antwort erstellen], links unten, drückst - dann kommt auch das volle Programm . . . . .
In beiden Fällen kommt der verschwundene C ode Button zum Vorschein :). Nicht zum Lesen gedacht: Die dämliche Organisation der Computer ist so komplex, dass man zum an sich unerwünschten "mal den Button drücken, mal den hier versuchen" animiert wird. Und sich dann wundert, wenn man in der Wüste/im Wald landet.
Hier im Forum kann eine halbe Stunde in der guten FAQ-Stube, Schaltfläche siehe oben-mitte, nützlich sein. Man muss ja nicht alles lesen - Hauptsache, man weiss wo man es findet.
Uuuups - war das DER Schubs? Viel Erfolg.
danke für den schubs !! ;-)
er hat geholfen :-)
nun mein code, denn erfunktioniert im simulator 1a (da werden die interrupts per mausklick im PINB aktiviert), aber leider nicht mit dem tiny13 :-(.
wenn ich ihn in den tiny lade (mittels platine und programm vom franzis lernpaket) scheint er sofort in die "clslatch" routine zu laufen, denn PB4 ist aktiv. wenn ich das signal an PB2 dann gegen Vcc bringe schaltet er ab.Code:;*******************************************************************
;*
;* Programm: GTRiegel
;*
;* Version: 1.0
;*
;*
;* Portzuordnung:
;* PB0 < Schalter Tor zu PinChange Interrupt
;* PB1 < Impuls Tor auf/zu INT0 Interrupt
;* PB2 < Sensor Riegel offen/zu 3 Zustände möglich!!! (ADC)
;* PB3 > Riegel auf
;* PB4 > Riegel zu
;* PB5 > Impuls zur Torelektronik auf/zu
;*
;* PB0 und PB1 sind Interrupt gesteuerte Eingänge ;*
;*******************************************************************
; Definitionen
;*******************************************************************
#include "tn13def.inc"
.cseg
.org 0x000 ; Interrupt Vektoren
rjmp MAIN ; Hauptprogrammroutine (Reset)
rjmp IMPLS ; Interrupt0
rjmp CLSLATCH ; PinChangeInterrupt Tor zu
rjmp TMROVF ; TimerOverFlow für Warteschleife
rjmp MAIN ; Hauptprogrammroutine
rjmp MAIN ; Hauptprogrammroutine
rjmp MAIN ; Hauptprogrammroutine
rjmp MAIN ; Hauptprogrammroutine
rjmp MAIN ; Hauptprogrammroutine
rjmp MAIN ; Hauptprogrammroutine
.def TIM1 = R16 ; Timer 1 für Wartezeit
.def TIM2 = R17 ; Timer 2 für Wartezeit
.def TSEC = R18 ; Sekundenregister für Zeitügabe
.def SCNT = R19 ; Sekundenregister für Timer
.def TEMP = R20 ; dient für diverse Operationen
.def SAVR = R21 ; dient zum Sichern des SREG
.def ADCV = R22 ; enthält Wert von ADCH nach AD-Wandlung
.def DIMI = R23 ; "Door In Motion" Indikator
; dient zur Abfrage bei weiterem Impuls
; während Tor in Bewegung
; Bit Bedeutungen:
; Bit2: 1=Tor während Bewegung gestoppt
; Bit1: 0=Bewegung war auf, 1=war zu
; Bit0: 1=in Bewegung, 0=abgeschlossen
;*******************************************************************
MAIN:
;*******************************************************************
; Generelle Initialisierungen
;-------------------------------------------------------------------
; Allgemeine Interrupts verhindern
cli
; Arbeitsregister löschen
clr ADCV
clr DIMI
; Stack anlegen
ldi temp,LOW(RAMEND)
out SPL,temp
; Ports initialisieren
ldi temp,0b00111000 ; Register für DDRB in/out laden
out DDRB,temp ; 0 1 2 Eingänge 3 4 5 Ausgänge
ldi temp,0b00000010 ; Register für PORTB PB1 laden
out PORTB,temp ; PB1 PullUp, Ausgänge low
; ADC initialisieren
ldi temp,6 ; Reg. für ADC prescaler laden
out ADCSRA,temp ; 6 (divider 64) sind ca 18kHz
ldi temp,1 ; Reg. für ADMUX PB2 laden
out ADMUX,temp ; ADMUX setzen
; Wait-Timer setzen
ldi temp,3 ; Vorteiler /64
out TCCR0B,temp
; Interrupt Register setzen
ldi temp,0b00110001 ; 0bxxxxxxx1 INT0 jede Level-
; änderung löst Interrupt aus
out MCUCR,temp ; 0bxx11xxxx Sleep-Mode auf
; PowerDown setzen
ldi temp,0b01100000 ; GIMSK Interrupt Mask setzen
out GIMSK,temp ; Int0 und PinChange enable
ldi temp,1 ; PinChange auf PB0 beschränken
out PCMSK,temp
; Initialisierung beendet > enter SLEEP-Modus
rjmp pwrdwn ; dann power down
;*******************************************************************
;******************** START INTERRUPT ROUTINEN *********************
;*******************************************************************
;*******************************************************************
IMPLS: ; OK
;-------------------------------------------------------------------
; Interruptroutine (INT0):
; Diese I-Routine besitz nur den RJUMP Befehl zur Subroutine, da
; diese auch aus dem Programmablauf aufgerufen werden können muss.
; SREG braucht nicht gesichert zu werden, da keine Rückkehr
; erfolgt (rjmp).
;*******************************************************************
rjmp impuls
reti
;*******************************************************************
CLSLATCH: ; OK
;-------------------------------------------------------------------
; Diese Interruptroutine wird durch den PINchange (Tor zu) an PB0
; ausgelöst und schließt den Riegel
;-------------------------------------------------------------------
in savr,SREG
cli ; weitere Interrupts verhindern
clr dimi ; Tor in (Soll)Endstellung ZU
sbi portb,4 ; PB 4 ein = Riegel schließen
WCLSLATCH:
rcall readadc
sbrs adcv,0 ; Bit1=1 = Riegel geschlossen
rjmp wclslatch ; neue Abfrage bis geschlossen
cbi portb,4 ; PB 4 aus
rjmp pwrdwn
reti
;*******************************************************************
TMROVF: ; OK
;-------------------------------------------------------------------
; Diese Interruptroutine wird durch den TimerOVF Interrupt
; aufgerufen
;-------------------------------------------------------------------
in savr,SREG
clr tim1
out TCNT0,tim1 ; Timer zurücksetzen
inc tim2
cpi tim2,75 ; 75 cylces = ca. Sekunde
brlo tmrovfe
clr tim2
inc scnt ; Sekundenzähler um 1 erhöhen
TMROVFE:
out SREG,savr
reti
;******************** ENDE INTERRUPTROUTINEN ***********************
;*******************************************************************
;*********************** START SUB ROUTINEN ************************
;*******************************************************************
;*******************************************************************
IMPULS: ; OK
;-------------------------------------------------------------------
; Fragt Status von Tor und Riegel ab und führt entsprechende
; Routinen aus
;-------------------------------------------------------------------
cli ; weitere Interrupts verhindern
cpi dimi,0 ; DIMI=0, Torbewegung abgeschlossen
breq normrun ; wenn ja, normaler Ablauf
sbrc dimi,2 ; Bit2=0 Tor in Bewegung > skip
rjmp revers
rcall doorimp ; Bewegung stoppen
sbr dimi,2 ; Tor in Bewegung gestoppt
rjmp pwrdwn
REVERS: ; letzte Torrichtung umdrehen
sbrs dimi,1 ; Tor Richtung war ZU > skip
rcall clsdoor ; mit Schließen des Riegels
rcall doorimp ; Tor öffnen
cbr dimi,1 ; Torrichtung = AUF
ldi tsec,30 ; Wartezeit laden
rcall wait
clr dimi ; wenn alles OK, DIMI = 0
rjmp pwrdwn
NORMRUN:
sbis pinb,2 ; Abfrage Riegel zu? > skip
rjmp clsdoor ; Tor + Riegel schließen
rjmp opndoor ; Riegel + Tor öffnen
ret
;*******************************************************************
READADC: ; OK
;-------------------------------------------------------------------
; Liest den A/D Wandler an PB2 aus ADC 10 Bit Messung
; Da es sich hier um keine digitale „Spannungsmessung“ handelt
; sondern lediglich um eine „Statusabfrage“ reicht hierzu nur die
; Abfrage des Hi-Byte (ADCH):
; 0V = Riegel offen ADCH = 0
; 2V = Riegel „unterwegs“ ADCH = 1
; 5V = Riegel geschlossen ADCH = 3 (oder Abfrage dec. >1)
; Die Messung muss doppelt erfolgen ansonsten wird die vorherige
; Messung eingelesen – Eigenheit des Tiny13
;-------------------------------------------------------------------
sbi ADCSRA,ADEN ; ADC ENable
sbi ADCSRA,ADSC ; ADC Start Conversion
WREADADC1: ; Schleife bis Messung
sbic ADCSRA,ADSC ; abgeschlossen = ADSC=0
rjmp wreadadc1
sbi ADCSRA,ADSC ; ADC Messung 2tes Mal starten
WREADADC2:
sbic ADCSRA,ADSC ; warten bis ADSC = 0
rjmp wreadadc2
in temp,ADCL ; lowbyte einlesen
in adcv,ADCH ; highbyte einlesen
cbi ADCSRA,ADEN ; ADC ausschalten
ret
;*******************************************************************
CLSDOOR: ; OK
;-------------------------------------------------------------------
; Schickt Tor Impuls zum Schließen, setzt DIMI
;-------------------------------------------------------------------
rcall doorimp
sbr dimi,1 ; Bit1=1 = Torbewegung ZU
rjmp pwrdwn ; sleep bis Interrupt „Tor zu“ (PB0)
ret
;*******************************************************************
OPNDOOR: ; OK
;-------------------------------------------------------------------
; Öffnet Riegel und Tor
;-------------------------------------------------------------------
sbi portb,3 ; PB 3 ein = Riegel öffnen
WOPEN:
rcall readadc
nop
cpi adcv,0 ; compare (0=offen)
brge wopen ; neue abfrage bis offen
cbi portb,3 ; PB 3 aus
rcall doorimp
ldi dimi,1 ; Torbewegung AUF
ldi tsec,30 ; Wartezeit von 30 Sek. für Wait
rcall wait ; Warteschleife
clr dimi ; DIM Indikator löschen
rjmp pwrdwn
ret
;*******************************************************************
DOORIMP: ; OK
;-------------------------------------------------------------------
; schickt einen Impuls von etwa 1 Sekunde zur Torelektronik
;-------------------------------------------------------------------
ldi tsec,1 ; Zeit für Impulsspreizung in Sek
sbi portb,5 ; PB 5 ein = Impuls Tor auf
rcall wait ; Impulsspreizung
cbi portb,5 ; PB 5 aus
ret
;*******************************************************************
WAIT: ; OK
;-------------------------------------------------------------------
; Warteschleife für diverse Zeitverzögerungen
; Wartezeit wird von aufrufender Routine in TSEC übergeben
; Es wird der PinChange Interrupt kurzfristig unterdrückt, da beim
; Öffnen des Tores ungewollt ein PCI ausgelöst wird.
; Der PCI wird vor dem enable wieder gelöscht, damit dieser nicht
; nach der generellen Freigabe der Interrupts ausgeführt wird.
;-------------------------------------------------------------------
in temp,GIMSK
cbr temp,5
out GIMSK,temp ; PCI disable
clr scnt
ldi temp,2
out TIMSK0,temp ; Timer Interrupt freigeben
; Timer läuft .....
sei
LOOP:
cp scnt,tsec ; Sekunden abgelaufen?
brlo loop
clr temp
out TIMSK0,temp ; Timer Interrupt sperren, restliche
; Interrupts bleiben ein
in temp,GIFR
cbr temp,5
out GIFR,temp ; PCI löschen
in temp,GIMSK
sbr temp,5
out GIMSK,temp ; PCI enable
clr scnt
ret
;******************************************************************
PWRDWN: ; OK
;-------------------------------------------------------------------
; Beendet alle Funktionen, gibt die Interrupts frei und schaltet ab
; Ein Interrupt an PB1 (INT0) oder an PB0 (PinChange) aktiviert
; den Processor wieder
;-------------------------------------------------------------------
sei ; alle Interrupts frei geben
sleep ; Power Down, warten auf Interrupts
;************************ ENDE SUBROUTINEN *************************
.EXIT
aber - und das ist komisch, kein interrupt bringt ihn aus dem schlaf oder aus der schleife, die ich testweise statt der letzten zeile "pwrdwn" in MAIN probiert habe:
Kreis:
sei
nop
rjmp kreis
hast du eine idee??
wo hab ich meinen gedankenfehler?
schon vorab danke für deine mühe und geduld mit mir !!
Auf die Schnelle kritisiere ich nicht gerne. Und es fehlt mir aktuell wirklich an Assembler-Erfahrung. ABER: Am Ende des main wird ein rjmp angetreten von dem es kein Zurück gibt . . . . und wenn es ein Zurück gäbe, dann würde IMPLS angesprungen. Denn ich sehe nicht, dass main eine Endlosschleife ist.
Aber wie gesagt - ich muss das mal in Ruhe durchlesen - und dann weiss ich ob ich überhaupt einen sinnvollen Kommentar abgeben kann. Vielleicht gibts erfahrene Assemblernutzer hier?
auch die alternative mit der "kreis-schleife" statt dem power down (sleep) ändert nichts an der sache.
hab vergessen zu sagen, dass (auch beim testen am tiny) an
PB0 normal HI liegt (= LO interrupt)
PB1 ein LO impuls kommt
PB2 ein spannungsteiler (2x200k) mit vorwiderstand von 1k liegt, wobei immer eine seite durch einen schalter kurz geschlossen wird)
es hängt also nichts "in der luft".
PB3-PB5 zum testen je 1 led mit 1k gegen GND.
Wenn man die ISRs nicht ordnungsgemäß wieder verläßt, wird der Stack irgenwann überlaufen. Das ist zumindestens bei clslatch der Fall.
Das CLI am Anfang der ISR ist unnötig, das I Flag ist schon gelöscht.
Hinter dem Sleep ist das programm einfach zuende, da muß eigentlich noch ein jump noch oben hin, denn nach einem Timer Interrupt geht es da weiter.
Der AD Wandler wird so weit ich sehr nie eingeschaltet, sondern nur der Teiler gesetzt-
so, habe weiter getestet und bin auf einiges drauf gekommen:
egal wie PB5 konfiguriert ist:
als eingang mit einem 10k R gegen GND
oder als ausgang mit einer led+1k an GND
dann geht der tiny in den RESET modus !!!
der int0 funktioniert weder mit + noch mit - flanke.
habe alle varianten im MCUCR gesetzt und probiert.
nur pinchange funktioniert (ausgenommen an PB5 - siehe oben).
das habe ich mit folgendem testprogramm raus gefunden:
nur PB3 + 4 liegen mit einer led + 1k an masse, sonst ist der tiny nicht beschalten.Code:; TEST
#include "tn13def.inc"
.cseg
.org 0x000 ; Interrupt Vektoren
rjmp MAIN ; Hauptprogrammroutine (Reset)
rjmp IMPULS ; Interrupt0
rjmp IMPULS ; PinChangeInterrupt Tor zu
rjmp SCHLEIFE ; TimerOverFlow für Warteschleife
rjmp SCHLEIFE ; Hauptprogrammroutine
rjmp SCHLEIFE ; Hauptprogrammroutine
rjmp SCHLEIFE ; Hauptprogrammroutine
rjmp SCHLEIFE ; Hauptprogrammroutine
rjmp SCHLEIFE ; Hauptprogrammroutine
rjmp SCHLEIFE ; Hauptprogrammroutine
.def PORT = R16
.def TEMP = R17
MAIN:
cli
ldi temp,LOW(RAMEND)
out SPL,temp
ldi temp,0b00011000 ; Register für DDRB in/out laden
out DDRB,temp ; 0 1 2 5 Eingänge 3 4 Ausgänge
ldi temp,0b00000010 ; Register für PORTB in/out laden
out PORTB,temp ; Eingang 1 pullup
ldi temp,0b00000011 ; 0b00000010 INT0 N-Flanke
out MCUCR,temp
ldi temp,0b01100000 ; GIMSK Interrupt Mask setzen
out GIMSK,temp ; Int0 und PinChange enable
ldi temp,33 ; PinChange auf PB0 + PB5 beschränken
out PCMSK,temp
sei
SCHLEIFE:
nop
rjmp schleife
IMPULS:
cpi port,0
brne next
ldi port,8 ; mit 8 und 16 PB3 + PB4 ein
NEXT:
out portb,port
lsl port
cpi port,32
brne end
clr port
END:
sei
reti
als "schalter" an PB0+PB1 für die interrupts verwende ich einen 1k widerstand gegen Vcc oder Vdd.
wenn ich an PB5 als pin change tippe = reset!
am simulator des avr studio4 funktioniert obiger code tadellos.
warum nicht am tiny??
kann es sein, dass er defekt ist?
kann mir jemand weiter helfen?
hallo besserwessi,
danke für deine mühe, dass du dir meinen code angeschaut hast!
ich dachte diese beiden befehle starten den wandler? ist dem nicht so?
sbi ADCSRA,ADEN ; ADC ENable
sbi ADCSRA,ADSC ; ADC Start Conversion
habe in "clslatch" die zeile >rjmp pwrdwn< durch >out SREG,savr< ersetzt, somit wird nun durch das >reti< die routine ordnungsgemäß beendet.
überflüssiges cli entfernt und am ende von "pwrdwn" ein rjmp auf den anfang eingefügt/angehängt.
hast du eine idee zum problem vom vorigen eintrag (INT0 + PB5)?
Das mit dem ADC einschalten hatte ich übersehen. Ich stelle den Teiler immer gleich beim Einschalten mit ein, vorher braucht man es ja nicht.
Das mit dem AD Wandler könnte funktionieren.
Aus dem PowerDown Sleep mode geht nur pin change oder Int0 mit Level Interrupt. Beim Leven Interrupt muß man auch noch aufpassen das man den von Hand in der ISR Abschalten muß, sonst wird der gleich nochmal aufgerufen. So wie es aussiehr geht bein Tiny13 nur ein Interrupts auf low Signal !
Beim PB5 müßte man die Resetfunktion erst über die Fuses abschalten, bevor man den Pin als normalen IO Pin nutzen kann. Das heißt dann aber das man weder Debugwire noch das normale ISP Interface nutzen kann. Da würde ich eher probieren ob man da die normale Resetfunktion als Teil des Programmablaufts nutzen kann. Immerhin bleiben beim Reset einige Daten (RAM) erhalten. Man kann auch zwischen Signal an Reset und Power on unterscheiden.
was meinst du mit "Leven Interrupt" ?Zitat:
Zitat von Besserwessi
das mit dem nutzen der reset funktion ist eine gute idee.
dazu braucht es aber nur einen impuls und kein solides signal.
lässt sich aber lösen.
danke
Zitat:
Zitat von Besserwessi
UUuuuups - könnte sein, dass Du das doc nicht hast oder suchen müsstest. Erstens: auf der At mel-doc-Download-site steht zum Tiny13 : Not recommended for new designs. Nichts destotrotz: Hol es Dir - zu jedem Controller gehört seine Dokumentation.Zitat:
Zitat von Atmel-doc 2535, Rev. 2535H–AVR–10/07, S 54
ich hab das dokument.
habe auch die verschiedenen varianten des int0 ausprobiert (MCUCR seite 27) - aber der tiny reagiert auf keine einizige variante (- + oder beides).
es wird kein interrupt ausgelöst :-(
im simulator funktionierts tadellos (siehe code test programm) - ist eben SIMULATOR ...
habe mir gerade einen neuen tiny13 besorgt.
werde damit am abend testen ...
Wenn der Tiny13 im Powerdown mode ist, reagiert er nur auf den Level Interrupt (Input an GND) am Int0 Pin. Die Interrrupts auf Flanken gehen dann nicht. Steht bei der Erklärung der Sleep Modes im Datenblatt.
Oh weh, da habe ich schlecht geraten - vielmehr völlig ungenügend das Datenblatt gelesen - - ich hatte einfach den Abschnitt Interrupt aufgeschlagen. Sorry ihr Beiden.Zitat:
Zitat von Besserwessi
aber nicht doch!
im kapitel 7.1.3 Power-Down Mode seite 31 steht als 3. satz (kopiert):
Only an External Reset, a Watchdog Reset, a Brown-out
Reset, an external level interrupt on INT0, or a pin change interrupt can wake up the MCU.
also kann JEDER dieser interrupts den tiny wieder wecken ...
auch aus dem power down modus.
Ich glaube, damit steht der Sieger in diesem kleinen Lesewettbewerb eindeutig fest.
Da steht im datenblatt aber auch die Einschränkung, das Int0 nur als Level Interrupts geht. Mit Pin Change interrupt ist der extra Pin-change Interruts gemeint, der auch die anderen Pins abdecken kann.
Was aber nicht geht ist Int0, wenn die Bits ISC01/ISC00 nicht 0/0 sind, also die Reaktion auf eine oder beide Flanken.
wo liest du, dass int0 nur als level interrupt geht? seite, kapitel?Zitat:
Zitat von Besserwessi
was meinst du mit "extra pin change" ??Zitat:
Zitat von Besserwessi
das kann ich auch nicht raus lesen:Zitat:
Zitat von Besserwessi
ISC01 ISC00 Description
0 0 The low level of INT0 generates an interrupt request.
0 1 Any logical change on INT0 generates an interrupt request.
1 0 The falling edge of INT0 generates an interrupt request.
1 1 The rising edge of INT0 generates an interrupt request.
übrigens hab ich das problem mit dem int0 geklärt.
zum laden des codes habe ich das lernprogramm und die platine von franzis verwendet - funktioniert ja, da bei den experimenten diverse codes in den tiny geladen wurden. aber solange nur diese codes lädt.
nur, was ich nicht bedacht habe, es bleibt aufgrund des noch vorhandenen bootladers PB1 für den datenaustausch mit dem pc aktiv ...
daran hatte ich nicht gedacht !!
ich muss also ein anderes programm zum echten "flashen" (mit PB5 > gnd) verwenden, damit ich den bootloader raus bringe und nur mehr mein code drin ist.
Das mit dem Int0 steht in der Fußnote zu Tabelle 11, und in der Erklärung zu External Interrupts.
Auch wenn da eine Bootloader drauf ist, kann man den Controller in den Powerdown Mode versetzen. Der Bootloader ist normalerweise nur direkt nach dem Reset aktiv. Wenn da kein Signal gefunden wird, wird das normale Programm gestartet ohne das der Bootloader wieder dran kommt. Man hat halt nur weniger Speicher (flash) zur verfügung als ohne Bootloader. Wenn man den Pin PB5 als reset lassen will, und über die Resetfunktion auswerten will, dann hat man natürlich mit den meisten Bootloadern ein Problem.
Grübelgrübelgrübel - ich habe das "Lernpaket Microcontroller" - und dazu habe ich ein Programm LPMicros und ein weiteres, das LPMicro ISP. Das erste lädt die Experimentierumgebung in den tiny13 - und der versprochene bzw. angeblich enthaltene Bootloader funktionierte bei mir leider nie. Daher hatte ich die selbst geschriebenen Programme als eigenständige Programme geschrieben und mit dem LPMicro ISP in den t13 geflasht. Lief immer bestens.Zitat:
Zitat von HeSt
Das LPMicros verwende ich immer noch und immer wieder. Es ist recht praktisch, damit mal eine LED anzuknipsen um deren Stromaufnahme zu messen, oder ähnliche, einfache Abläufe, die immer wieder mal vorkommen schnell aufzubauen und zu testen.
Ich grüße euch,
ich bin zwar auch nicht der Asm-Profi, aber ich versuche mal mitzuteilen wo (auch) ich eventuell ein Problem sehe.
Genau wie Besserwessi schon geschrieben hat, sehe ich auch an den gleichen Stellen ein grundsätzliches Problem.
Ich beziehe mich auf den einzigen geposteten Code von dir HeSt aus dem Post an dieser Stelle.
Wenn ich richtig geschaut habe, landen deine 3 Interrupt-Funktionen (und auch die nicht genutzten über main) alle wieder an einem "rjmp pwrdwn". Nun geht das main so von oben in diese sleep-Funktion.
Jetzt wird also mit dem "sleep" die CPU geparkt, und der erwartete Interrupt sollte seine Arbeit machen und wieder mit dem "rjmp pwrdwn" aus der ISR bzw. den aufgerufenen Funktionen irgendwie wieder, von oben zum "sleep" kommen.
Was aber dann nicht in den ISR-Funktionen ausgeführt wird ist der Befehl "reti".
Genau hier würde ich nun das Problem erwarten, da die AVR's (und wohl auch alle andere CPUs) das I am reti nutzen um einige Bits und Bytes in der Interrupt-Hardware/Register zu richten.
Da ich nun nicht weiß, ob dieses von dir benutzte Schema grundsätztlich funktioniert in dieser CPU, kann ich natürlich auf dem Holzweg sein.
Ich habe auch nicht geprüft, ob diese nicht durchgeführte Aktion vom fehlenden reti, in deinem Programm überhaupt eine Auswirkung hätte.
Meine ASM's hatte ich immer so geschrieben:
main
- init-Code
- sprungmarke: sleep
- jump sprungmarke
ISR
- tu was zu tun ist
- reti
--> reti wird ausgeführt, und im main geht es nach dem sleep mit speed wieder zum sleep. Genau so hatte Besserwessi ja auch schon geschrieben.
--> Ansonsten können nun die ISRs machen was sie wollen, und ich muss nicht darauf achten, dass sie alle wieder mit dem "rjmp pwrdwn" von oben zum sleep kommen. Sonst fehlt ja tatsächlich danach ein weiterer Befehl.
Hast du das, was ich gerade so umständlich beschrieben habe, somit schon erledigt? (Besserwessi hat nur ca. 2% meiner Wortanzahl benötigt ;-))Zitat:
Zitat von HeSt
Wohin springst du, wenn du ".. auf den anfang .." springst?
Ich hoffe, wir kommen gut in den Winter-Sleep und auch wieder raus.
Gruß Sternthaler
hallo sternthaler, danke für deine ausführungen.
ich werde leider mit dem tiny13 meine problemstellung in „normaler“ form – also ohne änderung der fuses – nicht realisieren können, da mir der port5 nicht als ein-/ausgang zur verfügung steht sondern nur als reset eingang.
und ich hab leider kein programm mit dem ich fuses ändern kann.
somit baue ich eine „hybrid“ lösung mit zusätzlichen herkömmlichen ic’s.
wie kann man das unterscheiden?Zitat:
Zitat von besserwessi
ich sehe keine möglichkeit, denn die i/o register werden alle resettet und das kann ich nicht brauchen, denn die ports müssen ihren status behalten um sie auslesen zu können.
und das lese ich nirgendwo raus, dass portb nicht auch auf 0 gestellt wird, samt ddrb.
portb, pinb und ddrb sind doch i/o register, oder irre ich hier?
auszug aus dem datenblatt:
During reset, all I/O Registers are set to their initial values, and the program starts execution from the Reset Vector.
eine frage noch zu den fuses:
ich müsste, um portb5 als „normalen“ ein-/ausgang verwenden zu können, das bit 4, SELFPRGEN Self Programming Enable im hi-byte der fuses umschießen – nachdem ich das programm geladen habe, denn sonst kann ich den tiny ja nicht mehr programmieren/flashen.
sehe ich das richtig?