Forum: Mikrocontroller und Digitale Elektronik A/D Wandler.


von Dieter (Gast)


Lesenswert?

(STK300 / ATmega103)

nun ist es endlich soweit. ich beschäftige mich mit meinem A/D-Wandler, 
und bin schon auf eine Menge Fragen gestoßen, von denen ich jetzt ein 
paar loslassen will.
ich habe meinen luftsensor an die AREF-spannung des A/D-Ports 
angeschlossen, und gemessen. 4,33V.
der ausgang meines sensors gibt mir 3,87V. Diesen Ausgang habe ich an 
einen der A/D Wandler geschlossen.
Die Masse vom Sensor habe ich an die Masse des STK300 geschlossen.
Im Programm lese ich mein ADCH und ADCL aus.
multipliziere diesen wert mit 4,33.
und dividiere das ganze durch 1024.
und raus bekomme ich 3,57V.

da 3,87 nicht gleich 3,57 ist, hab ich mir gedacht, da läuft irgend 
etwas falsch.

hier mein programmcode. ich hoffe jemand kann mir weiterhelfen.

--------------------------------------------------------
#include <mega103.h>
#include <stdio.h>
#include <delay.h>
#include <delay.h>
#include <stdlib.h>

unsigned int adc_data;
unsigned int a;
float b;
char s[6];
// ADC interrupt service routine
#pragma savereg-
interrupt [ADC_INT] void adc_isr(void)
{
printf("interrupt\n\r");
#asm
    push r30
    push r31
#endasm
// Read the AD conversion result
adc_data=ADCW;
#asm
    pop  r31
    pop  r30
#endasm

ADCSR|=0x40;
delay_ms(10);
a=ADCH;
a=a<<8;
delay_ms(10);
a=a | ADCL;
a*=4,33;
b= a/1024.0;
printf("%f\n\r",b);
ftoa(b,3,s);
puts(s);
putchar('\n');
putchar('\r');
getchar();

}
#pragma savereg+



// Read the AD conversion result
// with noise canceling
unsigned int read_adc(unsigned char adc_input)
{
printf("read_adc\n\r");
ADMUX=adc_input;
ADCSR&=0x7f;
ADCSR|=0xc0;
#asm
    in   r30,mcucr
    cbr  r30,__sm_mask
    sbr  r30,__se_bit
    out  mcucr,r30
    sleep
    cbr  r30,__se_bit
    out  mcucr,r30
#endasm
return adc_data;
}

unsigned char k;

void main(void)
{
// UART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// UART Receiver: On
// UART Transmitter: On
// UART Baud rate: 9600
UCR=0x18;
UBRR=0x19;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;

// ADC initialization
// ADC Clock frequency: 125,000 kHz
ADCSR=0x8D;

#asm("sei")

while (1)
      {
read_adc(0);
      }
}
--------------------------------------------------------

von infiniter (Gast)


Lesenswert?

Hallo!

Was ist dann denn für ein C-Compiler? Ich überlege gerade, ob "a = a | 
ADCL" ein ODER sein soll (kenne nur || für ODER).

Aber wenn der Compiler es schon möglich macht, 10 Bit-Werte zu 
dividieren (1024), dann könntest du den gesamten 16Bit-Wert (bzw. 10 
Bit) aus ADCH und ADCL deiner Variable a zuordnen und weiterrechnen. 
Wäre das nicht einfacher?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

"ich habe meinen luftsensor an die AREF-spannung des A/D-Ports 
angeschlossen, und gemessen. 4,33V"

Kannst du deinen Schaltplan mal näher erläutern?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

@infiniter:

| ist bitweises OR, d.h. die Bits werden einzeln verknüpft, während bei || nur 0 
oder 1 rauskommen kann.

http://web.cs.mun.ca/~michael/c/op.html

von Dieter (Gast)


Lesenswert?

CodeVisionAVR verwende ich.

übrigens danke für den Link Andreas.
mir ist gerade noch eine andere möglichkeit meiner schaltung 
eingefallen, ich werde die heute erstmal ausprobieren,
und mich dann nochmal melden.

von Dieter (Gast)


