Forum: Mikrocontroller und Digitale Elektronik mit kurzen Impulsen schalten / gegenseitig entriegeln / Attiny2313


von Wilhelm H. (gustav0815)


Lesenswert?

Hallo,

ich habe hier eine kleine Schaltung mit dem Attiny 2313.
Genauer gesagt handelt es sich um die 8 Kanal IR Fernbedienungsschaltung 
von Pollin (v1.1).

Nachdem ich den Attiny 2313 gewechselt und mit einer modifzierten 
Quellcode beschrieben habe, was auch soweit funktioniert, steh ich aber 
noch vor einem Problem.

die Frage ist:

Wie kann ich es anstellen, dass wenn ich Taste 1 drücke - Relais 1 zieht 
und gezogen bleibt bis ich zB. Taste 3 oder 2 oder 8 usw. drücke und 
dann das entsprechende Relais der zuletzt gedrückten Taste gezogen 
bleibt während das von Taste 1 wieder abfällt. (es muß also beliebig 
schaltbar sein, unabhängig von der Reihenfolge der jeweils gedrückten 
Tasten)

Ich möchte also keinen Toggelbetrieb oder Repeatbetrieb und auch keinen 
Impulsbetrieb (wie er derzeit in der schaltparameter.inc eingestellt 
ist)sondern sich gegenseitig entriegelnde Ausgänge an PortB.

Da ich zugegebenermassen ein blutiger Anfänger in Sachen AVR bin, 
bräuchte ich hier wirklich weiterführende Hilfe in Form von konkreten 
Lösungsansätzen.

Die Frage ist, läßt sich das ohne Weiteres mit der Software lösen oder 
brauchts dafür eine Zusatzbeschaltung an den Ports ala FlipFlop oä und 
wenn ja, wie müßte das aussehen.

Vieleicht habt ihr ja einen Schaltungsvorschlag bzw. einen Vorschlag wie 
der Quellcode zu ändern ist, würde mich freuen.

achja, ich benutze das AVR Studio 4 (Freeversion) und einen Multiprog 
2003XXL in Verbindung mit PonyProg V.2.0.7

von Einer (Gast)


Lesenswert?

PORTB ^= BitMask;
ersetzen durch
PORTB = BitMask;

BitMask = 0;
entfernen

von Wilhelm H. (gustav0815)


Lesenswert?

für jemanden der sich auskennt sicher eine hilfreiche Antwort.
Im Moment kann ich damit nicht wirklich viel anfangen.

Ich kann in den vorhandenen Dateien diesen Eintrag nicht finden.

ich hab ne *.hex, eine *.asm, die deklara.inc und die 
schaltparameter.inc

wie gesagt, ich bin momentan noch nicht auf dem Wissenstand um solche 
kurzen Antworten ohne größere Erklärung wirklich auswerten zu können - 
aber ich bemüh mich....

von Willi (Gast)


Lesenswert?

du setzt einfach bei jeder Taste das gesamte Byte, z.B

PORTB = 0b00000001  //für Taste "0" alle anderen Bit's werden "0"
PORTB = 0b00000010  // Taste "1"
.
.
.
PORTB = 0b10000000  // Taste "7"

von oldmax (Gast)


Lesenswert?

Hi
Na ja, dann will auch ich mal einen konkreten Lösungsansatz schreiben:
Du kaufst zusätzlich ein Relais und eine Diode. Auch einen Transistor. 
Die Schaltung findest du sicherlich in irgendeinem Tutorial. Dann nimmst 
du dein modifiziertes Programm und setzt das Port-Bit, wenn du eine 
Taste drückst. Drückst du eine andere, dann löscht du das Portbit. Ist 
doch ganz einfach. Und in Zeile 48 mußt du aufpassen, das die 
freigesetzten Elektronen nicht den Worbantrieb stören oder den 
Fluxkompensator auslösen.
Mal im Ernst, du schreibst uns, das du bei Pollin etwas gekauft hast. 
Das ist schön, für Pollin, denn damit verdient er sein Geld und für 
dich, denn nun hast du was zum basteln. Dann schreibst du uns, das du 
das Programm modifiziert hast. Auch das ist schön für dich, dabei hast 
du sicherlich etwas gelernt. Aber dann die Aufforderung an uns, konkrete 
Lösungsansätze zu liefern ist schon fast unverfroren. Wenn du mal Zeit 
hast, dann besuch mich, setz dich vor meinen PC und beantworte deinen 
Thread. Wenn du Hilfe willst, dann ist es schon wichtig, Informationen 
zu liefern. z.B. in welcher Sprache du zuhause bist und wie weit deine 
Kenntnisse um die Hardware reichen. Auch nicht schlecht ist ein 
Quellcode, wenn du schon etwas modifiziert hast, damit man dann gezielt 
ansetzen kann.
Gruß oldmax

von oldmax (Gast)


Lesenswert?

Ach ja, das muß ich noch los werden. Erwarte nicht, das wir uns nun alle 
bei Pollin diese Fernsteuerung kaufen und diese studieren, damit wir dir 
sagen, wie du damit Relais schaltest. Wie bereits gesagt, du willst 
etwas damit machen und da ist es an dir auch die erforderliche 
Information ´zu liefern, wenn du Hilfe brauchst. So wie es aussieht, 
gibt es ein Assemblerlisting. Das ist die Datei mit der Endung ".ASM" 
Schau dir diese erst einmal im AVR Studio an und suche die Stellen, wo 
du die Ports einliest (In <Register>, <Port>). Das wär dann schon mal 
ein Hinweis, wo deine Tastenwerte landen. Vielleicht hast du glück, und 
du findest einen Ausgang für eine LED bspw. (Out <Port>, <Register>)
Nun ist es dann angebracht, sich hier in die Tutorials einzulesen. Da 
gibt es dann sicherlich Hinweise, die du ausprobieren kannst.
Gruß oldmax

