Forum: Compiler & IDEs 1. ADC Programm


von Thomas (Gast)


Lesenswert?

Hallo zusammen,

ich habe in den letzten Tagen mein erstes C-Porgramm zur ADC-Auswertung 
geschrieben. Ich möchte über ein 10k Poti, Spannung am OC0 messen.

Ausgeben möchte ich den jeweiligen Wert über eine LED-Leiste über inkl. 
10 LED's.

Die Led's sind an PA0-PA7 und PA0-PA1.
Mein AtMega32 läuft über den internen Quarz mit 1MHz. Sonst habe ich nur 
den üblichen Grundaufbau am Mikrocontroller. Hardware sollte richtig 
verdrahten sein, da sich die LED's über ein anderes Programm ansprechen 
lassen. Weiter kann ich mit einem Multimeter einen veränderlichen 
Widerstand am Poti messen.
Es kann also nur noch an meinem Programm liegen, bzw. die Konfiguration 
dazu. Als Ref-Spannung nutze ich die 5V am AVCC.

Hier ist mein Programm:
1
#include <avr/io.h>
2
#include <inttypes.h>
3
4
5
volatile uint16_t voltage;      //Variable für Spannung an ADC 0-5V 5/1024 0,0048V pro Bit -> 4,8mV pro Bit, umgerechnet in Prozent
6
7
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples );
8
uint16_t ADC_Read( uint8_t channel );
9
10
DDRA = 0xff;
11
DDRB = 0x03;
12
13
int main(void)
14
{
15
    while(1)
16
    {
17
    //Auslesen des ADC
18
  voltage = ADC_Read_Avg(0, 4);  // Kanal 0, Mittelwert aus 4 Messungen
19
  
20
  
21
  //Ansteuern der LED's nach Spannungshöhe
22
  display_voltage(PORTA,PA0,100);
23
  display_voltage(PORTA,PA1,200);
24
  display_voltage(PORTA,PA2,300);
25
  display_voltage(PORTA,PA3,400);
26
  display_voltage(PORTA,PA4,500);
27
  display_voltage(PORTA,PA5,600);
28
  display_voltage(PORTA,PA6,700);
29
  display_voltage(PORTA,PA7,800);
30
  display_voltage(PORTB,PB0,900);
31
  display_voltage(PORTB,PB1,980);
32
    
33
  }
34
}
35
36
37
void ADC_Init(void) {
38
 
39
  // die Versorgungsspannung AVcc als Refernz wählen:
40
  ADMUX = (1<<REFS0);    
41
 
42
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
43
  // schon auf 0, also single conversion
44
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
45
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
46
 
47
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
48
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
49
  }
50
  (void) ADCW;
51
}
52
53
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )
54
{
55
  uint32_t sum = 0;
56
  
57
  for (uint8_t i = 0; i < nsamples; ++i ) {
58
    sum += ADC_Read( channel );
59
  }
60
  
61
  return (uint16_t)( sum / nsamples );
62
}
63
64
uint16_t ADC_Read( uint8_t channel )
65
{
66
  // Kanal waehlen, ohne andere Bits zu beeinflußen
67
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
68
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
69
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
70
  }
71
  return ADCW;                    // ADC auslesen und zurückgeben
72
}
73
74
75
void display_voltage(volatile uint8_t *Port, uint8_t Pin, uint8_t wert)
76
{  
77
  if (voltage >= wert){
78
    *Port |= (1<<Pin);      //Ausgang einschalten
79
  }
80
  else{
81
    *Port &= ~(1<<Pin);      //Ausgang ausschalten
82
  }
83
}

Kann mir vielleicht jemand sagen, wo mein Problem liegen kann?
Ich finde es einfach nicht. Hab schon mehrmals drüber geschaut.

Danke.

Gruß Thomas

: Verschoben durch User
von rava (Gast)


Lesenswert?

ich kenne ja deine Fehlermeldung nicht, aber schreibt doch mal die 
Funktionen in der Reihenfolge, in der sie benutzt werden:


ADC_Init und display_voltage sollten vor die main()-routine.
Außerdem rufst du ADC_Init gar nicht auf.

von Karl H. (kbuchegg)


Lesenswert?

rava schrieb:

> Außerdem rufst du ADC_Init gar nicht auf.

Erstens das und zweitens wird es auch eine gute Idee sein, die 
Ausgangspins an denen die LED hängen auch auf Ausgang zu schalten.

von N2 (Gast)


Lesenswert?

Hi,

ADC = Analog Digital Converter
Die Kanäle sind von ADC0 bis ADC7 (PA0 bis PA7).

Was Du mit dem Poti am OC0 (PB3) = Output Compare oder AIN0 (gehört zum 
AC = Analog COMPARATOR) machst, ist dem ADC ziemlich egal.

Du kannst den AC zwar für eine AD-Wandlung missbrauchen, aber dann wohl 
kaum mit Deiner ADC_Read...

Gruß N2

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> rava schrieb:
>
>> Außerdem rufst du ADC_Init gar nicht auf.
>
> Erstens das und zweitens wird es auch eine gute Idee sein, die
> Ausgangspins an denen die LED hängen auch auf Ausgang zu schalten.

Heck.
1
DDRA = 0xff;
2
DDRB = 0x03;
3
4
int main(void)
5
{
6
...

das compiliert doch gar nicht!

von Mirki (Gast)


Lesenswert?

Lass Dir das hier mal nochmal durch den Kopf gehen:

    //Auslesen des ADC
  voltage = ADC_Read_Avg(0, 4);  // Kanal 0, Mittelwert aus 4 Messungen


  //Ansteuern der LED's nach Spannungshöhe
  display_voltage(PORTA,PA0,100);
  display_voltage(PORTA,PA1,200);
  display_voltage(PORTA,PA2,300);
  display_voltage(PORTA,PA3,400);
  display_voltage(PORTA,PA4,500);
  display_voltage(PORTA,PA5,600);
  display_voltage(PORTA,PA6,700);
  display_voltage(PORTA,PA7,800);
  display_voltage(PORTB,PB0,900);
  display_voltage(PORTB,PB1,980);


void display_voltage(volatile uint8_t *Port, uint8_t Pin, uint8_t wert)
{
  if (voltage >= wert){
    *Port |= (1<<Pin);      //Ausgang einschalten
  }
  else{
    *Port &= ~(1<<Pin);      //Ausgang ausschalten
  }
}

von rava (Gast)


Lesenswert?

das finde ich, sieht noch fast okay aus.
1
uint8_t wert
 dürfte halt eigentlich nur zwischen 0 und 255 liegen.

von Thomas E. (thomase)


Lesenswert?

rava schrieb:
> das finde ich, sieht noch fast okay aus.

Aber nur fast. Die Leds liegen an PortA und der Adc auch. Krasses 
Multiplexing, sozusagen.

mfg.

von Thomas (Gast)


Lesenswert?

Hallo zusammen,

danke für all die Hinweise.
Es klappt nun. Hab die Hardware geändert, Programm neu strukturiert 
sowie ADC_init() rein gepackt.

Läuft bestens. :) Danke

Gruß Thomas

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.