Forum: Mikrocontroller und Digitale Elektronik AVR asm - Befehl nur jedes 2. mal ausführen


von olli (Gast)


Lesenswert?

Hallo,

ich versuche einen Drehzahlmesser zu programmieren.
Plan ist, die Zeit zwischen den Zündimpulsen über
das Zählen der eigenen Takte auszurechnen. Dazu ist
es notwendig, das alle 2 Takte gezählt wird und in
der Zeit dazwischen die Drehzahl ausgegeben wird.
Also Zap-CounterStarten-Zap-CounterStoppenUndAnzeigen-Zap... :-)

Nun läuft das ganze über den Int0. Eine Routine soll
nachgucken, ob sie nun den Counter starten oder
die Anzeige realisieren soll. Da habe ich an ein
Statusbit in r17 gedacht. Nur irgendwie will das
garnicht so wie ich.

Hier die Int-Routine:

  wdr
  cli    ; Interrupts AUS


    cpi  r17,0
    breq   int_ende


  sbi  PORTD,4
  rcall  wait
  cbi  PORTD,4  ; wird nur jedes 2. Mal ausgeführt
  rcall  wait

int_ende:
  ldi  r17,1
  sei    ; Interrupts wieder AN

  reti



Was mache ich falsch? Er kommt nicht in die
Routine rein, sondern loopt nur die Hauptschleife..?

Danke! :-)

von Peter II (Gast)


Lesenswert?

quellcode ist nicht vollsändigt. das Sprungziel wait fehlt.

von nachdenklicher (Gast)


Lesenswert?

Die komplette Architektur ist Mist.
Aus einem Int in irgendwelche externen Wait-Schleifen zu springen ist 
ganz, ganz schlechter Stil, das ist mal das erste.

Sende bitte den gesamten Code, dann kann man das sehr viel besser 
bewerten und auch lösen!

Joe

von Anton (Gast)


Lesenswert?

Frage:
Was soll das Abschalten des Ints im Int?
Der ist in diesem Moment sowieso aus.
Dito Einschalten am Ende der ISR.

Des weiteren die Register auf Stack
retten.

Ich möchte behautpten die Wait-Routine
wird auch außerhalb des Int aufgerufen!

Welcher Int ist es, wird der Initialisiert?

USW. USW.

Vorsichtig gesagt schlechter Stil.

Und ohne kompletten Code Hilfe nicht möglich,
meine Glaskugel ist gerade beim Reinigen.

von Uwe (Gast)


Lesenswert?

Einfach mal Inputcapture nachschlagen mal googlen oder Datenblatt.
Sollte Perfekt geignet sein. Muß nur einmal konfiguriert werden und 
läuft dann in Hardware. Man muß nur noch Register auslesen.

von olli (Gast)


Lesenswert?

Aha, jetzt klappts. Ich habe das "sei" und "cli" aus dem
Int entfernt. Komisch. Naja, jedenfalls der Code:

;Reset and Interruptvectoren  ;VNr.  Beschreibung
begin:
  rjmp  main  ; 1    POWER ON RESET
  rjmp  ignition  ; 2    Int0-Interrupt
  reti    ; 3    Int1-Interrupt
  reti    ; 4    TC2 Compare Match
  reti    ; 5    TC2 Overflow
  reti    ; 6    TC1 Capture
  reti    ; 7    TC1 Compare Match A
  reti    ; 8    TC1 Compare Match B
  reti    ; 9    TC1 Overflow
  reti    ;10    TC0 Overflow
  reti    ;11    SPI, STC Serial Transfer Complete
  reti    ;12    UART Rx Complete
  reti    ;13    UART Data Register Empty
  reti    ;14    UART Tx Complete
  reti    ;15    ADC Conversion Complete
  reti    ;16    EEPROM Ready
  reti    ;17    Analog Comperator
  reti    ;18    TWI (I²C) Serial Interface
  reti    ;19    Strore Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:
  ;Stack
  ldi  r16,hi8(RAMEND)
  out  ioSPH,r16
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
  out  ioSPL,r16  ;Init Stackpointer

  ;Interrupt
  ldi  r16,0b01000000  ;Maskiere INT0
  out  GICR,r16
  ldi  r16,0b00000011  ;Konfiguriere
  out  MCUCR,r16  ;fallende Flanke

  ;Taster, Lampen
  cbi  DDRD,2  ;PORTD2 Taster = IN
  sbi  PORTD,2  ;Pull-Up

  sbi  DDRD,3  ;Port D.3 = LED OUT
  sbi  DDRD,4  ;D4 als testport um Signal zu erzeugen

  ldi  r17,0b00000000  ;Statusbit auf 0


  sei    ;alle Interrupts erlauben
;----------------------------------------------------------------------- 
-
mainloop:
  wdr

  cli

  ; Anzeigen
  sbi  PORTD,3  ; LED AUS
  rcall  wait
  cbi  PORTD,3
  rcall  wait



  rcall  wait
  rcall  wait

  sei

  rjmp  mainloop
;----------------------------------------------------------------------- 
-
ignition:
  wdr

    cpi  r17,0
    brne   int_ende


  sbi  PORTD,4
  rcall  wait
  cbi  PORTD,4  ;
  rcall  wait

int_ende:
  com  r17

  reti

;----------------------------------------------------------------------- 
-

;----------------------------------------------------------------------- 
-
; UP WaitMs, Warteroutine im Millisekundenbereich
wait:  push  r16  ;r16 retten
  push  r17  ;r17 retten
  push  r18  ;r18 retten
  ldi  r16,100  ;Laufvariable ca x ms bei 3,6MHz
loop1:  ldi  r17,0xFF  ;Laufvariable loop1
loop2:  ldi  r18,13  ;Laufvariable loop3
loop3:  dec  r18  ;Zähler 3 -1, hier Kalibrierung auf MCU Takt
  brne  loop3  ;Solange nicht NULL
  dec  r17  ;Zähler 2 -1
  brne  loop2  ;Solange nicht NULL
  dec  r16  ;Zähler1 -1
  brne  loop1  ;Solange nicht NULL
  pop  r18  ;r18 wiederherstellen
  pop  r17  ;r17 wiederherstellen
  pop  r16  ;r16 wiederherstellen
  ret    ;Rücksprung
;----------------------------------------------------------------------- 
-

Ist nur Testcode. Die Waits sind nur temporär drin, damit
ich sehen kann was er macht. Der Code für den DZM ist zu
großen Teilen fertig, läuft aber hinten und vorne nicht.
Ich danke erstmal für die Hilfe und meld mich die Tage
nochmal mit der einen oder anderen Kleinigkeit ;)

Danke,

Olli

von olli (Gast)


Lesenswert?

Nochwas @Anton
Wieso die Register retten? Wenn ich sie nicht in anderen
Routinen auch brauche, kann ich sie doch so lassen? Muss
ich nicht retten, oder?

von Peter II (Gast)


Lesenswert?

olli schrieb:
> Der Code für den DZM ist zu
> großen Teilen fertig, läuft aber hinten und vorne nicht.

ist auch kein Wunder - du sicherst in dem Interupt SREG nicht.

von nachdenklicher (Gast)


Lesenswert?

> Der Code für den DZM ist zu
> großen Teilen fertig, läuft aber hinten und vorne nicht.

Was für einen Unsinn erzählst Du da eigentlich?
Wenn etwas "vorne und hinten nicht läuft"....
...dann ist das NICHT "in grossen Teilen fertig"!

WAS SOLL DER QUATSCH BITTE? WAS SOLL DAS?

Nochmal konkret:
Wie kann etwas "fertig" sein, das hinten und vorne nicht läuft?

Deine Architektur ist immer noch VÖLLIGER Mist.
Du hast praktisch NICHTS von dem verstanden, was Dir helfende Kräfte 
hier schrieben.

Wann würde sich das ändern, was muss geschehen?
Wie lernresistent kann ein Mensch sein?

Bitte um konkrete (SEHR konkrete) Antworten!

Joe

von oldmax (Gast)


Lesenswert?

Hi
Nun ja, so manche Kritik ist nicht unbegründet...
Also, Register, die in einer ISR benutzt werden, brauchen dann nicht 
gesichert werden, wenn sie nirgends anders verwendet werden, aber... 
mach es trotzdem. Du suchst dir einen Wolf, wenn aus welchen Gründen 
auch immer später mal schnell ein solches Register für andere Zwecke 
eingesetzt wird. Speziell, wenn es "nur" r17 heißt....
Außerdem ist es auch notwendig, das Statusregister zu sichern. Du hast 
doch in deiner ISR Abfragen, die das Statusregister beeinflussen, oder 
nicht ? Damit sind vorherige Statusinformationen nicht mehr gültig, auch 
die, die vor dem Interrupt noch irgendelche Aktionen ausführen sollten.
Dann gewöhn dir an, die Blöcke deines Programmes deutlich 
auseinanderzuhalten und um Gotteswillen ruf nicht aus einer ISR einen 
Wait auf. Wozu brauchst du dann noch eine ISR, wenn du sowieso nicht 
immer auf eintreffende Signale scharf bist ?
Wenn du eine Zeitverzögerung brauchst, dann nutze die Timer-ISR. 
Parametriere sie so, das sie im mSek-Takt aufgerufen wird. Wenn du nun 
eine Zeitverzögerung brauchst, zähl einfach in der ISR einen Wert nach 
Null, ob nun im mSek-Takt oder im Sekundentakt, das leitest du in der 
ISR ab.
1
 
