Midi auf dem Atmega8... unzuverlässige Werte... What do?

Nunja, Du schriebst:
...SREG sollte in einer IRQ-Routine immer gespeichert werden ...
"Immer" ist schon absolut.
Was ist den der Unterschied zu den ganzen anderen I/O-Registern, die nicht "immer" gesichert werden müssen? Wenn ich in verschiedenen ISR und ggf im Hauptprogramm die GPIOR verändere, muß ich sie auch sichern - sonst nicht.
Wenn sich keine der verwendeten Instruktionen das SREG ändert, muß es nicht gesichert werden.
 
Servus LotadaC,

Du hast damit natürlich recht. Ich stimme Dir zu 100% zu. Ich ziehe meine Aussage zurück und versuche beim nachstenmal treffender zu formulieren.

gruss

Gottfried
 
chillt mal jungs.

hat noch wer was zu meinem problem zu sagen? ihr wisst schon.. totzeiten, knick knack??
 
Servus matze f.
ich kann mir keinen so rechten Reim auf Deine totzeiten machen. Wenn Dein Programm schnell genug ist, kannst Du mal versuchen die ankommenden Mididaten im Hauptprogramm zu verarbeiten. Hab ich mal für ein Midiinterface gemacht. Lief auf einem Atiny 2313 mit 8Mhz.

Code:
  loop:

   cpi Clockteiler, 0xFF
   brne Get_Midi 
   rcall Teiler_einlesen


   Get_Midi:

   sbis UCSRA, RXC        ; warten bis ein Byte angekommen ist
   rjmp Get_Midi
   in   temp1, UDR
   cpi temp1, MidiClock
   Breq Midi_Clock
   cpi temp1, Start        ; Das Z-Flag wird gesetzt, wenn das Ergebnis Null ist
   Breq Start_Sequenz
   cpi temp1, Stop
   Breq Stop_Sequenz
   cpi temp1, Cont
   Breq Continue_Sequenz
   cpi temp1, Sys_Reset
   Breq System_Reset
   cpi temp1, Note_On
   Breq NoteON
   cpi temp1, Controller   ; Controller-Daten ?
   Breq CC
   cpi temp1, Note_On
   Breq NoteON
   rjmp loop              ; Endlosschleife

Am Anfang wurde ein Schalter eingelesen, der den Teilerfaktor für die Midiclock definiert.
Dann hab ich gewartet bis ein Byte angekommen ist. Je nach Inhalt bin ich in die zugehörige Routine verzweigt und hab das Byte verarbeitet. Anschliessend bin ich wieder in die Hauptschleife gesprungen und warte auf das nächste Byte.
Wenn das Programm kurz ist, geht dir keine Midiinformation verloren.
Ich hab die Midiclock und Start/Stop/Resset als DIN-Sync ausgegeben um meinen Sequenzer zu Steuern. Midinoten und Controller-Daten wurden auch verwertet. Da das ganze recht flott geht, hab ich nie Probleme mit verschluckten Daten gehabt. Und Midiclock sendet ja contiunierlich seine Daten.
Bei einem Start-Befehl hab ich den entsprechenden Port angesteuert und eine Led eingeschaltet.
Bei einem Stop Befehl wurde die Led wieder ausgeschaltet.
Code:
  Start_Sequenz:  ; Start bei Position Null, d.h. Start + Reset
                   ; Start_Stop = 1
				   ; Cont_Wait = 0 (Continuemodus)
				   ; Start = 1 für 10ms
				   ; Reset = 1 für 10ms


   ldi RES_H, HIGH(Time_Led) ; Hellphase Reset Led            01
   ldi RES_L, LOW(Time_Led)  ; Time Led x 0,256 ms            F4
   cbi Midi_Port, 6         ; Reset-LED

   
   sbi Sync_Out_PORT, Reset_Sequ
   cbi Sync_Out_PORT, Cont_Wait
   ldi CNT_Reset, TIME_50ms
   sbis Data_PIN, Mode_J2   ;  Midicontoller steuert Start-Stop
   rjmp loop                ;  Ja.
   sbi Sync_Out_PORT, Run
   sbi Sync_Out_PORT, Start_Sequ
   ldi CNT_Start, TIME_50ms
   rjmp loop

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   Stop_Sequenz:     ; Stop bei aktueller Position, kein Reset ( = Pause/Wait )
                     ; Start_Stop = 0
				     ; Cont_Wait = 1 (Waitmodus)
				     ; Stop = 1 für 10ms

   cbi Sync_Out_PORT, Run            ; Led aus
   sbi Sync_Out_PORT, Cont_Wait
   sbi Sync_Out_PORT, Stop_Sequ
   ldi CNT_Stop, TIME_50ms
   rjmp loop
