Forum: Mikrocontroller und Digitale Elektronik Tachoprogramm mit ATMega8535 C-Problem


von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Erstmal dazu ich habe übersoein Problem schon überall geguckt, aber es
kommt mir so vor als wenn noch niemand versucht hat ein Tachometer
zuprogrammieren.
Aufjedenfall habe ich ein Software Problem und zwar mit C.
Ich habe das Programm zwar fertig aber es funktioniert nicht.
Hardware ist in ordnung alles geprüft.
Ich kann mir nur nicht erklären warum das Programm selber nicht
funktioniert.
Das einzige was auf den 3 segment anzeigen angezeigt wird ist 0.
Das soll er auch tun aber er fängt nicht anzuzählen.
Ich wollte also fragen ob sich jemand damit auskennt und mir helfen
kann.
Ich hoffe jemand hat eine Idee.
Was ich falsch gemacht habe.
wenn ihr noch fragen habt was ihr braucht um mir zuhelfen dann schreibt
mir bitte per email oder hier als antwort.
Danke

von H.joachim S. (crazy_horse)


Lesenswert?

ups, na ja...
du solltest das Gundkonzept nochmal überdenken.
Die Segmentansteuerung sieht etwas sehr unübersichtlich aus (das macht
man mit einer Tabelle, die im Flash steht).

if(v => 100)
{

  v1=v/100;
  v2=(v-(v1*100))/10;
  v3=v-((v1*100)+(v2*10));
}
if(v => 10)
{


  v2=v/10;
  v3=(v-(v2*10));
}
if(v < 10)
{



  v3=v;
}
}
Das ist auch nicht gerade elegant gelöst, falsch noch dazu. Wenn schon
tippel-tappel-tour, müsste dann ein else if hin (falls v>=100 ist, wird
bei dir auch die Berechnung für v>=10 durchgeführt).
Da aber jegliche Kommentare fehlen, fällt es mir ziemlich schwer da
durchzusteigen. So könnte man nur mit viel Mühe dahinterkommen, was du
eigentlich da machst.

von Nils (Gast)


Lesenswert?

Hallo Dennis,

auf den ersten Blick fällt mir auf, dass Dein Prototyp und die Funktion
verschieden heißen, aber das ist wohl nur ein Tippfehler...

int avriabler_zaehler(void);
int variabler_zaehler(void){}

Hast Du schon mal etwas von switch-case-Abfragen gehört? Diese
1
if(v1==0) {
2
  PORTB = 0xf6;
3
}
4
...

Abfragerei ist ja gräßlich.

Probier mal:
1
switch( v1 )
2
     {
3
        case  0:  PORTB = 0xf6;
4
        case  1:  PORTB = 0x14;   
5
        case  2:        ...
6
     }

Zu Deinem eigentlichen Problem: Meine Glaskugel ist defekt, beschreibe
doch nur mal kurz, was Du da für Impulse detektierst. Am besten Du
zeigst mal eine Schaltung.

Kommentare im Quelltext sollen ungemein der Leserlichkeit von
Programmen dienen, hat mal jemand gesagt...

Gruß, Nils

von Nils (Gast)


Lesenswert?

Sorry für das Doppelposting... Ich weiß auch nicht, wie ich das
geschafft habe.

Ja, eine Tabelle ist noch um ein vielfaches eleganter.

Nils

von Karl heinz B. (kbucheg)


Lesenswert?

> int main(void)
> {
>   DDRA = 0xff;
>   DDRB = 0xff;
>   DDRC = 0x00;
>   DDRD = 0xff;
>
>   PORTA = 0xf6;
>   PORTB = 0xf6;
>   PORTD = 0xf6;
>
>
>
>     int zaehler(void);

Das hier ist kein Funktionsaufruf.
Das deklariert einfach nur das es irgendwo eine Funktion
namens 'zahler' gibt, die keine Argumente erwartet
und einen int zurückliefert.
Um die Funktion auszurufen, schreibst du

                zaehler();

>  do
>  {
>    int avriabler_zaehler(void);

dito

>    int berechnung(void);

dito

>    int segment_1(void);

dito

>    int segment_2(void);

dito

>    int segment_3(void);

dito

>  }

Wusste gar nicht, dass man in C jetzt auch mitten drin
Deklarationen machen kann.

Auf jeden Fall: Da sind noch einige andere Syntaxfehler.
Das gepostete geht nie und nimmer durch den Compiler.

Es heist

     if(  a >= b )

und nicht

     if(  a => b )


Du brauchst dringend Einführungsliteratur zum Thema 'Einführung
in C'

von Dennis Wolkenhauer (Gast)


Lesenswert?

Erstmal vielen vielen dank für die hilfe.
ICh weiß das ich selber kein C Ass bin :).
Und ich wundere mich eigentlich darüber das jeder auf die Syntax und
if-fehler aufmerksam geworden ist.
Diese werden natürlich sofort geändert.
Ich hätte nur noch ine Frage .
Und zwar sind die Timer richtig gemacht?
denn ich kenne mich mit controllern genauso gut aus wie mit C :)
und zum Compilieren.
Komischerweise kann ich das ohne fehler und warnungen Kompilieren.
Aber trotzdem werde ich es mit euren hilfen ändern.
Danke nochmal an alle

von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal meine Documentation.

