Forum: Mikrocontroller und Digitale Elektronik AVR Tasternetzwerk am Atmega16


von Stefan W. (arctic)


Angehängte Dateien:

Lesenswert?

Hallo,

ich sitze hier im Rahmen einer Studienarbeit an einem DJ-Mischpult mit 
Atmega16. Es soll die Zustände der verschiedenen Regler auslesen und 
über der USART an einen PC übertragen. Der PC übernimmt dann die 
Soundausgabe.

So weit, so gut. Die Schieberegler und Drehgeber werden ausgewertet und 
übertragen. Ich möchte jedoch zudem noch 10 Taster (5 je Kanal) 
anschließen. Ich habe keine freien digitalen I/O Ports mehr. Allerdings 
noch 2 Eingänge am ADC. Also kam mir die Idee, das alles über ein 
Widerstandsnetzwerk zu realisieren. Der Schaltplan liegt bei. Bei L_PBS 
hängt der ADC. Ich habe jetzt das Problem, dass die Werte, die ich vom 
ADC bekomme nicht stimmen. Sie sind einfach nicht reproduzierbar; d.h. 
wenn ich 2 mal die selbe Taste drücke kommen stark unterschiedliche 
Werte raus.
Das wird wohl daran liegen, dass der ADC eine nicht zu vernachlässigende 
Kapazität besitzt und die Spannung beim Drücken einer Taste nicht 
schnell genug absinkt.

Ich habe hier mal einen Codeauszug. Der Auszug ist aus der 
ISR(_VECTOR(14)), also der ADC_comlpete Interrupt.
1
if(lpbs != ADC) 
2
{
3
trigger=1;
4
}
5
for(shift=8;shift>=0;shift--)
6
  {
7
    lpbs_temp[(shift+1)]=lpbs_temp[shift];
8
  }
9
  lpbs_temp[0]=ADC;
10
11
  if((lpbs_temp[0] == lpbs_temp[1]) && trigger==1)
12
  {
13
    lpbs=ADC;
14
    senden(ADC); //Diese Fkt. überträgt den Wert
15
    trigger=0;
16
  }

Ich prüfe, ob sich der Analogwert seit der letzten Wandlung geändert 
hat. Falls ja, merke ich mir diese Tatsache.
Dann schreibe ich in eine Art FIFO, sodass ich immer die letzten 10 
Werte speichere. Kommen dann 2 gleiche Werte nacheinander ins FIFO, gehe 
ich davon aus, dass sich die Spannung am ADC eingeschwungen hat und 
sende den neuen Wert an den PC. Dann lösche ich den Trigger. Den Trigger 
benötige ich dazu, damit der normale Zustand, der ja auch ständig 
gleiche Werte liefer nicht immer übertragen wird.

Mein Problem ist, der AVR hängt und sendet nichts. Auch der Rest der 
Software steht still. Was mache ich falsch??

von Johannes M. (johnny-m)


Lesenswert?

Exakt gleiche Werte wirst Du bei der Anordnung vermutlich nie bekommen. 
Und die Kapazität des ADC-Eingangs liegt im pF-Bereich, das spielt bei 
den von Dir gewählten Widerstandswerten keine Rolle. Die Zeitkonstanten 
liegen damit allesamt im ns- bis µs-Bereich. Außerdem solltest Du Dich 
dringendst mal über Bildformate informieren!

BTW: Hast Du eigentlich mal die Forum-Suche bemüht? Es gibt da schon ein 
paar Beiträge, u.a. ein Beispiel von PeDa unter 
Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"
zum Auswerten einer Matrixtastatur.

von Stefan W. (arctic)


Lesenswert?

Tut mir leid wegen den Bildformaten, ich habe hier an den Uni-Rechnern 
nur sehr beschränkte möglichkeiten.

Dass ich nie exakt gleiche werte bekomme ist mir klar. ich bekomme aber, 
ohne etwas zu drücken schon schwankungen von 0x0800 bis 0x0000. das ist 
doch zu viel um es als eingestreute störung abzutun

von ... .. (docean) Benutzerseite


Lesenswert?

schon mal dran gedacht das die Tasten prellen könnten??

Mess mal mit dem Ossi die Spannunng die ADC anliegt...

von Gerhard (Gast)


Lesenswert?

da gibt's irgendwo in der Codesammlung ein Beispiel von Peter Danneger 
dazu, das könnte dir helfen. Musst mal nach suchen.

Gerhard

von Peter D. (peda)


Lesenswert?

Würde Dir es denn Spaß machen, so ein lieblos dahingeworfenes 
Code-Knäuel zu enträtseln?

Gewöhn Dir mal an, einen compilierbaren Code zu posten:

Also alle Variablen-Definitionen sind das mindeste.

Und ne umfassende Funktion um das Code-Knäuel, damit man den Kontext 
abgrenzt.

Und natürlich bei Hardwarezugriffen der genaue Target-Typ und das 
Include.

Und natürlich bei Hardwarezugriffen die dazugehörende Initialisierung.

Und dann noch ein Main, damit der Antwortende es sofort compilieren und 
simulieren kann, wenn er will.