Wenn ein Controllerbefehl reinkamm, bin ich in eine entsprechende Routine vertweigt, die dann auf das Datenbyte wartet, und es auswertet. Danach gings wieder in die Hauptschleife.
Code:
  CC: 

   sbic Data_PIN, Mode_J2   ;  Midicontoller steuert Start-Stop ?
   rjmp loop                ;  Nein.

 ; Midi-ontroller einlesen
   sbis UCSRA, RXC          ; warten bis ein Byte angekommen ist
   rjmp CC
   in   temp1, UDR
   cpi temp1, Ctrl_84       ; Stop
   Breq CC_84
   cpi temp1, Ctrl_85       ; Start
   Breq CC_85
   cpi temp1, Ctrl_86       ; Wait
   Breq CC_86
   cpi temp1, Ctrl_87       ; Reset
   Breq CC_87
   cpi temp1, Ctrl_88       ; Run. Evtl. nicht notwendig, da von Wait abhängig
   Breq CC_88

   rjmp loop
;++++++++++++++++++++


   CC_84:                        ; Steuert Stop
   sbis UCSRA, RXC               ; warten bis ein Byte angekommen ist
   rjmp CC_84
   in   temp1, UDR               ; Controllerwert einlesen
   cpi temp1, 0x40
   BRLO CC_84_LOW                ; Verzweige, wenn Controllerwert kleiner 64 ist
   cbi Sync_Out_PORT, Run        ; Led aus
   sbi Sync_Out_PORT, Stop_Sequ
   ldi CNT_Stop, TIME_50ms
   rjmp loop
Ich hab nur die Controller beachtet, für die ich eine Funktion programmiert hab.
Kann sein, dass das alles nicht so optimal programmiert ist, aber es lief.

Versuch mal Dein Programm neu zu schreiben, wenn Du mit der jetzigen Version nicht weiter kommst.
Programmablaufpläne sind selbst bei einfachen Dingen sehr hilfreich. Du solltest Dich mal damit auseinandersetzen.
Im Netz gibt es viele Infos dazu. Und so Akademisch genau müssen sie ja nicht sein.

Gruß

Gottfried
 
hallo gottfried,

danke für deine code. das muss ich mir die tage mal genauer ansehen. jetzt nur mal ein kurzes update...


Versuch mal Dein Programm neu zu schreiben, wenn Du mit der jetzigen Version nicht weiter kommst.
was heißt nicht weiterkommen. ich habe ja schon eine idee wie ich das alles besser lösen kann. aber trotzdem möchte ich gern wissen warum es zu dieser totzeit kommt. denn ich vermute das das ein problem ist, das auch in anderer form wieder auftreten könnte. irgendwie sowas, wie ein falsch initialisierter stack.

anyway. hab jetzt das ganze mal in avr-studio simuliert. das ganze hat ganz gut geklappt, ich konnte einzeln durchskipen und durch setzten des receive complete-bits einen interrupt simulieren. in der simulation klappt alles super. ich kann sofort nachdem ich einen interrupt ausgelöst habe und der abgearbeitet wurde einen neuen setzten und alles läuft wie es soll.

ich hab das ganze avr-studio-projekt hier mal als zipfile drangehängt. wenn jemand lust und muße hat kann er ja noch mal draufschauen... würde mich freuen...

ansonsten fang ich jetzt nochmal an das ganze neu und anders zu schreiben...


Anhang anzeigen totzeit.zip

edit: nicht wundern, wenn ich da "bite1" geschrieben hab, aber avr-studio lässt "byte1" nicht zu...
 
Servus,

hast Du auch einen Schaltplan mit den PIN-Belegungen. Damit tu ich mich leichter, was wann geschaltet wird.

