Forum: Compiler & IDEs ADC-Wandlungs-Ergebnis als Bitfolge an einem Port ausgeben


von Andre (Gast)


Angehängte Dateien:

Lesenswert?

hallo,
ich als Anfänger habe ein Problem was, so wie ich mir das denke, 
wahrscheinlich garnicht realisierbar ist. Also ich habe eine Schaltung 
(siehe Anhang: allerdings noch ohne Laserdiode) und möchte damit eine 
Temperatur messen. Den Spannungwert schicke ich dann an ADC0 also im 
falle meines Atmega16 PA0. Ab dort soll nun mein Programm den Wert 
erstmal digitalisieren und danach am PortB wieder ausgeben. Hierbei 
allerdings nur an einem Pin des PortB (in diesem Fall PB0). Hier soll 
die Bitfolge einfach hintereinander weg ablaufen und für jede 0 0V und 
jede 1 5V ausgeben. Da ich am Ausgang ein Ozziloskop angeschlossen habe 
kann ich dieses auch überprüfen. Leider komme ich zu keinen brauchbaren 
Ergebnissen. Ich werde direkt im Anschluss auch noch mein Code posten.
Ich hoffe jemand kann mir dabei helfen oder direkt sagen das ich das 
ganz anders angehen muss.
mfg andre

von Andre (Gast)


Angehängte Dateien:

Lesenswert?

hier der code.
mfg andre

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

1
#include "delay.h"
2
#define F_CPU ????
3
#define SYMBOL_DURATION 100
4
5
void send_data(uint8_t data) {
6
    uint8_t i;
7
    for (i=0; i<7; ++i) {
8
        if (data | 0x01) PORTB |= 0x01;
9
        else PORTB &= 0xFE;
10
        data <<= 1;
11
        _delay_ms(SYMBOL_DURATION);
12
    }
13
}

Vorher natürlich noch PB0 als Ausgang konfigurieren:

DDRB |= 0x01;


Hab den Code nicht getestet und es gibt jede Menge Möglichkeiten, das 
eleganter zu machen.

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz wrote:
>
1
> #include "delay.h"
2
> #define F_CPU ????
3
>

anders rum

>
1
> #define F_CPU ????
2
> #include "delay.h"
3
>

@Andre
F_CPU ist die Taktfrequenz deiner CPU. Diese muss natürlich vor dem 
Include von delay.h bekannt sein. Ein paar Makros in delay.h wollen 
nämlich damit Berechnungen anstellen.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Ups, sorry. Danke Karl Heinz.

von Andre (Gast)


Lesenswert?

danke für die schnellen antworten:)

ein paar kleine probleme sind hierbei jetz leider aufgetreten.

1. der ADC-Wert der sich hinter result verbirgt ist im uint16_t format. 
Dadurch spuckt er mir den Fehler aus das die Datei declarationen nicht 
ganz passen. Naja ist eigentlich nur ne Warnung.

2. und viel wichtiger ist: Ich habe garkeine delay.h :( jedenfalls sagt 
er das beim kompilieren. Ich benutze das STK500 mit AVR Studio 4 falls 
das irgendetwas ändert.

eine kleine Frage habe ich dann noch zu der Frequenz: lediglich den 
Zahlenwert in der Definition angeben, d.h. bei mir 4 die ich über den 
Externen Quarz habe oder 4 MHz?

mfg andre

von Karl H. (kbuchegg)


Lesenswert?

Andre wrote:
> danke für die schnellen antworten:)
>
> ein paar kleine probleme sind hierbei jetz leider aufgetreten.
>
> 1. der ADC-Wert der sich hinter result verbirgt ist im uint16_t format.
> Dadurch spuckt er mir den Fehler aus das die Datei declarationen nicht
> ganz passen. Naja ist eigentlich nur ne Warnung.

Die allerdings in deinem Fall ernst zu nehmen ist. Aber das wirst du 
schon noch sehen, wenn du dir die Werte erst mal extern ansiehst. :-)