Oftmals findet man Fehler schneller, wenn man sich die Compilerwarnungen 
ansieht.
Natürlich zeichnet sich ein gut vorbereiter Code zu einer Frage dadurch 
aus, daß er ohne Warnungen ist. Anderenfalls sollte man gleich darauf 
hinweisen, daß man die Warnungen nicht versteht.


Peter

von Stefan W. (arctic)


Lesenswert?

Ich habe hier mal den ganzen code. er ist leider nicht ganz kommentiert. 
ich werde morgen mal noch eine erklärung und eine nähere beschreibung 
posten.
1
/*************************************************************************
2
 *                                                                       *
3
 *   Projekt:    Studienarbeit 6.Semester                             *
4
 *   Thema:      Entwicklung eines DJ-Mischpultes mit USB-Anschluss   *
5
 *   Student:    Eric Schrön                                          *
6
 *   Kurs:      TEL05AAT                                             *
7
 *   Betreuer:    Prof. Walter Berthold                                *
8
 *   Datei:      mischpult.c                                          *
9
 *   Editor:    AVR Studio 4                     *
10
 *   Copmiler:      GNU-GCC Compiler                   *
11
 *   Abgabedatum:  27.03.2008                                           *
12
 *                                                                       *
13
 *   Beschreibung:  Das folgende Programm wird auf den Mikrocontroller   *
14
 *          im Mischpult geladen. Das Programm ist für einen   *
15
 *          ATMEGA16 von der Firma Atmel geschrieben.       *
16
 *          Das folgende Programm sammelt alle Daten der Dreh-   *
17
 *          geber und der Schiebepotis, wertet sie aus und     *
18
 *          ordnet ihnen die entsprechende Funktion zu. Außer-   *
19
 *          dem stellt das Programm die Kommuikation mit einem   *
20
 *          PC über die  USART Schnittstelle des µC her.       *
21
 *           Zunächst werden alle notwendigen Daten initiali-   *
22
 *          siert. Anschließend wird erstmalig der AD-Wandler   *
23
 *          zu Initialisierungszwecken aufgerufen. Der Ab-     *
24
 *          schluss der Wandlung wird von dem µC mit einem     *
25
 *          Interrupt signalisiert, womit eine entsprechende   *
26
 *          Interruptserviceroutine(ISR) aufgerufen wird. Dort   *
27
 *          wird zu Beginn der AD-Wandler wieder gestartet,     *
28
 *          der nur mit einem Bruchteil der Taktfrequenz, Ein-   *
29
 *          gangsdaten wandeln kann. In der Zwischenzeit werden   *
30
 *          alle nicht AD-Pins abgefragt und ausgewertet. Wenn   *
31
 *          sich bei irgendeinem Pin etwas wird dies in eine   *
32
 *          Variable geschrieben und in der dazu gehörigen     *
33
 *          Adressvariable ein Dirty-Bit gesetzt. Wenn die AD-   *
34
 *          Wandlung abgeschlossen ist, wird erneut die ISR     *
35
 *          aufgerufen.                       *
36
 *          Wenn die ISR nicht aktiv ist, wird main durch-     *
37
 *          laufen. Dort wird das Speicherabbild auf gesetzte   *
38
 *          Dirty-Bits geprüft. In diesem Fall wird eine     *
39
 *          Funktion senden aufgerufen, die das Adress- und     *
40
 *          Datenbyte des jeweiligen Reglers sendet. Außerdem   *
41
 *          ist ein 200 Byte großer FIFO implementiert.       *
42
 *                                                                       *
43
 *************************************************************************/
44
45
#include <stdint.h>
46
#include <avr/io.h>
47
#include <avr/interrupt.h>
48
#include <variablen.h>
49
//#include "funktionen.c"
50
51
#define F_OSC 12000000               /* oscillator-frequency in Hz */
52
#define UART_BAUD_RATE 57600
53
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1)
54
55
56
57
uint8_t geber(uint8_t bits_alt1, uint8_t bits_neu);
58
uint8_t taster(uint16_t wert);
59
void senden(uint8_t adresse, uint16_t wert);
60
61
/**************************************************
62
 *                          *
63
 *   Initialisierung der globalen Variablen      *
64
 *   Diese werden in main() und in der ISR      *
65
 *   benötigt                    *
66
 *                          *
67
 **************************************************/
68
69
   //vol, pitch, fader, lpbs, rpbs sind werte vom ADC
70
  uint16_t lvol, lpitch, mvol, fader, rpitch, rvol, lpbs, rpbs;
71
  uint16_t lvol_old, lpitch_old, mvol_old, fader_old, rpitch_old, rvol_old, lpbs_old, rpbs_old;
72
  uint16_t lpbs_temp[10]={0,0,0,0,0,0,0,0,0,0};
73
  uint8_t alvol, alpitch, amvol, afader, arpitch, arvol, altaste, artaste;
74
  uint8_t shift, trigger=0;
75
76
  //Digitalwerte von den Drehgebern
77
  uint8_t leh, lem, lel, reh, rem, rel, ljw, rjw, hpvol, hpsel;
78
  uint8_t aleh, alem, alel, areh, arem, arel, aljw, arjw, ahpvol, ahpsel;