von Wilhelm H. (gustav0815)


Lesenswert?

@oldmax

zunächstmal war die Frage nicht wie ein Relais mit nem Tiny angesteuert 
werden kann, denn soweit reichen meine Kenntnisse.
µC ist für mich allerdings Neuland.

Der Satz das konkrete Lösungsansätze gewünscht sind bezieht sich 
vornehmlich auf genau solche Kommentare oder besser gesagt auf die 
Vermeidung Selbiger, wie du sie hier abgegeben hast.
Ich wende mich an die User in einem Forum weil ich Hilfe brauche und auf 
die Erfahrung dieser Leute setze und nicht weil ich dumm angesülzt 
werden will.

In einer "Sprache" bin ich momentan noch garnicht zu Hause, da wie schon 
erwähnt, diese Materie Neuland für mich ist.

Soweit zu deinem ersten Kommentar.

Der Zweite war da schon etwas hilfreicher.
Um weitere Infos zu liefern - und mit dem Vorschlag hast du durchaus 
recht - hier die org. Assembler Datei.
1
*/
2
.include "tn2313def.inc"    ;Namen benannter Bytes und Bits bekannt machen
3
.include "deklara.inc"      ;Konstanten und Variablen
4
5
;Beginn des Programmspeichers, reservierte Adressen für Reset und Interrupts:
6
.cseg               ;Programmspeicher
7
.org 0              ;ab Adresse 0
8
 rjmp RESET         ;Reset Handler
9
 rjmp exti0         ;External Interrupt0 Handler
10
 rjmp nix;INT1          ;External Interrupt1 Handler
11
 rjmp nix;TIM1_CAPT     ;Timer1 Capture Handler
12
 rjmp TIM1_COMPA    ;Timer1 CompareA Handler
13
 rjmp nix;TIM1_OVF      ;Timer1 Overflow Handler
14
 rjmp nix;TIM0_OVF      ;Timer0 Overflow Handler
15
 rjmp nix;USART0_RXC    ;USART0 RX Complete Handler
16
 rjmp nix;USART0_DRE    ;USART0,UDR Empty Handler
17
 rjmp nix;USART0_TXC    ;USART0 TX Complete Handler
18
 rjmp nix;ANA_COMP      ;Analog Comparator Handler
19
 rjmp nix;PCINT         ;Pin Change Interrupt
20
 rjmp TIM1_COMPB    ;Timer1 Compare B Handler
21
 rjmp nix;TIMER0_COMPA  ;Timer0 Compare A Handler
22
 rjmp nix;TIMER0_COMPB  ;Timer0 Compare B Handler
23
 rjmp nix;USI_START     ;USI Start Handler
24
 rjmp nix;USI_OVERFLOW  ;USI Overflow Handler
25
 rjmp nix;EE_READY      ;EEPROM Ready Handler
26
 rjmp nix;WDT_OVERFLOW  ;Watchdog Overflow Handler
27
28
nix:                    ;eine Falle für unerlaubte Interrupts (Prog-Fehler)
29
 rjmp nix                   ;Falle...
30
; reti                       ;zurück...
31
32
reset:                  ;Initialisierung
33
 clr null                   ;immer 0
34
 ldi wl,1<<clkpce           ;Schreibschutz Taktvorteiler
35
 out clkpr,wl               ;aufheben
36
 out clkpr,null             ;Teilerfaktor 
37
 out clkpr,null             ;1 zu 1
38
 nop                        ;Zeit zum Einschwingen geben
39
 ldi wl,low(ramend)         ;Stackpointer
40
 out spl,wl                 ;initialisieren
41
 clr flags
42
 ;Ports
43
 ldi wl,$ff                 ;alle Pins von
44
 out porta,null             ;L-Pegel an PortA
45
 out portb,null             ;L-Pegel an PortB
46
 out ddra,wl                ;PortA als Ausgang
47
 out ddrb,wl                ;PortB als Ausgang
48
 ldi wl,0b00000111          ;an PortD TXD auf H, Pullup RXD
49
 out portd,wl               ;und Int0 ein
50
 ldi wl,0b11111010          ;PortD alles außer RXD und Int0
51
 out ddrd,wl                ;als Ausgang
52
 ;UART
53
 ldi wl,low(ubr)            ;Baudrate
54
 out ubrrl,wl               ;für
55
 ldi wl,high(ubr)           ;UART
56
 out ubrrh,wl               ;einstellen
57
 ldi wl,1<<txen             ;UART-Senden (TX)
58
 out ucsrb,wl               ;aktivieren
59
 ldi wl,(1<<ucsz1)|(1<<ucsz0)|(1<<usbs) ;8-Bit-Mode
60
 out ucsrc,wl               ;und 2 Stoppbits einstellen
61
 ;ext.Interrupt 0 und Sleep
62
 ldi wl,extib               ;beide Flanken für Int0 einstellen
63
 out mcucr,wl               ;und Sleep-Mode IDLE vorwählen
64
 ldi wl,1<<int0             ;Int0
65
 out gimsk,wl               ;freigeben
66
 ;Timer
67
 ldi wl,low(intervalla)     ;ersten
68
 ldi wh,high(intervalla)    ;Compare1A-Interrupt
69
 out ocr1ah,wh              ;auf 10 ms
70
 out ocr1al,wl              ;terminieren
71
 ldi wl,4                   ;Timer 1 mit Vorteiler 1:256
72
 out tccr1b,wl              ;einschalten (32 µs je Zahlenwert)
73
 ldi wl,ocbein              ;beide Comp1-Int
74
 out timsk,wl               ;freigeben
75
 ;divers
76
 ldi xl,low(teltout+1)      ;Pointer hinter das Ende