2
;-----Interruptroutine Timer 1 für Zeitbasis -------------------------
3
;*********************************************************************
4
;* Register ms0 = msek *10^0                                         *
5
;* Register ms1 = msek *10^1                                         *
6
;* Register ms2 = msek *10^2                                         *
7
;* Register Sekunden                                                *
8
;* Register Number dient als Vergleichswert (10, 60, 24 etc.         *
9
;*********************************************************************
10
 
11
isrTimer1:  
12
  PUSH  Temp_Reg      ; Register sichern
13
  IN  Temp_Reg, SREG    ; SREG sichern    
14
  PUSH  Temp_Reg
15
  PUSH  a0
16
  PUSH  a1
17
  PUSH  Number
18
    
19
;************************ 1 ms ****************************************    
20
  RCALL  Seg_Anzeige    ; Aufruf Multiplexer Anzeige
21
  LDI  a0,10
22
  MOV  Number, a0                 ; Vergleichswert 10
23
  INC  ms0
24
  CP  ms0, Number    ; ms * 10 ^ 0
25
  BRLO  End_ISR1
26
;************************ 10 ms ***************************************        
27
  CLR  ms0
28
  INC  ms1
29
  CP  ms1, Number    ; ms * 10 ^ 1
30
  BRLO  End_ISR1
31
;********************** 100 ms **************************************    
32
  CLR  ms1  
33
  INC  ms2
34
  CP  ms2, Number    ; m * 10 ^ 2
35
  BRLO  End_ISR1
36
;********************** Sekunden ***********************************    
37
  CLR  ms2
38
    INC  Sekunden
39
  LDI  a0,60  
40
  MOV  Number, a0    ; Sekunden
41
  CP  Sekunden, Number
42
  BRLO  End_ISR1
43
;*********************** Minuten ************************************    
44
  CLR  Sekunden
45
  INC  Minuten      ; Minuten
46
  CP  Minuten, Number
47
  BRLO  End_ISR1
48
;************************ Stunden **********************************    
49
  CLR  Minuten
50
  INC  Stunden      ; Stunden
51
  LDI  a0,24
52
  MOV  Number,a0
53
  CP  Stunden, Number
54
  BRLO  End_ISR1
55
  CLR  Stunden
56
    
57
  
58
  
59
End_Isr1:  
60
  POP  Number
61
  POP  a1
62
  POP  a0
63
  POP  Temp_Reg    
64
  OUT  SREG, Temp_Reg    ; SREG wiederherstellen
65
  POP  Temp_Reg
66
    
67
RETI

Ich hab dir mal einen Aufruf für ein Zeitabhängiges Unterprogramm 
dirngelassen. Genausogut kannst du dir in dieser Timer ISR bits setzen, 
die dann vom Hauptprogramm einmalig abgearbeitet werden, d. H. die 
Routinen, die du dann aufrifst, löschen dieses Bit wieder. So kannst du 
Ereignisse, die z. B. im Sekundenbereich liegen ohne merklichen 
Zeitversatz abarbeiten lassen.
Gruß oldmax

von rups (Gast)


Lesenswert?

olli schrieb:
> Aha, jetzt klappts. Ich habe das "sei" und "cli" aus dem
> Int entfernt. Komisch.
Nicht komisch. Wenn die Warteschleifen lang genug sind wird das 
Interruptflag wieder gesetzt bevor die ISR verlassen wurde. Da du die 
Interrupts in der ISR mit sei wieder aktivierst dürfte das eine Art 
Rekursion ergeben, die ISR wird immer wieder aufgerufen und irgendwann 
ist der Stack alle...

von olli (Gast)


Lesenswert?

nachdenklicher schrieb:
>> Der Code für den DZM ist zu
>> großen Teilen fertig, läuft aber hinten und vorne nicht.
>
> Was für einen Unsinn erzählst Du da eigentlich?
> Wenn etwas "vorne und hinten nicht läuft"....
> ...dann ist das NICHT "in grossen Teilen fertig"!
>
> WAS SOLL DER QUATSCH BITTE? WAS SOLL DAS?
>
> Nochmal konkret:
> Wie kann etwas "fertig" sein, das hinten und vorne nicht läuft?
>
> Deine Architektur ist immer noch VÖLLIGER Mist.
> Du hast praktisch NICHTS von dem verstanden, was Dir helfende Kräfte
> hier schrieben.
>
> Wann würde sich das ändern, was muss geschehen?
> Wie lernresistent kann ein Mensch sein?
>
> Bitte um konkrete (SEHR konkrete) Antworten!

Man, sag mal hast Du keine anderen Probleme oder
Quellen der Lebensfreude? Stress mit der Frau?

Ich versuch mir ASM seit einer Weile beizubringen, ist da
irgendwas falsch dran, soll ich das ändern oder was?
Der prinzipielle Ablauf ist fertig geschrieben, es
muss nur noch die genaue Taktanzahl ausgerechnet
und angepasst werden. Problem war eben, dass das Programm
eben nicht das macht was es soll, ich aber nicht weiß
wo der Fehler liegt. Deshalb nehme ich das Stück für
Stück auseinander und suche den Fehler. Darf ich
das? Danke.

von olli (Gast)


Lesenswert?

@oldmax

Danke Dir. Ich werde es mir nachher mal genauer
angucken. Mein Ziel ist eigentlich das ganze ohne
den Timer zu machen, nur durch Zählen der Takte.
Mal gucken! :-)

von Helmut L. (helmi1)


Lesenswert?

olli schrieb:
> Mein Ziel ist eigentlich das ganze ohne
> den Timer zu machen, nur durch Zählen der Takte.

Warum? Der uC ist ganz bezahlt und es gibt kein Geld zurueck fuer nicht 
verwendete Hardware.

von oldmax (Gast)


Lesenswert?

Hi
Du kannst schon die Takte zählen und dir so eine Warteschleife aufbauen, 
aber... und hier steckt der Teufel im Detail, nicht diese Warteschleife 
aus einer ISR heraus aufrufen. Eine ISR ist dazu da, Ereignisse von 
kurzer Dauer zu erfassen und mit Kurz meine ich auch Kurz. Wenn du deine 
ISR mit irgendwelchen sinnlosen Schleifen beschäftigst, läufst du 
Gefahr, das ein Interrupt halt nicht ausgelöst wird, wenn er dadurch 
geblockt ist oder wie auch schon erwähnt, wenn freigegeben, eben den 
Stack vollmüllt.
Und nun mal ein kleines Rechenexempel, wenn es um kurze Impulse geht. 
Deine Welle macht bei jeder Umdrehung 360°.  Dein Nocken betätigt etwa 
für 5° einen Sensor. Eine Umdrehung braucht  bei 6000 U/Min 1/100 
Sekunden.
5° sind (1*5) / (100 *360) also 0,000138 sek. also 138 µSek.
Bei einer Frequenz von 16 MHZ dauert die Bearbeitung eines Befehles 125 
nSek. Nun kommt es auf den umfang deines Programmes an, ob du das Signal 
noch pollen kannst oder auf eine ISR ausweichen mußt. Taktest du 
geringer, ist natürlich auch die Befehlsverarbeitungszeit größer.
Also, egal wie du es machst, es ist keine gute Idee, in einer ISR eine 
Zeitschleife einzubauen. Das ergibt auch nicht wirklich Sinn. Viele 
Zeitverzögerungen sind bei genauer Betrachtung überflüssig. Also nutz 
die Innereien deines Controllers und mach keine Klimmzüge, die dich 
sowieso nicht zu einem vernünftigen Ergebnis bringen. Nur weil der Timer 
eine neue Erfahrung ist, braucht man darum keinen Bogen machen. Wenn 
dein Drehzahlmesser z. B. eine 7 Segmentanzeige bekommen sollte, macht 
es auch sinn, diese über den Timer zu multiplexen. Das garantiert dir 
gleichbleibende helligkeit, da die Programmlaufzeitunterschiede 
ausgebügelt werden.
Gruß oldmax

von olli (Gast)


Lesenswert?

Also ich wollts so machen: Angenommene Höchstdrehzahl ist
16384 (2^14). Bei 3,7 MHz würden zwischen den Zündungen 220 Takte
vergehen. Also baue ich eine Routine die alle 220 Takte
ein 16bit-Register hochzählt. Dann kommt die ISR, der
16-bit Zähler wird übergeben. Ist der Zähler niedrig, ist
die Drehzahl hoch und andersrum.
Dann setze ich die obersten 2 Bits auf 1 und komplementiere
das gesamte 16 Bit Register. Viola, da steht dann meine
Drehzahl drin.
Insofern ohne besondere Wait-Schleife, außer eben die 220
Takte.
Da wird dann der Zwischenraum jeder ungeraden Zündung
gezählt, in der Zeit nach der Zündung mache ich die Auswertung
(die dann auch nicht mehr als 220 Takte lang sein darf,
oder ich zähle nur alle 3 Zündungen mal).
Ausgabe auf 8 LEDs, ich will z.B. nur den Bereich von
5500-7500 darstellen, weil da mein Zweitakter seine
Resokurve hat.

von olli (Gast)


Lesenswert?

Problem ist auch: Das ganze ist für ein Preisauschreiben
und muss inkl. PDF am 1. Mai fertig sein. Weiß nicht,
ob ich das noch schaffe. Nur jetzt alles umzuschmeißen
kostet Zeit, auch wenn der Timer des ATMega schon
abbezahlt ist g

von Helmut L. (helmi1)


Lesenswert?

Dafuer wurde der Inputcapture Mode erfunden.
Du brauchst nur einen der  Timer zu starten. Dann Flanke auswaehlen und 
Interrupt fuer Input Capture freigeben. Jetzt kommt dein Capture 
Interrupt. Die Hardware des uC speichert dir dann den aktuellen 
Timerwert (der laueft staendig durch)  ins Inputcapture Register ab. 
Dann wird ein Interrupt generiert und deine Service Routine gestartet. 
Die liest den Wert des Registers aus. Dann ziehst du davon den alten 
Wert Vorzeichenrichtig ab und dann hast du deinen Messwert. Und das 
alles ohne selber hochzaehlen zu muessen. Die Hardware des uC macht das 
fuer dich.

olli schrieb:
> Das ganze ist für ein Preisauschreiben

Das gibt aber so keinen Preis :-)

von olli (Gast)


Lesenswert?

Icke wieder :-)
Programm ist länger geworden, wurde umstrukturiert.
Den AVR Timer will ich nicht nutzen, da ich sonst
alles umschmeißen müsste und dafür die Zeit nicht
reicht. Ich würds schon gern so lassen.

Das ist recht kompliziert, wenn sich jemand reinstürzen
möchte... dauert ein bisschen :->
Programmablauf arbeitet mit zwei Flags in r17 und r18.
Ablauf ist:
Zündung, r17 nicht gesetzt, also Zählschleife beginnen, r17 setzen;
Zündung, r17 gesetzt, Drehzahl anzeigen; r17 und r18 auf 0; danach
Endlosschleife (was soll er auch sonst in der Zeit machen)
dann wieder von vorn.

r17 sorgt dafür das nach den Zündungen sich Zählschleife
und Auswertung+Anzeige abwechseln

r18 sorgt dafür das im Mainloop die Endlosschleife betreten
wird (nach Anzeige)

Ich mache da nochmal ein Ablaufdiagramm, damit es
anschaulicher wird (Frau will einkaufen^^)


Hier das Programm:

------------------------------------------------------------------------
.equ  F_CPU,  3686400
.include  "AVR.H"
;Reset and Interruptvectoren  ;VNr.  Beschreibung
begin:
  rjmp  main  ; 1    POWER ON RESET
  rjmp  ignition  ; 2    Int0-Interrupt
  reti    ; 3    Int1-Interrupt
  reti    ; 4    TC2 Compare Match
  reti    ; 5    TC2 Overflow
  reti    ; 6    TC1 Capture
  reti    ; 7    TC1 Compare Match A
  reti    ; 8    TC1 Compare Match B
  reti    ; 9    TC1 Overflow
  reti    ;10    TC0 Overflow
  reti    ;11    SPI, STC Serial Transfer Complete
  reti    ;12    UART Rx Complete
  reti    ;13    UART Data Register Empty
  reti    ;14    UART Tx Complete
  reti    ;15    ADC Conversion Complete
  reti    ;16    EEPROM Ready
  reti    ;17    Analog Comperator
  reti    ;18    TWI (I²C) Serial Interface
  reti    ;19    Strore Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:
;Stack
  ldi  r16,hi8(RAMEND)
  out  ioSPH,r16
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
  out  ioSPL,r16  ;Init Stackpointer

;Interrupt
  ldi  r16,0b01000000  ;Maskiere INT0
  out  GICR,r16
  ldi  r16,0b00000011  ;Konfiguriere
  out  MCUCR,r16  ;fallende Flanke

;Taster, Lampen
  cbi  DDRD,2  ;PORTD2 Taster = IN
  sbi  PORTD,2  ;Pull-Up

  sbi  DDRD,3  ;Port D.3 = LED OUT
  cbi  PORTD,3

  sbi  DDRB,0
  cbi  PORTB,0

  sbi  DDRB,1
  cbi  PORTB,1

  sbi  DDRB,2
  cbi  PORTB,2

  sbi  DDRC,0
  cbi  PORTC,0

  sbi  DDRC,1
  cbi  PORTC,1

  sbi  DDRC,2
  cbi  PORTC,2

  sbi  DDRC,3
  cbi  PORTC,3

  sbi  DDRC,4
  cbi  PORTC,4


  ldi  r17,0b00000000  ;Statusbit B auf 0
  ldi  r18,0b00000000  ;Statusbit A auf 0

  sei    ;alle Interrupts erlauben