79
  uint8_t leh_old, lem_old, lel_old, reh_old, rem_old, rel_old, ljw_old, rjw_old, hpvol_old, hpsel_old;
80
  uint8_t ljw_old2, rjw_old2;
81
  //Zähler zur ADC-Kanal auswahl
82
  uint8_t zaehler, k;
83
84
int main(void)
85
{
86
  
87
  
88
/**************************************************
89
 *                          *
90
 *   Initialisierung der Variablen für den FIFO    *
91
 *                          *
92
 **************************************************/
93
94
//daten[200]: FIFO für die Datenvariablen
95
//adresse[200]: FIFO für die Adressvariablen
96
//i: Zählvariable für den schreibenden Zugriff auf das FIFO
97
//j: Zählvariable für den lesenden Zugriff auf das FIFO
98
//imax: maximal mögliche Anzahl schreibender Einträge im nächsten Zyklus
99
//jmax: maximal mögliche Anzahl lesender Einträge
100
//zaehler: Zählvariable für die Auswahl des Analogeinganges
101
102
  uint8_t i, j, imax, jmax, adresse[200];
103
  uint16_t daten[200];
104
  i = 0;
105
  j = 0;
106
  imax = 200;
107
  jmax = 200;
108
  zaehler = 0;
109
110
/*********************************************************
111
 *                               *
112
 *   Initialisierung der Variablen für die Reglerdaten   *
113
 *   entsprechend den Bezeichnungen der Bauteile     *
114
 *                               *
115
 *********************************************************/
116
117
  leh = 128;
118
  lem = 128;
119
  lel = 128;
120
  reh = 128;
121
  rem = 128;
122
  rel = 128;
123
  ljw = 128;
124
  rjw = 128;
125
  hpsel = 128;
126
  hpvol = 128;
127
128
  leh_old = 0xFF;
129
  lem_old = 0xFF;
130
  lel_old = 0xFF;
131
  reh_old = 0xFF;
132
  rem_old = 0xFF;
133
  rel_old = 0xFF;
134
  ljw_old = 0xFF;
135
  rjw_old = 0xFF;
136
  hpvol_old = 0xFF;
137
  hpsel_old = 0xFF;
138
  ljw_old2 = 0xFF;
139
  rjw_old2 = 0xFF;
140
141
  lvol = 0;
142
  lpitch = 0;
143
  mvol = 0;
144
  fader = 0;
145
  rpitch  = 0;
146
  rvol  = 0;
147
  lpbs = 0;
148
  rpbs = 0;
149
150
  lvol_old = 0xFFFF;
151
  lpitch_old = 0xFFFF;
152
  mvol_old = 0xFFFF;
153
  fader_old = 0xFFFF;
154
  rpitch_old  = 0xFFFF;
155
  rvol_old  = 0xFFFF;
156
  lpbs_old = 0xFFFF;
157
  rpbs_old = 0xFFFF;
158
159
160
/***************************************************************
161
 *                                   *
162
 *   Initialisierung der Adressvariablen für die Reglerdaten   *
163
 *                                   *
164
 ***************************************************************/
165
  
166
  alvol = 0x10;
167
  alpitch = 0x18;
168
  amvol = 0x20;
169
  afader = 0x28;
170
  arpitch = 0x30;
171
  arvol = 0x38;
172
  aleh = 0x40;
173
  alem = 0x48;
174
  alel = 0x50;
175
  ahpvol = 0x58;
176
  areh = 0x60;
177
  arem = 0x68;
178
  arel = 0x70;
179
  aljw = 0x78;
180
  arjw = 0x80;
181
  ahpsel = 0x88;
182
  altaste = 0x90;
183
  artaste = 0x98;
184
185
/*********************************************************
186
 *                             *
187
 *   Initialisierung der Ports des µC           *
188
 *   PORTx für die Aktivierung der Pull-Up Widerstände   *
189
 *   DDRx für die Angabe der Datenrichtung (I/O)     *
190
 *                             *
191
 *********************************************************/
192
193
//PORTx: Einstellung für die Pull-Up Widerstände
194
//DDRx: Einstellung für die Datenrichtung (I/O)
195
    
196
  PORTA = 0x00;
197
  DDRA = 0x00;
198
  PORTB = 0x3F;
199
  DDRB = 0xC0;
200
  PORTC = 0xFF;
201
  DDRC = 0x00;
202
  PORTD = 0xFC;
203
  DDRD = 0x02;
204
205
/***********************************************************************
206
 *                                       *
207
 *   Initialisierung der Variablen für den USART und des AD-Wandlers   *
208
 *                                       *
209
 ***********************************************************************/
210
211
//UBRR: Register zur Einstellung der Baudrate
212
//RXEN: Aktivierung des µC zum Empfangen von Daten
213
//TXEN: Aktivierung des µC zum Senden von Daten
214
//URSEL: Schreibzugriff auf UCSRC Register
215
//USBS: Anzahl der Stoppbits, hier 1
216
//UCSZ0: Anzahl der Datenbits, hier 8
217
218
  UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8);
219
  UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);
220
221
  