Lesenswert?

es funktioniert.
ich erklärs mal, falls ein anderer mal nen luftdrucksensor an ein STK300 
anschliesen möchte.

Versorgungspannung von 5V hab ich vom LCD-displayanschluss genommen. ich 
wollts erst von einen Portausgang nehmen, aber da brach die spannung 
immer zusammen. ich weiss aber nicht warum. vielleicht kann mir da ja 
jemand weiterhelfen.
den ausgang des sensors hab ich an Pin1 vom analogport angeschlossen.
die spannung vom LCDdisplayausgang muss man zusätzlich noch an AREF 
anlegen, da das maximale AREF vom STK ansonsten über einen drehknopf 
einstellbar ist, der aber bei maximum nicht auf 5V kommt, zumindest be 
mir nicht. die Referenzspannung muss aber gleich der eingangsspannung am 
Sensor sein.
dann folgendes programm, und fertig.

----------------------------------------------------------
#include <mega103.h>
#include <stdio.h>
#include <delay.h>
#include <stdlib.h>

unsigned int adc_data;
int Vmess;
float b;
char s[6];
// ADC interrupt service routine
#pragma savereg-
interrupt [ADC_INT] void adc_isr(void)
{
printf("interrupt\n\r");
#asm
    push r30
    push r31
#endasm
// Read the AD conversion result
adc_data=ADCW;
#asm
    pop  r31
    pop  r30
#endasm

}
#pragma savereg+



// Read the AD conversion result
// with noise canceling
unsigned int read_adc(unsigned char adc_input)
{

printf("read_adc\n\r");

ADMUX=adc_input;
ADCSR&=0x7f;
ADCSR|=0xc0;
#asm
    in   r30,mcucr
    cbr  r30,__sm_mask
    sbr  r30,__se_bit
    out  mcucr,r30
    sleep
    cbr  r30,__se_bit
    out  mcucr,r30
#endasm
return adc_data;
}



void main(void)
{
// UART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// UART Receiver: On
// UART Transmitter: On
// UART Baud rate: 9600
UCR=0x18;
UBRR=0x19;

#asm("sei")

while (1)
      {

if (PIND.0==0)
  {
  ADCSR|=0x40;            //Bei High im 6. Bit wird Conversation 
gestartet
  Vmess=read_adc(0b00000001);    //wert aus ADCL und ADCH an Pin1 
auslesen
  delay_ms(10);
  printf ("%7d",Vmess);
  delay_ms(10);
  Vmess*=5;
  b= Vmess/1023.0;
  printf("%f\n\r",b);
  ftoa(b,3,s);
  puts(s);
  putchar('\n');
  putchar('\r');
  delay_ms(400);
  }
      }
}
----------------------------------------------------------

ich muss trotzdem nocheinmal nachfragen.
warum kann ich den sensor nicht mit 5V von irgendeinem PortPin 
betreiben?
warum fällt die spannung da zusammen?

von Dieter (Gast)


Lesenswert?

ich wollte nun weiter arbeiten.

hab das programm nicht verändert, aber es geht nicht mehr.
es hat auch nichts mit dem problem zu tun, was ich hier auch gerade 
gepostet habe, da ich der chip manchmal doch richtig programieren lässt.

ich hab herrausgefunden, dß es an folgender stelle klemmt.
und zwar bleibt er in der praxis irgendwo in diesem codestück hängen.

im AVR-studio geht er zwar durch, setzt aber das ADIF-Bit im 
ADCSR-register nicht, welches ja den interrupt auslösen soll, der ADCH 
und ADCL beschreibt.

------------------------------

#asm
    in r30,mcucr
    cbr r30,__sm_mask
    sbr r30,__se_bit
    out mcucr,r30
    sleep
    cbr r30,__se_bit
    out mcucr,r30
#endasm

------------------------------

mein assembler ist leider zu schlecht, als ob ich hier einen fehler 
bemerken könnte.

dazu sei noch gesagt, daß dieser programmteil vom codewizard geschrieben 
wurde.
und wie gesagt vorher funktionierte.

ich kapiers einfach nicht.

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.