www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Tasternetzwerk am Atmega16


Autor: Stefan Wachter (arctic)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.
if(lpbs != ADC) 
{
trigger=1;
}
for(shift=8;shift>=0;shift--)
  {
    lpbs_temp[(shift+1)]=lpbs_temp[shift];
  }
  lpbs_temp[0]=ADC;

  if((lpbs_temp[0] == lpbs_temp[1]) && trigger==1)
  {
    lpbs=ADC;
    senden(ADC); //Diese Fkt. überträgt den Wert
    trigger=0;
  } 

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??

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Wachter (arctic)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schon mal dran gedacht das die Tasten prellen könnten??

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

Autor: Gerhard (Gast)
Datum:

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

Gerhard

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Wachter (arctic)
Datum:

Bewertung
0 lesenswert
nicht 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.
/*************************************************************************
 *                                                                       *
 *   Projekt:    Studienarbeit 6.Semester                             *
 *   Thema:      Entwicklung eines DJ-Mischpultes mit USB-Anschluss   *
 *   Student:    Eric Schrön                                          *
 *   Kurs:      TEL05AAT                                             *
 *   Betreuer:    Prof. Walter Berthold                                *
 *   Datei:      mischpult.c                                          *
 *   Editor:    AVR Studio 4                     *
 *   Copmiler:      GNU-GCC Compiler                   *
 *   Abgabedatum:  27.03.2008                                           *
 *                                                                       *
 *   Beschreibung:  Das folgende Programm wird auf den Mikrocontroller   *
 *          im Mischpult geladen. Das Programm ist für einen   *
 *          ATMEGA16 von der Firma Atmel geschrieben.       *
 *          Das folgende Programm sammelt alle Daten der Dreh-   *
 *          geber und der Schiebepotis, wertet sie aus und     *
 *          ordnet ihnen die entsprechende Funktion zu. Außer-   *
 *          dem stellt das Programm die Kommuikation mit einem   *
 *          PC über die  USART Schnittstelle des µC her.       *
 *           Zunächst werden alle notwendigen Daten initiali-   *
 *          siert. Anschließend wird erstmalig der AD-Wandler   *
 *          zu Initialisierungszwecken aufgerufen. Der Ab-     *
 *          schluss der Wandlung wird von dem µC mit einem     *
 *          Interrupt signalisiert, womit eine entsprechende   *
 *          Interruptserviceroutine(ISR) aufgerufen wird. Dort   *
 *          wird zu Beginn der AD-Wandler wieder gestartet,     *
 *          der nur mit einem Bruchteil der Taktfrequenz, Ein-   *
 *          gangsdaten wandeln kann. In der Zwischenzeit werden   *
 *          alle nicht AD-Pins abgefragt und ausgewertet. Wenn   *
 *          sich bei irgendeinem Pin etwas wird dies in eine   *
 *          Variable geschrieben und in der dazu gehörigen     *
 *          Adressvariable ein Dirty-Bit gesetzt. Wenn die AD-   *
 *          Wandlung abgeschlossen ist, wird erneut die ISR     *
 *          aufgerufen.                       *
 *          Wenn die ISR nicht aktiv ist, wird main durch-     *
 *          laufen. Dort wird das Speicherabbild auf gesetzte   *
 *          Dirty-Bits geprüft. In diesem Fall wird eine     *
 *          Funktion senden aufgerufen, die das Adress- und     *
 *          Datenbyte des jeweiligen Reglers sendet. Außerdem   *
 *          ist ein 200 Byte großer FIFO implementiert.       *
 *                                                                       *
 *************************************************************************/

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <variablen.h>
//#include "funktionen.c"

#define F_OSC 12000000               /* oscillator-frequency in Hz */
#define UART_BAUD_RATE 57600
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1)



uint8_t geber(uint8_t bits_alt1, uint8_t bits_neu);
uint8_t taster(uint16_t wert);
void senden(uint8_t adresse, uint16_t wert);