> 2. und viel wichtiger ist: Ich habe garkeine delay.h :( jedenfalls sagt
> er das beim kompilieren. Ich benutze das STK500 mit AVR Studio 4 falls
> das irgendetwas ändert.

die ist in  <util/delay.h>


http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#avr-libc_Versionen_ab_1.6

> lediglich den Zahlenwert in der Definition angeben, d.h. bei mir 4
> die ich über den Externen Quarz habe oder 4 MHz?

#define F_CPU 4000000

von Andre (Gast)


Lesenswert?

danke schon mal im vorraus. compileren tut er jetz schon mal ohne 
probleme. ich programmiere das mal fix auf meinen µc und versuche dann 
die schaltung zu komplettieren.
mfg andre

von Andre (Gast)


Angehängte Dateien:

Lesenswert?

hier nun noch mal die neue code-datei mit allen anpassungen. habe ich 
noch irgendwelche fehler gemacht? beim declarieren erhalte ich jetz 
keine warnungen oder fehler mehr.
mfg andre

von Karl H. (kbuchegg)


Lesenswert?

1
uint16_t ReadChannel(uint8_t mux)
2
{
3
  uint8_t i;
4
  uint16_t result;
5
  ADMUX = mux;

Boing.
Genau jetzt hast du dir in ADMUX die Konfiguration der Referenzspannung 
zerschossen, die du vorher per Adcaktivate() eingestellt hast.

von Andre (Gast)


Angehängte Dateien:

Lesenswert?

upps... ja das hatte ich vorhin leicht hin und her verschoben... weil 
irgendwer meinte das es besser sei die referenzspannung nicht jedesmal 
neu einzustellen sondern nur einmal. aber so müsste es doch jetz stimmen 
oder?
mfg andre

von Andre (Gast)


Lesenswert?

leider funktioniert anscheinend das programm immer noch nicht. 
jedenfalls zeigt das ozilloskop keinen einzigen ausschlag auf 5V an die 
spannung klemmt eher die ganze zeit auf 0V. ich habe langsam die 
vermutung das ich mir veilleicht vorher schon den µc zerschossen haben 
könnte. aber dann würde mein stk den doch garnicht mehr erkennen und 
programmieren oder?
mfg andre

von Karl H. (kbuchegg)


Lesenswert?

Haben wir alle übersehen

> uint16_t send_data(uint16_t data)
> {
>     uint8_t i;
>     for (i=0; i<7; ++i)
>   {
>         if (data | 0x01) PORTB |= 0x01;
>         else PORTB &= 0xFE;
>         data <<= 1;

falsche Richtung. muss lauten
          data >>= 1;

>     _delay_ms(10);
>   }
>   return 0;
> }

Gib halt mal zur Kontrolle das Datenbyte auch auf Port C aus. Dann hast 
du eine Komponente (nämlich das Raustakten auf B) weniger, die 
fehlerhaft sein kann.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Du kannst ja mal in der Endlosschlaufe nur send_data(0xAA) ausführen 
lassen, dann siehst du schon mal, ob der Teil mit dem Port funktioniert. 
So sollte der Pin ca. im 100ms Takt zwischen 0 V und 5 V wechseln.

Kleines Detail: Es genügt, PB0 nur einmal als Ausgang zu konfigurieren. 
D. h. DDRB = 0xff; kannst du vor die Endlosschlaufe setzen.

Dein ganzer AD-Teil scheint mir ein wenig abeteuerlich. Lies nochmals 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29

Mit welcher Auflösung möchtest du Sampeln? 8 Bit genügt in vielen 
Fällen, und dann musst du schauen, dass das Ergebnis im ADC-Register 
richtig ausgerichtet ist. Bei 8 Bit optimalerweise rechtsbündig.

Noch ein Detail: result /= 4; kann man auch als result >>= 2; schreiben. 
Weiss nicht, ob der Compiler das sowieso schon optimisiert, aber schaden 
tut's sicher nicht.


Und nochmals: Vielen Dank Karl Heinz, ich erschrecke immer wieder, wie 
viele Fehler ich mache ;-)

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz wrote:

> Noch ein Detail: result /= 4; kann man auch als result >>= 2; schreiben.
> Weiss nicht, ob der Compiler das sowieso schon optimisiert, aber schaden
> tut's sicher nicht.

Ja tut er. Ich kenn keinen einzigen Compiler, der das nicht drauf hat 
(auch in schwierigeren Fällen, bei denen n keine 2-er Potenz ist)

Hier gilt die Regel: Schreibs so, wies für einen Menschen am klarsten 
ist. Bei einem arithmetischen Mittel ist die Division sicherlich klarer 
als irgendwelche Shifts. Alles andere überlass dem Compiler. Der kennt 
schon noch ein paar Tricks um Taktzyklen zu sparen, die 95% aller C 
Programmierer nicht kennen. Und die, die wir alle kennen, die hat er 
sowieso drauf.

Das ermöglicht dann auch, einen potentiellen Fehler zu vermeiden (den 
der OP glaub ich sogar schon gemacht hat)
1
#define SAMPLES 4
2
3
uint16_t ReadChannel()
4
{
5
  uint8_t i;
6
  uint16_t result;
7
  ADCSRA |= (1<<ADSC);              
8
  while ( ADCSRA & (1<<ADSC) ) 
9
    ;
10
  result=ADCW;  
11
  result = 0; 
12
  for( i=0; i<SAMPLES; i++ )
13
  {
14
    ADCSRA |= (1<<ADSC);           
15
    while ( ADCSRA & (1<<ADSC) ) 
16
      ;   
17
18
    result += ADCW;        
19
  }
20
  return result / SAMPLES;
21
}

und schon kann es nicht mehr passieren, dass mit einer anderen Zahl 
dividiert wird als der Anzahl an Messungen. Und einfach anzupassen ist 
diese Anzahl dann auch :-)