222
  // Enable receiver and transmitter; enable RX interrupt
223
  UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
224
225
  //asynchronous 8N1
226
  UCSRC = (1 << URSEL) | (3 << UCSZ0);
227
228
229
//ADEN: Aktivierung des AD-Wandlers
230
//ADPS0-2: Teilungsfaktor für AD-Takt, hier 64
231
//ADIE: Aktivierung des AD-Wandler Interrupts
232
//ADMUX: Auswahl des AD-Input Pins
233
234
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
235
  ADCSRA |= (1<<ADIE);
236
  ADMUX = 0x20;
237
  
238
/**********************************************************************
239
 *                                    *
240
 *   Aktivieren des Global Interrupt Enable Flags im Statusregister   *
241
 *   Starten des AD-Wandler für die Initialisierung            *
242
 *                                    *
243
 **********************************************************************/
244
245
  sei(); //Aktivierung des Global Interrupt Enable Flags im Statusregister (SREG)
246
247
  ADCSRA |= (1<<ADSC); //Aktivierung des AD-Wandlers
248
  while(!(ADCSRA & 0x10)) //Warten auf Beendigung der AD-Wandlung
249
  {
250
251
  }
252
253
/**************************************************************************
254
 *                                      *
255
 *   Beginn der Endlosschleife zur Abfrage der Dirty-Bits          *
256
 *   1) Prüfen ob noch genügend Platz im FIFO ist (30 Werte mindestens)   *
257
 *      - "i" ist die Zählvariable der schreibenden Einträge im FIFO    *
258
 *    - "imax" ist die Maximalanzahl von schreibbaren Einträgen      *
259
 *   2) Prüfen ob im jeweiligen Adressbyte das Dirty-Bit gesetzt ist    *
260
 *    - Maskierung mit 0x04 und gleichzeitigen Prüfen aus "TRUE"      *
261
 *   3) Wenn "FALSE" ist wird das nächste Adressbyte geprüft        *
262
 *   4) Wenn "TRUE" ist, dann werden der Interrupt deaktiviert,        *
263
 *     Adress- und Datenbyte in den FIFO geschrieben, das Dirty-Bit    *
264
 *    gelöscht, der Interrupt aktiviert und "i" inkrementiert.      *
265
 *                                      *
266
 **************************************************************************/
267
268
  while(1)   //Endlosschleife