In Deiner IRQ-Routine hast Du die Befehle INC und IN.
Code:
;Timer0 Overflow interrupt
TIMER0:

	inc zeit1
reti

;Uart interrupt
UART:

	in bite1, UDR	
reti

Folgendes lese ich in der Beschreibung der Befehle:

INC - Increment
Syntax: INC Rd
Funktion: Dieser Befehl addiert eine 1 zum Inhalt des angegebenen Registers und legt das Ergebnis im Register ab. Das Carry-Flag wird dabei nicht verändert, so dass der Befehl in einem Schleifenzähler verwendet werden kann, ohne die eigentlichen Berechnungen zu beeinflussen.
Wenn mit vorzeichenlosen Werten gearbeitet wird, arbeiten nur die BREQ- und BRNE- Verzweigungsbefehle korrekt. Wenn mit Zweierkomplement-Werten gearbeitet wird, können alle vorzeichenbehaftete Verzweigungsbefehle verwendet werden.
Operation: Rd ← Rd + 1
Operanden: 0 ≤ d ≤ 31
Programmzähler: PC ← PC + 1
Words: 1 (2 Byte)
Zyklen: 1
16 Bit Operations Code: 1001 010d dddd 0011

Flags im Status-Register (SREG):
I T H S V N Z C
- - - ↔ ↔ ↔ ↔ -
S: Das S-Flag wird gesetzt, wenn entweder das V-Flag oder das N-Flag gesetzt ist. Wenn beide Bits gleich sind, wird das S-Flag gelöscht.
V: Das V-Flag wird gesetzt, wenn aus der Operation ein Zweierkomplement- Überlauf erfolgt, andernfalls wird das Flag gelöscht. Ein Zweierkomplement- Überlauf kann nur auftreten, wenn Rd vor der Operation den Wert 80h hatte.
N: Das N-Flag wird gesetzt, wenn das MSB des Ergebnisses gesetzt ist, andernfalls wird es gelöscht.
Z: Das Z-Flag wird gesetzt, wenn das Ergebnis 00h ist, andernfalls wird das Flag gelöscht.

Also: SREG wird verändert.

Befehl IN verändert SREG nicht.

Versuche mal SREG in der Timer ISR zu Speichern und wiederherzustellen.

Ansonsten ist mir auf die schnelle nichts aufgefallen. Bei nächster Gelegenheit schau ich mir den Code genauer an.

Gruß

Gottfried
 
du meinst, direkt am anfang des interrupt-vektors sreg auf den stack zu tun, und nach dem inc direkt wieder holen? ok, probiere ich aus. danke für den tipp

edit: schaltplan hab ich keinen da, müsste ich mir noch machen. reicht ne abfotografierte handskizze?
 
Nicht ganz: am Anfang der ISR die verwendeten nicht reservierten Rechenregister UND das SREG (sofern es manipuliert wird) auf den Stack, und am Ende der ISR alles in umgekehrter Reihenfolge (LIFO) wieder zurück.
 
Servus,

photo von ´ner Handskizze reicht.
du meinst, direkt am anfang des interrupt-vektors sreg auf den stack zu tun, und nach dem inc direkt wieder holen?
Genau! In etwa so:
Code:
push temp0
lds  temp0, SREG

	inc zeit1

sts SREG, temp0
pop temp0

reti

Stell Dir vor Du vergleichst "cp msg1, key1", beide Werte sind gleich, Z-Flag wird gesetzt.
Genau jetzt kommt ein Timerinterupt.
"inc zeit1" erhöht Zeit1 zB von 0 auf 1. Das ergebnis ist ungleich Null, Z-Flag wir gelöscht.
Nach Rückkehr von der Timer ISR ist Dein Z-Flag gelöscht und Du verzweigst falsch.

Und nimm CLI/SEI mal probeweise aus Loop0 raus. Sollte meiner Meinung nach nicht nötig sein.

Code:
	ret_ausgabe_off:

	rjmp loop0

; ausgabe_off
	ausgabe_off:
	ldi temp0, 0xFF
	out PORTB, temp0
	
	rjmp ret_ausgabe_off
	ldi zeit1, 0


; ausgabe_on
	ausgabe_on:
Wann wird "ldi zeit1, 0" ausgeführt ? Du springst ja vorher schon weg!

Gruß
 
ja das meinte ich. vielleicht verwende ich den begriff interrupt-vektor falsch.
 
Hallo ihr lieben menschen!

Ich muss diesen alten kaffee nochmal aufwärmen.. Ich bin nämlich immernoch dran.

kurz zur lage: ich habe den Optokopper gegen einen 6N137 getauscht, der verspricht 10 Mbit/s sollte reichen für midi, wa? nun, es ergibt sich folgendes bild:

wenn ich auf meinem midi-keyboard eine taste drücke (und gedrückt halte), dann kommen die bytes korrekt am atmega8 an. allerdings sieht das anders aus, wenn ich die taste schnell drücke und wieder gleich los lasse. dann kommen von der "off-message" nur das 2. byte und das 3. byte an. das 1. byte (also dass, welches die kanal-nummer und den on/off befehl beinhaltet) geht verloren.
ich habe mir dazu ein kleines programm für den atmega geschrieben, dass die ankommenden bytes erstmal alle auf den speicher schreibt und ich danach per taster (an int1) einzeln durch klicken kann, was da angekommen ist. dabei zeigt sich das oben beschriebene fehlverhalten. wenn ich zwischen drücken und loslassen etwas warte, dann kommen alle 6 bytes korrekt an.

Die ausgabe geschieht an PORTB auf dem STK500. weil die obersten beiden bits da aber nicht angezeigt werden können (pins werden für osc gebraucht), geben DIESE an PORTD auf meinem DIY-board an zwei leds gesondert aus... aber das sollte nicht so wichtig sein.

anbei der quellcode für das angesprochene testprogramm und der schaltplan. schaltplan ist nicht norm-konform, ich hoffe ihr könnt mir das nachsehen. Jeder, der mir weiter helfen kann bekommt von mir ein bier ausgegeben!


ach ja: fuse bytes sind:
low: E0 und
high: D9

schaltplan.png
Anhang anzeigen midi-box.asm
 
Bist Du sicher, daß das Telegramm bei kurzer/schnell wiederholter Tastenbetätigung überhaupt korrekt gesendet wird?

Übrigens ist es etwas umständlich, den Code auf'm Mobile zu lesen (zu bekommen) - warum stellst Du den nicht als ASM-Block rein?


CodeBox Assembler
.include "m8def.inc"


.org 0x000
         rjmp MAIN            ; Reset Handler
.org INT0addr
       rjmp int0_handler                   
.org INT1addr
       rjmp int1_handler
.org URXCaddr
         rjmp UART


MAIN:
.def midi_byte = r16
.def temp0 = r17
.def bite1 = r20				//wird gebraucht um kruzfristig den inhalt der einkommenden messages zu speichern und temp0 frei zu haben
.def temp1 = r25





.equ F_CPU = 16000000
.equ BAUD = 31250




// Berechnungen						so gesehen auf http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))      ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate gr�sser 1 Prozent und damit zu hoch!"
.endif


//**********Stackpointer initialisieren**********
 
    ldi     temp0, HIGH(RAMEND)
    out     SPH, temp0
    ldi     temp0, LOW(RAMEND)
    out     SPL, temp0

//**********uart konfigurieren**********
 
    ldi     temp0, HIGH(UBRR_VAL)
    out     UBRRH, temp0
    ldi     temp0, LOW(UBRR_VAL)
    out     UBRRL, temp0

	ldi temp0, (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)			//Frame format auf 8 bit setzten. 
	out UCSRC, temp0

	sbi UCSRB, RXCIE
	sbi UCSRB, RXEN

//**********INTX initialisieren**********

	ldi temp0, (1<<ISC00) | (1<<ISC01) | (1<<ISC10) | (1<<ISC11)	//INT1 und INT0 auf steigende flanke konfigurieren
	out MCUCR, temp0


	ldi temp0, (1<<INT0) | (1<<INT1)								//INT0 aktivieren
	out GICR, temp0				