;----------------------------------------------------------------------- 
-
mainloop:
  wdr

  cpi  r18,0  ; Statusbit "nach Anzeige -> endless" gesetzt?
  breq  endless  ; Wenn nicht gesetzt, dann springe in Endlosschleife

  ldi    R17, 73
Warte220:   dec    R17
             brne   Warte220
            nop

  adiw   r24,1  ; Zähler
  rjmp  mainloop


endless:  wdr

  rjmp   endless

;----------------------------------------------------------------------- 
-
ignition:
  wdr

  push  r19  ; Statusregister retten
  in  r19, SREG  ; eben


  cpi  r17,0  ; Statusflag "jedes zweite Mal" gesetzt?
  brne  r17r18loeschen  ; Wenn gesetzt, dann  Flags löschen und zurück 
zum Mainloop

  ldi  r17,1  ; Statusflag "jedes zweite Mal" setzen
  ldi  r18,1

  ;Ausrechnen
  set    ; T-Bit setzen; wird für folgende Anweisung gebraucht
      bld  r25,7  ; die oberen 2 Bits werden nicht gebraucht,
    bld  r25,6  ; müssen aber im nächsten Schritt "0" sein; also T-Bit 
auf Pos 6 und 7
    com  r25  ; Komplement bilden, also Bits umdrehen
    com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---

    movw  r26,r24  ; R24:25 in R26:27 sichern <---


  ;Anzeigen <-------------------------------
  sbrc  r24,0
  rcall  lampe0

  sbrc  r24,1
  rcall  lampe1

  sbrc  r24,2
  rcall  lampe2

  sbrc  r24,3
  rcall  lampe3

  sbrc  r24,4
  rcall  lampe4

  sbrc  r24,5
  rcall  lampe5

  sbrc  r24,6
  rcall  lampe6

  sbrc  r24,7
  rcall  lampe7


int_fertig:

  eor  r24,r24  ; r24:25 löschen
  eor  r25,r25
  eor  r26,r26
  eor  r27,r27

  out  SREG,r19  ; Statusregister wiederherstellen
  pop  r19  ; dito

  reti    ; zurück zu main und Ints wieder an

;----------------------------------------------------------------------- 
-
r17r18loeschen:
  ldi  r17,0  ; Statusbit "jedes zweite Mal" löschen
  ldi  r18,0  ; Statusbit "nach Anzeige -> endless" löschen,
  rjmp  int_fertig  ; denn er muss erstmal Zählen


;----------------------------------------------------------------------- 
-

lampe0:
   sbi  PORTB,0
   ret
lampe1:
   sbi  PORTB,1
   ret

lampe2:
   sbi  PORTB,2
   ret

lampe3:
   sbi  PORTC,0
   ret

lampe4:
   sbi  PORTC,1
   ret

lampe5:
   sbi  PORTC,2
   ret

lampe6:
   sbi  PORTC,3
   ret

lampe7:
   sbi  PORTC,4
   ret

------------------------------------------------------------------------ 
-

Jetzt mein Problem: Die Routine "Anzeigen" (mit Pfeil)
zeigt mir probeweise nur den Inhalt von r24 an. Müsste
aus 0er und 1er bestehen, hängt an einem Frequenzgenerator
mit 118 Hz. Zeigt aber alles 1er an. Warum?

2. Problem... sichern von SREG. Die Routine ist in
anderer Reihenfolge als im Tutorial beschrieben. Ich
sehe keinen Sinn darin r19 zu pushen und dann r19
zu belegen. Müsste nicht SREG in r19 gesichert
werden und dann gepusht?

Danke und frohes Osterfest :-)

von Hannes L. (hannes)


Lesenswert?

olli schrieb:
> Jetzt mein Problem: Die Routine "Anzeigen" (mit Pfeil)
> zeigt mir probeweise nur den Inhalt von r24 an. Müsste
> aus 0er und 1er bestehen, hängt an einem Frequenzgenerator
> mit 118 Hz. Zeigt aber alles 1er an. Warum?

Ich kann nicht erkennen, wo und wie Du die Anzeigen wieder löscht.

>
> 2. Problem... sichern von SREG. Die Routine ist in
> anderer Reihenfolge als im Tutorial beschrieben. Ich
> sehe keinen Sinn darin r19 zu pushen und dann r19
> zu belegen. Müsste nicht SREG in r19 gesichert
> werden und dann gepusht?

Der AVR verfügt über 32 Register, das ist recht viel. Ich verurteile 
immer eins davon zur SREG-Kopie, der Rest ist immernoch mehr als genug. 
Und zwar ein unteres Register (meist r2 oder r3), da diese nicht ganz so 
wertvoll sind (können nicht mit Konstanten operieren). Ich nenn' das 
dann "SRSK" (SREG-SicherheitsKopie) und nutze das für nix Anderes als 
die Sicherung des SREG. Da braucht man nix Pushen und Poppen, da reicht 
einfach
 in srsk,sreg          ;SREG sichern
zu Beginn der ISR und
 out sreg,srsk         ;SREG wiederherstellen
 reti                  ;fertig, zurück...
am Ende der ISR.

Und da wir gerade bei den Exclusivregistern (Register für nur einen 
Zweck) sind, wenn ich 16-bittig addieren oder subtrahieren muss, dann 
benutze ich ein weiteres Exclusiv-Register namens "null" (meist r3 oder 
r2), das den Wert 0 enthält und nie für andere Zwecke genutzt wird. Es 
eignet sich dann sehr gut zum Addieren/Subtrahieren von Überträgen 
(Carry) und macht den Code etwas schlanker und schneller.

...

von olli (Gast)


Angehängte Dateien:

Lesenswert?

Danke hannes, das Löschen hab ich vergessen. Ist nun
drin, ändert aber nichts an der Ausgabe. Es erscheint
als wenn das Register r24:25 immer leer übergeben wird?
Jedenfalls sind alle LEDs noch an.
Ich habe mal 2 Ablaufpläne wegen der Übersichtlichkeit
erstellt, einmal Hauptprogramm und die ISR.

Ich Depp habe außerdem r17 für die Zählschleife und
das Flagregister genutzt :-/

also r17 "jede 2. Zündung" und
r18 "nach Anzeige Endlosschleife"

------------------------------------------------------------------------ 
-

.equ  F_CPU,  3686400
.include  "AVR.H"
;Reset and Interruptvectoren  ;VNr.  Beschreibung
begin:
  rjmp  main  ; 1    POWER ON RESET
  rjmp  ignition  ; 2    Int0-Interrupt
  reti    ; 3    Int1-Interrupt
  reti    ; 4    TC2 Compare Match
  reti    ; 5    TC2 Overflow
  reti    ; 6    TC1 Capture
  reti    ; 7    TC1 Compare Match A
  reti    ; 8    TC1 Compare Match B
  reti    ; 9    TC1 Overflow
  reti    ;10    TC0 Overflow
  reti    ;11    SPI, STC Serial Transfer Complete
  reti    ;12    UART Rx Complete
  reti    ;13    UART Data Register Empty
  reti    ;14    UART Tx Complete
  reti    ;15    ADC Conversion Complete
  reti    ;16    EEPROM Ready
  reti    ;17    Analog Comperator
  reti    ;18    TWI (I²C) Serial Interface
  reti    ;19    Strore Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:
;Stack
  ldi  r16,hi8(RAMEND)
  out  ioSPH,r16
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
  out  ioSPL,r16  ;Init Stackpointer

;Interrupt
  ldi  r16,0b01000000  ;Maskiere INT0
  out  GICR,r16
  ldi  r16,0b00000011  ;Konfiguriere
  out  MCUCR,r16  ;fallende Flanke

;Taster, Lampen
  cbi  DDRD,2  ;PORTD2 Taster = IN
  sbi  PORTD,2  ;Pull-Up

  sbi  DDRD,3  ;Port D.3 = LED OUT
  cbi  PORTD,3

  sbi  DDRB,0
  cbi  PORTB,0

  sbi  DDRB,1
  cbi  PORTB,1

  sbi  DDRB,2
  cbi  PORTB,2

  sbi  DDRC,0
  cbi  PORTC,0

  sbi  DDRC,1
  cbi  PORTC,1

  sbi  DDRC,2
  cbi  PORTC,2

  sbi  DDRC,3
  cbi  PORTC,3

  sbi  DDRC,4
  cbi  PORTC,4


  ldi  r17,0b00000000  ;Statusbit B auf 0
  ldi  r18,0b00000000  ;Statusbit A auf 0

  sei    ;alle Interrupts erlauben
;----------------------------------------------------------------------- 
-
mainloop:
  wdr

  cpi  r18,0  ; Statusbit "nach Anzeige -> endless" gesetzt?
  breq  endless  ; Wenn nicht gesetzt, dann springe in Endlosschleife

  ldi    r21, 73
Warte220:
  dec    r21
  brne   Warte220
  nop

  adiw   r24,1  ; Zähler
  rjmp  mainloop


endless:  wdr

  rjmp   endless

;----------------------------------------------------------------------- 
-
ignition:
  wdr

  in   r2, SREG  ; Statusregister retten

  cpi  r17,0  ; Statusflag "jedes zweite Mal" gesetzt?
  brne  r17r18loeschen  ; Wenn gesetzt, dann  Flags löschen und zurück 
zum Mainloop

  ldi  r17,1  ; Statusflag "jedes zweite Mal" setzen
  ldi  r18,1

  ;Ausrechnen
  set    ; T-Bit setzen; wird für folgende Anweisung gebraucht
  bld  r25,7  ; die oberen 2 Bits werden nicht gebraucht,
  bld  r25,6  ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf 
Pos 6 und 7
  com  r25  ; Komplement bilden, also Bits umdrehen
  com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---

  movw  r26,r24  ; R24:25 in R26:27 sichern <---


  cbi  PORTB,0
  cbi  PORTB,1
  cbi  PORTB,2
  cbi  PORTC,0
  cbi  PORTC,1
  cbi  PORTC,2
  cbi  PORTC,3
  cbi  PORTC,4


  ;Anzeigen
  sbrc  r24,0
  rcall  lampe0

  sbrc  r24,1
  rcall  lampe1

  sbrc  r24,2
  rcall  lampe2

  sbrc  r24,3
  rcall  lampe3

  sbrc  r24,4
  rcall  lampe4

  sbrc  r24,5
  rcall  lampe5

  sbrc  r24,6
  rcall  lampe6

  sbrc  r24,7
  rcall  lampe7


int_fertig:

   eor  r24,r24  ; r24:25 und Sicherheitskopie löschen
   eor  r25,r25
   eor  r26,r26
   eor  r27,r27

  out  SREG,r2  ; Statusregister holen

  reti    ; zurück zu main und Ints wieder an

;----------------------------------------------------------------------- 
-
r17r18loeschen:
  ldi  r17,0  ; Statusbit "jedes zweite Mal" löschen
  ldi  r18,0  ; Statusbit "nach Anzeige -> endless" löschen,
  rjmp  int_fertig  ; denn er muss erstmal Zählen


;----------------------------------------------------------------------- 
-

lampe0:
   sbi  PORTB,0
   ret
lampe1:
   sbi  PORTB,1
   ret

lampe2:
   sbi  PORTB,2
   ret

lampe3:
   sbi  PORTC,0
   ret

lampe4:
   sbi  PORTC,1
   ret

lampe5:
   sbi  PORTC,2
   ret

lampe6:
   sbi  PORTC,3
   ret

lampe7:
   sbi  PORTC,4
   ret


-----------------------------------------------------------------------

Any more ideas? :-)

Frohe Ostern,

Olli

von olli (Gast)


