Forum: Mikrocontroller und Digitale Elektronik noch probleme mit attiny 12


von Jürgen K. (jk2010)


Lesenswert?

Hi !

nachdem mir hier etliche Hilfestellung und Beispiele gegeben haben, hier 
mal mein Beispielprog.

Es funktioniert bis auf die Interruptroutine.
Möchte, wenn ein gültiges Signal (0,7 bis 2,3 ms) anliegt, eine Lampe 
(im Text search auf pb4) schalten.
Aber es funktioniert net.

Vielleicht seid ihr so nett und schaut mal über den Quältext ;))) (Ist 
mein erstes Prog in Assembler seit der 64er Ära)
1
.NOLIST
2
.INCLUDE "tn12def.inc"
3
.LIST
4
5
;Konstanten
6
7
.equ clock=1200000      ;Taktfrequenz 1,2MHz
8
.equ irqfreq=10000      ;Interruptfrequenz 10kHz
9
.equ Tail=pb0        ;Portpin Heckleuchte
10
.equ impuls=pb1        ;Portpin ImpulsRC_eingang
11
.equ U_canopy=pb2      ;Portpin Kanzel oben
12
.equ L_canopy=pb3      ;Portpin Kanzel unten
13
.equ search=pb4        ;Portpin Suchscheinwerfer
14
.equ RC_min=13        ;minimal gültige Impulsbreite (0,7ms)
15
.equ RC_max=43        ;maximal gültige Impulsbreite (2,3ms)
16
.equ RC_aus=26        ;Schaltschwelle aus 1,3ms
17
.equ RC_ein=30        ;Schaltschwelle ein 1,7ms
18
.equ RC_neutral=28      ;neutralstellung fällt hier aus, da nur an oder aus
19
20
21
.equ RISING   = 0x03    ;steigende Flanke
22
.equ FALLING   = 0x02    ;fallende Flanke
23
24
25
;berechnete Konstanten
26
27
;.equ tim0zu=clock/irqfreq  ;Zählumfang Timer0
28
29
.def NULL    =r0
30
.def saveSREG  =r16  
31
.def Timer1    =r17
32
.def Timer2    =r18
33
.def Timer3    =r19
34
.def temp     =r20     ;Tempregister
35
.def puls     =r21     ;Pulslänge
36
.def highLow   =r22     ;High oder Low Flanke
37
.def LED_Port  =r23     ;Status sichern
38
39
40
41
42
43
;Angeschlossene LED´s
44
;PB0 Tail
45
;PB2 upper canopy
46
;PB3 lower canopy
47
;PB4 Suchscheinwerfer
48
49
;PB1 Input Funke
50
51
52
53
;******************************************************************
54
.cseg              ;CODE segment
55
.org 0
56
  rjmp  init        ;resethandler
57
.org INT0addr
58
  rjmp  EXT_INT_handler        ;Interrupthandler
59
60
61
62
.org $6
63
init:   
64
;Kalibrierung interne RC
65
  ldi   ZL, low(flashend*2)
66
  ldi   ZH, high(flashend*2)
67
  lpm
68
  ser   ZL
69
  cpse   r0, ZL
70
  out   OSCCAL, r0
71
;Kalibrierungsende
72
73
  in    NULL, 0x00
74
75
  ldi    LED_Port,0b111101
76
  out    DDRB,LED_Port       ;set portb as output Pin 1 is in
77
  ldi    LED_Port, 0b111111
78
  out    PORTB, LED_Port      ;set portb outputs all off PB1 Pull_up active
79
  ldi   highLow, RISING     ;highLow initialisieren. 1. Flanke ist eine HIGH
80
  out   MCUCR, highlow
81
  ldi   temp, (1<<INT0)       ;Enable externen Interrupt
82
  out   GIMSK, temp
83
 
84
                  ;Konfiguriere externen Interrupt
85
86
  
87
  ldi    temp, (1<<CS01) | (1<<CS00)  ;teiler 64
88
  out    TCCR0,temp
89
  out    TCNT0, NULL
90
91
  sei               ;Enable Interrupts
92
93
94
start:
95
; LED_Port ist noch $FF also alle Lichter aus!
96
  cbr   LED_Port, (1<<Tail) | (1<<U_Canopy)     ; Tail + Upper_Canopy
97
  out    PORTB,LED_Port              ; write to port
98
  rcall   wait_70ms      
99
  sbr    LED_Port, 1<<U_Canopy
100
  out    PORTB,LED_Port      ;write to port