//**********Ports konfigurieren**********

	ldi temp0, 0xFF				//PORTB = ausgang, da hier die pins getoggelt werden			
	out DDRB, temp0				//genau genommen w�re es korrekt DDRB mit 0b00111111 zu laden, da die beiden oberen bits ja vom oszillator beansprucht werden...

	ldi temp0, 0b10111111		//PORTD = ausgang, au�er pin6	
	out DDRD, temp0				//offenbar MUSS f�r die aktivierung von int0 und int1 die beiden pins (PD2 & PD3) als AUSGANG konfiguriert werden

								//PD1 ist die "error"-led. 				000000X0

//**********Register initialisieren**********

	ldi temp0, 0b11111110			//Eine LED leuchtet, wenn startbereit
	out PORTB, temp0
	
	ldi temp0, 0b00000000			//evtl. nicht n�tig

	ldi temp0, 0b00000000			//evtl. nicht n�tig
	mov midi_byte, temp0

//**********Ram initialisieren**********


	ldi zl, 0x6C				//ich initialisiere das hier auf 0x6C initialisiere, da das hier nur ein Testprogramm zur analyse der  
	ldi zh, 0x00				//ankommenden bytes ist. im eigentlichen programm brauche ich die ersten 12 bytes im speicher f�r 
								//f�r andere dinge. deshalb... aber eigentlich willk�rlich.
	ldi xl, 0x6C
	ldi xh, 0x00

	ldi yl, 0x60
	ldi yh, 0x00







//**********main loop**********


sei


loop0:
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
rjmp loop0









	
error:							//schaltet die "error"-led an 
	in temp0, PIND
	cbr temp0, 0b00001000			//vielleicht ist es schlau das hier zu machen, da vielleicht wegen dem taster noch das eine bit gesetzt ist. auf der anderen seite: ich gebe es ja nur auf den selben port aus. sollte keinen unterschied machen...
	sbr temp0, 0b00000010
	out PORTD, temp0
ret


midi_byte_ausgeben:

	mov temp0, midi_byte				//die obersten zwei bits muss ich an PORTD ausgeben, da an PB6 und PB7 zeug vom oszillator h�ngt
	lsr temp0
	lsr temp0
	andi temp0, 0b00110000
	out PORTD, temp0


	ldi temp1, 0b00111111				//aber die unteren 6 bit gehen an PORTB.
	mov temp0, midi_byte
	eor temp0, temp1					//da die LEDs aber auf dem STK500 invertiert sind, muss ich das hier auch negieren
	out PORTB, temp0

ret



UART:

	in bite1, UDR	//empfangenes Byte auslesen

	st z+, bite1 	//empfangenes byte auf den speicher schreiben
	
reti



int0_handler:			//hier wird der z-pointer zur�ck gesetzt und die "error"-led ausgeschaltet

	ldi temp0, 0
	out PORTD, temp0			//Alle LEDs aus!

	mov zh, temp0				//zur�ck setzten
	ldi temp0, 0x6C
	mov zl, temp0


	rcall speicher_frei_raeumen

	ldi temp0, 0b11111110
	out PORTB, temp0


reti




int1_handler:

	

	ld  midi_byte, x+

	rcall midi_byte_ausgeben

	cp xl, zl											
	brlo x_ist_noch_niedriger_als_z						//branche if same or higher -> wenn der x-pointer den z-pointer �berholt,

	rcall error											//dann schalte "error"-led an

speicher_frei_raeumen:									//und initialisiere den x-pointer wieder mit dem anfangswert
														//man kann dann erneut durch steppen..
	ldi xh, 0
	ldi xl, 0x6C			//eigentlich ist es kooler, wenn ich z garnicht nulle, dann k�nnen neue bytes drauf geschrieben werden und man kann von neuem durch-skippen
		

	x_ist_noch_niedriger_als_z:					//wenn x niedriger als z, dann raus
	nop											//nopt ist hier nur verzierung


reti


  

Deine Taster sind im Plan unkonventionell verdrahtet, der UART gar nicht angeschlossen. Wwarum machst Du Dir das mit der Error-LED so schwer? Das PORT-Register ist direct bit accessible -> SBI/CBI
 
Deine Taster sind im Plan unkonventionell verdrahtet, der UART gar nicht angeschlossen

wieso? hängt doch an PD0. das ist doch der eingang für uart