Und nochmal zur erklärung, damit ihr das auch versteht.
Als Simulator haben wir ein 28 zoll Rad mit einem Signalgeber (TTL) das
bei jedem mal wenn das Rad einmal rum ist ein signal gibt.
Da ich irgendwie die Frequenz meines Controllers rausfand habe ich mir
überlegt wie das umgehen kann.
Undzwar in dem ich impulse zähle wenn das Rad bei 1km/h einmal
herumlaüft.
Also signal timer start zweites signal Timer auslesen. Das wird
gespeichert.
Am besten für immer hab nur noch nicht rausgefunden wie.
Das macht er in der Funktion zaehler.
Dann haben wir die Funktion variabler_zaehler dort wird es dauerhaft
geprüft.
Ich meine damit das sowie der motor an ist der das Rad antreibt,
jedesmal wenn das rad rum ist die geschwindigkeit anzeigt.
Und hier wird halt gezählt um dies mit der festen impulszahl die wir
bei 1km/h gezählt haben ins verhältnis setzt.
Also stellt euch vor das Rad bewegt sich mit einer geschwindigkeit von
5km/h, dann muss natürlich ein fünftel von dem gezählt werden wie bei 1
km/h weil sich das rad ja fünfmal schneller dreht.
und die restlichen berechnungen mit 100 und 10 dient nur dazu die
zahlen zu vereinzeln. Also wenn ich 293 km/h raus habe soll er ja auf
jedem meiner 3 segmente eine zahl ausgeben und um das zugewährleisten
muss ich diese in 3 zahlen aufteilen.
Ich hoffe das hilft euch weiter.
Danke

von H.joachim S. (crazy_horse)


Lesenswert?

Ohne dir schon wieder an den Karren fahren zu wollen - Word-Dokumente
sind hier nicht sonderlich beliebt, bei mir gibts nichtmal Word. Gehts
auch als reine Text-Datei?

von Simon K. (simon) Benutzerseite


Lesenswert?

Oben bei dieser Switch-Case Anweisung ist ein Fehler. Nach jedem
case-Block muss ein break; kommen, damit er aus dem Konstrukt
herausspringt.

von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

Hier als txt docu.

Habe es allerdings nur kopiert und weil da grafiken drinnen sind kann
es sein das dort stellen sind wo rauf ich mich auf die grafik bezogen
habe.
Aber wenn man den quellcode dazu nimmt kommt man eigentlich ganz gut
zurecht.
Und nochwas ich kann schon einiges ab und keine fährt mir an den
karren.
warum auch ich erwarte sogar das ihr mir eure meinung dazu sagt, damit
ich es beim nächsten mal besser machen kann. also danke

von Karl H. (kbuchegg)


Lesenswert?

> Und ich wundere mich eigentlich darüber das jeder auf die Syntax und
> if fehler aufmerksam geworden ist

Liegt vielleicht daran, dass das ganz elementare Fehler sind.
Jeder C-Anfänger sollte eigentlich einen Grossteil dieser
Fehler nach der zweiten Lehrstunde 'Einführung in C' nicht
mehr machen, bzw. selbst finden können

> Hier nochmal meine Documentation.
Und?
Wo ist jetzt dein korrigiertes Program?

Du kannst mal davon ausgehen, dass diejenigen die dein
Pgm hier korrigieren schon einige Jährchen programmieren
am Buckel haben. Denen brauchst du nicht die elementarsten
Dinge der Sprache C erklären. Was wir aber von dir erwarten:
Wenn wir dir schon Hilfestellung geben, dass du dann dein
Pgm entsprechend umbaust und das veränderte Pgm, falls
du noch Schwierigkeiten hast, wieder postest.

Persönlich denke ich, dass du dich mit der Aufgabenstellung
etwas übernommen hast. Du versucht, bildlich gesprochen,
einen Marathon zu gewinnen noch bevor du gehen gelernt hast.

von Dennis Wolkenhauer (Gast)


Lesenswert?

>> Liegt vielleicht daran, dass das ganz elementare Fehler sind.
>> Jeder C-Anfänger sollte eigentlich einen Grossteil dieser
>> Fehler nach der zweiten Lehrstunde 'Einführung in C' nicht
>> mehr machen, bzw. selbst finden können

Diesen kommentar hättest du dir auch sparen können.
Ich weiß selber das ich ein grosser Anfänger bin.
Meiner meinung nach ist das was ich aber gmacht habe nur schlechter
c-stil und ich glaube nicht das das so wichtig hier ist oder.
Genauso wenn ich mich verschrieben haben soll bei diesen if warum
meckert der compiler dann nicht.

Aber sry das jemand der nicht gut in etwas ist fragen hat.
Aber typisch wenn man was kann vergisst man schnell das man selber mal
angefangen hat.
Und ausserdem ist das ein projekt für die schule und nicht für mich.
Ich finde es echt schade das es soviele leute gibt die einen an den
kopf werfen müssen das man schlechter als ein anfänger ist nur weil man
was nicht so begriffen hat.
Ma sehen vielleicht bekomme ich das noch hin.
Vielleicht ist ja jemand hier der sich die mühe macht die documentation
durchzulesen und mir dann bei meinen Problem zuhelfen.
Danke

von Dennis Wolkenhauer (Gast)


Lesenswert?

zu crazy_horse

Vielleicht sagst du mir mal ob du damit ein bestimmtes buch meinst oder
einfach nur als Satz.
wenn es ein buch ist könntest du mir die ISBN nummer gebn und den autor
name wäre cool
Danke

von Karl H. (kbuchegg)


Lesenswert?