/**************************************************
 *                          *
 *   Initialisierung der globalen Variablen      *
 *   Diese werden in main() und in der ISR      *
 *   benötigt                    *
 *                          *
 **************************************************/

   //vol, pitch, fader, lpbs, rpbs sind werte vom ADC
  uint16_t lvol, lpitch, mvol, fader, rpitch, rvol, lpbs, rpbs;
  uint16_t lvol_old, lpitch_old, mvol_old, fader_old, rpitch_old, rvol_old, lpbs_old, rpbs_old;
  uint16_t lpbs_temp[10]={0,0,0,0,0,0,0,0,0,0};
  uint8_t alvol, alpitch, amvol, afader, arpitch, arvol, altaste, artaste;
  uint8_t shift, trigger=0;

  //Digitalwerte von den Drehgebern
  uint8_t leh, lem, lel, reh, rem, rel, ljw, rjw, hpvol, hpsel;
  uint8_t aleh, alem, alel, areh, arem, arel, aljw, arjw, ahpvol, ahpsel;
  uint8_t leh_old, lem_old, lel_old, reh_old, rem_old, rel_old, ljw_old, rjw_old, hpvol_old, hpsel_old;
  uint8_t ljw_old2, rjw_old2;
  //Zähler zur ADC-Kanal auswahl
  uint8_t zaehler, k;

int main(void)
{
  
  
/**************************************************
 *                          *
 *   Initialisierung der Variablen für den FIFO    *
 *                          *
 **************************************************/

//daten[200]: FIFO für die Datenvariablen
//adresse[200]: FIFO für die Adressvariablen
//i: Zählvariable für den schreibenden Zugriff auf das FIFO
//j: Zählvariable für den lesenden Zugriff auf das FIFO
//imax: maximal mögliche Anzahl schreibender Einträge im nächsten Zyklus
//jmax: maximal mögliche Anzahl lesender Einträge
//zaehler: Zählvariable für die Auswahl des Analogeinganges

  uint8_t i, j, imax, jmax, adresse[200];
  uint16_t daten[200];
  i = 0;
  j = 0;
  imax = 200;
  jmax = 200;
  zaehler = 0;

/*********************************************************
 *                               *
 *   Initialisierung der Variablen für die Reglerdaten   *
 *   entsprechend den Bezeichnungen der Bauteile     *
 *                               *
 *********************************************************/

  leh = 128;
  lem = 128;
  lel = 128;
  reh = 128;
  rem = 128;
  rel = 128;
  ljw = 128;
  rjw = 128;
  hpsel = 128;
  hpvol = 128;

  leh_old = 0xFF;
  lem_old = 0xFF;
  lel_old = 0xFF;
  reh_old = 0xFF;
  rem_old = 0xFF;
  rel_old = 0xFF;
  ljw_old = 0xFF;
  rjw_old = 0xFF;
  hpvol_old = 0xFF;
  hpsel_old = 0xFF;
  ljw_old2 = 0xFF;
  rjw_old2 = 0xFF;

  lvol = 0;
  lpitch = 0;
  mvol = 0;
  fader = 0;
  rpitch  = 0;
  rvol  = 0;
  lpbs = 0;
  rpbs = 0;

  lvol_old = 0xFFFF;
  lpitch_old = 0xFFFF;
  mvol_old = 0xFFFF;
  fader_old = 0xFFFF;
  rpitch_old  = 0xFFFF;
  rvol_old  = 0xFFFF;
  lpbs_old = 0xFFFF;
  rpbs_old = 0xFFFF;


/***************************************************************
 *                                   *
 *   Initialisierung der Adressvariablen für die Reglerdaten   *
 *                                   *
 ***************************************************************/
  
  alvol = 0x10;
  alpitch = 0x18;
  amvol = 0x20;
  afader = 0x28;
  arpitch = 0x30;
  arvol = 0x38;
  aleh = 0x40;
  alem = 0x48;
  alel = 0x50;
  ahpvol = 0x58;
  areh = 0x60;
  arem = 0x68;
  arel = 0x70;
  aljw = 0x78;
  arjw = 0x80;
  ahpsel = 0x88;
  altaste = 0x90;
  artaste = 0x98;

/*********************************************************
 *                             *
 *   Initialisierung der Ports des µC           *
 *   PORTx für die Aktivierung der Pull-Up Widerstände   *
 *   DDRx für die Angabe der Datenrichtung (I/O)     *
 *                             *
 *********************************************************/

//PORTx: Einstellung für die Pull-Up Widerstände
//DDRx: Einstellung für die Datenrichtung (I/O)
    
  PORTA = 0x00;
  DDRA = 0x00;
  PORTB = 0x3F;
  DDRB = 0xC0;
  PORTC = 0xFF;
  DDRC = 0x00;
  PORTD = 0xFC;
  DDRD = 0x02;

/***********************************************************************
 *                                       *
 *   Initialisierung der Variablen für den USART und des AD-Wandlers   *
 *                                       *
 ***********************************************************************/

//UBRR: Register zur Einstellung der Baudrate
//RXEN: Aktivierung des µC zum Empfangen von Daten
//TXEN: Aktivierung des µC zum Senden von Daten
//URSEL: Schreibzugriff auf UCSRC Register
//USBS: Anzahl der Stoppbits, hier 1
//UCSZ0: Anzahl der Datenbits, hier 8

  UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8);
  UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);

  
  // Enable receiver and transmitter; enable RX interrupt
  UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);

  //asynchronous 8N1
  UCSRC = (1 << URSEL) | (3 << UCSZ0);