77
 ldi xh,high(teltout+1)     ;der Timeout-Zähler
78
reset1: ;Loop
79
 st -x,null                 ;RAM für Timeout-Zähler und TX-Puffer löschen
80
 cpi xl,txbuffer            ;Anfang erreicht?
81
 brne reset1                ;nein, nochmal...
82
 sts lepo,xl                ;Lesepointer setzen
83
 sei                        ;Interrupts freigeben
84
85
86
mainloop:           ;Hauptschleife
87
 lds yl,lepo                ;Lesepointer holen
88
 cp xl,yl                   ;Enthält TX-Puffer Daten?
89
 breq mainloop1             ;nein, weiter...
90
 rcall job_sendbyte         ;ja, senden...
91
mainloop1:
92
 sbrc flags,neubyte         ;neues Telegramm eingetroffen?
93
 rjmp job_neues_byte        ;ja, abarbeiten...
94
 sbrc flags,neu10ms         ;sind 10 Millisekunde vergangen? - nein...
95
 rjmp job_10ms              ;ja, abarbeiten...
96
 sleep                      ;CPU-Takt bis zum nächsten Interrupt aus
97
 rjmp mainloop              ;nochmal...
98
99
100
job_sendbyte:       ;Job der Mainloop, sendet ein Byte per UART
101
 sbis ucsra,udre            ;ist UART busy? - nein...
102
 ret                        ;ja, fertig, später noch mal probieren...
103
 clr yh                     ;RAM liegt in Page 0
104
 ld wl,y+                   ;Byte aus Puffer lesen
105
 out udr,wl                 ;und versenden
106
 sbrs yl,5                  ;Puffer-Ende erreicht? - nein...
107
 ldi yl,txbuffer            ;ja, Pointer auf Anfang setzen
108
 sts lepo,yl                ;Pufferpointer wieder sichern
109
 ret                        ;fertig...
110
111
112
job_10ms:           ;Job der Mainloop, Aufruf alle 10 Millisekunden
113
 cbr flags,1<<neu10ms       ;Jobauftrag entwerten
114
 ;erstmal Telegramm-TimeOut managen
115
 lds wl,teltout             ;Telegramm-Timeout holen,
116
 tst wl                     ;schon abgelaufen?
117
 breq job_10ms1             ;ja, nicht behandeln
118
 dec wl                     ;nein, herunterzählen und
119
 sts teltout,wl             ;wieder sichern
120
 brne job_10ms1             ;jetzt abgelaufen? - nein...
121
 cbr flags,1<<adress        ;weitere Bytes als ungültig markieren
122
job_10ms1:      ;Ausgänge abschalten
123
 ldi yl,low(toz)            ;Pointer auf Timeout-Zähler
124
 ldi yh,high(toz)           ;im SRAM
125
 ldi zl,low(bimu*2)         ;Pointer auf Bitmustertabelle
126
 ldi zh,high(bimu*2)        ;im Flash
127
job_10ms1a:
128
 ld wl,y                    ;TimeOut-Zähler holen
129
 tst wl                     ;TimeOut aktiv?
130
 breq job_10ms1b            ;nein...
131
 dec wl                     ;herunterzählen
132
 st y,wl                    ;und sichern
133
 brne job_10ms1b            ;abgelaufen? - nein...
134
 adiw zh:zl,3               ;Tastencode, Mode und Schaltzeit überspringen
135
 lpm r0,z+                  ;Bitmuster PortA holen
136
 com r0                     ;und invertieren
137
 in r1,porta                ;zu ändernden Port einlesen
138
 and r1,r0                  ;Bit löschen
139
 out porta,r1               ;und zurückschreiben
140
 lpm r0,z+                  ;Bitmuster PortB holen
141
 com r0                     ;und invertieren
142
 in r1,portb                ;zu ändernden Port einlesen
143
 and r1,r0                  ;Bit löschen
144
 out portb,r1               ;und zurückschreiben
145
 lpm r0,z+                  ;Bitmuster PortD holen
146
 com r0                     ;und invertieren
147
 in r1,portd                ;zu ändernden Port einlesen
148
 and r1,r0                  ;Bit löschen
149
 out portd,r1               ;und zurückschreiben
150
 sbiw zh:zl,6               ;Pointer korrigieren
151
job_10ms1b:
152
 adiw zh:zl,6               ;Flash-Pointer auf nächsten Datensatz
153
 adiw yh:yl,1               ;SRAM-Pointer auf nächsten Timeout-Zähler
154
 cpi zl,low(endbimu*2)      ;letzter Datensatz fertig?
155
 brne job_10ms1a            ;ja, nochmal...
156
 rjmp mainloop              ;fertig...
157
158
159
job_neues_byte:     ;es ist ein neues Byte eingetroffen
160
 cbr flags,1<<neubyte       ;Jobflag entwerten
161
 ldi yl,low(toz-1)          ;Pointer vor Timeout-Zähler
162
 ldi yh,high(toz-1)         ;im SRAM
163
 ldi zl,low(bimu*2-5)       ;Pointer 5 vor Bitmustertabelle
164
 ldi zh,high(bimu*2-5)      ;im Flash
165
 lds wl,cmd                 ;Byte holen
166
 bst wl,repeat              ;Repeat-Bit sichern
167
 andi wl,63                 ;und löschen
168
job_neues_byte1:
169
 adiw zh:zl,5               ;Bitmusterbytes kompensieren
170
 adiw yh:yl,1               ;Timeout-Index mitzählen
171
 cpi zl,low(endbimu*2)      ;letzter Datensatz fertig?
172
 breq job_neues_byte_e      ;ja, Abbruch, Code nicht gefunden...
173
 lpm r0,z+                  ;Tastencode aus Tabelle holen