Lesenswert?

Und danke für die Hilfe. :-)

von olli (Gast)


Lesenswert?

edit:
wenn ich einen Wert in der Hauptroutine in r24 lade,
kommt "0" raus. Wenn ich in die Interruptroutine diesen
Wert lade, wird dieser korrekt angezeigt.  Wird r24 irgendwie
gelöscht?

von Klaus (Gast)


Lesenswert?

Nimm mal den Befehl WDR ( Watchdog Reset) raus.

So wie ich das sehe hast du den nicht richtig initalisiert und 
behandelt.
Dadurch könnte der Controller möglicherweise selber einen Reset auslösen 
bevor die ISR aufgerufen wird.

von olli (Gast)


Lesenswert?

wdr hat nichts gebracht. Die unseelige Endlosschleife habe
ich jetzt aber entfernt, jetzt kann ich in die Bits
je nach Frequenz reingucken :-) Ich frage mich nur, ob
der jetzt auch anzeigt was ich mir ausdenke^^

von spess53 (Gast)


Lesenswert?

Hi

>endless:  wdr
>  rjmp   endless

Was soll danach noch passieren?

>reti    ; zurück zu main und Ints wieder an

Glaubst du das wirklich?

>  set    ; T-Bit setzen; wird für folgende Anweisung gebraucht
>  bld  r25,7  ; die oberen 2 Bits werden nicht gebraucht,
>  bld  r25,6  ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf

Ein 'ori r25, 0b11000000' hätte auch gereicht.

>  com  r25  ; Komplement bilden, also Bits umdrehen
>  com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---

Unnötig, wenn du

  sbrs  r24,0
  rcall  lampe0   benutzt

>  movw  r26,r24  ; R24:25 in R26:27 sichern <---

Wozu?

MfG Spess



>  cpi  r17,0  ; Statusflag "jedes zweite Mal" gesetzt?
>  brne  r17r18loeschen  ; Wenn gesetzt, dann  Flags löschen und zurück
>zum Mainloop

>  ldi  r17,1  ; Statusflag "jedes zweite Mal" setzen
>  ldi  r18,1

Kannst du dir alles sparen. Einfach
1
  inc r17
2
  sbrc r17,0
3
  rjmp int_fertig

>  ldi  r17,0b00000000  ;Statusbit B auf 0
>  ldi  r18,0b00000000  ;Statusbit A auf 0
>  eor  r24,r24  ; r24:25 und Sicherheitskopie löschen
>  eor  r25,r25
>  eor  r26,r26
>  eor  r27,r27

von spess53 (Gast)


Lesenswert?

Hi

Zu schnell auf 'Absenden' gedrückt.

>>  ldi  r17,0b00000000  ;Statusbit B auf 0
>>  ldi  r18,0b00000000  ;Statusbit A auf 0
>>  eor  r24,r24  ; r24:25 und Sicherheitskopie löschen
>>  eor  r25,r25
>>  eor  r26,r26
>>  eor  r27,r27

Dafür gibt es 'clr rxy'.

MfG Spess

von Hannes L. (hannes)


Lesenswert?

spess53 schrieb:
> Dafür gibt es 'clr rxy'.

Sieht aber nicht so kryptisch und damit nicht so intelligent aus... ^^

...

von olli (Gast)


Lesenswert?

spess53 schrieb:

Ah, danke Spess. Fangen wir an...

>>endless:  wdr
>>  rjmp   endless
>
> Was soll danach noch passieren?
Der soll von der Zündung wieder zum Leben
erweckt werden. Da liegt dann aber wohl der Fehler,
er rennt zurück in die Endlosschleife und hängt
sich dort... ahhh! :-)
Fahre den jetzt in SLEEP, allerdings bin ich nicht
sicher ob das zu was gut ist.


>>reti    ; zurück zu main und Ints wieder an
> Glaubst du das wirklich?
Zurück zu Mainloop meinte ich.


>>  set    ; T-Bit setzen; wird für folgende Anweisung gebraucht
>>  bld  r25,7  ; die oberen 2 Bits werden nicht gebraucht,
>>  bld  r25,6  ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf
>
> Ein 'ori r25, 0b11000000' hätte auch gereicht.
okay.



>
>>  com  r25  ; Komplement bilden, also Bits umdrehen
>>  com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
>
> Unnötig, wenn du
>
>   sbrs  r24,0
>   rcall  lampe0   benutzt
Das ist nur für die weitere Rechnung. Ich muss noch
die Bereiche jeder einzelnen LED festlegen, das eine z.B.
zwischen 6540 und 6590 Umdrehungen angeht. Jetzt wollte
ich ja nur mal eine Anzeige machen, ob der überhaupt


>>  movw  r26,r24  ; R24:25 in R26:27 sichern <---
Relikt. :-)


> Kannst du dir alles sparen. Einfach
>   inc r17
>   sbrc r17,0
>   rjmp int_fertig
Right you are!



>>  ldi  r17,0b00000000  ;Statusbit B auf 0
>>  ldi  r18,0b00000000  ;Statusbit A auf 0
>>  eor  r24,r24  ; r24:25 und Sicherheitskopie löschen
>>  eor  r25,r25
>>  eor  r26,r26
>>  eor  r27,r27
Okay, clr. Ich habe als Teenager mal einen ASM-Kurs
für PCs mitgemacht. Da hieß es: Register löschen mit XOR ;-)


Problem jetzt ist, das er bei 113 Hz (6780 U/m) in
r24:25 eine Umdrehungszahl von 16237 hat. Da muss ich jetzt mal
suchen.

-----------------------------------------------------------------------

;Start, Power ON, Reset
main:
;Stack
  ldi  r16,hi8(RAMEND)
  out  ioSPH,r16
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
  out  ioSPL,r16  ;Init Stackpointer

;Interrupt
  ldi  r16,0b01000000  ;Maskiere INT0
  out  GICR,r16
  ldi  r16,0b00000011  ;Konfiguriere
  out  MCUCR,r16  ;fallende Flanke

;Taster, Lampen
  cbi  DDRD,2  ;PORTD2 Taster = IN
  sbi  PORTD,2  ;Pull-Up

  sbi  DDRD,3  ;Port D.3 = LED OUT
  cbi  PORTD,3

  sbi  DDRB,0
  cbi  PORTB,0

  sbi  DDRB,1
  cbi  PORTB,1

  sbi  DDRB,2
  cbi  PORTB,2

  sbi  DDRC,0
  cbi  PORTC,0

  sbi  DDRC,1
  cbi  PORTC,1

  sbi  DDRC,2
  cbi  PORTC,2

  sbi  DDRC,3
  cbi  PORTC,3

  sbi  DDRC,4
  cbi  PORTC,4


  clr  r17
  clr  r18  ;Statusbit B auf 0


  sei    ;alle Interrupts erlauben
;----------------------------------------------------------------------- 
-
mainloop:
  ldi    r21, 73
Warte220:
        dec    r21
        brne   Warte220
        nop

  adiw   r24,1  ; Zähler

  rjmp  mainloop

;----------------------------------------------------------------------- 
-
ignition:
  wdr

  in   r2, SREG  ; Statusregister retten


  inc   r17
  sbrc   r17,0
  rjmp   int_fertig



  ;Ausrechnen


  ori  r25,0b11000000
     com  r25  ; Komplement bilden, also Bits umdrehen
       com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---


  cbi  PORTB,0
    cbi  PORTB,1
   cbi  PORTB,2
   cbi  PORTC,0
   cbi  PORTC,1
  cbi  PORTC,2
   cbi  PORTC,3
   cbi  PORTC,4


  ;Anzeigen
  sbrc  r24,0
  rcall  lampe0

  sbrc  r24,1
  rcall  lampe1

  sbrc  r24,2
  rcall  lampe2

  sbrc  r24,3
  rcall  lampe3

  sbrc  r24,4
  rcall  lampe4

  sbrc  r24,5
  rcall  lampe5

  sbrc  r24,6
  rcall  lampe6

  sbrc  r24,7
  rcall  lampe7


int_fertig:

   clr  r24
   clr  r25

  out  SREG,r2  ; Statusregister holen

  sleep

  reti    ; zurück zu mainloop und Ints wieder an

;----------------------------------------------------------------------- 
-
r17r18loeschen:
  clr  r17  ; Statusbit "jedes zweite Mal" löschen
  clr  r18  ; Statusbit "nach Anzeige -> endless" löschen,
  rjmp  int_fertig  ; denn er muss erstmal Zählen


;----------------------------------------------------------------------- 
-

lampe0:
   sbi  PORTB,0
   ret
lampexy...

------------------------------------------------------------------------ 
-

von olli (Gast)


Lesenswert?

r17r18loeschen ist auch Relikt..

von Jobst M. (jobstens-de)


Lesenswert?

Hmmm ....

Was ist das eigentlich?

2-Takter, 4-Takter?
Wieviele Zylinder?
Reihen-, Boxer- oder V-Motor?
Und wo greifst Du die Impulse ab?

Weshalb ich diese Fragen stelle: Zwischen den einzelnen Zylindern hast 
Du möglicherweise unterschiedliche Zündwinkel. D.h. bei selber Drehzahl 
unterschiedliche Zeiten zwischen den Zündungen.

Aber selbst wenn ich von einem 1-Zyl. 2-Takter ausgehe, finde ich die 
Herangehensweise etwas ungeschickt.

Du möchtest doch letzlich Umdrehungen pro Zeit haben und nicht Zeit pro 
Umdrehung. (Was bringt Dir die Angabe '8,57ms/U' ... ? :-)


Meine Herangehensweise wäre:

- Hauptprogramm initialisiert Timer und IRQs und legt sich dann 
schlafen.
- Zähle 'Zündimpulse' in einem IRQ.
- Timer-IRQ alle 120ms: Zündimpulse*500 (=U/min) auf Display ausgeben 
und Zündimpulse auf 0 setzen.



Gruß

Jobst

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> ori  r25,0b11000000
>      com  r25  ; Komplement bilden, also Bits umdrehen
>        com   r24  ; R25:24 enthält nun Drehzahl/Minute in Reinform <---


Komplement ist im übrigen nicht der Kehrwert, den Du aber benötigst ...



Gruß

Jobst

von ggast (Gast)


Lesenswert?

Nebenbei: AVR-ASM bitte in [avrasm ] Hier steht der Code [/avrasm ] 
(ohne Leerzeichen) einfassen bzw. (wenns länger ist) als Datei (Endung 
asm!) anhängen.

von olli (Gast)


Lesenswert?

Jobst M. schrieb:
> Hmmm ....
>
> Was ist das eigentlich?
Eine Simme. Also 2 Takte, ein Zylinder. geht ab wie Schmidt seine Katze 
=:-)

> Und wo greifst Du die Impulse ab?
Ein Schmitt-Trigger, 4093 heißt der glaube ich. Ist schon
fertig, tut was er soll und kann direkt an den AVR angeschlossen
werden.

> Aber selbst wenn ich von einem 1-Zyl. 2-Takter ausgehe, finde ich die
> Herangehensweise etwas ungeschickt.
Hm, hm, mag sein. Anfänger halt ;)

> Du möchtest doch letzlich Umdrehungen pro Zeit haben und nicht Zeit pro
> Umdrehung. (Was bringt Dir die Angabe '8,57ms/U' ... ? :-)
Oh man. Ich glaube ich verstehe langsam was Du meinst. Ich
habe mir das falsch überlegt. Das ist ja kein Wunder wenn nicht
das rauskommt was ich will.