Die ADC Routine hab ich mir jetzt nicht weiter im Detail angesehen. Im 
kurzen Überfliegen ist mir nichts mehr ins Auge gestochen

von Andre (Gast)


Lesenswert?

hi

nachdem ich jetz all eure weitern hinweise beherzigt habe und auch mal 
die ports durchprobiert habe und sogar auf internen takt zurückgestellt 
habe um auszuschlißen das der quarz kaputt ist gehe ich davon aus das er 
µc kaputt ist denn es rührt sich immer noch garnichts an den ausgängen. 
sagt zumindestens mein ozilloskop. bei dem gehe ich allerdings davon aus 
das es funktioniert da es alles andere problemlos messen kann. ich danke 
euch trotz dessem und hoffe das das programm und die schaltung mit einem 
neuen µc funktioniert. falls irgendeinem noch etwas in meinem programm 
auffällt das totaler blödsinn ist meldet ecuh bitte:)

mfg andre

von Andre (Gast)


Lesenswert?

ich habe eben mit erstaunen entdeckt das ich mit dem abgeänderten 
programm an PC3 und PC5 um die 3,5V anliegen habe... allerdings auch 
ständig ohne das sich an dem wert was ändert. da ich im programm 
allerdings den gesamten port als ausgang geschaltet habe und auch auf 
den gesamten port meine daten sende müsste meiner meinung auf dem 
gesamten port auch dasselbe ausgangssignal anliegen oder? die restlichen 
pins von portc sind übrigens auf 0V. es ist aber auch immer noch ein und 
der selbe µc. habe es noch nicht geschafft einen neuen zu besorgen.
mfg andre

von Karl H. (kbuchegg)


Lesenswert?

> µc kaputt ist denn es rührt sich immer noch garnichts an den ausgängen.

In so einem Fall fall ich sofort zurück auf Plan Alpha:

Schalt einfach mal an einem Port das Bitmuster 0xAA auf und schau nach 
ob abwechselnd ein Pin 0 bzw. 1 ist.

Wenn das kommt, dann ist der µC nicht defekt

int main()
{
  DDRB = 0xFF;
  PORTB = 0xAA;

  while( 1 )
    ;
}

von Karl H. (kbuchegg)


Lesenswert?

Mega16 und Probleme am Port C. Das JTAG hast du per Fuse abgeschaltet?

Wie programmierst du eigentlich deinen Mega16. In deinem Schaltplan da 
oben ist kein ISP Interface eingezeichnet.
Welchen Programmer benutzt du (ist mir passiert: benutzte einen 
Minimalprogrammer direkt am Parallelport vom PC, und das sch... Windows 
hat mir den Prozessor ständig im Reset gehalten)

von Andre (Gast)


Angehängte Dateien:

Lesenswert?

ja das habe ich angewendet. im send_data und auch einfach im 
main-programm. aber kein resultat... alle pins bleiben tot bis auf die 
beiden pins von portc, was sehr verwunderlich ist. anbei ist nochmals 
das programm, nicht das ich da was falsch interpretiert habe. bei der 
simulation im avr zeigt er mir das auch schön an. nur mein 
microcontroller macht irgendwie nix von dem was ich ihm auftrage...
mfg

von Andre (Gast)


Lesenswert?

achso ich benutze ein stk500. die fusebits sind eigentlich im default 
zusatnd bis auf der externe takt den ich auf EXT. Crystal/resonator 
gestellt habe. sonst würde er ja meinen quarz garnicht verwenden. laut 
dem avr-studio benutze ich PP/HVSP als programm mode. also keine in 
system programmierung. die einstellungen auf dem board sind auch 
dementsprechend.

von Andre (Gast)


Lesenswert?

achso: das jtag habe ich eben dann auch mal abgeschaltet... das ist ja 
im auslieferungszustand gesetzt...

von Andre (Gast)


Lesenswert?

positiv ist nachdem ich jtag ausgeschaltet habe habe ich keine 3,5V mehr 
auf PC3 und PC5:) leider habe ich niergenswo irgendwelche V. alles ist 
auf 0V. ich fand aber die idee mit dem reset sehr interessant. kann das 
auch mit dem stk500 passieren? oder kann es sein das ich mich durch die 
fusebits aus dem µc ausgesperrt habe? vielleicht läuft er ja einfach 
garnicht mehr an...
mfg

von Karl H. (kbuchegg)


Lesenswert?

Mit dem STK500 sollte es solche Probleme eigentlich nicht geben.

Was ist mit einem Minimalprogramm? Einfach mal einen Port komplett auf 1 
setzen

int main()
{
   DDRC = 0xFF;
   PORTC = 0xFF;

   while( 1 )
     ;
}

machen die Pins mit?

(So ein Testprogramm ist in 0 Komma Nix geschrieben und es geht nur 
darum festzustellen, ob den µC schon geschrottet ist oder nicht, ob du 
dich ausgesperrt hast, ob die Programmierung klappt, ...)

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.