Wwarum machst Du Dir das mit der Error-LED so schwer?

wieso schwer?


Das PORT-Register ist direct bit accessible -> SBI/CBI
ja aber so wie ich das gemacht habe gehts doch auch... ich arbeite lieber mit wenigen befehlen...


EDIT: achso, du meinst mit "schwer" bezüglich error-led, dass ich das als sub-routine gemacht habe? ja, das kommt daher, dass in dem eigentlichen programm welches ich geschrieben habe das sinn machte. hätte ich in diesem test-programm einfacher machen können.

aber das sind ja alles keine sachen, die erklären, warum das zweite byte-tripel nicht ordnungsgemäß ankommt...
 
wieso? hängt doch an PD0. das ist doch der eingang für uart...
Laut Deinem Plan aus #51 hängt der OK an C0, D0 (RXD) ist unbeschaltet und an TXD (D1) hängt die Error-LED...

Das mit den Tastern ist auch nicht klar.
Du schaltest den ganzen D-Port als Ausgang - ausser D6 wo aber nichts drannhängt. Das aktiviert also auch für die beiden INT-Beine (mit den Tastern dran) die internen Ausgangstreiber, die erstmal auf Gnd geschaltet sind. Extern mit 10K auf Gnd gezogen. Werden die Beine mit dem PORT-Register auf Vcc gelegt, fließt Strom über den Pulldown. Aber was ist jetzt mit den Tastern? Die legen über 9V auf den Pin? Das verträgt der nicht.
//offenbar MUSS f�r die aktivierung von int0 und int1 die beiden pins (PD2 & PD3) als AUSGANG konfiguriert werden
Sollte eigentlich nicht so sein, Du mußt allerdings den tatsächlichen triggernden Pegel draufbekommen. INT0/1 als alternative Portfunktion beeinflussen PORT/DDR-Register nicht, es gibt lediglich eine Beeinflussung im Sleep (beim Digital Input Enable Override Enable (DIEOE) und dessen Override Value (DIEOV)).
... ich arbeite lieber mit wenigen befehlen...
Egal ob in einer Extra-Routine oder nicht:


CodeBox Assembler
SBI PORTD, 0b00000010
sind doch weniger Befehle als


CodeBox Assembler
in temp0, PIND
...
sbr temp0, 0b00000010
out PORTD, temp0
oder?

P.S.: Versuch mal, mehr definierte Konstanten zu verwenden - für die LED- und Taster-Bit-Nummern zB oder die Anfangsadresse deines Datenpuffers im SRAM. Das macht den Code verständlicher/besser lesbar, für Dich auch besser editierbar. Der Compiler macht ja da dieselben Werte draus, aber weniger potentielle Tippfehler als Du (insbesondere, wenn man irgendwo was ändert/umsteckt, und das dann überall im Code ändern muß;))

P.P.S.: So wie's aussieht, klemmt die Verwendung der Oszillatorbeine als solche die korrespondierenden PORT-/DDR-/PIN-Register-Bits komplett vom Bus ab (Schreiboperationen landen im Nirvana, Leseoperationen liefern 0).
 
Laut Deinem Plan aus #51 hängt der OK an C0, D0 (RXD) ist unbeschaltet

Stimmt. da hab ich mich vertan im schaltplan.

und an TXD (D1) hängt die Error-LED...

ja, da ich UART nicht schreiben will ist das doch in ordnung, oder? lesen reicht für meine anwendung...

Das mit den Tastern ist auch nicht klar.
Du schaltest den ganzen D-Port als Ausgang - ausser D6 wo aber nichts drannhängt.
jup. das ist deshalb, weil in dem schon angesprochenen "eigentlichen programm" der Pin6 von PORTD als eingang für einen schalter dienen soll. der ist aber noch nicht implementiert und auch physisch auf meinem diy-boad nicht vorhanden..


Das aktiviert also auch für die beiden INT-Beine (mit den Tastern dran) die internen Ausgangstreiber, die erstmal auf Gnd geschaltet sind. Extern mit 10K auf Gnd gezogen. Werden die Beine mit dem PORT-Register auf Vcc gelegt, fließt Strom über den Pulldown
Aber was ist jetzt mit den Tastern? Die legen über 9V auf den Pin? Das verträgt der nicht.
stimmt. Es tut mir schrecklich leid, aber auch an dieser stelle habe ich mich im schaltplan verzeichnet. das sind 5 volt an den schalter. das ganze diy-board liegt auf 5 V. 9 Volt sind nur von das stk500 da...