> Meine Herangehensweise wäre:
>
> - Hauptprogramm initialisiert Timer und IRQs und legt sich dann
> schlafen.
> - Zähle 'Zündimpulse' in einem IRQ.
> - Timer-IRQ alle 120ms: Zündimpulse*500 (=U/min) auf Display ausgeben
> und Zündimpulse auf 0 setzen.
Ohne irgendwas zu verstehen, versuche ich mich jetzt mal daran.

von olli (Gast)


Lesenswert?

Problem bei den 120ms und Impulse*500 ist doch aber
die Auflösung, oder? Ich möchte später Umdrehungen in
einer Auflösung von ungefähr 100 darstellen. Zusätzlich
wäre noch die Erweiterbarkeit auf ein LCD angedacht, deshalb
würd ich die Umdrehungen gern sehr genau angeben.
Oh man, ich seh schon. Das wird was. Bis Donnerstag muss der
Code fertig sein, damit ich noch die Stromversorgung und Halterung
fürs Mopped bauen kann. PDF muss auch noch geschrieben werden
und Sonntag ist Abgabe. Ob ich das noch hinkrieg? :-/

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> Ich möchte später Umdrehungen in
> einer Auflösung von ungefähr 100 darstellen.

Dann nimmst Du den Mittelwert aus den letzten 5 Messungen.
Das ist aber leicht nachzurüsten, wenn der Rest läuft.

Aber rechne auch mal nach, wie viele LEDs Du dafür benötigst!


Jobst M. schrieb:
> Und wo greifst Du die Impulse ab?

Damit meinte ich eigentlich die Stelle im Motor. Ist aber bei einem 
1-Zylinder auch egal.


olli schrieb:
> Bis Donnerstag muss der Code fertig sein

Sollte machbar sein ;-)



Gruß

Jobst

von olli (Gast)


Lesenswert?

Also ich machs so wie Du mit den 120ms geschrieben hast
und nehme dann den Mittelwert von 5 Umdrehungen? Klingt
logisch, ich frag mich nur ob es nicht genauer geht?
Muss ich unbedingt den Interrupt-Capture von PortB nutzen?
Weil der ist schon mit einer LED belegt...

Das mit den LEDs passt. Es sind 8 Stück. Mit denen soll
nur die Resokurve dargestellt werden, also z.b. 5500-7500.
Mit 8 Lampen kann ich bei Doppelbelegungen 15 Zustände
anzeigen, also 2000/15=133 Umdrehungen.
Hmpf...

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> Muss ich unbedingt den Interrupt-Capture von PortB nutzen?

Für den Eingang des Zündimpulses benötigst Du einen IRQ-Pin. Welchen ist 
egal. Aber den hast Du doch schon angeschlossen!?

Für den Timer-IRQ benötigst Du keinen Pin.


olli schrieb:
> Mit 8 Lampen kann ich bei Doppelbelegungen 15 Zustände
> anzeigen

Was bedeutet Doppelbelegung?


olli schrieb:
> und nehme dann den Mittelwert von 5 Umdrehungen?

Nein, den Mittelwert von 5 Messungen. Du kannst auch alternativ 600ms 
warten, aber ich vermute, daß Dir das zu ruckelig wird.

D.h. Du musst Dir die letzten 5 Messungen merken. Diese 5 Werte addierst 
Du schlicht und setzt '00' dahinter. Bis 255+'00' U/min geht das noch in 
einem Byte.


Welchen uC verwendest Du eigentlich?


Gruß

Jobst

von olli (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jobst,

ich nutze den Int0, also D2 beim AtMega8.

Doppelbelegungen heißt erst alle Lampen hintereinander
an, dann bei 1 beginnend wieder ausknispen. Ergibt 15
Kombinationen bei 8 LEDs und stellt die Leistungskurve
recht anschaulich dar.

Nochmal: Ich konfiguriere den Timer darauf, alle 120ms
einen Int auszulösen. Innerhalb dieser Ints zähle ich
die Zündungen, also bei 8000 U/min sind das z.B.
133 U/s / 8,33 = 15,96 Impulse in dem 120ms Intervall.
Dann speichere ich 5 Messungen, also 5*16 = 80. Und
da kommen dann eben die zwei 00er dran. Aha. Auflösung
ergibt dann 100 Umdrehungen, gelle? Könnte ich 1500
Umdrehungen aus meinem Band raussuchen. Habe die Kurve
mal angehangen, oben Leistung, unten Drehmoment. Würde
den Huckel bei 7000 darstellen wollen.

Danke,

Olli

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> ich nutze den Int0, also D2 beim AtMega8.

Das kannst Du ja auch so lassen, wenn das schon läuft.


> Würde den Huckel bei 7000 darstellen wollen.

Also 6300 - 7700 U/min

6300 U/min ist der Wert 63 - da soll die Skala also beginnen.

Also vom Wert 62 abziehen. Klappt das ohne Unterlauf (Carry-Flag) ist 
der Wert gültig, sonst alle LEDs aus.
Bei 1 dann die erste LED einschalten, bei 2 auch die zweite ... etc.


Gruß

Jobst

von Jobst M. (jobstens-de)


Lesenswert?

Das ganze Programm hat 138 Byte :-)


Gruß

Jobst

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

So, habe es nochmal ein wenig überarbeitet und erweitert.

Ich habe es allerdings nicht getestet!!



Gruß

Jobst

von spess53 (Gast)


Lesenswert?

Hi

>ignition:  CLI
>    LDS  backup, SREG -> in backup, SREG
>    INC  counter
>    STS  SREG, backup -> out SREG, backup
>               SEI     -> das macht RETI

Lds/sts gehen auch, aber nur mit SREG + $20.

>    ADD  temp, merker2
>    ADD  temp, merker3
>    ADD  temp, merker4
>    ADD  temp, merker5

>    ; LED-Muster aus dem ROM holen
>    ldi  ZL, LOW(LEDs*2)    ; Basisadresse in Z laden
>    ldi  ZH, HIGH(LEDs*2)
>    ADD  ZL, temp    ; temp dazu addieren
>               ....

Meinst du nicht, das hier eine Division durch 5 fehlt?

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Noch etwas:

>    ADD  temp, merker2
>    ADD  temp, merker3
>    ADD  temp, merker4
>    ADD  temp, merker5

Bist du sicher, das das Ganze < 255 bleibt?

MfG Spess

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

Eingepflegt. (Wieso kann das nicht alles, wie beim 8051 MOV sein? :)


spess53 schrieb:
> Meinst du nicht, das hier eine Division durch 5 fehlt?

Nein, fehlt nicht. Wird ja immer nur 1/5 gemessen


Gruß

Jobst

von Jobst M. (jobstens-de)


Lesenswert?

spess53 schrieb:
> Bist du sicher, das das Ganze < 255 bleibt?

Unwichtig. Sollte es drüber sein, ist der Motor schon lange hin.



Gruß

Jobst

von spess53 (Gast)


Lesenswert?

Hi

Die riesen Tabelle kannst du dir übrigens mit ein befehlen sparen:
1
           ldi r16,70    ; Testwert
2
3
;-------------------------------------------
4
           
5
           ldi r20,77    ; Obergrenze
6
           clr r17       ; Ledmuster
7
8
           cp r20,r16
9
           brcs aaa
10
11
           subi r20,14
12
           
13
           sub r16,r20
14
           brcs aaa
15
16
           ldi ZL, Low(Leds<<1)
17
           ldi ZH,High(Leds<<1)
18
           add ZL,r16
19
           adc ZH,r17
20
           lpm r17,Z
21
22
aaa:       out PortB,r17
23
           .....
24
; ******************************************
25
;  LEDs
26
; ******************************************
27
leds:
28
.db 0b10000000, 0b11000000  ; 6300, 6400
29
.db  0b11100000,  0b11110000 ; 6500, 6600
30
.db  0b11111000,  0b11111100 ; 6700, 6800
31
.db  0b11111110,  0b11111111 ; 6900, 7000
32
.db  0b01111111,  0b00111111 ; 7100, 7200
33
.db  0b00011111,  0b00001111 ; 7300, 7400
34
.db  0b00000111,  0b00000011 ; 7500, 7600
35
.db  0b00000001,  0          ; 7700

MfG Spess

von Jobst M. (jobstens-de)


Lesenswert?

spess53 schrieb:
> Die riesen Tabelle kannst du dir übrigens mit ein befehlen sparen:

Die ist nachträglich sogar erst rein gewandert ;-)
So ähnlich hatte ich es zuerst.
(Das war zu diesem Zeitpunkt: 
Beitrag "Re: AVR asm - Befehl nur jedes 2. mal ausführen" )

Aber damit hat man nun die Möglichkeit, auch für die anderen Drehzahlen 
noch Muster festzulegen.
Ausserdem ist der Speicherplatz ja da ...

Edit: Ich hatte zwischendurch auch die Idee, in der Tabelle die 
Drehmomentkurve abzulegen.


Gruß

Jobst

von olli (Gast)


Lesenswert?

Halt ein, ich arbeite ja auch dran. Bisher ändern sich
die LEDs mit der neuen Routine wenn ich die Frequenz ändere...
ich hatte nur noch nicht viel Zeit für die eigentliche
Abfrage der richtigen Bereiche für die LEDs. Morgen abend! :-)

Danke,

Olli :-)

von Jobst M. (jobstens-de)


Lesenswert?

Hey, die SW ist fertig !

Beitrag "Re: AVR asm - Befehl nur jedes 2. mal ausführen"

Kannst ja mal sagen, wie das läuft ... :-)


Gruß

Jobst

von olli (Gast)


Angehängte Dateien:

Lesenswert?

Der Code gefällt mir. Problem ist, das ganze ist
zur Teilnahme an einem Gewinnspiel von myavr.de .
Ich nutze die Software von denen, Workpad. Und obwohl
es mit AVR-Assembler kompatibel sein soll, kann ich
die .db Tabelle nicht einfügen. Jetzt kann ich natürlich
AVR-Studio nutzen, aber ich probier noch ein bisschen
rum ob ich es in Workpad zum Laufen kriege ;) Habe mit
AVR-Studio auch noch nicht gearbeitet und weiß nicht
ob er mein Board erkennt (ISP wäre möglich, ist
aber kompliziert).

von Hannes L. (hannes)


Lesenswert?

olli schrieb:
> das ganze ist
> zur Teilnahme an einem Gewinnspiel von myavr.de .

Dann solltest Du aber den Gewinn an die Helfer abtreten...

...

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> Workpad

Ähm ... sehe ich das richtig, daß es kein pdf-Handbuch dafür gibt, 
sondern nur ein Windows-Hilfe-File? -.-

Wie fügt man denn dort Datenfelder ein?


Hannes Lux schrieb:
> Dann solltest Du aber den Gewinn an die Helfer abtreten...

Sehe ich persönlich nicht so eng. Ich wusste es ja schon vorher.


Gruß

Jobst

von Hannes L. (hannes)


Lesenswert?

Jobst M. schrieb:
> Sehe ich persönlich nicht so eng. Ich wusste es ja schon vorher.

Ich will da keinesfalls was von abhaben, habe mich ja auch rausgehalten, 
seitdem von Abgabetermin die Rede war. Allerdings mag ich es nicht 
besonders, wenn man sich mit fremden Federn schmückt.
Andererseits passt das ja voll in unsere heutige Gesellschaft. Das 
Pferd, das den Hafer verdient, bekommt ihn sowiso nicht...

...

von Jobst M. (jobstens-de)


Lesenswert?

Hannes Lux schrieb:
> Allerdings mag ich es nicht
> besonders, wenn man sich mit fremden Federn schmückt.