> Diesen kommentar hättest du dir auch sparen können.

Nur dann wenn du dir gespart hättest:
>>Und ich wundere mich eigentlich darüber das jeder auf die Syntax und
>> if fehler aufmerksam geworden ist

> Meiner meinung nach ist das was ich aber gmacht habe nur
> schlechter c-stil
Na ja.

Im Ernst: so schlecht ist dein Stil gar nicht. OK. die
riesengrossen switch-case Leisten hätte man vermeiden
können, aber Rest ist gar nicht so übel.
Bis auf die paar lausigen und üblen Syntax-Fehler.
Aber wenn du die korrigierst, sollte man im AVR-Studio
im Simulator schon einiges sehen können. Wenn du
allerdings nichts korrigierst wirst du auch nicht viel
sehen, da dein Pgm dann ausser der Initialisierung nichts
macht.

von Karl H. (kbuchegg)


Lesenswert?

> v=(((3.14*(28*2.54))/100)/(8,037/impuls_diverenz))*3.6;

                              ^
                              |
                           Kommazahlen werden mit einem .
                           geschrieben, nicht mit einem ,

Durch das , hat dein Code eine interessante Wendung bekommen.
Das soll auch mal folgendes verdeutlichen
* Wenn der Compiler ein Pgm anstandslos annimmt, heist
  das noch lange nichts
* In C ist es möglich mit nur einem falsch gesetzten Zeichen
  ein Pgm komplett im Sinn zu verändern. Und zwar ohne das
  der Compiler etwas auszusetzen hätte. Das Pgm entspricht
  immer noch den C-Sprachregeln, macht aber etwas komplett
  anderes.
* daraus folgt: In C muss man besonders grosse Sorgfalt walten
  lassen. Vieles was syntaktisch richtig ist, ist aus Sicht
  allgemeiner Programmierlogik kompletter Unsinn.

von Dennis Wolkenhauer (Gast)


Lesenswert?

gut das du noch da bist ich habe das mit den funktionen ausprobiert und
der compiler meckert wenn ich es so mache wie du aber nicht wenn ich
die funktion in der main mit int und void mache.
muss ich noch zusätzlich zaehler(); ?

von Dennis Wolkenhauer (Gast)


Lesenswert?

krass nur ein kleiner tipp fehler und alle fehler sind weg :)

von Dennis Wolkenhauer (Gast)


Lesenswert?

../probe.c:42: warning: implicit declaration of function `zaehler'

das habe ich jetzt stehen wenn ich das so mache wie du gesagt hast bei
allen meinen funktionen.
WAs heißt das genau?

von Karl H. (kbuchegg)


Lesenswert?

Punkt 1)
  Wie sieht dein Pgm jetzt exakt aus
  Poste mal die Quellcode-Datei
Punkt 2)
  Sag niemals: Der Compiler meckert.
  Der Compiler gibt dir eine Fehlermeldung. Die gibt (meist)
  einen Hinweis darauf was falsch ist.
Punkt 3)
  So wie du es gemacht hast, ist das zwar syntaktisch richtig
  (= entspricht den Regeln der Sprache) ist aber trotzdem
  Unsinn. Du willst an dieser Stelle ja nicht die Funktion
  deklarieren, sondern du willst die Funktion aufrufen.

von Dennis Wolkenhauer (Gast)


Lesenswert?

#include <avr/io.h>

#include <stdint.h>

int zaehler();
int variabler_zaehler();
int berechnung();
int segment_1();
int segment_2();
int segment_3();





int v=0;

int v1=0;

int v2=0;

int v3=0;

int impuls_diverenz;

unsigned int impuls_1;
unsigned int variable_impuls_1;
unsigned int impuls_2;
unsigned int variable_impuls_2;
unsigned int impuls_fest;
unsigned int impuls_variable;






int main(void)
{
  DDRA = 0xff;
  DDRB = 0xff;
  DDRC = 0x00;
  DDRD = 0xff;

  PORTA = 0xf6;
  PORTB = 0xf6;
  PORTD = 0xf6;



    zaehler();
  do
  {
    variabler_zaehler();
    berechnung();
    segment_1();
    segment_2();
    segment_3();
  }
  while(PINC2==0);

}

von Dennis Wolkenhauer (Gast)


Lesenswert?

Aso und als warnung kommt noch

../probe.c:62: warning: control reaches end of non-void function

das andere habe ich behoben da ich die funktionen garnicht deklariert
hatte.

von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

hier die ganze datei

von Karl H. (kbuchegg)


Lesenswert?

> ../probe.c:42: warning: implicit declaration of function `zaehler'

OK.
Der Compiler arbeitet dein Pgm von oben nach unten durch.
Wenn er oben anfängt weiss er noch gar nichts, ausser den
C-Schluesselwoertern. Stoesst er jetzt auf etwas, was ernicht
kennt, dann gibt es 2 Moeglichkeiten:
* wird das was er nicht kennt wie eine Variable verwendet, zb
    i = 2 * j;    // j nicht deklariert
  dann lautet die Fehlermeldung meist: undefined reference
  oder so ähnlich
* wird das was er nicht kennt wie ein Funktionsaufruf verwendet
  zb.
     zaehler();
  dann geht der Compiler davon aus, dass tatsaechlich irgendwo
  eine Funktion namens 'zaehler' existiert. Da er aber nichts
  weiter darueber weis, nimmt er Standardannahmen an:
  * die Funktion erwartet keine Argumente
  * die Funktion liefert einen int zurück.

  Und genau das teilt dir der Compiler mit: implizit declaration
  also: eine durch die Verwendung festgelegte Deklaration. Durch
  die Art und Weise wie du die Funktion verwendet hast, bastelt
  sich der Compiler selbst eine Deklaration zurecht.