hier der überarbeitet schaltplan: schaltplan3.png

Sollte eigentlich nicht so sein, Du mußt allerdings den tatsächlichen triggernden Pegel draufbekommen. INT0/1 als alternative Portfunktion beeinflussen PORT/DDR-Register nicht,
ja wundert mich auch. aber die ganze aufbaute reagiert anders wenn ich den DDREG von PORTD mit nullen anstatt mit einsen an der entsprechenden stelle beschreibe. mit einsen, wie im obigen quellcode funktioniert es so wie ich es erwarte. mit nullen kommt es zu teils kaotischen ausgaben an der led-kette. zumindest kann ich mir die bitmuster darauf dann nicht mehr erklären...


es gibt lediglich eine Beeinflussung im Sleep (beim Digital Input Enable Override Enable (DIEOE) und dessen Override Value (DIEOV)).
ja gut, das thema sleep-modus fang ich an der stelle noch nicht an...

Egal ob in einer Extra-Routine oder nicht:
Programmiersprache Assembler
1 SBI PORTD, 0b00000010

sind doch weniger Befehle als
Programmiersprache Assembler
1 in temp0, PIND
2...
3 sbr temp0, 0b00000010
4 out PORTD, temp0

richtig. mit wenigen befehlen meinte ich auch wenige verschieden befehle. dann lieber drei zeilen mit standard befehlen als eine zeile, bei der ich immer im manual nachlesen muss was das macht. natürlich ist das rausgepickte beispielt hier anders. sbi benutze ich ja an anderer stelle auch. ich werde das nachbessern.
ich benutze auch fast immer den befehl breq wenns ums verzeigen geht. das ist zwar sicher nicht immer das effizienteste aber in meiner denke einfach das logischste.


P.S.: Versuch mal, mehr definierte Konstanten zu verwenden - für die LED- und Taster-Bit-Nummern zB oder die Anfangsadresse deines Datenpuffers im SRAM. Das macht den Code verständlicher/besser lesbar, für Dich auch besser editierbar. Der Compiler macht ja da dieselben Werte draus, aber weniger potentielle Tippfehler als Du (insbesondere, wenn man irgendwo was ändert/umsteckt, und das dann überall im Code ändern muß)
danke für den tip. werde ich in zukunft machen. wie gesagt, das ist nur ein test-programm. es ist ja noch nicht so komplex...

P.P.S.: So wie's aussieht, klemmt die Verwendung der Oszillatorbeine als solche die korrespondierenden PORT-/DDR-/PIN-Register-Bits komplett vom Bus ab (Schreiboperationen landen im Nirvana, Leseoperationen liefern 0).
leider kann ich die info gerade nicht einordnen. ist da etwas, was ich übersehen habe??


Echt vielen dank, dass du dir die mühe machst und den quellcode und den schaltplan durchschaust! ich hoffe du hast noch ne idee, die vielleicht das eigentliche problem erklärt...
 
Wie gesagt
Bist Du sicher, daß das Telegramm bei kurzer/schnell wiederholter Tastenbetätigung überhaupt korrekt gesendet wird?...
Der Rest sollte mit dem eigentlichen Problem nichts zu tun haben (es geht ja, wenn Du zwischen den Betätigungen genug Zeit läßt. Solange Du die Int-Taster nicht betätigst, laufen nur der UART-IRQ und die NOPs im Hauptprogramm, die URXC-ISR ist schon sehr kurz/schnell gehalten, die Baudrate ziemlich langsam -> ankommende Bytes sollte der AVR locker in den SRAM schaufeln können. Abgesehen davon ist der Reciever ja doppelt gepuffert (das erste vollständig im Empfangs-Schieberegister empfangene Byte wird in den Zwei-Level-Lesepuffer kopiert (und dabei das RXC-Flag gesetzt, der IRQ getriggert). Währenddessen kann das 2te Byte im Schieberegister eingelesen werden. Wenn der Empfangs-IRQ bis dahin nicht zum Zuge gekommen sein sollte, und auch das 2te Byte komplett empfangen wurde, wird auch dieses in den 2-Level-Lesepuffer kopiert (der ist damit also voll), das Leseschieberegister kann das dritte Byte empfangen. Das RXC-Flag bleibt weiterhin gesetzt. Wenn der Lese-FIFO auch nach dem Empfang des 3ten Bytes voll ist, sind die 3 Bytes immer noch auslesbar (zwei im FIFO, eins im Empfangs-Schieberegister). Erst wenn das Startbit des 4ten Bytes das Schieberegister beansprucht, verlierst Du das 3te Byte. Auswerten kannst Du dafür das DOR-Flag.) Aber wie gesagt, Dein Programm sollte schnell genug sein, um kontinuierlich Daten ins SRAM zu schreiben.)