269
  {
270
    if((i+30)<imax)   //Überprüfung ob genügend Speicherplatz im FIFO vorhanden ist
271
    {
272
      if(alvol & 0x04)   ///Überprüfung, ob das Dirty-Bit gesetzt ist
273
      {
274
        cli();   //Löschen des Global Interrupt Enable Flags im Statusregister
275
        alvol &= ~0x04;   //Löschen des Dirty-Bits
276
        adresse[i] = alvol;   //Speichern der Adressvariablen im FIFO
277
        daten[i] = (lvol >> 6);   //Speicherung der Datenvariablen im FIFO
278
        sei();   //Setzen des Global Interrupt Enable Flags im Statusregister
279
        i++;   //Inkrementierung des Indizes für den schreibenden Zugriff auf das FIFO
280
      }
281
      if(alpitch & 0x04)
282
      {
283
        cli();
284
        alpitch &= ~0x04;
285
        adresse[i] = alpitch;
286
        daten[i] = (lpitch >> 6);
287
        sei();
288
        i++;
289
      }
290
      if(amvol & 0x04)
291
      {
292
        cli();
293
        amvol &= ~0x04;
294
        adresse[i] = amvol;
295
        daten[i] = (mvol >> 6);
296
        sei();
297
        i++;
298
      }
299
      if(afader & 0x04)
300
      {
301
        cli();
302
        afader &= ~0x04;
303
        adresse[i] = afader;
304
        daten[i] = (fader >> 6);
305
        sei();
306
        i++;
307
      }
308
      if(arpitch & 0x04)
309
      {
310
        cli();
311
        arpitch &= ~0x04;
312
        adresse[i] = arpitch;
313
        daten[i] = (rpitch >> 6);
314
        sei();
315
        i++;
316
      }
317
      if(arvol & 0x04)
318
      {  
319
        cli();
320
        arvol &= ~0x04;
321
        adresse[i] = arvol;
322
        daten[i] = (rvol >> 6);
323
        sei();
324
        i++;
325
      }
326
      if(aleh & 0x04)
327
      {
328
        cli();
329
        aleh &= ~0x04;
330
        adresse[i] = aleh;
331
        daten[i] = leh;
332
        sei();
333
        i++;
334
      }
335
      if(alem & 0x04)
336
      {
337
        cli();
338
        alem &= ~0x04;
339
        adresse[i] = alem;
340
        daten[i] = lem;
341
        sei();
342
        i++;
343
      }
344
      if(alel & 0x04)
345
      {
346
        cli();
347
        alel &= ~0x04;
348
        adresse[i] = alel;
349
        daten[i] = lel;
350
        sei();
351
        i++;
352
      }
353
      if(ahpvol & 0x04)
354
      {
355
        cli();
356
        ahpvol &= ~0x04;
357
        adresse[i] = ahpvol;
358
        daten[i] = hpvol;
359
        sei();
360
        i++;
361
      }
362
      if(areh & 0x04)
363
      {
364
        cli();
365
        areh &= ~0x04;
366
        adresse[i] = areh;
367
        daten[i] = reh;
368
        sei();
369
        i++;
370
      }
371
      if(arem & 0x04)
372
      {
373
        cli();
374
        arem &= ~0x04;
375
        adresse[i] = arem;
376
        daten[i] = rem;
377
        sei();
378
        i++;
379
      }
380
      if(arel & 0x04)
381
      {
382
        cli();
383
        arel &= ~0x04;
384
        adresse[i] = arel;
385
        daten[i] = rel;
386
        sei();
387
        i++;
388
      }
389
      if(aljw & 0x04)
390
      {
391
        cli();
392
        aljw &= ~0x04;
393
        adresse[i] = aljw;
394
        daten[i] = ljw;
395
        sei();
396
        i++;
397
      }
398
      if(arjw & 0x04)
399
      {
400
        cli();
401
        arjw &= ~0x04;
402
        adresse[i] = arjw;
403
        daten[i] = rjw;
404
        sei();
405
        i++;
406
      }
407
      if(ahpsel & 0x04)
408
      {
409
        cli();
410
        ahpsel &= ~0x04;
411
        adresse[i] = ahpsel;
412
        daten[i] = hpsel;
413
        sei();
414
        i++;
415
      }
416
      if(altaste & 0x04)
417
      {
418
        cli();
419
        altaste &= ~0x04;
420
        adresse[i] = altaste;
421
        daten[i] = lpbs;
422
        sei();
423
        i++;
424
      }
425
      if(artaste & 0x04)
426
      {
427
        cli();
428
        artaste &= ~0x04;
429
        adresse[i] = artaste;
430
        daten[i] = rpbs;
431
        sei();
432
        i++;
433
      }
434
    }
435
436
/***********************************************************************************
437
 *                                           *
438
 *   5) Wenn mehr geschriebene als gelesene Daten im FIFO sind,             *
439
 *     wird die Funktion "senden" aufgerufen und "j" inkrementiert           *
440
 *    - "j" ist die Zählvariable der lesenden Einträge im FIFO           *
441
 *    - "jmax" ist die Maximalanzahl der zu lesenden Einträgen           *
442
 *   6) Wenn "i" größer als 170 wird, werden "imax", "jmax", und "i" neu gesetzt   *
443
 *   7) Wenn "j" die Maximalanzahl erreicht, wird j zurückgesetzt           *
444
 *   Ende der Endlosschleife                             *
445
 *                                           *
446
 ***********************************************************************************/
447
448
    if(i!=j)   //Überprüfung ob Indizes für schreibenden und lesenden Zugriff gleich ist, Index für schreibenden Zugriff ist immer voreilend
449
    {
450
      if(UCSRA & 0x20)   //Überprüfung ob das Senden-Register leer ist
451
      {
452
        senden(adresse[j], daten[j]);   //Aufruf der Funktion senden
453
        j++;   //Inkrementierung des Indizes für den lesenden Zugriff
454
        if(imax<=(i+30)) imax++;   //Überprüfung, ob noch Platz im FIFO für zu speichernde Werte ist
455
      }
456
    }
457
458
    if(i>170)   //Überprüfung, ob FIFO beim nächsten Durchlauf überlaufen könnte
459
    {
460
      imax = j;   //Festlegung der maximal zu schreibenden Einträge
461
      jmax = i;   //Festlegung der maximal zu lesenden Einträge
462
      i = 0;   //Reset des Indizes der schreibenden Einträge
463
    }
464
465
    if(j==jmax) j = 0;   //Wenn die maximal zu lesende Anzahl der lesenden Einträge erreicht ist, wird Index für die lesenden Einträge resetet
466
467
  }
468
      
469
  return 0;
470
}
471
472
/***********************************************************************************
473
 *                                           *
474
 *   Beginn der ISR, die aufgerufen wird, wenn die AD-Wandlung abgeschlossen ist   *
475
 *                                           *
476
 ***********************************************************************************/