Was kannst du dagegen tun.
Das einfachste ist es, die Funktion einfach vor ihrer Verwendung
zu definieren. ALso in der Art

void zaehler()
{
  ....  // mach was
}

int main()
{
  ....
  zaehler();
}

Wenn sich jetzt der Compiler wieder von oben nach unten
durcharbeitet, so sieht er zuerst die Funktion zaehler() in
ihrer ganzen Pracht und kann sich daher auch merken, wie die
Schnittstelle zu ihr aussieht: das sie keine Argumente entgegen
nimmt und nichts zurückliefert.
Wenn er dann auf den Funktionsaufruf stösst, schaut der Compiler
in seinen internen Tabellen nach, ob er eine Funktion zaehler()
kennt. "a da ist sie. Wie war das: nimmt keine Argument und
liefert nichts zurück. Prima, passt genau zu der Art und Weise
wie die Funktion aufgerufen wird. Alles klar, kann ich so übersetzen"

Eine andere Möglichkeit ist es, eine Funktion einfach nur vor
der ersten Verwendung zu deklarieren:

void zaehler( void );  /* das ist eine Deklaration. Sie sagt nur
                          aus, dass es irgendwo eine Funktion namens
                          zaehler gibt und dass sie keine Argumente
                          erwartet und auch nichts zurückliefert
                       */

int main()
{
  ...
  zaehler();           /* mit der Deklaration von oben, hat der
                          Compiler alles was er an dieser Stelle
                          braucht.
                          Er weiss, dass es tatsaechlich eine
                          Funktion zaehler gibt (koennte ja auch
                          ein Tippfehler sein). Er weiss auch, dass
                          zahler() keine Argument annimmt und nichts
                          zurückliefert.
                          Mehr interessiert ihn an dieser Stelle
                          nicht. Der Compiler will nur überprüfen
                          ob der Aufruf der Funktion dieser Schnitt-
                          stellenvereinbarung entspricht oder nicht.
                        */
  ...
}

void zaehler()
{
   .....     /* und hier ist dann die Funktion zaehler in ihrer
                ganzen Pracht
             */
}

von Dennis Wolkenhauer (Gast)


Lesenswert?

man finde ich echt nett das du mir das so ordentlich erklärst und
voralle dem ich habs sogar verstanden:)
Danke für die mühe
finde ich super

von Karl H. (kbuchegg)


Lesenswert?

OK  (unsere Nachrichten überschneiden sich)

Also, den implicit declaration hast du ja jetzt behoben
War wohl Möglichkeit 3: ein simpler Tippfehler.

Was heist jetzt: control reaches end of non-void Funktion.

Nun. Du hast eine Funktion

int zaehler()
{
  ..
}

das 'int' da vorne bedeutet: Diese Funktion liefert einen
int (also eine Ganzzahl) zurück. Nur, hier ist die
Funktion:

int zaehler()
{
  if(PINC1 == 1)
  {
    TCCR1B |= (1<<CS12)|(1<<CS10);
  }
  if(PINC1 == 1)
  {
    impuls_1 = TCNT1L;
    impuls_2 = TCNT1H;
    impuls_fest = impuls_1 + impuls_2;
  }
}

Wo liefert die irgendetwas zurück?
Ich sehe da keinen
   return 1;
oder
   return irgendetwas;
oder
   return ...  (irgendwas was als int Zahl gilt)

Wenn deine Funktionen nichts zurückliefern, weil es keinen
vernünftigen Return Wert gibt (oder du noch nicht weist wie
man das macht) dann sind das void Funktionen.

void zaehler()
{
  ...
}

(Nicht vergessen: die Deklaration ganz am Anfang auch
umändern. Sonst stimmen Deklaration und Implementierung
der Funktion nicht zusammen)

von Dennis Wolkenhauer (Gast)


Lesenswert?

kann man nur ein wert zurückgeben?
Da ich bei der funktion berechnung v1,v2 und v3 als wert auch in
anderen funktionen brauche.

von Karl H. (kbuchegg)


Lesenswert?

> kann man nur ein wert zurückgeben?

Ich sag jetzt mal: Ja, man kann nur einen Wert zurückliefern.

Natürlich gibt es Mittel und Wege diese Beschränkung zu umgehen
(Stichwort: struct), aber nicht zuviel auf einmal. struct's
sind ein Thema für später.

von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

hier mal wie ich versucht habe es zu lösen
kann man das so lösen?

von Karl H. (kbuchegg)


Lesenswert?

Ja, könnte man.

Was bringt's.
Im Moment nicht viel, da der Aufrufer nichts mit dem zurückgegebenen
Wert macht.
Wie würde das aussehen:

int main()
{
  int Impulse;

  ...

  Impulse = zaehler();


zaehler() liefert jetzt einen Wert zurück und in main()
(also beim Aufrufer) wird er zurückgegebene Wert in einer
Variablen gespeichert. Den könnte man dann wieder an
andere Funktionen übergeben, etc.

Wart mal einen Moment, ich bereite grade eine ander Nachricht
vor, die dir mehr bringt, da sie einiges an der Programmlänge
verändert.

von Karl H. (kbuchegg)


Lesenswert?

Es geht um diese Funktion hier:

int segment_1()
{
  if(v1==0)
  {
    PORTB = 0xf6;
  }

  else if(v1==1)
  {
    PORTB = 0x14;
  }

  else if(v1==2)
  {
    PORTB = 0xba;
  }

  else if(v1==3)
  {
    PORTB = 0x9e;
  }

  else if(v1==4)
  {
    PORTB = 0x5c;
  }

  else if(v1==5)
  {
    PORTB = 0xce;
  }

  else if(v1==6)
  {
    PORTB = 0xee;
  }

  else if(v1==7)
  {
    PORTB = 0x94;
  }

  else if(v1==8)
  {
    PORTB = 0xfe;
  }

  else if(v1==9)
  {
    PORTB = 0xde;
  }

  return v1;
}

Alleine durch ihre enorme Länge sollte einem diese Funktion
schon sauer aufstossen und den Magen umdrehen.
Dabei ist die Sache doch sehr einfach. Wenn wir uns mal die if-s
ansehen, dann wird hier immer dieselbe Variable mit den Zahlen
0 bis 9 verglichen und je nachdem welche Zahl es war ein anderer
Wert an PortB zugewiesen.
Das muss doch auch eifnacher gehen. Was wir bräuchten ist ein
Konstrukt, in das man mit dem Wert von v1 hineingeht (der ja
nur die Zahlen von 0 bis 9 enthalten kann) und das dann den
Wert liefert der an PortB ausgegeben werden soll. So was
wie eine Tabelle, oder so.
Langer Rede, kurzer Sinn: so ein Konstrukt gibt es. Das ist
doch genau das was ein Array macht! v1 (also die Zahlen von
0 bis 9) dient als Index in das Array und im Array stehen
dann die Werte:

int segment_1()
{
  static unsigned char Werte[] = { 0xf6,    /* 0 */
                                   0x14,    /* 1 */
                                   0xba,    /* 2 */
                                   0x9e,    /* 3 */
                                   0x5c,    /* 4 */
                                   0xce,    /* 5 */
                                   0xee,    /* 6 */
                                   0x94,    /* 7 */
                                   0xfe,    /* 8 */
                                   0xde     /* 9 */
                                 };

  PORTB = Werte[ v1 ];
  return v1;
}

Wesentlich kürzer und auch übersichtlicher.
Selbiges kann man natürlich auch mit den anderen beiden
segment Funktionen machen.

von Karl H. (kbuchegg)


Lesenswert?

Da fällt mir noch was auf:
So wie du PINCx verwendest, funktioniert das nicht
zb hier:

  do
  {
    variabler_zaehler();
    berechnung();
    segment_1();
    segment_2();
    segment_3();
  }
  while(PINC2==0);

PINC2 ist ein Makro. Wenn man das mal sucht, dann findet man

#define PINC2  2

d.h. der Text PINC2 wird durch eine einfache 2 ersetzt. Macht
der Präprozessor das, dann steht da

        while( 2 == 0 );

Nicht ganz das was du willst.
Du willst: Die Schleife soll solange wiederholt werden, wie
der Pin 2 vom Port C den Wert 0 hat.

Jetzt verweise ich dich mal ans Tutorial.
Im AVR-GCC-Tutorial auf dieser Seite (in der Link-Liste links
in der unteren Hälfte zu finden) gibt es einen Abschnitt
'Allgemeiner Zugriff auf Register'. Den solltest du dir mal
reinziehen.

von Dennis Wolkenhauer (Gast)


Lesenswert?

Heißt das das in den headerdateien schon PINC2 auf 2 gesetzt worden ist
? oder muss ich das mittels #define definieren?

von Karl H. (kbuchegg)


Lesenswert?

Das ist im Header File für dich schon definiert.
Kommt über
#include <avr/io.h>
rein.

Wenn es das nicht wäre, würde sich der Compiler beschweren.
Du weisst schon: Alles was er nicht kennt ist ein
Fehler.

von Dennis Wolkenhauer (Gast)


Angehängte Dateien:

Lesenswert?

so ich habe das jetzt soweit ich das verstanden habe verändert und
compiliert ohne fehler und warnungen.
Nur jetzt macht mein Programm rein garnichts.
Er geht nichtmal mehr in die main .
Woran kann das liegen?
hier das programm:

danke

von Karl H. (kbuchegg)


Lesenswert?

> Er geht nichtmal mehr in die main

Wie muss ich das verstehen?
In die main() muss er auf jeden Fall reinkommen.
Dort ist Programmbeginn.

von Karl H. (kbuchegg)


Lesenswert?

Testest du im AVR-Simulator?

von H.joachim S. (crazy_horse)


Lesenswert?

nur ne Kürzung, hat mit deinem Problem nichts zu tun,

flash unsigned char Werte[10] = { 0xf6,    /* 0 */
                                   0x14,    /* 1 */
                                   0xba,    /* 2 */
                                   0x9e,    /* 3 */
                                   0x5c,    /* 4 */
                                   0xce,    /* 5 */
                                   0xee,    /* 6 */
                                   0x94,    /* 7 */
                                   0xfe,    /* 8 */
                                   0xde     /* 9 */
                                 };


void drive_segmente (){

PORTB = Werte[ v1 ];
PORTD = Werte[ v2 ];
PORTA = Werte[ v3 ];
}

flash muss bei deinem Compiler wahrscheinlich const heissen

von Dennis Wolkenhauer (Gast)


Lesenswert?

zu karls frage:

Ja ich teste im simulator.
er macht nichts. Der pfeil der anzeigt wo das programm gerade ist endet
bereits am ingang der main.

int main()
{ - - - > hier

und zu crazy_horse ich verstehe dein teil nicht.

von Karl H. (kbuchegg)


Lesenswert?

Na ja, der Simulator wartet auf deine Befehle.
Drück mal F10.
Das führt den nächsten Befehl aus.

von Karl H. (kbuchegg)


Lesenswert?

Die Kürzung die crazy_horse vorschlägt wolle ich auch
noch machen. Aber alles zu seiner Zeit. Mach dir jetzt
noch keine Gedanken drüber. Ich sprech dich dann durch
wenn's soweit ist. Dein Pgm sollte eigentlich soweit
funktionieren, dass kein grober Schnitzer mehr drinnen
ist. Ob die Berechnungen an sich stimmen hab ich nicht
kontrolliert, ich hab mich nur auf den C-Aspekt des
Problems konzentriert.

Im Simulator (klapp einfach mal das Degbug Menü
herunter, da sind alle Befehle drinnen):
F10  macht einen Schritt im Programm.
     Wenn der SChritt der Aufruf einer
     Funktion ist, dann wird die Funktion
     komplett still ausgeführt und wenn die
     Funktion ausgeführt ist meldet sich
     der Simulator wieder
F11  so wie F10, nur werden Funktionen ebenfalls
     Schritt für Schritt ausgeführt.

dann gibts da noch jede Menge anderes Zeugs.
Man kann sich Variableninhalte anschauen,
das Programm für sich alleine (also nicht
schrittweise) ausführen, Breakpoints setzen
(ein Breakpoint ist eine Stelle, wenn das Pgm
darauf trifft wird die Ausführung unterbrochen
und der Simulator meldet sich wieder) usw.
Am Anfang wirst du wahrscheinlich hauptsächlich
F10 und F11 benutzen, sowie Variablen anschauen.
Mach dich mit den Möglichkeiten dieses Simulators
(=Debugger; ein 'Bug' ist ein logischer Fehler
im Programm, ein De-bug-ger ist daher ein Pgm,
das einem hilft logische Fehler zu finden)
vertraut, du wirst noch viel Zeit mit diesem
Teil verbringen.

von Karl H. (kbuchegg)


Lesenswert?

Du solltest auch gleich mal im linken Fenster den Reiter
im unteren Abschnitt auf 'I/O View' stellen.
Im Baum wählst du dann den letzten Punkt 'I/O AtMEGA16'
(oder welchen Przessor du halt eingestellt hast) aus.
Da tauchen dann alle simulierten Ports und sontige
Einrichtungen deines Prozessors auf. Mach mal die
ganzen 'PORTA' bis 'PORTD' auf. Wenn die DDRA =
Zuweisungen ausgeführt werden, müsstest du sehen
können wie sich der Zustand verändert.

von Dennis Wolkenhauer (Gast)


Lesenswert?

ok mit F10 funktionierts ob er auch richtig rechnet hab ich noch nicht
überprüft.
Das kann auch noch warten.
Auf jedenfall funkt es mit f10 macht auch alles richtig.
Jetzt wäre es cool wenn ihr mir hilft bei den timern und countern.
denn damit kenne ich mich nicht richtig aus und habe es nur mit hilfe
des avr-gcc tutorials auf dieser seite gemacht.
und vielen vielen dank an karl und crazy ich weiß eure hilfe echt
zuschätzen , besonders dir karl.
danke

von Karl H. (kbuchegg)


Lesenswert?

Wobei kennst du dich nicht richtig aus?
Das AVR-gcc-Tutorial ist in dem Punkt eigentlich
recht umfangreich.

Ich wuerde mal folgendes machen:
Geh mal einen Schritt zurück, bildlich gesprochen,
und vergiss dein eigentliches Problem. Fang ein
2.tes Projekt an, dass ich nur mit dem Timer
beschäftigt.
Also Timer konfiguerieren (Vorteiler einstellen,
Timer einschalten) und im Simulator die Timer
Komponente beobachten ob sie auch wirklich
zaehlt.
Selbiges wenn du den Timer als Counter betreibst.
(Du kannst im Simulator auf die Port-Pins [die
kleinen Rechtecke} klicken, der Simulator
wertet das als Eingabe an den Port).

So ein Testprojekt ist eine gute Sache. Denn
es erlaubt dir dich nur auf einen bestimmten
Teil zu konzentrieren, während alles andere
aus dem richtigen Projekt erst mal aussen vor
bleibt. Mit dem Testprojekt testet man ab, ob
die Dinge wirklich so funktionieren wie man denkt.
Hat man dann den Teil verstanden, ist es normalerweise
nicht mehr schwer, das Gelernte im richtigen Projekt
anzuwenden.

Du betritts jetzt eine neue Welt. Teil dieser
Welt ist auch, dass man experimentiert und selbst
seine Schlussfolgerungen zieht.

von Dennis Wolkenhauer (Gast)


Lesenswert?

so getestet er scheint zu zählen aber die prüfung funktioniert nicht.
als die if anweisung ignoriert er denn er fängt auch an zuzählen wenn
PINc1 nicht 1 ist.
Woran kann das liegen?

von Peter D. (peda)


Lesenswert?

Ich stimme Karl Heinz zu, Du solltest Dich erstmal mit den Grundlagen
der C und MC-Programmierung beschäftigen.


Also LED an, aus, blinken, mit Timer blinken, mit Interrupt blinken,
Tasten abfragen, Tasten entprellen usw..

Eben wie jeder erfolgreiche Programmierer mal angefangen hat.


Und auch mal anschauen, wie C-Programme aufgebaut sind, denn das hier
ist totaler Schwachfug:
1
int main()          
2
{
3
...
4
  return impuls_fest;
5
  return impuls_variable;
6
  return v1;
7
  return v2;
8
  return v3;
9
}

1.
Dein Compiler sollte dich warnen, daß die letzten 4 Zeilen
unerreichbarer Code sind. Return macht genau das, was es bedeutet, es
gibt nichts dahinter.

2.
Wohin soll denn das Main zurückkehren, Du hast aufm MC doch kein
Betriebssystem. Auf MCs enthält das Main ausnahmslos eine
Endlosschleife, d.h. es läuft immer, bis man den Saft abschaltet.


Nur um mal 2 der gröbsten Fouls zu nennen.


Sich bequem alle Fouls von den anderen rausmachen zu lassen, ist nicht
fein. Ich staune schon lange, daß sich noch Dumme dafür finden.


Peter

von Karl H. (kbuchegg)


Lesenswert?

> die if anweisung ignoriert er

Das tut er 100% nicht.
Anfaenger neigen gerne dazu, einem Computer sowas
wie Eigenleben zu unterstellen. Sei versichert,
dass es das nicht gibt. Die sog. Elektronengehirne
die sich gegen ihre Schöpfer auflehnen sind eine
Erfindung Hollywoods. Wenn eine Abfrage oder
sonst ein Programmteil nicht so funktioniert
wie du dir das vorstellst, dann liegt es
ausnahmslos immer daran, dass du als Programmierer
die Dinge falsch formuliert hast. Falsch heist
in diesem Falle: die Logik stimmt nicht. Dass
dein Programm den Regeln der Programmiersprache
entspricht, darum kümmert sich der Compiler. Aber
das ist nicht alles was ein Programm ausmacht; die
Logik dahinter muss auch stimmen. Und die ist Aufgabe
des Programmierers.

von Dennis Wolkenhauer (Gast)


Lesenswert?

Ich frage nur ungern, aber mir fällt echt nichts ein.
ICh bekomme den timer einfach nicht hin, da wollte ich fragen ob einer
von euch ein test programm kennt oder irgendwas wo es gut beschrieben
ist wie man die Timer/Counter benutzt.

Also ich möchte das wenn ein bestimmter Pin auf high geht der timer
anfängt zu zählen und wenn der selbe Pin das zweite mal auf high geht
der timer ausgelesen wird.

Wie im vorrigen beschrieben soll genau das mit nem Rad geschehen.
sozusagen die zeit für einmal rum gemessen werden.
Aber ich hab es bis jetzt noch nicht hinbekommen.
Ich versuches schon die ganze zeit und werdes es auch weiter versuchen
aber es wäre toll wenn mir jemand bei diesem Problem hilft.
danke

von Dennis Wolkenhauer (Gast)


Lesenswert?

>>Um nun also den Timer0 in Betrieb zu setzen und ihn mit einer Frequenz
>>von 1/1024-tel des CPU-Taktes zählen zu lassen, schreiben wir die
>>folgende Befehlszeile:
>>
>>TCCR0 |= (1<<CS00)|(1<<CS02);
>>
>>Der Zähler zählt nun aufwärts bis 255, um dann wieder bei 0 zu
>>beginnen. Der aktuelle Zählerstand steht in TCNT0.

Das steht im avr-gcc-tutorial aber ich habe das ausprobiert und frage
mich nun , müsste den in TCNT0 laufend die PINS an und ausgehen?
bei mir macht er das halt nicht.

von Karl H. (kbuchegg)


Lesenswert?

Das könnte man so machen.
Ein geübter Programmierer würde es zwar
nicht so machen, sondern mit einem Input-
Capture arbeiten, aber ich denke du solltest
mal klein anfangen.

#include <avr/io.h>
#include <stdint.h>

int main()
{
  unsigned int Wert;

  // den Eingabeport konfigurieren
  DDRC = 0x00;    // Port C alles auf Eingang
  PORTC = 0x01;   // am Pin 0 den Pullup einschalten

  // warten bis Port C, Pin 0 auf 1 geht
  while( ( PINC & ( 1 << PINC0 )  ) == 0 )
    ;

  // Vorteiler auf 1024, damit's nicht zu schnell geht
  // sobald der Vorteiler gesetzt ist, zaehlt der Timer
  // auch schon, wir wollen ihn ausserdem bei 0 anfangen lassen
  // zu zählen. Auf den kurzen Zeitverzug, der durch diese
  // Operationen entsteht, pfeifen wir mal kurzerhand.
  TCNT1 = 0;
  TCCR1B = ( 1 << CS12 ) | ( 1 << CS10 );

  // jetzt warten wir, bis Port C, Pin 0 wieder zurueck noch 0 faellt
  // das muessen wir tun, da wir ja nicht wissen, wie lange die 1,
  // die weiter oben die while Schleife abgebrochen hat, noch
  // andauert. Und wir wollen ja schliesslich nicht, dass dieselbe
  // 1, die den ganzen Vorgang ausgelöst hat, ihn auch wieder
  // stoppt. Erst die nächste 1 soll das tun.
  while( ( PINC & ( 1 << PINC0 ) ) == 1 )
    ;

  // gut. PinC ist wieder auf 0, d.h. wir koennen auf den naechsten 1
  // Puls auf PinC-0 warten.
  while( ( PINC & ( 1 << PINC0 ) ) == 0 )
    ;

  // der 2.-te Puls ist eingetroffen, den Timer auslesen
  Wert = TCNT1;

  //
  // den mC in eine Endlosschleife schicken, damit er keinen
  // Unsinn macht.
  while( 1 )
    ;
}

von Karl H. (kbuchegg)


Lesenswert?

> müsste den in TCNT0 laufend die PINS an und ausgehen?
> bei mir macht er das halt nicht.

Langsam: das passiert schon. Nur hast du einen Vorteiler
von 1024. s.h. der Prozessor macht 1024 Befehle (grob
gesprochen), bevor der Timer um 1 weiterzählt. D.h.
du musst im Simulator schon einige male eine Schleife
durchlaufen, bevor du am Timer was siehst. Stell einfach
mal den Vorteiler weiter runter, dann sollte es eigentlich
schneller gehen.

von Dennis Wolkenhauer (Gast)


Lesenswert?

er zeigt nur auf TCNT0 was an wenn ich auf pause drücke ist das normal?

von Karl H. (kbuchegg)


Lesenswert?

Ja, das ist normal.
Während der Simulator eigenständig läuft wird die
Anzeige der Ports und sonstiges nicht nachgeführt.
Mir ist klar, dass Atmel damit Simulationszeit
einsparen möchte. Allerdings würde es den Simulator
gehörig aufwerten, wenn es einen Simulations-Modus gäbe,
in dem die Port-Anzeige bzw. was noch wichtiger wäre,
die Input-Pins, auch dann nachgeführt bzw. ausgewertet
werden, wenn das Pgm tatsächlich ausgeführt wird und
nicht nur im Single-Step.

Vielleicht macht Atmel das irgendwann. Zur Zeit
jedenfalls nicht (oder ich hab den Schalter dafür
einfach noch nicht gefunden).

von Karl H. (kbuchegg)


Lesenswert?

Oh, ich vergass.
Zur Not, kann man auch den 'Auto-Trace' benutzen.
Das funktioniert allerdings nicht wirklich gut.

von Dennis Wolkenhauer (Gast)


Lesenswert?

hab aber dein Programm probiert und bei dir funktioniert es
das alles angezeigt wird.

Aber durch dein Programm habe ich rausgefunden das ich richtig gedacht
es aber falsch ausgeführt habe.
Denn auf die idee mit dem wieder auf null schalten bin ich nicht
gekommen.
:)

Also ich weiß echt nicht wie ich dir danken soll.
Hab den ganzen tag gesucht um rauszufinden wie man den timer benutzt
und nur weil ich dachte das ich ihn falsch benutze .
Aso kurze frage wird der timer nur mit TCNT1 ausgelesen?
Ich hatte gedacht man muss den low und high teil noch zusammen
rechnen.
danke nochmals

von Dennis Wolkenhauer (Gast)


Lesenswert?

Ich habe leider nochmal ne frage.
Und zwar hab ich das jetzt eingebunden (ich hoffe du hast nichts
dagegen) und ich frag mich jetzt warum ich bei den funktionen zaehler
und variabler_zaehler im Programm immer auf Pause drücken muss bevor es
weiter geht?
kann man das irgendwie unterbinden und muss das so sein?

von Dennis Wolkenhauer (Gast)


Lesenswert?

Aber anscheinend Funktioniert das Ganze Programm jetzt.
Denn er zählt und gibt alles aus.
Sogar verschiedene zahlen :)

