Forum: Mikrocontroller und Digitale Elektronik Problem mit externer ADwandler und Atmega16


von smith (Gast)


Lesenswert?

Hallo

ich habe die 8bit Ausgänge von externer adwandler an PORTC von Atmega16 
angeschlossen.adwandler funktioniert gut
das problem liegt daran wenn ich die 8bit werte aus dem PORTC lesen will 
und damit ein LED anschalte bleibt der LED an auch wenn ich den Wert 
überschreite.
hiermit meine Source code:
Danke im Voraus für die hilfe

#define NR_SAMPLES 3    // Anzahl der Messungen, die gemittelt werden
#define LED1  PD0
#define OE    PD6
#define START PD7
#define C     PA6
#define B     PA5
#define A     PA4
#define data  PORTC

unsigned char ADC0809(unsigned char channel);
void init_ports();
int main()
{

  unsigned char d;

  init_ports();
  TIMER1_interrupt_init();

 sei();

  while( 1 )

  {
    d=ADC0809(0);
    if ( d < 125 )
    PORTD |= (1<<LED1);
    else PORTD &= ~(1<<LED1);
  }
}

void init_ports()
{
DDRD=0xFF; //PORTD als Ausgang
PORTD =0x00;
DDRC=0x00; //PORTC als Eingang
PORTC =0xFF;
}
unsigned char ADC0809(unsigned char channel)
{
  unsigned char adwert;
  unsigned char j;

  if ( channel == 0 )
  {
   PORTA &= ~ ( 1 << A) | ( 1 << B) | ( 1 << C) ;
  }
  if ( channel == 1 )
  {
   PORTA &= ~ ( 1 << B) | ( 1 << C) ;
   PORTA |=   ( 1 << A);
  }
  if ( channel == 2 )
  {
   PORTA &= ~ ( 1 << A) | ( 1 << C) ;
   PORTA |=   ( 1 << B) ;
  }
  if ( channel == 3 )
  {
   PORTA &= ~ ( 1 << C) ;
   PORTA |=   ( 1 << A) | ( 1 << B) ;
  }

  PORTD |=  ( 1 << START );
  PORTD &= ~( 1 << START );

  while( !(PINA & (1<<PINA3)) ) ;     //check for EOC to go high
  for( j = 0; j < NR_SAMPLES; j++ )
  {

   PORTD |=  ( 1 << OE );//enable output data
   adwert += data;      //read data
   PORTD &= ~ ( 1 << OE );            //disable adc
  }
  PORTD &= ~ ( 1 << OE );
  adwert /= NR_SAMPLES;


return adwert;          //return data
}

von Hc Z. (mizch)


Lesenswert?

smith schrieb:
> PORTD |=  ( 1 << OE );//enable output data
>    adwert += data;      //read data

Beim Einlesen eines Port-Werts hast Du eine Verzögerungszeit (1 Takt). 
Somit liest Du hier den Wert ein, der anlag, bevor OE angelegt wurde. 
Das ist nicht das tatsächliche ADC-Resultat.

Hätte der ADC keine OE-Verzögerungszeit, bräuchtest Du hier mindestens 
einen NOP dazwischen.  Dazu kommt die ADC-OE-Zeit.

Noch'n paar Anmerkungen:
1
  for( j = 0; j < NR_SAMPLES; j++ )
2
  {
3
4
   PORTD |=  ( 1 << OE );//enable output data
5
   adwert += data;      //read data
6
   PORTD &= ~ ( 1 << OE );            //disable adc
7
  }
Hier liest Du NR_SAMPLES mal ein, ohne eine Konversion neu zu starten. 
Eine sinnlose Übung, denn Du bekommst einfach immer denselben Wert, 
insgesamt also den NR_SAMPLESfachen Wert, anstatt mehrere Male 
tatsächlich zu sampeln.

Die ganze if-Kette in Deinem Programm kann übrigens durch eine Zeile
1
PORTA = (PORTA & ~(1<<A|1<<B|1<<C)) | (channel << A)
ersetzt werden.  Befasse Dich mal näher mit Bitmanipulationen, um 
weniger unnötige Bitwurschtelei zu erzeugen.

von smith (Gast)


Lesenswert?

Hc Zimmerer schrieb:
> PORTA = (PORTA & ~(1<<A|1<<B|1<<C)) | (channel << A)
biste sicher dass es richtig so? wenn wir channel 2 wählen was hat A da 
zu suchen.bin halt anfänger:)

von Hc Z. (mizch)


Lesenswert?

smith schrieb:
> Hc Zimmerer schrieb:
>> PORTA = (PORTA & ~(1<<A|1<<B|1<<C)) | (channel << A)
> biste sicher dass es richtig so?

Ich kann zwar keinen Fehler entdecken, aber das ist keine Garantie 
dafür, dass keiner drin ist.  Ich bin jedenfalls der Ansicht, dass das 
richtig so ist.

> wenn wir channel 2 wählen was hat A da
> zu suchen.bin halt anfänger:)

Das A ganz rechts steht für die Verschiebung der Bits in „channel“ und 
„<<“ ist der Verschiebeoperator.  Ich denke, das Einfachste wird sein, 
dass Du Dir ein Blatt Papier nimmst und Dir klar machst, was passiert, 
wenn Du die Bits in channel um 4 Bitpositionen nach links verschiebst (A 
hat ja den Wert 4).  Du wirst sehen, dass sie im Port auf den für A, B, 
und C vorgesehenen Plätzen landen.

Ein C-Buch leistet da wertvolle Dienste.

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.