174
 cp r0,wl                   ;identisch?
175
 brne job_neues_byte1       ;nein, nächsten Datensatz prüfen
176
 ;Tastencode wurde in Tabelle gefunden
177
 lpm wh,z+                  ;Mode-Bits holen
178
 lpm wl,z+                  ;Schaltzeit holen
179
 lpm r0,z+                  ;Bitmuster PortA holen
180
 sbrs wh,toggel             ;hat dieser Portpin Toggelmode? - ja...
181
 rjmp job_neues_byte2       ;nein, weiter...
182
 ;dieser Schaltbefehl hat Toggelmode
183
 brts job_neues_byte_e      ;ja, Repeat-Bit im empfangenen Byte? - ja...
184
 ;es ist das erste Byte des Telegramms
185
 in r1,porta                ;Port einlesen,
186
 eor r1,r0                  ;Bit toggeln
187
 out porta,r1               ;und zurückschreiben
188
 lpm r0,z+                  ;Bitmuster PortB holen
189
 in r1,portb                ;Port einlesen,
190
 eor r1,r0                  ;Bit toggeln
191
 out portb,r1               ;und zurückschreiben
192
 lpm r0,z+                  ;Bitmuster PortD holen
193
 in r1,portd                ;Port einlesen,
194
 eor r1,r0                  ;Bit toggeln
195
 out portd,r1               ;und zurückschreiben
196
 rjmp job_neues_byte_e      ;fertig...
197
job_neues_byte2:    ;es war kein Toggel-Mode
198
 sbrs wh,repeat             ;Repeat-Bit in Tabelle gesetzt? - ja...
199
 brts job_neues_byte_e      ;nein, Repeat-Bit im empfangenen Byte? - ja...
200
 sbrc wh,nuraus             ;soll nur ausgeschaltet werden? - nein...
201
 rjmp job_neues_byte3       ;ja, Porteinschalten überspringen...
202
 in r1,porta                ;Port einlesen,
203
 or r1,r0                   ;Bit setzen
204
 out porta,r1               ;und zurückschreiben
205
 lpm r0,z+                  ;Bitmuster PortB holen
206
 in r1,portb                ;Port einlesen,
207
 or r1,r0                   ;Bit setzen
208
 out portb,r1               ;und zurückschreiben
209
 lpm r0,z+                  ;Bitmuster PortD holen
210
 in r1,portd                ;Port einlesen,
211
 or r1,r0                   ;Bit setzen
212
 out portd,r1               ;und zurückschreiben
213
job_neues_byte3:
214
 st y,wl                    ;Schaltzeit setzen
215
job_neues_byte_e:
216
 rjmp mainloop              ;fertig...
217
218
219
exti0:              ;ISR, externer Interrupt, Impuls vom TSOP1736
220
 in srsk,sreg               ;PSW sichern
221
 in it3,tcnt1l              ;Zeitstempel
222
 in it4,tcnt1h              ;holen
223
 mov it1,it3                ;und
224
 mov it2,it4                ;kopieren
225
 sub it1,zsl                ;Impulsbreite (Differenz neu-alt)
226
 sbc it2,zsh                ;berechnen
227
 mov ibl,it1                ;und
228
 mov ibh,it2                ;sichern
229
 mov zsl,it3                ;Zeitstempel dieses Interrupts
230
 mov zsh,it4                ;als Impulsbeginn merken
231
 cpi status,17              ;relevanter Teil das Telegramms fertig?
232
 brlo exti00                ;nein, weiter...
233
 rjmp exti0_15plus          ;ja, separat behandeln...
234
exti00:         ;Telegramm ist noch nicht fertig
235
 cpi status,3               ;ist Pre-Signal und Startbit schon durch?
236
 brsh exti01                ;ja, weiter...
237
 rjmp exti0_pre             ;nein, separat behandeln...
238
exti01:         ;Telegramm ist im Datenbitbereich
239
 tst it2                    ;viel zu lange Impulsdauer?
240
 brne exti00e               ;ja, Error...
241
 cpi it1,iblimitu           ;Impulsdauer zu kurz?
242
 brlo exti00e               ;ja, Error...
243
 cpi it1,iblimito           ;Impulsdauer zu lang?
244
 brlo exti02                ;nein, es war ein gültiger kurzer Impuls
245
 cpi it1,iblimitu*2         ;doppelte Impulsdauer zu kurz?
246
 brlo exti00e               ;ja, Error...
247
 cpi it1,iblimito*2         ;doppelte Impulsdauer zu lang?
248
 brlo exti03                ;nein, es war ein gültiger langer Impuls
249
exti00e:
250
 rjmp exti0_err             ;Fehler...
251
exti02:         ;kurzen Impuls empfangen
252
 sbrc status,1              ;ist Status ungeradzahlig? - ja...
253
 rjmp exti0es1              ;nein, nicht shiften, Status erhöhen und fertig...
254
 lsr shiftreg               ;Bits weitershiften
255
 sbrs flags,bit             ;ist Bitwert=1? - nein...
256
 sbr shiftreg,32            ;ja, Shiftbit setzen
257
 rjmp exti0es1              ;Status erhöhen und fertig...
258
exti03:         ;langen Impuls empfangen
259
 ldi it2,1<<bit             ;Bitwert
260
 eor flags,it2              ;toggeln
261
 lsr shiftreg               ;Bits weitershiften
262
 sbrs flags,bit             ;ist Bitwert=1? - nein...
263
 sbr shiftreg,32            ;ja, Shiftbit setzen
264
 rjmp exti0es2              ;Status doppelt erhöhen und fertig...
265
exti0_pre:      ;vor dem Datenbitbereich
266
 cpi status,0               ;Wartephase auf das Pre-Signal?
267
 brne exti0_pre1            ;nein, weiter...