101
  rcall   wait_200ms      
102
  cbr   LED_Port, (1<<U_Canopy) | (1<<Tail) ;set LED_Port bits  tail and upper-canopy
103
  out    PORTB,LED_Port      ;write to port
104
  rcall   wait_70ms
105
  sbr    LED_Port, (1<<Tail) | (1<<U_Canopy) ; set LED_Port bits off 
106
  out    PORTB,LED_Port      ;write to port
107
  rcall   wait_200ms
108
  rcall   wait_200ms
109
  rcall   wait_70ms        
110
111
  cbr    LED_Port, 1<<L_Canopy   ;set LED_Port bit lower_canopy
112
  out    PORTB,LED_Port      ;write to port
113
  rcall   wait_70ms
114
115
  sbr    LED_Port, 1<<L_Canopy   ;set LED_Port bits off
116
  out    PORTB,LED_Port      ;write to port
117
    rcall   wait_200ms
118
  rcall   wait_200ms  
119
  rcall   wait_70ms
120
  
121
rjmp  start
122
123
EXT_INT_handler:
124
  in     saveSREG, SREG
125
  out   TCNT0, NULL        ;Counter resetten
126
  cpi   highLow, RISING     ;Der Puls ist eine steigende Flanke
127
  brne   FALLING_EDGE       ;Wenn eine fallende Flanke, spring zur Routine
128
  ldi   highLow, FALLING     ;Nächster Puls ist eine Fallende Flanke
129
  out   MCUCR, highlow
130
  out   SREG, saveSREG
131
reti
132
133
FALLING_EDGE:
134
  in     saveSREG, SREG
135
  ldi    puls, TCNT0
136
  cpi    highlow, FALLING
137
  brne  Fehler_Flanke
138
  
139
  ldi   highLow, RISING     ;Nächser Puls ist eine Steigende Flanke
140
  out   MCUCR, highlow
141
  rcall   checkPuls         ;auswertung der Pulslänge
142
  
143
Fehler_Flanke:
144
  out   SREG, saveSREG
145
reti
146
147
148
checkPuls:
149
    cpi     puls, RC_min      ;kleiner als Schaltschwelle ->raus
150
    brlo    Fehler
151
  cpi    puls, RC_max      ;größer als max ->raus
152
  brsh  Fehler
153
  cbr   LED_Port, 1<<search      ;OK, dann Scheinwerfer an und raus
154
ret                           
155
 
156
Fehler:
157
  sbr LED_Port, 1<<search
158
ret    
159
160
161
162
wait_200ms:
163
          ldi  Timer1, $02
164
WGLOOP0:  ldi  Timer2, $C6
165
WGLOOP1:  ldi  Timer3, $C9
166
WGLOOP2:  dec  Timer3
167
          brne WGLOOP2
168
          dec  Timer2
169
          brne WGLOOP1
170
          dec  Timer1
171
          brne WGLOOP0
172
; ----------------------------- 
173
; delaying 18 cycles:
174
          ldi  Timer1, $06
175
WGLOOP3:  dec  Timer1
176
          brne WGLOOP3
177
      ret
178
; ============================= 
179
180
wait_70ms:  
181
; ============================= 
182
;    delay loop generator 
183
;     84000 cycles:
184
; ----------------------------- 
185
; delaying 83997 cycles:
186
          ldi  Timer1, $99
187
WGLOOP4:  ldi  Timer2, $B6
188
WGLOOP5:  dec  Timer3
189
          brne WGLOOP5
190
          dec  Timer1
191
          brne WGLOOP4
192
; ----------------------------- 
193
; delaying 3 cycles:
194
          ldi  Timer1, $01
195
WGLOOP6:  dec  Timer1
196
          brne WGLOOP6
197
      ret
198
; ============================= 
199
; ----------------------------
200
; wait subroutine 
201
; ----------------------------
202
;wait:    
203
;  ldi  count1,155    
204
205
;d1:
206
;  ldi  count2,155    
207
208
;d2:
209
;  dec  count2      
210
;  brne  d2  
211
;  dec    count1      
212
;  brne   d2      
213
;  ret
214
; ----------------------------

Grüße
Jürgen

von Fred S. (Gast)


Lesenswert?

Hi Jürgen,