//ADEN: Aktivierung des AD-Wandlers
//ADPS0-2: Teilungsfaktor für AD-Takt, hier 64
//ADIE: Aktivierung des AD-Wandler Interrupts
//ADMUX: Auswahl des AD-Input Pins

  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
  ADCSRA |= (1<<ADIE);
  ADMUX = 0x20;
  
/**********************************************************************
 *                                    *
 *   Aktivieren des Global Interrupt Enable Flags im Statusregister   *
 *   Starten des AD-Wandler für die Initialisierung            *
 *                                    *
 **********************************************************************/

  sei(); //Aktivierung des Global Interrupt Enable Flags im Statusregister (SREG)

  ADCSRA |= (1<<ADSC); //Aktivierung des AD-Wandlers
  while(!(ADCSRA & 0x10)) //Warten auf Beendigung der AD-Wandlung
  {

  }

/**************************************************************************
 *                                      *
 *   Beginn der Endlosschleife zur Abfrage der Dirty-Bits          *
 *   1) Prüfen ob noch genügend Platz im FIFO ist (30 Werte mindestens)   *
 *      - "i" ist die Zählvariable der schreibenden Einträge im FIFO    *
 *    - "imax" ist die Maximalanzahl von schreibbaren Einträgen      *
 *   2) Prüfen ob im jeweiligen Adressbyte das Dirty-Bit gesetzt ist    *
 *    - Maskierung mit 0x04 und gleichzeitigen Prüfen aus "TRUE"      *
 *   3) Wenn "FALSE" ist wird das nächste Adressbyte geprüft        *
 *   4) Wenn "TRUE" ist, dann werden der Interrupt deaktiviert,        *
 *     Adress- und Datenbyte in den FIFO geschrieben, das Dirty-Bit    *
 *    gelöscht, der Interrupt aktiviert und "i" inkrementiert.      *
 *                                      *
 **************************************************************************/

  while(1)   //Endlosschleife
  {
    if((i+30)<imax)   //Überprüfung ob genügend Speicherplatz im FIFO vorhanden ist
    {
      if(alvol & 0x04)   ///Überprüfung, ob das Dirty-Bit gesetzt ist
      {
        cli();   //Löschen des Global Interrupt Enable Flags im Statusregister
        alvol &= ~0x04;   //Löschen des Dirty-Bits
        adresse[i] = alvol;   //Speichern der Adressvariablen im FIFO
        daten[i] = (lvol >> 6);   //Speicherung der Datenvariablen im FIFO
        sei();   //Setzen des Global Interrupt Enable Flags im Statusregister
        i++;   //Inkrementierung des Indizes für den schreibenden Zugriff auf das FIFO
      }
      if(alpitch & 0x04)
      {
        cli();
        alpitch &= ~0x04;
        adresse[i] = alpitch;
        daten[i] = (lpitch >> 6);
        sei();
        i++;
      }
      if(amvol & 0x04)
      {
        cli();
        amvol &= ~0x04;
        adresse[i] = amvol;
        daten[i] = (mvol >> 6);
        sei();
        i++;
      }
      if(afader & 0x04)
      {
        cli();
        afader &= ~0x04;
        adresse[i] = afader;
        daten[i] = (fader >> 6);
        sei();
        i++;
      }
      if(arpitch & 0x04)
      {
        cli();
        arpitch &= ~0x04;
        adresse[i] = arpitch;
        daten[i] = (rpitch >> 6);
        sei();
        i++;
      }
      if(arvol & 0x04)
      {  
        cli();
        arvol &= ~0x04;
        adresse[i] = arvol;
        daten[i] = (rvol >> 6);
        sei();
        i++;
      }
      if(aleh & 0x04)
      {
        cli();
        aleh &= ~0x04;
        adresse[i] = aleh;
        daten[i] = leh;
        sei();
        i++;
      }
      if(alem & 0x04)
      {
        cli();
        alem &= ~0x04;
        adresse[i] = alem;
        daten[i] = lem;
        sei();
        i++;
      }
      if(alel & 0x04)
      {
        cli();
        alel &= ~0x04;
        adresse[i] = alel;
        daten[i] = lel;
        sei();
        i++;
      }
      if(ahpvol & 0x04)
      {
        cli();
        ahpvol &= ~0x04;
        adresse[i] = ahpvol;
        daten[i] = hpvol;
        sei();
        i++;
      }
      if(areh & 0x04)
      {
        cli();
        areh &= ~0x04;
        adresse[i] = areh;
        daten[i] = reh;
        sei();
        i++;
      }
      if(arem & 0x04)
      {
        cli();
        arem &= ~0x04;
        adresse[i] = arem;
        daten[i] = rem;
        sei();
        i++;
      }
      if(arel & 0x04)
      {
        cli();
        arel &= ~0x04;
        adresse[i] = arel;
        daten[i] = rel;
        sei();
        i++;
      }
      if(aljw & 0x04)
      {
        cli();
        aljw &= ~0x04;
        adresse[i] = aljw;
        daten[i] = ljw;
        sei();
        i++;
      }
      if(arjw & 0x04)
      {
        cli();
        arjw &= ~0x04;
        adresse[i] = arjw;
        daten[i] = rjw;
        sei();
        i++;
      }
      if(ahpsel & 0x04)
      {
        cli();
        ahpsel &= ~0x04;
        adresse[i] = ahpsel;
        daten[i] = hpsel;
        sei();
        i++;
      }
      if(altaste & 0x04)
      {
        cli();
        altaste &= ~0x04;
        adresse[i] = altaste;
        daten[i] = lpbs;
        sei();
        i++;
      }
      if(artaste & 0x04)
      {
        cli();
        artaste &= ~0x04;
        adresse[i] = artaste;
        daten[i] = rpbs;
        sei();
        i++;
      }
    }

/***********************************************************************************
 *                                           *
 *   5) Wenn mehr geschriebene als gelesene Daten im FIFO sind,             *
 *     wird die Funktion "senden" aufgerufen und "j" inkrementiert           *
 *    - "j" ist die Zählvariable der lesenden Einträge im FIFO           *
 *    - "jmax" ist die Maximalanzahl der zu lesenden Einträgen           *
 *   6) Wenn "i" größer als 170 wird, werden "imax", "jmax", und "i" neu gesetzt   *
 *   7) Wenn "j" die Maximalanzahl erreicht, wird j zurückgesetzt           *
 *   Ende der Endlosschleife                             *
 *                                           *
 ***********************************************************************************/

    if(i!=j)   //Überprüfung ob Indizes für schreibenden und lesenden Zugriff gleich ist, Index für schreibenden Zugriff ist immer voreilend
    {
      if(UCSRA & 0x20)   //Überprüfung ob das Senden-Register leer ist
      {
        senden(adresse[j], daten[j]);   //Aufruf der Funktion senden
        j++;   //Inkrementierung des Indizes für den lesenden Zugriff
        if(imax<=(i+30)) imax++;   //Überprüfung, ob noch Platz im FIFO für zu speichernde Werte ist
      }
    }

    if(i>170)   //Überprüfung, ob FIFO beim nächsten Durchlauf überlaufen könnte
    {
      imax = j;   //Festlegung der maximal zu schreibenden Einträge
      jmax = i;   //Festlegung der maximal zu lesenden Einträge
      i = 0;   //Reset des Indizes der schreibenden Einträge
    }

    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

  }
      
  return 0;
}