477
478
ISR(_VECTOR(14))
479
{
480
481
/******************************************************************************************
482
 *                                              *
483
 *   Auswahl der zu vergleichenden Reglervariablen mit dem ADC-Register,          *
484
 *   das mit dem Ergfebnis der vorherigen Wandlung belegt ist                *
485
 *   1) Wenn Ungleichheit besteht wird die Datenvariable mit dem  ADCH Register belegt,   *
486
 *    und das Dirty-Bit gesetzt. Bei xPBS wird eine extra Funktion aufgerufen.        *
487
 *   2) Wenn Gleichheit besteht, wird die Funktion fortgeführt                *
488
 *   3) Wenn "zaehler" einmal alle AD-Pins durchlaufen hat, wird er auf "0" gesetzt      *
489
 *                                              *
490
 ******************************************************************************************/
491
492
  switch(zaehler)   //Auswahl des AD-Einganges
493
  {
494
    case 0: if((lvol != ADC) && (lvol_old != ADC))
495
        {
496
          lvol_old=lvol;
497
          lvol = ADC;
498
          alvol |= 0x04;
499
        };
500
    break;
501
    case 1: if((lpitch != ADC) && (lpitch_old != ADC))   //bei Auswahl Vergleich, ob sich Datenvariable geändert hat
502
        {
503
          lpitch_old = lpitch;
504
          lpitch = ADC;   //Speichern der neuen Datenvariablen
505
          alpitch |= 0x04;   //setzen des Dirty-Bits
506
        };
507
    break;
508
    case 2: /*{
509
          if((lpbs != ADC) && (lpbs_old!=ACD))
510
          {
511
            trigger=1;
512
          }
513
          for(shift=8;shift>=0;shift--)
514
          {
515
            lpbs_temp[(shift+1)]=lpbs_temp[shift];
516
          }
517
          lpbs_temp[9]=lpbs_temp[8];
518
          lpbs_temp[8]=lpbs_temp[7];
519
          lpbs_temp[7]=lpbs_temp[6];
520
          lpbs_temp[6]=lpbs_temp[5];
521
          lpbs_temp[5]=lpbs_temp[4];
522
          lpbs_temp[4]=lpbs_temp[3];
523
          lpbs_temp[3]=lpbs_temp[2];
524
          lpbs_temp[2]=lpbs_temp[1];
525
          lpbs_temp[1]=lpbs_temp[0];
526
          lpbs_temp[0]=ADC;
527
528
          if((lpbs_temp[0] == lpbs_temp[1]) && trigger==1)
529
          {
530
            lpbs_old=lpbs;
531
            lpbs=ADC;
532
            altaste |= 0x04;
533
            trigger=0;
534
          } 
535
        };*/
536
    break;
537
    case 3: if((mvol != ADC) && (mvol_old != ADC))
538
        {
539
          mvol_old = mvol;
540
          mvol = ADC;
541
          amvol |= 0x04;
542
        };
543
    break;
544
    case 4: if((fader != ADC) && (fader_old != ADC))   
545
        {
546
          fader_old=fader;      
547
          fader = ADC;   
548
          afader |= 0x04;
549
550
        };
551
    break;
552
    case 5: /*if(rpbs != ADC)
553
        {
554
          rpbs = ADC;
555
          artaste |= 0x04;
556
        };
557
    break;*/
558
    case 6: if((rpitch != ADC) &&(rpitch_old != ADC))
559
        {
560
          rpitch_old = rpitch;
561
          rpitch = ADC;
562
          arpitch |= 0x04;
563
        };
564
    break;
565
    case 7: if((rvol != ADC) && (rvol_old != ADC))
566
        {
567
          rvol_old = rvol;
568
          rvol = ADC;
569
          arvol |= 0x04;
570
        };
571
    break;
572
  }
573
574
  zaehler++;   //Inkrmentierung zur Auswahl des nächsten Analogeingangs
575
  if(zaehler==8) zaehler = 0;   //Wenn alle Analogeingänge abgefragt wurden, wird der Zähler zurückgesetzt
576
577
  ADMUX = 0x20 | zaehler;   //Setzen des Auswahlregisters für den Analogeingang
578
  ADCSRA |= (1<<ADSC);   //Aktivieren des AD-Wandlers
579
580
/*******************************************************************************
581
 *                                         *
582
 *   Vergleichen aller nicht AD-Variablen mit den jeweiligen Pinzuständen     *
583
 *   1) Belegen von "k" mit den Variablenzuständen                 *
584
 *   2) Vergleichen von "k" mit den Datenvariablen                 *
585
 *   3) Wenn "FALSE", dann werden die restlichen Werte verglichen         *
586
 *   4) Wenn "TRUE", dann wird die Funktion zur Berechnung der Geberwerte     *
587
 *    aufgerufen, das Dirty-Bit gesetzt und die Vergleichsvariable belegt.   *
588
 *                                         *
589
 *******************************************************************************/
590
591
  k = PINB & 0x03;   //Belegung einer Variable mit den entsprechenden Pins
592
  if(k!=leh_old)   //Überprüfung, ob sich die Bitkombination geändert hat
593
  {
594
    leh = geber(k, leh_old);   //Aufrufen der Funktion "geber" zur Berechnung des absoluten Wertes
595
    aleh |= 0x04;   //setzen des Dirty-Bits
596
    leh_old=k;
597
  }
598
  
599
  k = (PINB & 0x0C) >> 2;  
600
  if(k!=lem_old)
601
  {
602
    lem = geber(k, lem_old);
603
    alem |= 0x04;
604
    lem_old=k;
605
  }
606
607
  k = (PINB & 0x30) >> 4;
608
  if(k!=lel_old)
609
  {
610
    lel = geber(k, lel_old);
611
    alel |= 0x04;
612
    lel_old=k;
613
  }
614
615
  k = PINC & 0x03;
616
  if(k!=hpvol_old)
617
  {
618
    hpvol = geber(k, hpvol_old);
619
    ahpvol |= 0x04;
620
    hpvol_old=k;
621
  }
622
623
  k = (PINC & 0x0C) >> 2;
624
  if(k!=reh_old)
625
  {
626
    reh = geber(k, reh_old);
627
    areh |= 0x04;
628
    reh_old=k;
629
  }
630
631
  k = (PINC & 0x30) >> 4;
632
  if(k!=rem_old)
633
  {
634
    rem = geber(k, rem_old);
635
    arem |= 0x04;
636
    rem_old=k;
637
  }
638
639
  k = (PINC & 0xC0) >> 6;
640
  if(k!=rel_old)
641
  {
642
    rel = geber(k, rel_old);
643
    arel |= 0x04;
644
    rel_old=k;
645
  }
646
647
  k = (PIND & 0x0C) >> 2;
648
  if((k!=ljw_old) && (k!=ljw_old2))
649
  {
650
    ljw = geber(k, ljw_old);
651
    aljw |= 0x04;
652
    
653
    ljw_old=k;
654
  }
655
  ljw_old2=ljw_old;
656
  k = (PIND & 0x30) >> 4;
657
  if((k!=rjw_old) && (k!=rjw_old))
658
  {
659
    rjw = geber(k, rjw_old2);
660
    arjw |= 0x04;
661
    
662
    rjw_old=k;
663
  }
664
  rjw_old2=rjw_old;
665
  k = (PIND & 0xC0) >> 6;
666
  if(k!=hpsel_old)
667
  {
668
    hpsel = geber(k, hpsel_old);
669
    if(hpsel==1)
670
    {
671
      PINB |=0x80;
672
      PINB &=0xBF;
673
    }
674
    if(hpsel==3)
675
    {
676
      PINB |=0x40;
677
      PINB &=0x7F;
678
    }
679
    ahpsel |= 0x04;
680
    hpsel_old=k;
681
  }
682
}
683
684
/**********************************************************************************
685
 *                                            *           *
686
 *   Die ISR wird aufgerufen, sobald ein Zeichen über die USART-Schnittstelle     *
687
 *   empfangen wurde. Das empfangene Zeichen steht dann im USART-Datenregister.   *
688
 *   Empfangen werden Anforderungen zur Datenübertragung. Es ist möglich vom PC   *
689
 *   aus alle oder nur einzelne Werte neu anzufordern. Eine Neuanforderung        *
690
 *   ist nur für die Werte der Schieberegler sinnvoll, da die Drehgeber und       *
691
 *   die Taster im Normalzustand 0 sind. Das  Senden wird ausgelöst durch setzen  *
692
 *   des jeweiligen Dirty-Bits.                            *
693
 *                                          *
694
 *********************************************************************************/