beim schnellen Drüberlesen fällt mir erstens auf, dass Du TCNT0 in 
Deiner Interrupt-Routine auf NULL setzt, ohne vorher den Zähler-Inhalt 
zu lesen. Ein paar Zeilen weiter versuchst Du (sollte statt ldi auch 
in heißen!!), den Zähler-Inhalt zu lesen, der dürfte dann aber (bei 
etwa 5,3ms/Zähler-Tic) noch Null sein!

EXT_INT_handler:
  ...
  out   TCNT0, NULL        ; ????
  ....
  reti

FALLING_EDGE:
  ...
  ldi    puls, TCNT0
          ; Du hast Deinen Zähler doch gerade genullt!
          ;  ... zudem müsste es in heißen!

Drittens ist mir nicht klar, wieso Du für EXT_INT_handler und für 
Falling_Edge das gleiche Register ("saveSREG") zum Sichern des 
Status-Regs benutzt.

Viertens: Statt
          in NULL, 0x00
                 meinst Du sicher clr NULL
                            oder  /ldi reghigh, 0/
                                  /mov NULL,reghigh/

Wie gesagt, ich habe nur ganz schnell über Deinen Code gesehen, es 
können durchaus noch mehr Käfer drin sein!

Gruß

Fred

von Jürgen K. (jk2010)


Lesenswert?

Hi !

dank Dir für die Antwort.
Wenn ich mich nicht verrechnet habe sind
1,2MHz    1 clk  0,000000833s  ~0,83µs

prescale 64

1,2MHz / 64   1 clk  0,000053333s  ~53µs  ~0,053ms

Den Timer setze ich bei steigender Flanke auf null, weil ich die Länge 
des Impulses messen möchte. Bei der Funke von 0,7ms minimum bis 2,3ms 
maximum
Liegt der puls dazwischen ist er gültig. Dann LED an.


__|TCCR0=0 ----|__lesen TCCR0 für die Länge

Vielleicht bin ich ja betriebsblind. habe ich etwas übersehen oder einen 
Denkfehler ??


Habe das gleiche Register zum Sichern gewählt, weil ja der Puls 
unterschiedlich lang sein kann. Vor verlassen der jeweiligen Routine 
wird SREG ja wieder restauriert.


Grüße

Jürgen

von fubu1000 (Gast)


Lesenswert?

Hallo,
du dec in der Schleife Timer3 der nit gesetzt ist, müsste wohl eher 
Timer2 sein.


wait_70ms:
; =============================
;    delay loop generator
;     84000 cycles:
; -----------------------------
; delaying 83997 cycles:
          ldi  Timer1, $99
WGLOOP4:  ldi  Timer2, $B6
WGLOOP5:  dec  Timer3               <--------------- Fehler
          brne WGLOOP5
          dec  Timer1
          brne WGLOOP4
; -----------------------------
; delaying 3 cycles:
          ldi  Timer1, $01
WGLOOP6:  dec  Timer1
          brne WGLOOP6
      ret
; =============================


GRUSS fubu

von Jürgen K. (jk2010)


Lesenswert?

Hi Fubu !

Dank Dir, Du hast recht, ist wohl beim tippern verunglückt.

Gruß

Jürgen

von Fred S. (Gast)


Lesenswert?

Hallo Jürgen,

Deine TimerTic-Länge stimmt, ich habe mich versehen.

Aber:
> __|TCCR0=0 ----|__lesen TCCR0 für die Länge
Was Du damit meinst, verstehe ich nicht.

Du springst aus Deinem INT0-Handler, wo Du TCNT0 auf 0 gesetzt hast, 
nach FALLING_EDGE, wo Du TCNT0 nach "puls" einlesen willst (falsche 
Syntax!). Dann wertest Du "puls" aus. "puls" ist dann aber höchsten 
eins!

Ich bin nicht sicher, ob Du nicht ein grundsätzliches Problem mit dem 
Verständnis der Syntax hast; Du verwechselst mehrmals in mit ldi 
usw.

Gruß

Fred

von Jürgen K. (jk2010)


Lesenswert?

Hi !

Also, wie beschrieben, mein erstes Assemblerprogramm seit der Steinzeit.
ldi ist für Register R16-R31 load immediately.
in bzw. out für SFR Register. Liege ich da richtig?

Fällt mir noch ein bisschen schwer, der Wiedereinstieg.


Deshalb, Danke für Euer Engagement.

Grüße und schönen Sonntag vom

Käfersuchenden

Jürgen


@fred:   wenn die steigende Flanke kümmt, TCNT0=0
         wenn fallende, Impuls ende, TCNT0 auslesen

zulässiger Bereich 0,7 bis 2,3 ms

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.