/***********************************************************************************
 *                                           *
 *   Beginn der ISR, die aufgerufen wird, wenn die AD-Wandlung abgeschlossen ist   *
 *                                           *
 ***********************************************************************************/

ISR(_VECTOR(14))
{

/******************************************************************************************
 *                                              *
 *   Auswahl der zu vergleichenden Reglervariablen mit dem ADC-Register,          *
 *   das mit dem Ergfebnis der vorherigen Wandlung belegt ist                *
 *   1) Wenn Ungleichheit besteht wird die Datenvariable mit dem  ADCH Register belegt,   *
 *    und das Dirty-Bit gesetzt. Bei xPBS wird eine extra Funktion aufgerufen.        *
 *   2) Wenn Gleichheit besteht, wird die Funktion fortgeführt                *
 *   3) Wenn "zaehler" einmal alle AD-Pins durchlaufen hat, wird er auf "0" gesetzt      *
 *                                              *
 ******************************************************************************************/

  switch(zaehler)   //Auswahl des AD-Einganges
  {
    case 0: if((lvol != ADC) && (lvol_old != ADC))
        {
          lvol_old=lvol;
          lvol = ADC;
          alvol |= 0x04;
        };
    break;
    case 1: if((lpitch != ADC) && (lpitch_old != ADC))   //bei Auswahl Vergleich, ob sich Datenvariable geändert hat
        {
          lpitch_old = lpitch;
          lpitch = ADC;   //Speichern der neuen Datenvariablen
          alpitch |= 0x04;   //setzen des Dirty-Bits
        };
    break;
    case 2: /*{
          if((lpbs != ADC) && (lpbs_old!=ACD))
          {
            trigger=1;
          }
          for(shift=8;shift>=0;shift--)
          {
            lpbs_temp[(shift+1)]=lpbs_temp[shift];
          }
          lpbs_temp[9]=lpbs_temp[8];
          lpbs_temp[8]=lpbs_temp[7];
          lpbs_temp[7]=lpbs_temp[6];
          lpbs_temp[6]=lpbs_temp[5];
          lpbs_temp[5]=lpbs_temp[4];
          lpbs_temp[4]=lpbs_temp[3];
          lpbs_temp[3]=lpbs_temp[2];
          lpbs_temp[2]=lpbs_temp[1];
          lpbs_temp[1]=lpbs_temp[0];
          lpbs_temp[0]=ADC;

          if((lpbs_temp[0] == lpbs_temp[1]) && trigger==1)
          {
            lpbs_old=lpbs;
            lpbs=ADC;
            altaste |= 0x04;
            trigger=0;
          } 
        };*/
    break;
    case 3: if((mvol != ADC) && (mvol_old != ADC))
        {
          mvol_old = mvol;
          mvol = ADC;
          amvol |= 0x04;
        };
    break;
    case 4: if((fader != ADC) && (fader_old != ADC))   
        {
          fader_old=fader;      
          fader = ADC;   
          afader |= 0x04;

        };
    break;
    case 5: /*if(rpbs != ADC)
        {
          rpbs = ADC;
          artaste |= 0x04;
        };
    break;*/
    case 6: if((rpitch != ADC) &&(rpitch_old != ADC))
        {
          rpitch_old = rpitch;
          rpitch = ADC;
          arpitch |= 0x04;
        };
    break;
    case 7: if((rvol != ADC) && (rvol_old != ADC))
        {
          rvol_old = rvol;
          rvol = ADC;
          arvol |= 0x04;
        };
    break;
  }

  zaehler++;   //Inkrmentierung zur Auswahl des nächsten Analogeingangs
  if(zaehler==8) zaehler = 0;   //Wenn alle Analogeingänge abgefragt wurden, wird der Zähler zurückgesetzt

  ADMUX = 0x20 | zaehler;   //Setzen des Auswahlregisters für den Analogeingang
  ADCSRA |= (1<<ADSC);   //Aktivieren des AD-Wandlers

/*******************************************************************************
 *                                         *
 *   Vergleichen aller nicht AD-Variablen mit den jeweiligen Pinzuständen     *
 *   1) Belegen von "k" mit den Variablenzuständen                 *
 *   2) Vergleichen von "k" mit den Datenvariablen                 *
 *   3) Wenn "FALSE", dann werden die restlichen Werte verglichen         *
 *   4) Wenn "TRUE", dann wird die Funktion zur Berechnung der Geberwerte     *
 *    aufgerufen, das Dirty-Bit gesetzt und die Vergleichsvariable belegt.   *
 *                                         *
 *******************************************************************************/

  k = PINB & 0x03;   //Belegung einer Variable mit den entsprechenden Pins
  if(k!=leh_old)   //Überprüfung, ob sich die Bitkombination geändert hat
  {
    leh = geber(k, leh_old);   //Aufrufen der Funktion "geber" zur Berechnung des absoluten Wertes
    aleh |= 0x04;   //setzen des Dirty-Bits
    leh_old=k;
  }
  
  k = (PINB & 0x0C) >> 2;  
  if(k!=lem_old)
  {
    lem = geber(k, lem_old);
    alem |= 0x04;
    lem_old=k;
  }

  k = (PINB & 0x30) >> 4;
  if(k!=lel_old)
  {
    lel = geber(k, lel_old);
    alel |= 0x04;
    lel_old=k;
  }

  k = PINC & 0x03;
  if(k!=hpvol_old)
  {
    hpvol = geber(k, hpvol_old);
    ahpvol |= 0x04;
    hpvol_old=k;
  }

  k = (PINC & 0x0C) >> 2;
  if(k!=reh_old)
  {
    reh = geber(k, reh_old);
    areh |= 0x04;
    reh_old=k;
  }

  k = (PINC & 0x30) >> 4;
  if(k!=rem_old)
  {
    rem = geber(k, rem_old);
    arem |= 0x04;
    rem_old=k;
  }

  k = (PINC & 0xC0) >> 6;
  if(k!=rel_old)
  {
    rel = geber(k, rel_old);
    arel |= 0x04;
    rel_old=k;
  }

  k = (PIND & 0x0C) >> 2;
  if((k!=ljw_old) && (k!=ljw_old2))
  {
    ljw = geber(k, ljw_old);
    aljw |= 0x04;
    
    ljw_old=k;
  }
  ljw_old2=ljw_old;
  k = (PIND & 0x30) >> 4;
  if((k!=rjw_old) && (k!=rjw_old))
  {
    rjw = geber(k, rjw_old2);
    arjw |= 0x04;
    
    rjw_old=k;
  }
  rjw_old2=rjw_old;
  k = (PIND & 0xC0) >> 6;
  if(k!=hpsel_old)
  {
    hpsel = geber(k, hpsel_old);
    if(hpsel==1)
    {
      PINB |=0x80;
      PINB &=0xBF;
    }
    if(hpsel==3)
    {
      PINB |=0x40;
      PINB &=0x7F;
    }
    ahpsel |= 0x04;
    hpsel_old=k;
  }
}