268
 ;Bereitschaft, es wurde noch kein Bit empfangen, Beginn des Pre-Signals
269
 sbic pind,irbit            ;ist jetzt L-Pegel geworden? - ja...
270
 rjmp exti0_err             ;nein, Fehler...
271
 sbrc flags,akt             ;Empfang schon aktiv? - nein...
272
 rjmp exti0_err             ;ja, Fehler...
273
exti0_pre0:
274
 ;Pause war groß genug, es ist Impulsbeginn (L-aktive Impulse)
275
 sbr flags,1<<akt           ;Telegrammempfang als aktiv markieren
276
 sbi ledport,ledbit
277
 rjmp exti0es1              ;Status erhöhen und fertig...
278
exti0_pre1:
279
 cpi status,1               ;Ende Pre-Signal?
280
 brne exti0_pre1a           ;nein, weiter...
281
 ;Impulsende des Pre-Signals
282
 cbi ledport,ledbit         ;Busy-LED aus
283
 ldi it1,77                 ;Pre-Pause
284
 add zsl,it1                ;alten Zeitstempel um 4 Impulsbreiten
285
 adc zsh,null               ;vordatieren (Pre-Pause kompensieren)
286
 mov it1,ibl                ;akt. Zeitstempel 
287
exti0_pre1a:    ;Einsprung aus 2 und 3
288
 cpi it2,0                  ;Impulsbreite viel zu groß?
289
 brne exti0_pre1b           ;ja...
290
 cpi it1,iblimito           ;Impulsbreite zu groß?
291
 brsh exti0_pre1b           ;ja...
292
 cpi it1,iblimitu           ;Impulsbreite zu klein?
293
 brlo exti0_pre1b           ;ja...
294
 rjmp exti0_pre1c           ;nein, Impulsbreite ok...
295
exti0_pre1b:    ;Impulsbreite fehlerhaft
296
 rjmp exti0_err             ;
297
exti0_pre1c:    ;Impulsbreite Pre-Signal ist ok
298
 sbr flags,1<<bit           ;mit Einsbit beginnen
299
 rjmp exti0es1              ;Status erhöhen und fertig...
300
exti0_15plus:   ;es wurden bereits mehr als 6 Bits eingesammelt
301
 cbr status,64              ;Überlauf verhindern
302
exti0_15plus1:
303
 rjmp exti0e                ;fertig...
304
exti0_err:      ;Error Impulsbreite
305
 sbr status,32              ;Error-Bit setzen
306
 rjmp exti0es1              ;weiter...
307
exti0es2:       ;Ende langer Impuls (Status um 2 erhöhen)
308
 inc status                 ;Status erhöhen
309
exti0es1:       ;Ende kurzer Impuls (Status um 1 erhöhen)
310
 inc status                 ;Status erhöhen
311
 ldi it1,low(iblimito*25)    ;Byte-Timeout
312
 ldi it2,high(iblimito*25)   ;auf
313
 add it1,zsl                ;jetzt
314
 adc it2,zsh                ;plus
315
 out ocr1bh,it2             ;6 Impulslimits
316
 out ocr1bl,it1             ;setzen
317
 ldi it2,telzeit            ;Telegramm-TimeOut
318
 sts teltout,it2            ;auf Startwert setzen
319
exti0e:         ;Ende ohne Statusänderung
320
 out sreg,srsk              ;PSW wiederherstellen
321
 reti                       ;fertig...
322
323
324
tim1_compa:         ;ISR, Timer1 CompareA, Zeitbasis 10 ms
325
 in srsk,sreg               ;PSW sichern
326
 sbr flags,1<<neu10ms       ;Job 10ms anmelden
327
 in it1,ocr1al              ;Auslösetermin dieses
328
 in it2,ocr1ah              ;Interrupts holen
329
 subi it1,low(-intervalla)  ;Intervall für 10 ms
330
 sbci it2,high(-intervalla) ;aufaddieren
331
 out ocr1ah,it2             ;als Termin für nächsten
332
 out ocr1al,it1             ;Interrupt setzen
333
 out sreg,srsk              ;PSW wiederherstellen
334
 reti                       ;fertig...
335
336
337
tim1_compb:         ;ISR, Timer1 CompareB, Telegramm-Bit-Timeout
338
 in srsk,sreg               ;PSW sichern
339
 cbr flags,1<<akt           ;Byte-Empfang als beendet markieren
340
 cpi status,15              ;erlaubte Anzahl Bits empfangen?
341
 breq tim1_compb1           ;ja, Telegramm ist ok...
342
 cpi status,16              ;erlaubte Anzahl Bits empfangen?
343
 breq tim1_compb1           ;ja, Telegramm ist ok...
344
 rjmp tim1_compb_e          ;nein, Telegramm verwerfen...
345
tim1_compb1:
346
 sbrs flags,adress          ;ist die Startkennung schon durch? - ja...
347
 rjmp checkadress           ;nein, weiter
348
 ;Adresse (Startbyte) wurde bereits empfangen
349
 cpi shiftreg,62            ;war es das Stoppbyte?
350
 brne tim1_compb2           ;nein...
351
 cbr flags,1<<adress        ;ja, eventuelle Restbytes entwerten
352
 ldi shiftreg,255           ;Merkbytes der Entprellung und Repeaterkennung 
353
 rjmp tim1_compb5           ;entwerten...
354
tim1_compb2: 
355
 cp shiftreg,alt            ;wurde dieses Byte bereits empfangen?
356
 brne tim1_compb5           ;nein, Bytes nachrücken lassen und Ende...
357
 clr it1                    ;ja, Bits und Wiederhol-Kennung erstmal löschen
358
 cp shiftreg,uralt          ;wurde dieses Byte bereits mehrfach empfangen?