Vielen dank für die grosse hilfe.

von Karl H. (kbuchegg)


Lesenswert?

> Ich hatte gedacht man muss den low und high teil noch zusammen
> rechnen.

Das muss man auch. Aber das erledigt der Compiler für
dich.

von Ronny (Gast)


Lesenswert?

Ach sind das schöne Zeiten...als ich mit programmieren angefangen
hab,hatte ich weder Internet noch Foren,das alles hat mich viele
Nachmittage über Büchern und mit probieren gekostet.

@Dennis:

Dennoch,interessantes Projekt.Vielleicht etwas zu gross um eine
Programmiersprache vernünftig zu lernen,aber interessant :)

Viel Erfolg noch mit deinem Projekt.

von Dennis Wolkenhauer (Gast)


Lesenswert?

Wow endlich mal einer der mich nicht gleich kritisiern.
Ich will zwar tatsächlich c-lernen aber eigentlich nur in richtung
software.
Der Tacho ist ein schulprojekt.
Aber du hast recht auch interesant.
Das hat mich halt auf die idee gebracht mal den Butterfly zukaufen und
so damit zu lernen.
Danke und gute nacht

von Dennis Wolkenhauer (Gast)


Lesenswert?

Wenn einer gute Bücher oder online-tutorials zum thema c kennt wäre es
toll wenn er die hier posten würde.
Danke

von Karl H. (kbuchegg)


Lesenswert?

Mit dem Klassiker, 'K&R' kann man eigentlich
nichts falsch machen.

Programmieren in C. ANSI C (2. A.).
Brian W. Kernighan, Dennis M. Ritchie

http://www.amazon.de/exec/obidos/ASIN/3446154973/qid=1149471247/sr=8-1/ref=pd_ka_1/302-5852458-4580021

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.