/**********************************************************************************
 *                                            *           *
 *   Die ISR wird aufgerufen, sobald ein Zeichen über die USART-Schnittstelle     *
 *   empfangen wurde. Das empfangene Zeichen steht dann im USART-Datenregister.   *
 *   Empfangen werden Anforderungen zur Datenübertragung. Es ist möglich vom PC   *
 *   aus alle oder nur einzelne Werte neu anzufordern. Eine Neuanforderung        *
 *   ist nur für die Werte der Schieberegler sinnvoll, da die Drehgeber und       *
 *   die Taster im Normalzustand 0 sind. Das  Senden wird ausgelöst durch setzen  *
 *   des jeweiligen Dirty-Bits.                            *
 *                                          *
 *********************************************************************************/
ISR(_VECTOR(11))
{
  int8_t wert;

  wert=UDR;

  if (wert==0x99) //Alle Werte neu senden. Sendeanforderung durch Setzten des Dirty-Bits
  {
    alvol   |= 0x04;
    alpitch |= 0x04;
    amvol  |= 0x04;
    afader   |= 0x04;
    arpitch |= 0x04;
    arvol  |= 0x04;
  }
  else
  {
    switch (wert)
    {
      case 0x10: 
      {
        alvol   |= 0x04;
        break;
      }
      case 0x18:
      {
        alpitch |= 0x04;
        break;
      }
      case 0x20:
      {
        amvol |= 0x04;
        break;
      }
      case 0x28:
      {
        afader   |= 0x04;
        break;
      }
      case 0x30:
      {
        arpitch |= 0x04;
        break;
      }
      case 0x38:
      {
        arvol |= 0x04;
        break;
      }
    }
  }
}