Ja, prinzipiell gebe ich Dir da Recht.
Allerdings war der Code zur Hälfte in einem anderen Programm schon 
fertig und es hat mir in den Fingern gekribbelt. :-)
Und dann finde ich es auch blöd zu sagen: 'Hey! Ich hab's schon fertig, 
bekommst Du aber nicht'
Und ich hatte nicht den Eindruck, als ob er faul auf dem Arsch sitzt und 
auf die Lösung wartet. Da kann man das mal machen. ;-)


Gruß

Jobst

von Hannes L. (hannes)


Lesenswert?

Ist mir doch auch schon öfters passiert, das letzte mal ist noch gar 
nicht so lange her: Beitrag "Re: Schalter zu Taster"
Da ging's aber glaube nicht um einen Wettbewerb oder um Hausaufgaben. 
;-)

Ich versuche ja, mich auf Hilfe zur Selbsthilfe zu beschränken. Aber oft 
sind die Programmansätze dermaßen daneben (umständlich), dass es sich 
nicht lohnt, daran herumzubasteln.

Hast übrigens 'ne schöne HP. Habe aber leider keine Elektronikbasteleien 
gefunden... 8-(

...

("..." heißt soviel wie: "Beste Grüße, Hannes")

von olli (Gast)


Lesenswert?

@hannes
Den Gedanken habe ich auch. Ohne Euch, besonders Jobst,
wäre die Sache jetzt aussichtslos.

Ich habe da auch schon was im Sinn. Ganz mit fremden Federn
schmücken werde ich mich jedenfalls nicht, auch wenn es
sich schwer vermeiden lässt. Eine Nennung ist selbstverständlich,
ein Anteil (sofern es sich nicht um den Büchergutschein handelt)
ist auch drin. Ich schätze sehr das sich Jobst so reingehangen
hat, immerhin schwirrte das Projekt schon Monate in meinem Kopf.

So, jetzt aber ran ans Werk.

Gruß,

Olli

p.s. Übrigens sehr schicke Fotos, Jobst! :-D

von Hannes L. (hannes)


Lesenswert?

olli schrieb:
> So, jetzt aber ran ans Werk.

Jawoll, tu was für den Ruhm... ;-)

Und viel Erfolg dabei...

...

von olli (Gast)


Lesenswert?

Also ich habe den Code von Jobst etwas abgeändert, u.a.
wird eine andere Warteroutine verwendet.
Die .db bekomme ich mit Workpad nicht in den Speicher
geladen, er erkennt den Syntax nicht. Habe den
Support angeschrieben.

Ich versuche es ohne die .db, mit <> Abfragen.
Momentan reicht mir aber eine korrekte Anzeige
von r16 (temp), ich gebe sie direkt auf die LEDs
aus. Diese ist bei 113 Hz (6800 Umdrehungen)
01000100, also 68, bzw. bei 166,67 Hz (10.000 U)
01100100, also 100 dezimal!! (Jetzt fehlt der Smiley
mit den zwei Biergläsern^^). :-)

Muss grad los, heute Abend entweder mit .db Tabelle,
oder ich versuche die <> Abfragen einzufügen.
1
.equ  F_CPU,  3686400
2
.include  "AVR.H"
3
4
;Reset and Interruptvectoren  ;VNr.  Beschreibung
5
begin:
6
  rjmp  main  ; 1    POWER ON RESET
7
  rjmp  ignition  ; 2    Int0-Interrupt
8
  reti    ; 3    Int1-Interrupt
9
  reti    ; 4    TC2 Compare Match
10
  reti    ; 5    TC2 Overflow
11
  reti    ; 6    TC1 Capture
12
  reti    ; 7    TC1 Compare Match A
13
  reti    ; 8    TC1 Compare Match B
14
  reti    ; 9    TC1 Overflow
15
  rjmp  onTC0  ;10    TC0 Overflow
16
  reti    ;11    SPI, STC Serial Transfer Complete
17
  reti    ;12    UART Rx Complete
18
  reti    ;13    UART Data Register Empty
19
  reti    ;14    UART Tx Complete
20
  reti    ;15    ADC Conversion Complete
21
  reti    ;16    EEPROM Ready
22
  reti    ;17    Analog Comperator
23
  reti    ;18    TWI (I²C) Serial Interface
24
  reti    ;19    Strore Program Memory Ready
25
;------------------------------------------------------------------------
26
;Start, Power ON, Reset
27
main:
28
;Stack
29
  ldi  r16,hi8(RAMEND)
30
  out  ioSPH,r16
31
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
32
  out  ioSPL,r16  ;Init Stackpointer
33
34
;Interrupt Zündung
35
  ldi  r16,0b01000000  ;Maskiere INT0
36
  out  GICR,r16
37
  ldi  r16,0b00000011  ;Konfiguriere
38
  out  MCUCR,r16  ;fallende Flanke
39
40
;Interrupt Timer
41
  ldi  r16,0b00000101  ; Vorteiler 1024
42
  out  TCCR0, r16
43
  ldi  r16,0b00000001  ; Timer 0 Overflow
44
  out  TIMSK, r16  ; Overflow Interrupt aktiviert
45
  
46
;Taster, Lampen
47
  cbi  DDRD,2  ;PORTD2 Taster = IN
48
  sbi  PORTD,2  ;Pull-Up
49
  
50
  sbi  DDRD,4  ;Port D.3 = LED OUT
51
  cbi  PORTD,4
52
  
53
  
54
  sbi  DDRB,0
55
  cbi  PORTB,0
56
  
57
  sbi  DDRB,1
58
  cbi  PORTB,1
59
  
60
  sbi  DDRB,2
61
  cbi  PORTB,2
62
  
63
  sbi  DDRC,0
64
  cbi  PORTC,0
65
  
66
  sbi  DDRC,1
67
  cbi  PORTC,1
68
    
69
  sbi  DDRC,2
70
  cbi  PORTC,2
71
  
72
  sbi  DDRC,3
73
  cbi  PORTC,3
74
  
75
  sbi  DDRC,4
76
  cbi  PORTC,4
77
    
78
  clr  r17
79
  
80
  sei    ;alle Interrupts erlauben
81
;------------------------------------------------------------------------
82
mainloop:
83
    
84
  rjmp  mainloop
85
86
;------------------------------------------------------------------------
87
ignition:
88
  cli
89
  in   r2, SREG  ; Statusregister retten
90
  inc  r17
91
  out  SREG,r2  ; Statusregister holen
92
  reti    ; zurück zu mainloop und Ints wieder an
93
94
95
;------------------------------------------------------------------------
96
onTC0:
97
  cli
98
  in   r2, SREG
99
    
100
  com  r5  ;
101
  sbrc r5,0
102
  rjmp TC0_fertig  ; ab hier nur jedes 2. Mal...
103
  
104
  ;------------------------------------------
105
  ;Auswertungsroutine der gezählten Zündungen
106
  
107
  mov  r16, r17  ; counter kopieren
108
  clr  r17  ; counter =0
109
110
  sei    ; IRQs dürfen nun wieder stören
111
  
112
  mov  r22, r21  ; letzten 5 Werte schieben
113
  mov  r21, r20
114
  mov  r20, r19
115
  mov  r19, r18
116
  mov  r18, r16
117
  add  r16, r19
118
  add  r16, r20
119
  add  r16, r21
120
  add  r16, r22  ; temp = temp(=merker1)+merker2+...+merker5
121
      ; r16 enthält nun 0-100
122
123
124
  cbi  PORTB,0
125
  cbi  PORTB,1
126
  cbi  PORTB,2
127
  cbi  PORTC,0
128
  cbi  PORTC,1
129
  cbi  PORTC,2   
130
  cbi  PORTC,3
131
  cbi  PORTC,4
132
   
133
       
134
   ;Anzeigen
135
   sbrc  r16,0
136
   rcall  lampe0
137
   
138
   sbrc  r16,1
139
   rcall  lampe1
140
   
141
   sbrc  r16,2
142
   rcall  lampe2
143
   
144
   sbrc  r16,3
145
   rcall  lampe3
146
   
147
   sbrc  r16,4
148
   rcall  lampe4
149
   
150
   sbrc  r16,5
151
   rcall  lampe5
152
   
153
   sbrc  r16,6
154
   rcall  lampe6
155
   
156
   sbrc  r16,7
157
   rcall  lampe7  
158
  
159
  
160
161
162
TC0_fertig:
163
  ldi  r23, 39  ; Reinitialisierungswert für Timer
164
  out  TCNT0, r23  ; 60 ms = 221184 Takte, /1024 = 216; 255-216 = 39
165
  
166
  out  SREG,r2
167
  
168
  reti
169
  
170
  
171
;------------------------------------------------------------------------
172
; Unterprogramme für einzelne LEDs
173
174
lampe0:
175
   sbi  PORTB,0
176
   ret
177
lampe1:
178
   sbi  PORTB,1
179
   ret
180
181
lampe2:
182
   sbi  PORTB,2
183
   ret
184
185
lampe3:
186
   sbi  PORTC,0
187
   ret
188
189
lampe4:
190
   sbi  PORTC,1
191
   ret
192
193
lampe5:
194
   sbi  PORTC,2
195
   ret
196
197
lampe6:
198
   sbi  PORTC,3
199
   ret
200
201
lampe7:
202
   sbi  PORTC,4
203
   ret

von Jobst M. (jobstens-de)


Lesenswert?

Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O

Und für Register kann man auch keine Namen definieren? :-/

Wieso möchtest Du nur jedes 2. Mal messen?
Und wenn, dann mach es auch. Denn den Zähler setzt Du erst nach dem 
Sprung wieder zurück.
(Und wenn Du es dann geschafft hast, funktioniert es nicht mehr!) ;-)

Okay, Du gibst die Drehzahl derzeit binär aus - leider nicht sehr 
einfach abzulesen.

Füge nach den 4 Additionen doch mal dies ein:
1
  SUBI  r16, 62      ; 62 abziehen (negative Ergebnisse sind egal)
2
3
  CLR  r24      ; default-Muster
4
5
  CPI  r16, 1      ; vergleichen
6
  BRNE  test2
7
  LDI  r24, 128    ; wenn zutreffend, neues Muster setzen
8
test2;
9
  CPI  r16, 2
10
  BRNE  test3
11
  LDI  r24, 192    ; ... und so weiter
12
test3;
13
  CPI  r16, 3
14
  BRNE  test4
15
  LDI  r24, 224
16
test4;
17
  CPI  r16, 4
18
  BRNE  test5
19
  LDI  r24, 240
20
test5;
21
  CPI  r16, 5
22
  BRNE  test6
23
  LDI  r24, 248
24
test6;
25
  CPI  r16, 6
26
  BRNE  test7
27
  LDI  r24, 252
28
test7;
29
  CPI  r16, 7
30
  BRNE  test8
31
  LDI  r24, 254
32
test8;
33
  CPI  r16, 8
34
  BRNE  test9
35
  LDI  r24, 255
36
test9;
37
  CPI  r16, 9
38
  BRNE  test10      ; Klapper-di-klapper
39
  LDI  r24, 127
40
test10;
41
  CPI  r16, 10
42
  BRNE  test11
43
  LDI  r24, 63
44
test11;
45
  CPI  r16, 11
46
  BRNE  test12
47
  LDI  r24, 31
48
test12;
49
  CPI  r16, 12
50
  BRNE  test13
51
  LDI  r24, 15
52
test13;
53
  CPI  r16, 13
54
  BRNE  test14
55
  LDI  r24, 7
56
test14;
57
  CPI  r16, 14
58
  BRNE  test15
59
  LDI  r24, 3
60
test15;
61
  CPI  r16, 15