695
ISR(_VECTOR(11))
696
{
697
  int8_t wert;
698
699
  wert=UDR;
700
701
  if (wert==0x99) //Alle Werte neu senden. Sendeanforderung durch Setzten des Dirty-Bits
702
  {
703
    alvol   |= 0x04;
704
    alpitch |= 0x04;
705
    amvol  |= 0x04;
706
    afader   |= 0x04;
707
    arpitch |= 0x04;
708
    arvol  |= 0x04;
709
  }
710
  else
711
  {
712
    switch (wert)
713
    {
714
      case 0x10: 
715
      {
716
        alvol   |= 0x04;
717
        break;
718
      }
719
      case 0x18:
720
      {
721
        alpitch |= 0x04;
722
        break;
723
      }
724
      case 0x20:
725
      {
726
        amvol |= 0x04;
727
        break;
728
      }
729
      case 0x28:
730
      {
731
        afader   |= 0x04;
732
        break;
733
      }
734
      case 0x30:
735
      {
736
        arpitch |= 0x04;
737
        break;
738
      }
739
      case 0x38:
740
      {
741
        arvol |= 0x04;
742
        break;
743
      }
744
    }
745
  }
746
}
747
748
749
/**********************************************************************************
750
 *                                            *  
751
 *   Der Funktion "geber" wird die Ausgabe der Drehgeber übergeben                *
752
 *   Je nach Bitkombination wird die Drehrichtung bestimmt und ein Wert         *
753
 *   zurückgegeben. Dieser Wert basiert auf dem Drehsinn eines "normalen"         *
754
 *   Drehreglers in der HiFi-Technik (links=- und rechts=+).                      *
755
 *                                            *                                            *
756
 *********************************************************************************/