/**********************************************************************************
 *                                            *  
 *   Der Funktion "geber" wird die Ausgabe der Drehgeber übergeben                *
 *   Je nach Bitkombination wird die Drehrichtung bestimmt und ein Wert         *
 *   zurückgegeben. Dieser Wert basiert auf dem Drehsinn eines "normalen"         *
 *   Drehreglers in der HiFi-Technik (links=- und rechts=+).                      *
 *                                            *                                            *
 *********************************************************************************/
uint8_t geber(uint8_t bits_alt, uint8_t bits_neu)   //Übergabe der alten und neuen Bitkombination, Datenvariable 
{
  uint8_t wert;  

  switch(bits_alt)
  {
    case 0x00: 
    {    
          if(bits_neu==0x01) //Linksdrehung
            wert=1;
          else if(bits_neu==0x02) //Rechtsdrehung
            wert=3;  
          else 
            wert=2; //Keine Drehung
          break;
    }    
    
    case 0x01: 
    {   
          if(bits_neu==0x03) //Linksdrehung
            wert=1;
          else if(bits_neu==0x00) //Rechtsdrehung
            wert=3;
          else
            wert=2;  //Keine Drehung
          break;
    }

    case 0x02: 
    {   
          if(bits_neu==0x00) //Linksdrehung
            wert=1;
          else if(bits_neu==0x03) //Rechtsdrehung
            wert=3;
          else
            wert=2;  //Keine Drehung
          break;
    }

    case 0x03: 
    {   
          if(bits_neu==0x02) //Linksdrehung
            wert=1;
          else if(bits_neu==0x01) //Rechtsdrehung
            wert=3;
          else
            wert=2;  //Keine Drehung
          break;
    }
  
    default: wert=0xFF; //Nur zu Debug-Zwecken
  }


  return wert;   //Rückgabe der Drehrichtung
}