Zum "Rest":
Taster: statt der "Pads" oder was Du da in Eagle verwendet hast, solltest Du Vcc oder 5V-Symbole verwenden (findest Du wie auch die Gnd-Symbole als "Bauteil" unter "Supply".
Das STK500 legt übrigens auch keine 9V auf Vcc - hinter der Stromversorgunggsbuchse liegt 'ne TVS-Doppeldiode zum ESD-Schutz und'n Gleichrichter. Dahinter dann ein 5V-Linearregler, der das STK selbst, insbesondere den Master-Controller auf dem STK versorgt.
Außerdem hängt hinter dem Gleichrichter ein variabler Linearregler (LM317), der VTG (also die Versorgungsspannung der Sockel, Taster-, LED-Header) generiert. Dieser Linearregler wird über den Master-Controller beeinflußt (PWM (Timer1 KanalA) -> Tiefpaß(mehrfach) -> OPAMP(LM358) -> Linearregler(LM317)-Adjust), die so erzeugte Target Spannung vom Master-Controller über ADC7 (A7) gemessen/geregelt. VTG kannst Du im Studio vorgeben (inwiefern das mit neuen Versionen noch geht, diese das STK überhaupt noch unterstützen, weiß ich nicht. Ich nutze den AVRISP mkII, auch als Programmer für Targets auf dem STK, die beiden RS232-Stecker verwende ich nicht mehr)
Sleep: ich meinte, daß keine mögliche alternative Funktion dieser Beine die PORT, DDR Bits "OVERRIDEt" - lediglich der Digital-Input-Kram wird übersteuert. Das betrifft aber nur einige Sleep-Modi (Hintergrund: in einigen Modi werden die digitalen Input-Buffer abgeschaltet/auf Gnd geschaltet. Da die INTs aber zum Aufwecken verwendet werden (können), darf das hier nicht geschehen. Deswegen wird das Abschalten des Buffers des Beinchens durch das INT0/1-enable "Overridet", wenn also der INT aktiviert ist, bleibt der Input-Buffer des Beinchens auch im Sleep aktiv).
Also: die Register-Bits/Beine sollten sich so verhalten, wie Du es von Deinem Programm her vorgibst - der INT als draufgeschaltete Hardware muscht Dir da nicht rein.
SBI: dachte ich, ist Dir schon bekannt, da Du es ja auch zum Einstellen des UART benutztest...
Oszillatorbeine/Bits der Beine: Du hattest da irgend'n Kommentar im Code. Solange die Beine alternativ als Oszi-Beine verwendet werden, werden alle Lese/Schreibinstruktionen auf diese Bits "ignoriert". Stellst Du aber das Programm(Fusebits) irendwann auf'n Quarzoszillator/internen Oszillator um, würden die entsprechenden Bits an dieser Stelle (LDI...OUT...) wirksam werden. Da das aber Nullen genauso wie Einsen betrifft, ist das eh Wurscht - wenn(falls) das beachtet werden muß, mußt Du zum konfigurieren der Ports eh RMW-Zuweisungen nutzen (also Register laden, mit Maske logisch verknüpfen, Register schreiben) oder direkt über die Bits gehen (SBI/CBI - was ab 4Bits weniger effizient als RMW ist, aber kein I/O-Register braucht)

*Lufthol - KaffeeKochenGeh*
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)