Forum: Compiler & IDEs Help: ADC code br0ken seit upgrade auf gcc 4.7.2


von ●● pit ●. (Gast)


Lesenswert?

Hi,

bin etwas ratlos und würde mich über einen Tipp freuen:

Habe von gcc 4.6.2 - mit dem mein Projekt einwandfrei läuft - auf 4.7.2 
aktualisiert, nun klappt mein ADC-Oversampling Code nicht mehr. Bevor 
ich den gcc gewechselt habe, hat der Code recht gut 12 Bit aus dem ADC 
interpoliert.

Kann mir netterweise jemand erklären, was nun mit dem neuen gcc in 
meinem Code falsch ist und - optional - warum das vorher geklappt hat?

Der Code soll einfach im Interrupt 128 samples aufaddieren und dann 
dividieren, so das 1023 dann (128 * 1023) >> 5 == 4092 wäre.

Nun aber kommt nur 0-31 raus, wenn ich den Wert von
1
adcOversampledValue[n]
 auslese. Die Hardware ist nicht verändert.

Ohne Oversampling (kommentierte Zeile) bekomme ich erwartungsgemäß 
0-1023.

Config & Code unten.

1000dank,

 - pit

System/Config: ATMega328p, 8MHz int. Oszillator.
ADC Prescaler auf 62.5kHz
Free Running Mode
ich lese abwechselnd 2 ADC-Channels

1
#define adcChannels  2
2
#define adcSelectChannel(channel) \
3
  (ADMUX = (ADMUX & (~((1<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0)))) | (channel))
4
5
uint8_t adcChannel = 0;
6
volatile uint32_t adcOversampledValue[adcChannels];
7
8
ISR(ADC_vect) 
9
{
10
  // adcOversampledValue[adcChannel] = ADC; // <- klappt, 0-1023
11
  
12
  static uint32_t adcOversampleSum[adcChannels];
13
  static uint8_t  adcOversampleCounter[adcChannels];
14
15
  adcOversampleSum[adcChannel] += ADC;
16
17
  if (++adcOversampleCounter[adcChannel] >= 128) {
18
    adcOversampledValue[adcChannel] = adcOversampleSum[adcChannel] >> 5;
19
    adcOversampleSum[adcChannel] = 0;
20
  }
21
22
  if (++adcChannel > (adcChannels - 1)) {
23
    adcChannel = 0;
24
  }
25
26
  adcSelectChannel(adcChannel);
27
}

von ●● pit ●. (Gast)


Lesenswert?

OK, hab's gefunden.

Man muss jetzt
1
adcOversampleCounter
auf 0 setzen, vorher hat der überlauf des uint8_t von 127->0 das wohl 
erledigt.

von Klaus W. (mfgkw)


Lesenswert?

BTW: Wenn adcChannel außerhalb der ISR angefasst wird, sollte sie 
volatile sein.
Oder wenn nicht: dann würde ich sie static in die ISR nehmen, damit es 
klar ist.

von MWS (Gast)


Lesenswert?

pit p. schrieb:
> Man muss jetzt
> adcOversampleCounterauf 0 setzen, vorher hat der überlauf des uint8_t von
> 127->0 das wohl  erledigt.

Seit wann läuft denn ein uint8 nach 127 über ?

von ●● pit ●. (Gast)


Lesenswert?

ja das ist mir dann im bett auch eingefallen :)
man sollte um 2 uhr nicht mehr alten code debuggen...

zwischenzeitlich im git nachgeschaut: war immer ein uint8_t und hatte 
ihn nicht zurück gesetzt in dem if()....

habe also noch immer keinen schimmer warum das jemals geklappt hat...


Klaus: adcChannel wird nur innerhalb angefasst, außer wenn cli()

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.