/***********************************************************************************************
 *                                                 *
 *   Der Funktion "taster" wird der Wert des ADC übergeben. Über ein Array, das die zu den     *
 *   jeweiligen Tastenkominationen gehörenden Analogwerte beinhaltet erfolgt die Auswertung    *
 *   Je nach Analogwert wird die Variable "taste" mit einem Wert belegt und zurückgegeben.     *
 *                                                 *
 ***********************************************************************************************/

uint8_t taster(uint16_t wert)   //Übergabe der Datenvariable
{
  uint16_t taste=0;   //Festlegung einer Speichervariablen
  uint8_t i;
  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};
  
  if(wert>=512)   //Folgender Block dient der Auswahl der Tasterkombination
  {
    for(i=0; i<32; i++)
    {
      if(wert <= widerstand[i])
      {
        taste=32-i;
        break;
      }
    }
  }

  else taste = 0x00;

  return taste;
}

/****************************************************************************************
 *                                            *
 *   Der Funktion "senden" wird die entsprechende Adress- und Datenvariable übergeben   *
 *   Unmittelbar nacheinander werden Adresse und Das High und Low-Byte der Daten-       *
 *   variable gesendet. Im Anschluss wird noch ein Füll-Byte übetragen, da der PC mit   *
 *   vier Byte besser umgehen kann. Dieses Füll-Byte zeigt zugleich auch das Ende eines *
 *   Datensatzes an und kann somit zur Synchronisation verwendet werden.        *                                          *
 ****************************************************************************************/

void senden (uint8_t adresse, uint16_t wert)   //Übergabe der Adress- und Datenvariable
{
  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind

  UDR = adresse;   //Adresse senden

  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind

  UDR = (wert >> 8 );   //Daten HIGH senden

  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind

  UDR = (wert & 0xFF);   //Daten LOW senden

  while (!( UCSRA & (1<<UDRE)));   //Warten bis Daten gesendet sind

  UDR = 'X';   //Auf 4 Byte auffüllen
}



Autor: Der Taster (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo in der Schaltung ist der ADC Eingang angeschlossen?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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?
          for(shift=8;shift>=0;shift--)
          {
            lpbs_temp[(shift+1)]=lpbs_temp[shift];
          }
          lpbs_temp[9]=lpbs_temp[8];
          lpbs_temp[8]=lpbs_temp[7];
          lpbs_temp[7]=lpbs_temp[6];
          lpbs_temp[6]=lpbs_temp[5];
          lpbs_temp[5]=lpbs_temp[4];
          lpbs_temp[4]=lpbs_temp[3];
          lpbs_temp[3]=lpbs_temp[2];
          lpbs_temp[2]=lpbs_temp[1];
          lpbs_temp[1]=lpbs_temp[0];
          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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.