62
  BRNE  test16
63
  LDI  r24, 1
64
test16;
65
66
  MOV  r16,r24

Ich hasse Workpad jetzt schon ... die reinste Spaghettischleuder ...



... und am ENDE sagst Du ihm, er soll sich in 60ms wieder melden ... 
+grübel+ (Tut er das?)
Gut, der Code nimmt nur wenig Zeit in Anspruch - das wird es kaum 
verfälschen.

Wenn Du das sowieso 2 mal machst, wieso nimmst Du dann nicht gleich 1x 
120ms ?


Ach, ... aber wieso? ... häää? :-D

Also: Du wirfst jeden 2. Timer-IRQ quasi weg. Dafür hast Du die Anzahl 
verdoppelt ... Wieso machst Du das?



Gruß

Jobst

von olli (Gast)


Lesenswert?

> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O
Ich bin mir nicht sicher, ich glaube es wird als
Empfehlung gegeben. Gewöhnt man sich aber schnell dran,
finde ich leichter zu lesen als Atmel-AVR.

> Und für Register kann man auch keine Namen definieren? :-/
Ich habe es noch nicht gefunden wie es geht... wenn es geht.
1
 ganz viel Code...

Mensch Jobst... da wars dann um meinen Eigenanteil.
Ich hab den neuen Code eingefügt, muss noch die Richtung
ändern. aber erstmal genau überlegen was der macht.
Danke erstmal soweit.


> Ich hasse Workpad jetzt schon ... die reinste Spaghettischleuder ...
Du meinst viele Zeilen? ;)

> Wenn Du das sowieso 2 mal machst, wieso nimmst Du dann nicht gleich 1x
> 120ms ?
Ich habe die Routine geschrieben, bevor Deine kam. Habs
aus dem myAVR-Buch, nur in dem Beispiel gingen eben nur
maximal irgendwas unter 120ms... also hab ich einfach zweimal
eine 60er gemacht :-) Schlechter Stil, oder?

Routine passt ja jetzt soweit. Ich denk mich da
jetzt noch rein und mache etwas Feinschliff. Dann kann
ich ja morgen schon mit der PDF anfangen :-)

Danke Dir und wir hören uns ;)

Olli

von olli (Gast)


Lesenswert?

Ach nochwas. Die Anzeige pendelt immer um eine LED
am Rand. Ist wegen der 120er Intervalle, die die
Kommastelle abhacken, oder?
Also z.B. bei 12,3 U/s:
12, 12, 12, 12, 13, 12...
Hmmm...

von Jobst M. (jobstens-de)


Lesenswert?

olli schrieb:
> Mensch Jobst... da wars dann um meinen Eigenanteil.

Ach, verdammt. Tut mir leid. Nimm's wieder raus! :-)


olli schrieb:
> Du meinst viele Zeilen? ;)

Vor allem Zeilen, die alle (fast) das selbe machen ...


olli schrieb:
> Die Anzeige pendelt immer um eine LED
> am Rand. Ist wegen der 120er Intervalle, die die
> Kommastelle abhacken, oder?

Solange Du die Drehzahl nicht mit den 120ms synchronisierst, wird das 
immer wieder passieren. Das ist nochmal eine kleine Denkaufgabe, das 
heraus zu filtern ;-)


Gruß

Jobst

von Hannes L. (hannes)


Lesenswert?

olli schrieb:
> Die Anzeige pendelt immer um eine LED
> am Rand.

Das ist eigentlich bei so ziemlich jeder Messwerterfassung der Fall. Ich 
eliminiere das meist mittels Hysterese, übernehme also Änderungen des 
Messwertes erst, wenn sie einen bestimmten Betrag überschreiten.

olli schrieb:
> Die .db bekomme ich mit Workpad nicht in den Speicher
> geladen, er erkennt den Syntax nicht. Habe den
> Support angeschrieben.
>
> Ich versuche es ohne die .db, mit <> Abfragen.

Als Alternative gibt's noch das EEPROM oder ein Array im SRAM.

Wobei ich mich schon lange nach der Existenzberechtigung des Workpads 
und der anderen myAVR-Software frage, denn AVR-Studio ist kostenfrei und 
trotzdem sehr brauchbar.

Jobst M. schrieb:
> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O

Das mache ich auch im AVR-Studio grundsätzlich so, ergibt halt eine 
unfragmentierte Hex-Datei. Ist auch kein Problem, denn ich habe 
inzwischen die Interrupt-Sprungtabellen der von mir benutzten AVRs in 
eine Textdatei kopiert, aus der ich mir bei jedem neuen Projekt die 
Tabelle herauskopiere. Mit .Org und Angabe der Adresse über vereinbarte 
Namen muss man ja auch die korrekte Reihenfolge einhalten, da kann man 
auch gleich die ganze Liste kopieren und die unbenutzten Einträge 
"deaktivieren". Ist in meinen Augen übersichtlicher. Eine neue 
Sprungtabelle kopiere ich aus dem Datenblatt heraus und lösche dann die 
Adressen raus.

...

von Jobst M. (jobstens-de)


Lesenswert?

Hannes Lux schrieb:
> Jobst M. schrieb:
>> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O
> [...]

Okay. Ich meinte das eigentlich anders:

Gibt es bei Workpad kein .org ?
Nicht, daß man es benutzen muß.


Gruß

Jobst

von Hannes L. (hannes)


Lesenswert?

Jobst M. schrieb:
> Gibt es bei Workpad kein .org ?

Gibt es einen Grund, Workpad zu benutzen?

> Nicht, daß man es benutzen muß.

Eben!

Was gibt es für einen Grund, ein Drittanbieter-Produkt zu benutzen, das 
dem kostenlos erhältlichen Original nicht das Wasser reichen kann?

Und ja, ich habe auch mal ein Projekt auf einem myAVR-Board 
programmiert, hatte auch die (sauteure) CD mit der Sisy-Software hier. 
Ich habe es aber mit AVR-Studio realisiert und den "Auftraggeber" (ein 
Papi, der dem Sportverein seiner Tochter eine lichtschrankengesteuerte 
Stoppuhr sponsern wollte) dazu gebracht, den Mist zu ignorieren und das 
AVR-Studio zu benutzen. Das Projekt steht seit Jahren auf meiner HP. 
Sisy hat es gefunden und mich gebeten, es auf ihrer Seite als Referenz 
angeben zu dürfen, obwohl ich es nicht mit ihrem Workpad realisiert 
hatte und auch kein Kunde von ihnen bin.

Wer Hardware von dort kaufen will, weil er nicht basteln will, der soll 
es tun.
Wer aber meint, er könne dort "Wissen" kaufen, der irrt. Das Wissen muss 
man sich selbst erarbeiten. Und da ist es nicht besonders ratsam, auf 
die Original-Programmiersoftware von Atmel zu verzichten und eine völlig 
quelltextinkompatible Alternative zu benutzen.

Ich sehe also keinerlei Anlass, zu erforschen, wie man bei Workpad 
gewisse Dinge löst, die anders sind als bei AVR-Studio.

...

von olli (Gast)


Lesenswert?

> Was gibt es für einen Grund, ein Drittanbieter-Produkt zu benutzen, das
> dem kostenlos erhältlichen Original nicht das Wasser reichen kann?
myAVR macht das alles komplett. Also Hardware+Software+Buch.
Workpad ist sehr übersichtlich, hat z.B. eine farbliche
Abhebung der einzelnen Befehle und viele Beispiele die
out-of-the-box mit myAVR Hardware läuft und so spielerisch
die Grundlagen vermittelt. Es ist nicht das non+ultra,
aber ich arbeite gern damit.
Was etwas nervt sind die unterschiedlichen Dialekte von
Atmel und Gnu. .db wird zu .byte usw. Ist leider auch nicht
gut von myAVR dokumentiert.
Sisy ist wirklich etwas teuer, aber Workpad gibts ja schon
für 15 bzw. 25 Euro.


Momentaner Stand der Software ist jetzt, das ich die Overrev-LEDs
mit 8,3 Hz blinken lasse, wenn 7700 Umdrehungen überschritten
werden. Wollte das Bit in r5 nutzen, ging aber nicht?!
jedenfalls jetzt r4 genommen und alles schick. Ich schau nochmal
wegen eines Filters, wenn ich es gleich nicht hinbekomme, ist
auch nicht so wild. Wenn Ihr noch stilistische Ideen habt,
immer her damit! :)
1
.equ  F_CPU,  3686400
2
.include  "AVR.H"
3
4
;Reset and Interruptvectoren  ;VNr.  Beschreibung
5
begin:
6
  rjmp  main  ; 1    POWER ON RESET
7
  rjmp  ignition  ; 2    Int0-Interrupt
8
  reti    ; 3    Int1-Interrupt
9
  reti    ; 4    TC2 Compare Match
10
  reti    ; 5    TC2 Overflow
11
  reti    ; 6    TC1 Capture
12
  reti    ; 7    TC1 Compare Match A
13
  reti    ; 8    TC1 Compare Match B
14
  reti    ; 9    TC1 Overflow
15
  rjmp  onTC0  ;10    TC0 Overflow
16
  reti    ;11    SPI, STC Serial Transfer Complete
17
  reti    ;12    UART Rx Complete
18
  reti    ;13    UART Data Register Empty
19
  reti    ;14    UART Tx Complete
20
  reti    ;15    ADC Conversion Complete
21
  reti    ;16    EEPROM Ready
22
  reti    ;17    Analog Comperator
23
  reti    ;18    TWI (I²C) Serial Interface
24
  reti    ;19    Strore Program Memory Ready
25
;------------------------------------------------------------------------
26
;Start, Power ON, Reset
27
main:
28
;Stack
29
  ldi  r16,hi8(RAMEND)
30
  out  ioSPH,r16
31
  ldi  r16,lo8(RAMEND)  ;Stack Initialisierung
32
  out  ioSPL,r16  ;Init Stackpointer
33
34
;Interrupt Zündung
35
  ldi  r16,0b01000000  ;Maskiere INT0
36
  out  GICR,r16
37
  ldi  r16,0b00000011  ;Konfiguriere
38
  out  MCUCR,r16  ;fallende Flanke
39
40
;Interrupt Timer
41
  ldi  r16,0b00000101  ; Vorteiler 1024
42
  out  TCCR0, r16
43
  ldi  r16,0b00000001  ; Timer 0 Overflow
44
  out  TIMSK, r16  ; Overflow Interrupt aktiviert
45
  
46
;Taster, Lampen
47
  cbi  DDRD,2  ; Eingang für Zündsignal
48
  sbi  PORTD,2  ; Pull-Up
49
  sbi  DDRB,0  ; LED als Ausgang
50
  cbi  PORTB,0  ; LED ausknipsen
51
  sbi  DDRB,1  ; dito B1
52
  cbi  PORTB,1
53
  sbi  DDRB,2  ; ...
54
  cbi  PORTB,2
55
  sbi  DDRC,0
56
  cbi  PORTC,0
57
  sbi  DDRC,1
58
  cbi  PORTC,1
59
  sbi  DDRC,2
60
  cbi  PORTC,2
61
  sbi  DDRC,3
62
  cbi  PORTC,3
63
  sbi  DDRC,4
64
  cbi  PORTC,4
65
  sbi  DDRC,5  ; rote LED
66
  cbi  PORTC,5
67
  sbi  DDRB,3  ; dito
68
  cbi  PORTB,3
69
  
70
  sei    ;alle Interrupts erlauben
71
;------------------------------------------------------------------------
72
mainloop:
73
    
74
  rjmp  mainloop  ; eine Endlosschleife; Programm wird durch das