359
 brne tim1_compb3           ;nein, noch nicht...
360
 sbr it1,1<<repeat          ;ja, Wiederhol-Kennung setzen
361
tim1_compb3:
362
 or it1,shiftreg            ;Nutzbyte zur Repeatkennung kopieren
363
 sts cmd,it1                ;Nutzbyte sichern
364
 sbr flags,1<<neubyte       ;und anmelden
365
 st x+,it1                  ;Nutzbyte in den Sendepuffer
366
 sbrs xl,5                  ;Puffer-Ende erreicht? - nein...
367
 ldi xl,txbuffer            ;ja, Pointer auf Anfang setzen
368
 rjmp tim1_compb5           ;Bytes nachrücken lassen und Ende...
369
checkadress:    ;Telegramm auf Startbyte prüfen
370
 cpi shiftreg,62            ;Startbyte?
371
 brne tim1_compb_e          ;nein, Byte verwerfen...
372
 ;Byte war ein gültiges Startbyte
373
 sbr flags,1<<adress        ;Telegramm als gültig markieren
374
 rjmp tim1_compb_e          ;fertig...
375
tim1_compb5:    ;Byte war ein Nutzbyte
376
 mov uralt,alt              ;Bytewerte
377
 mov alt,shiftreg           ;nachrücken lassen
378
 clr shiftreg               ;
379
tim1_compb_e:   ;Ende
380
 clr status                 ;Bitzähler von vorn beginnen
381
 out sreg,srsk              ;PSW wiederherstellen
382
 reti                       ;fertig...
383
384
bimu:   ;Bitmuster für Portpins
385
.include "schaltparameter.inc"  ;Datei mit Daten zum Schaltverhalten
386
endbimu:


und hier noch die schaltparameter.inc :
1
*/
2
;Taste,Mode,Zeit,A,  B,  D
3
.db 17,imp, 10,  0,  1,  0  ;Taste 1        PB0 Impuls 100 ms
4
.db 18,imp, 10,  0,  2,  0  ;Taste 2        PB1 Impuls 100 ms
5
.db 19,imp, 10,  0,  4,  0  ;Taste 3        PB2 Impuls 100 ms
6
.db 20,imp, 10,  0,  8,  0  ;Taste 4        PB3 Impuls 100 ms
7
.db 21,imp, 10,  0, 16,  0  ;Taste 5        PB4 Impuls 100 ms
8
.db 22,imp, 10,  0, 32,  0  ;Taste 6        PB5 Impuls 100 ms
9
.db 23,rep, 10,  0, 64,  0  ;Taste 7        PB6 Tastendruckdauer + 100 ms
10
.db 24,rep, 10,  0,128,  0  ;Taste 8        PB7 Tastendruckdauer + 100 ms
11
.db 25,tog,  0,  0,  0,  8  ;Taste 9        PD3 Toggelmodus
12
.db 16,tog,  0,  0,  0, 16  ;Taste 0        PD4 Toggelmodus
13
.db 26,tog,  0,  0,  0, 64  ;Taste 1...     PD6 Toggelmodus
14
.db 27,tog,  0,  2,  0,  0  ;Taste 2...     PA1 Toggelmodus
15
.db  2,aus,  1,  2,255, 88  ;Taste OFF      alles nach 10 ms aus
16
.db  5,tog,  0,  2,  0, 88  ;Taste P/C      Toggelpins toggeln
17
.db 11,aus,  1,  0,  1,  0  ;Taste H-       PB0 in 10 ms ausschalten
18
.db 10,imp,  0,  0,  1,  0  ;Taste H+       PB0 dauerhaft einschalten
19
20
/*


in dieser Schaltparameter.inc gehts um die ersten 6 Ports PB0-PB5

von oldmax (Gast)


Lesenswert?

Hi
Und jetzt erwartest du, das ich mir die Zeit nehme, den Code bearbeite 
und dir genau sage, wo du ansetzen sollst. Dazu nochmal ein Zitat:
>und auf die Erfahrung dieser Leute setze und nicht weil ich dumm >angesülzt 
werden will.

Warum wirst du denn dumm angesülzt ? Es ist die Art, wie du hier im 
Forum auftrittst. Du willst Hilfe, nicht ich oder ein anderer 
hilfsbereiter Experte. Und so solltest du ein wenig dem folgen, was dir 
emfohlen wird. Auch dazu ein Zitat:
>Schau dir diese erst einmal im AVR Studio an und suche die Stellen, wo
>du die Ports einliest (In <Register>, <Port>). Das wär dann schon mal
>ein Hinweis, wo deine Tastenwerte landen.
Was machst du ? Du stellst hier den kompletten Code rein so nach dem 
Motto: "Sucht mal fleißig"
Der Code ist doch prima kommentiert. Lesen und verstehen ist dein Bier, 
nicht meines.
trotzdem, eine kleine Hilfe geb ich dir mal:
1
.cseg               ;Programmspeicher
2
.org 0              ;ab Adresse 0
3
 rjmp RESET         ;Reset Handler
4
 rjmp exti0         ;External Interrupt0 Handler
5
 rjmp nix;INT1          ;External Interrupt1 Handler
6
 rjmp nix;TIM1_CAPT     ;Timer1 Capture Handler
7
 rjmp TIM1_COMPA    ;Timer1 CompareA Handler
8
 rjmp nix;TIM1_OVF      ;Timer1 Overflow Handler
9
 rjmp nix;TIM0_OVF      ;Timer0 Overflow Handler
10
 rjmp nix;USART0_RXC    ;USART0 RX Complete Handler
11
 rjmp nix;USART0_DRE    ;USART0,UDR Empty Handler
12
 rjmp nix;USART0_TXC    ;USART0 TX Complete Handler
13
 rjmp nix;ANA_COMP      ;Analog Comparator Handler
14
 rjmp nix;PCINT         ;Pin Change Interrupt
15
 rjmp TIM1_COMPB    ;Timer1 Compare B Handler
16
 rjmp nix;TIMER0_COMPA  ;Timer0 Compare A Handler
17
 rjmp nix;TIMER0_COMPB  ;Timer0 Compare B Handler
18
 rjmp nix;USI_START     ;USI Start Handler
19
 rjmp nix;USI_OVERFLOW  ;USI Overflow Handler
20
 rjmp nix;EE_READY      ;EEPROM Ready Handler
21
 rjmp nix;WDT_OVERFLOW  ;Watchdog Overflow Handler
22
23
nix:                    ;eine Falle für unerlaubte Interrupts (Prog-Fehler)
24
 rjmp nix                   ;Falle...
25
; reti                       ;zurück...

Überall, wo "rjmp nix" steht, ist ein Interrupt, der nicht vorgesehen 
ist und der den Controller in einen "unbedienbaren Zustand" setzt. 
Eigentlich kannst du das auch gleich vergessen, denn dich interessieren 
andere Interrupts, z.B. "rjmp exti0". Dieser Interrupt taucht auf, wenn 
eine Taste betätigt wird und du landest bei:
1
exti0:              ;ISR, externer Interrupt, Impuls vom TSOP1736
2
 in srsk,sreg               ;PSW sichern
3
 in it3,tcnt1l              ;Zeitstempel
4
 in it4,tcnt1h              ;holen
5
 mov it1,it3                ;und
6
 mov it2,it4                ;kopieren
7
 sub it1,zsl                ;Impulsbreite (Differenz neu-alt)
8
 sbc it2,zsh                ;berechnen
9
 mov ibl,it1                ;und
10
 mov ibh,it2                ;sichern
11
 mov zsl,it3                ;Zeitstempel dieses Interrupts
12
 mov zsh,it4                ;als Impulsbeginn merken
13
 cpi status,17              ;relevanter Teil das Telegramms fertig?
14
 brlo exti00                ;nein, weiter...
15
 rjmp exti0_15plus          ;ja, separat behandeln...
16
exti00:         ;Telegramm ist noch nicht fertig
17
; usw

So, nun kannst du dich auch mal selbst ein wenig mit dem Programm 
auseinander setzen. Interessant ist vielleicht noch die Initialisierung, 
u. A.
1
 ldi wl,$ff                 ;alle Pins von
2
 out porta,null             ;L-Pegel an PortA
3
 out portb,null             ;L-Pegel an PortB
4
 out ddra,wl                ;PortA als Ausgang
5
 out ddrb,wl                ;PortB als Ausgang
Für eine Ausgabe an ein Relais suchst du dir einen freien Portpinvon 
Port a oder B. Ach ja, da hilft ein Blick in das Datenblatt, falls du es 
noch nicht hast.  Kannst du über Google finden.
So, mehr Zeit hab ich erst mal nicht.
Gruß oldmax

von Karl H. (kbuchegg)


Lesenswert?

Wie geht man beispielsweise vor?

Erst mal, und das ist ganz wichtig, keine Angst.
Repekt - ja. Neugier - ja. Aber Angst - nein.

Auch der größte und längste Code ist analysierbar. Es dauert ein wenig 
aber im Endeffekt lernt man mit der Herausforderung. Hier schlagen doch 
eh immer wieder im Forum Typen auf, die sich Projekte suchen, die 10 
Schuhnummern zu groß und zu schwer für sie sind, und die auf die 
Aufforderung doch mit etwas einfacherem anzufangen, immer kommen mit 
'Aber ich will das doch lernen und ausserdem wächst man mit der 
Herausforderung'. Ich bin zwar nicht ihrer Meinung (denn sonst müssten 
sie nicht hier im Forum fragen) aber diesmal kannst du sie dir 
ausnahmsweise zum Vorbild nehmen.

OK. Genug Vorgeplänkel.

Was wissen wir.
In dem Programm geht es um 2 Themenkreise. Da ist auf der einen Seite 
ein Programmteil mit Infrarot-Empang samt Decodierung. Und auf der 
anderen Seite werden Ausgänge angesteuert. Der Infrarot-Teil 
interessiert uns nicht. Wir suchen den Relais Teil.

Nachdem das klar ist, fangen wir einfach mal an.
Programme folgen einem generellen Muster
Am Anfang erfolgt ein Sprung in die Initialisierung, in der die Hardware 
eingestellt wird, Dinge initialisiert werden und alles vorbereitet wird.
Der Sprung steht ganz am Anfang
1
 rjmp RESET         ;Reset Handler

also suchen wir mal, wo RESET ist.
1
reset:                  ;Initialisierung
2
 clr null                   ;immer 0
3
 ldi wl,1<<clkpce           ;Schreibschutz Taktvorteiler
4
 out clkpr,wl               ;aufheben
5
 ...
was da genau alles passiert, soll uns momentan nicht weiter kümmern. Wir 
verfolgen den Code weiter nach unten und stossen auf
1
 sei                        ;Interrupts freigeben
2
3
4
mainloop:           ;Hauptschleife
5
 lds yl,lepo                ;Lesepointer holen
6
 cp xl,yl                   ;Enthält TX-Puffer Daten?
7
 breq mainloop1             ;nein, weiter...
8
 rcall job_sendbyte         ;ja, senden...
9
mainloop1:
10
 sbrc flags,neubyte         ;neues Telegramm eingetroffen?
11
 rjmp job_neues_byte        ;ja, abarbeiten...
12
 sbrc flags,neu10ms         ;sind 10 Millisekunde vergangen? - nein...
13
 rjmp job_10ms              ;ja, abarbeiten...
14
 sleep                      ;CPU-Takt bis zum nächsten Interrupt aus
15
 rjmp mainloop              ;nochmal...

das ist aber nett vom Original-Programmierer, dass er die obligate 
Hauptschleife auch 'mainloop' genannt hat. Damit wissen wir: hier ist 
das Herz des Programms - die Steuerzentrale. Die Drehscheibe, von der 
alles ausgeht.

Jetzt studieren wir mal ein wenig die Kommentare in der Hoffnung, dass 
sie nicht allzu falsch sind. Da steht 'neues Telegramm eingetroffen?' - 
'ja, abarbeiten'    Das klingt doch schon mal nicht schlecht. Das klingt 
genau nach dem was wir suchen um den Fuss in die Tür zu bekommen. Mit 
'Neues Telegram' wird wohl das Infrarot-Telegram gemeint sein, welches 
die Fernsteuerung losschickt, wenn man eine Taste drückt. Na und was 
wird wohl abarbeiten sein? Genau - das könnte was mit den Relais zu tun 
haben.
Da wird also ein Sprung nach 'job_neues_byte' gemacht.
Na dann sehen wir doch mal dort nach
1
job_neues_byte:     ;es ist ein neues Byte eingetroffen
2
 cbr flags,1<<neubyte       ;Jobflag entwerten
3
 ldi yl,low(toz-1)          ;Pointer vor Timeout-Zähler
4
 ldi yh,high(toz-1)         ;im SRAM
5
 ldi zl,low(bimu*2-5)       ;Pointer 5 vor Bitmust
6
...
und auch da verschaffen wir uns erst mal einen ersten Überblick, in dem 
wir die Kommentare lesen. Tun wir das, dann stossen wir nach einigen 
Zeilen auf etwas interessantes.
1
...
2
 ;Tastencode wurde in Tabelle gefunden
3
 lpm wh,z+                  ;Mode-Bits holen
4
 lpm wl,z+                  ;Schaltzeit holen
5
 lpm r0,z+                  ;Bitmuster PortA holen
6
 sbrs wh,toggel             ;hat dieser Portpin Toggelmode? - ja...
7
 rjmp job_neues_byte2       ;nein, weiter...
8
 ;dieser Schaltbefehl hat Toggelmode
9
 brts job_neues_byte_e      ;ja, Repeat-Bit im empfangenen Byte? - ja...
10
 ;es ist das erste Byte des Telegramms
11
 in r1,porta                ;Port einlesen,
12
 eor r1,r0                  ;Bit toggeln
13
 out porta,r1               ;und zurückschreiben
14
 lpm r0,z+                  ;Bitmuster PortB holen
15
 in r1,portb                ;Port einlesen,
16
 eor r1,r0                  ;Bit toggeln
17
 out portb,r1               ;und zurückschreiben
18
 lpm r0,z+                  ;Bitmuster PortD holen
19
 in r1,portd                ;Port einlesen,
20
 eor r1,r0                  ;Bit toggeln
21
 out portd,r1               ;und zurückschreiben
22
 rjmp job_neues_byte_e      ;fertig...

Da ist bereits von den Ports die Rede und das Pins getoggelt werden. 
Sieht man sich den Code an, dann stösst man auf die Sequenz
1
...
2
 in r1,porta                ;Port einlesen,
3
 eor r1,r0                  ;Bit toggeln
4
 out porta,r1               ;und zurückschreiben
5
...
und das ist eigentlich schon recht eindeutig. Da wird der Zustand vom 
Port A gelesen, ein oder mehrere Bit, welche offenbar in r0 stehen 
werden rein-ge-xodert (und damit getoggelt) und das Ergebnis geht wieder 
an den Port A.

Heureka: Das ist die Stelle an der die Relais getoggelt werden! Hier ist 
dein Angriffspunkt und hier kannst du eingreifen. Jetzt analysierst du 
noch, wie r0 zu seinem Wert kommt (das ist nicht wirklich schwer) und 
wie da ganz offensichtlich der Zusammenhang mit den Spalten A, B, D in
1
;Taste,Mode,Zeit,A,  B,  D
2
.db 17,imp, 10,  0,  1,  0  ;Taste 1        PB0 Impuls 100 ms
3
.db 18,imp, 10,  0,  2,  0  ;Taste 2        PB1 Impuls 100 ms
ist, und du hast deinen Fuss soweit in der Tür, dass du anfangen kannst, 
das Programm zu modifizieren und an deine Bedürfnisse anzupassen.

Und das ganze war gar nicht mal so schwer zu finden, wenn man nicht 
dasteht wie das Kaninchen vor der Schlange und sich vor dem scheinbaren 
vielem Code in die Hose macht.

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Erst mal, und das ist ganz wichtig, keine Angst. Repekt - ja. Neugier - ja. > 
Aber Angst - nein.

Der hat doch keine Angst, der ist einfach faul.

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> Karl Heinz Buchegger schrieb:
>> Erst mal, und das ist ganz wichtig, keine Angst. Repekt - ja. Neugier - ja. >
> Aber Angst - nein.
>
> Der hat doch keine Angst, der ist einfach faul.

In dubio ....
:-)


(Ich weiß schon, dass er einen Dummen sucht, der ihm die Anpassung 
macht. Ich mach sie ihm nicht. Denn ich bin der Meinung, dass jemand der 
gerade mal mit Nagelschere und -Feile umgehen kann, nicht versuchen 
sollte ein Schrott-Auto wieder flott zu machen. Aber den Tip, wie er die 
Spur kontrollieren kann, und das er den Rahmen auf einer Streckbank 
ausrichten muss, den kriegt er)

von oldmax (Gast)


Lesenswert?

Hi
Und das in einer Top Erklärung. Besser hätt ich's auch nicht 
gekonnt.....
Gruß oldmax

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.