757
uint8_t geber(uint8_t bits_alt, uint8_t bits_neu)   //Übergabe der alten und neuen Bitkombination, Datenvariable 
758
{
759
  uint8_t wert;  
760
761
  switch(bits_alt)
762
  {
763
    case 0x00: 
764
    {    
765
          if(bits_neu==0x01) //Linksdrehung
766
            wert=1;
767
          else if(bits_neu==0x02) //Rechtsdrehung
768
            wert=3;  
769
          else 
770
            wert=2; //Keine Drehung
771
          break;
772
    }    
773
    
774
    case 0x01: 
775
    {   
776
          if(bits_neu==0x03) //Linksdrehung
777
            wert=1;
778
          else if(bits_neu==0x00) //Rechtsdrehung
779
            wert=3;
780
          else
781
            wert=2;  //Keine Drehung
782
          break;
783
    }
784
785
    case 0x02: 
786
    {   
787
          if(bits_neu==0x00) //Linksdrehung
788
            wert=1;
789
          else if(bits_neu==0x03) //Rechtsdrehung
790
            wert=3;
791
          else
792
            wert=2;  //Keine Drehung
793
          break;
794
    }
795
796
    case 0x03: 
797
    {   
798
          if(bits_neu==0x02) //Linksdrehung
799
            wert=1;
800
          else if(bits_neu==0x01) //Rechtsdrehung
801
            wert=3;
802
          else
803
            wert=2;  //Keine Drehung
804
          break;
805
    }
806
  
807
    default: wert=0xFF; //Nur zu Debug-Zwecken
808
  }
809
810
811
  return wert;   //Rückgabe der Drehrichtung
812
}
813
814
/***********************************************************************************************
815
 *                                                 *
816
 *   Der Funktion "taster" wird der Wert des ADC übergeben. Über ein Array, das die zu den     *
817
 *   jeweiligen Tastenkominationen gehörenden Analogwerte beinhaltet erfolgt die Auswertung    *
818
 *   Je nach Analogwert wird die Variable "taste" mit einem Wert belegt und zurückgegeben.     *
819
 *                                                 *
820
 ***********************************************************************************************/
821
822
uint8_t taster(uint16_t wert)   //Übergabe der Datenvariable
823
{
824
  uint16_t taste=0;   //Festlegung einer Speichervariablen
825
  uint8_t i;
826
  uint16_t widerstand[32]={524,533,541,551,560,570,580,590,601,613,624,636,649,662,676,690,705,720,737,754,771,790,809,830,851,874,898,923,950,979,1009};
827
  
828
  if(wert>=512)   //Folgender Block dient der Auswahl der Tasterkombination
829
  {
830
    for(i=0; i<32; i++)
831
    {
832
      if(wert <= widerstand[i])
833
      {
834
        taste=32-i;
835
        break;
836
      }
837
    }
838
  }
839
840
  else taste = 0x00;
841
842
  return taste;
843
}
844
845
/****************************************************************************************
846
 *                                            *
847
 *   Der Funktion "senden" wird die entsprechende Adress- und Datenvariable übergeben   *
848
 *   Unmittelbar nacheinander werden Adresse und Das High und Low-Byte der Daten-       *
849
 *   variable gesendet. Im Anschluss wird noch ein Füll-Byte übetragen, da der PC mit   *
850
 *   vier Byte besser umgehen kann. Dieses Füll-Byte zeigt zugleich auch das Ende eines *
851
 *   Datensatzes an und kann somit zur Synchronisation verwendet werden.        *                                          *
852
 ****************************************************************************************/
853
854
void senden (uint8_t adresse, uint16_t wert)   //Übergabe der Adress- und Datenvariable
855
{
856
  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
857
858
  UDR = adresse;   //Adresse senden
859
860
  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
861
862
  UDR = (wert >> 8 );   //Daten HIGH senden
863
864
  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
865
866
  UDR = (wert & 0xFF);   //Daten LOW senden
867
868
  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind
869
870
  UDR = 'X';   //Auf 4 Byte auffüllen
871
}

von Der Taster (Gast)


Lesenswert?

Wo in der Schaltung ist der ADC Eingang angeschlossen?

von Peter D. (peda)


Lesenswert?

Keiner will den ganzen Code wissen, sondern nur das, was mit Deinem 
Problem zu tun hat.

Und die Postingregeln (Dateinanhang benutzen!!!) sind nicht nur da, weil 
sie so schön aussehen, sondern zum lesen.

Und Dein Code ist einfach grauenhaft.
Hau mal die vielen unnötigen globalen Variablen raus und benutze lokale 
Variablen.
Sonst kann da keiner mehr durchsehen (Du auch nicht!).
Außerdem wird durch globale Variablen der Code nur unnötig groß und 
langsam.


Was soll denn dieser komische Code machen?
1
          for(shift=8;shift>=0;shift--)
2
          {
3
            lpbs_temp[(shift+1)]=lpbs_temp[shift];
4
          }
5
          lpbs_temp[9]=lpbs_temp[8];
6
          lpbs_temp[8]=lpbs_temp[7];
7
          lpbs_temp[7]=lpbs_temp[6];
8
          lpbs_temp[6]=lpbs_temp[5];
9
          lpbs_temp[5]=lpbs_temp[4];
10
          lpbs_temp[4]=lpbs_temp[3];
11
          lpbs_temp[3]=lpbs_temp[2];
12
          lpbs_temp[2]=lpbs_temp[1];
13
          lpbs_temp[1]=lpbs_temp[0];
14
          lpbs_temp[0]=ADC;

Wo wird z.B. der Wert lpbs_temp[9] verwendet?
Da er global ist, müßte man sich bei jeder Variable dumm und dämlich 
suchen.

Du solltest mal zeilenbezogene Kommentare verwenden, nicht nur ne grobe 
Beschreibung der gesamten Funktion.
So weiß man ja nicht, welche Codezeile das von Dir gewünschte machen 
soll.


Peter

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.