75
      ; Eintreten eines Interrupts (Zündung oder Timerintervall)
76
      ; geweckt und macht sonst garnichts
77
78
;------------------------------------------------------------------------
79
ignition:      ; Okay, Zündung löste Interrupt aus!
80
  cli    ; Interrupts blockieren
81
  in   r2, SREG  ; Statusregister retten
82
     inc  r17  ; Counter für Zündung innerhalb 120ms Intervall
83
  out  SREG,r2  ; gespeichertes Statusregister wieder zurücksetzen
84
  reti    ; zurück zu mainloop und Interrupts wieder an
85
86
87
;------------------------------------------------------------------------
88
onTC0:      ; Timer löste Interrupt aus; Interrupt alle 60 ms
89
  cli    ; Ints blockieren
90
  in   r2, SREG  ; Statusregister retten
91
  
92
  com  r5  ; Register r5 komplementieren, also Wechsel 1, 0, 1...
93
  sbrc   r5,0  ; wenn Bit 0 von r5 = 0, dann nächsten Befehl überspringen (um 120ms zu stoppen)
94
  rjmp   TC0_fertig  ; ...ansonsten Interrupt jetzt beenden und in 60 ms wiederkommen.
95
  
96
  ;------------------------------------------
97
  ;Auswertungsroutine der gezählten Zündungen
98
  
99
  mov  r16, r17  ; Counter r17 nach r16 kopieren
100
  clr  r17  ; Counter zurücksetzen
101
102
  sei    ; IRQs dürfen nun wieder stören
103
  
104
  mov  r22, r21  ; letzten 5 Werte schieben
105
  mov  r21, r20  ; ein Stapel, von unten wird der aktuelle Wert reingeschoben
106
  mov  r20, r19
107
  mov  r19, r18
108
  mov  r18, r16
109
  
110
  add  r16, r19  ; dann werden die letzten 4 Werte zum aktuellen Wert in r16
111
  add  r16, r20  ; dazu addiert
112
  add  r16, r21   
113
  add  r16, r22    
114
      
115
      
116
      ; r16 enthält nun Drehzahl / 100
117
   subi    r16, 61        ; 61 abziehen (negative Ergebnisse sind egal)
118
       ; 6100 U/min sind die Untergrenze, ab 6200 soll die
119
       ; erste LED angehen
120
121
    clr    r24        ; default-Muster, wird angezeigt wenn außerhalb
122
        ; des Bereichs: also alle LEDs aus
123
        
124
    cbi  PORTB,0  ; alle LEDs löschen
125
      cbi  PORTB,1
126
     cbi  PORTB,2
127
     cbi  PORTC,0
128
     cbi  PORTC,1
129
    cbi  PORTC,2   
130
     cbi  PORTC,3
131
     cbi  PORTC,4
132
   cbi  PORTC,5
133
   cbi  PORTB,3
134
135
    
136
    cpi    r16, 1        ; Konstante vergleichen: 61+1=62, ergo jetzt 6300 Umdrehungen?
137
    brne    test2  ; Wenn nein, dann unten weitertesten
138
    ldi    r24, 128      ; Wenn doch, dann neues Muster in r24 setzen
139
      ; 128 dezimal = 10000000 binär
140
        
141
test2:
142
  cpi    r16, 2
143
    brne    test3
144
    ldi    r24, 192      ; 11000000
145
test3:
146
    cpi    r16, 3
147
    brne    test4
148
    ldi    r24, 224  ; 11100000
149
test4:
150
    cpi    r16, 4
151
    brne    test5
152
    ldi    r24, 240  ; 11110000
153
test5:
154
    cpi    r16, 5
155
    brne    test6
156
    ldi    r24, 248
157
test6:
158
    cpi    r16, 6
159
    brne    test7
160
    ldi    r24, 252
161
test7:
162
    cpi    r16, 7
163
    brne    test8
164
    ldi    r24, 254
165
test8:
166
    cpi    r16, 8
167
    brne    test9
168
    ldi    r24, 255  ; 11111111
169
test9:
170
    cpi    r16, 9
171
    brne    test10        ; Klapper-di-klapper
172
    ldi    r24, 127  ; 01111111
173
test10:
174
    cpi    r16, 10
175
    brne    test11
176
    ldi    r24, 63
177
test11:
178
    cpi    r16, 11
179
    brne    test12
180
    ldi    r24, 31
181
test12:
182
    cpi    r16, 12
183
    brne    test13
184
    ldi    r24, 15
185
test13:
186
    cpi    r16, 13
187
    brne    test14
188
    ldi    r24, 7
189
test14:
190
    cpi    r16, 14
191
    brne    test15
192
    ldi    r24, 3
193
test15:
194
    cpi    r16, 15
195
    brne    test16
196
    ldi    r24, 1
197
test16:
198
 
199
  cpi  r16, 16  ; Wenn 1600 Umdrehungen über Referenzwert 6100, dann 
200
    brsh  rot_an
201
        ; die roten LEDs an1        
202
backfromred:    
203
    mov    r16,r24   ; r16 enthält nun das zu verwendende Bitmuster
204
   
205
   
206
   
207
       
208
   ;Anzeigen
209
   sbrc  r16,0  ; Skip if Bit in Register is Cleared; also wenn Bit 0
210
   sbi  PORTC,4  ; in r16 0 ist, dann nächste Anweisung (LED setzen) überspringen
211
   
212
   sbrc  r16,1  ; und die einzelnen Bits in r16 abklappern...
213
   sbi  PORTC,3
214
   
215
   sbrc  r16,2
216
  sbi  PORTC,2
217
   
218
   sbrc  r16,3
219
   sbi  PORTC,1
220
   
221
   sbrc  r16,4
222
   sbi  PORTC,0
223
   
224
   sbrc  r16,5
225
   sbi  PORTB,2
226
   
227
   sbrc  r16,6
228
   sbi  PORTB,1
229
   
230
   sbrc  r16,7
231
  sbi  PORTB,0
232
233
234
TC0_fertig:
235
  
236
  ldi  r23, 39  ; Reinitialisierungswert für Timer
237
  out  TCNT0, r23  ; 60 ms = 221184 Takte, /1024 = 216; 255-216 = 39
238
  
239
  out  SREG,r2  ; Statusregister wiederherstellen
240
  
241
  reti
242
  
243
  
244
;------------------------------------------------------------------------
245
rot_an:
246
  com  r4  ; Register r5 komplementieren, also Wechsel 1, 0, 1...
247
  sbrc   r4,0  ; wenn Bit 0 von r5 = 0, dann nächsten Befehl überspringen (um 120ms zu stoppen)
248
  rjmp   rot_flackern  ; ...ansonsten Interrupt jetzt beenden und in 60 ms wiederkommen.
249
  cbi  PORTB,3
250
  cbi  PORTC,5
251
  ret
252
  
253
rot_flackern:
254
   sbi  PORTB,3
255
   sbi  PORTC,5
256
   rjmp  backfromred

von Hannes L. (hannes)


Lesenswert?

Heute wurde ich per Mail von myAVR-Team benachrichtigt, dass dieser 
Wettbewerb läuft. Ist ja noch viel Zeit bis zum Termin... ;-)

Man gut, dass ich für Wettbewerbe sowiso nichts übrig habe...

...

von spess53 (Gast)


Lesenswert?

Hi

>Wenn Ihr noch stilistische Ideen habt,
>immer her damit! :)

Z.B. wenn ich deine CPI-Orgie wird mir richtig schlecht.
1
                      ldi r24,$FF
2
                      cpi r16,8
3
                      breq test11
4
                      brcc test05
5
6
                      ldi r17,8
7
                      sub r17,r16
8
9
test04:               lsl r24
10
                      dec r17
11
                      brne test04
12
                      rjmp test11
13
14
test05:               subi r16,8
15
test06:               lsr r24
16
                      dec r16
17
                      brne test06               
18
19
test11:               .....       ; Muster in r24

MfG Spess

von Jobst M. (jobstens-de)


Lesenswert?

spess53 schrieb:
> Z.B. wenn ich deine CPI-Orgie wird mir richtig schlecht.

Mir auch. Obwohl sie von mir stammt.
Also die CPI-Orgie. Aber woher stammt Dein Zitat? :-)


Olli:

Wenn .db durch .byte ersetzt werden kann, bau doch die Tabelle einfach 
wieder ein :-)


Gruß

Jobst

von olli (Gast)


Lesenswert?

Jungs, da habt Ihr wohl recht. Die Sache ist nur, ich bin
Anfänger und finde das Programm so wie es jetzt ist gut
und Eure Veränderungen gehen mir etwas zu sehr ins Mark.
Also nicht böse sein, ich lass es jetzt so und sehe zu
das Video und PDF zu basteln... vielleicht habe ich
sogar am Sonntag noch ein bisschen Freizeit um in die
Sonne zu gehen.. ;)

von spess53 (Gast)


Lesenswert?

Hi

>Jungs, da habt Ihr wohl recht.

du hast doch geschrieben:

Wenn Ihr noch stilistische Ideen habt, immer her damit! :)

Z.B. die exessive Benutzung von sbi/cbi bei der Initialisierung der 
Ports.
An der Stelle brauchst du keine Rücksicht auf den Zustand der Register 
nehmen. Da reicht also:

  ldi r16,blabla
  out Portxy, r16

MfG Spess

von olli (Gast)


Lesenswert?

Danke soweit.

Ich habs heute mal eingebaut. Es ging ab und zu mal,
war schon fein. Nur ständige Aussetzer. Also nochmal
die Zündabnahme nachgelötet.
Jetzt geht es garnicht mehr am Moped. Schließe ich
einen Frequenzgenerator (anderer AtMega) an, funktionierts.
Habe mein Problem mit Bild zwecks größerem Publikum
nochmal in einen anderen Thread geschrieben, also wer
will kann auch nochmal ein Auge werfen:

Beitrag "Selbstbau Drehzahlmesser und 5V Signal"

Danke,

Olli :-)

von olli (Gast)


Lesenswert?

So, ich habe es eingereicht. Sind dann doch 14 Seiten PDF
mit Bildern geworden. Ich stells mal rein wenn es
dort veröffentlicht wurde, myAVR will erst nochmal drübergucken.

Danke an alle die mitgeholfen haben,

Olli :-)

von olli (Gast)


Lesenswert?

So, das Projekt samt Abstimmung ist online. Sind immerhin 10
Projekte, was bei 10 Preisen schonmal mindestens einen
Einkaufsgutschein ausmacht ;)

Ich habe mir überlegt das wenn ich es unter die ersten 3 schaffen
sollte - was ein Preisgeld bedeutet - ich Jobsten 1/3 davon
abgebe. Was meint Ihr, ist das angemessen?

Hier, wenn Ihr schauen&voten wollt:

http://projekte.myavr.de/?sp=voting/listProjekt&vId=2&MENUS=Infos%20/%20Preisausschr.

Gruß,

Olli :-)

von Jobst M. (jobstens-de)


Lesenswert?

Öch Mönsch ...Jobstens - mit s ... oder nur Jobst ...naja, egal :-)

Ja, feini! :-)

Wünsch uns viel Glück! ;-)


Gruß

Jobst

von olli (Gast)


Angehängte Dateien:

Lesenswert?

Ähh... uh... Jobst... natürlich. Ich nehme an das
ist Dein Vorname? Hab ich noch nie gehört, daher
frag ich :) Also sorry for misspelling!

Gruß,

Olli

von Jobst M. (jobstens-de)


Lesenswert?

Ja, das ist ein altdeutscher Vorname.


Gruß

Jobst

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.