Forum: Mikrocontroller und Digitale Elektronik Programmablauf - wie?


von Hannes S. (hannestum)


Lesenswert?

Hallo!

Ich stehe gerade vor dem Problem, dass ich nicht weiß wie ich eine 
Aufgabe
am besten programmieren soll, da ich bisher nur sehr einfache Sachen mit 
MC's gemacht habe.

Und zwar soll mein ATMEGA8 so alle halbe Sekunde eine AD-Wandlung 
durchführen und das umgerechnete Ergebnis am Display ausgeben.
Das alleine läuft und ist kein Problem.

Jetz sollte er jedoch weiters noch an einem Eingangspin Impulse zählen 
und an 2 weiteren Eingangspins auf Tastendrücke warten und ggf. 
reagieren.


Vl könntet ihr mir mal ein paar Ideen oder Denkanstöße geben wie ich das 
am besten löse und ob ich dafür Interrupts verwenden soll oder nicht. - 
Hab damit leider noch keine Erfahrung!

mfg
Hannes

von Jens (Gast)


Lesenswert?

Des Teil hat 2 extrene Interrupts, also einen zum Zählen.

(grad ein register increasen und gegebenenfalls Carry Flag auswerten und 
dann im 2ten Register increasen, je nachdem wieviele Impulse du zählen 
musst)

Den adren nimmste für ne Tastaturmatrix mit Timerentprellung.

von Manni (Gast)


Lesenswert?

Also wie du Impulse zählen kannst geht wie folgt (ATmeg32)


   #define SET_BIT(PORT, BITNUM)  ((PORT) |= (1<<(BITNUM)))
   uint8_t i;
/*
** Init Counter
*/
   RainCounter_Init ();
// Endless Loop
   while (1)
      {
      i = RainCounter_Read ();
// In i steht nun die Anzahl der Pulse
      }
/*******************************************************
 Public Function: RainCounter_Init

 Purpose: Initiate the Timer/Counter 0 with
     external clock on Pin T0 / PB0 at falling edge

 Input Parameter: None

 Return Value: None

*******************************************************/
void RainCounter_Init (void)
  {
/*
** Set Timer/Counter Control register 0 to enable
** external clock source falling edge,
** Input port is:
**  - PD4 in ATmega-8
**  - PB0 in ATmega-32
*/
  TCCR0 = (1<<CS02)|(1<<CS01);
/*
** Enable Pullup Resistor
*/
//  SET_BIT (PORTD, 4);
  SET_BIT (PORTB, 0);

  return;
  }
/*******************************************************
 Public Function: RainCounter_Read

 Purpose: Read the counter content

 Input Parameter: None

 Return Value: uint8_t
   - Rain counter content

*******************************************************/
uint8_t RainCounter_Read (void)
  {
  uint8_t    i;
/*
** Read and return the counter content
*/
  i = TCNT0;
/*
** Reset the counter
*/
  TCNT0 = 0;

  return i;
  }

von Hannes S. (hannestum)


Lesenswert?

Danke für die Antworten,

mir ist schon klar wie ich die einzelnen Teilaufgaben die ich 
implementieren will funktionieren - jede für sich zumindest.

Es würde mir sehr helfen, wenn mir wer sagen könnte wie ich die 3 
Aufgaben sinnvoll unter inen Hut bekomme, sodass sie sich nicht 
untereinander stören.
Bis jetz hab ich einfach eine Endlosschleife die den ADC ausliest dann 
500ms wartet dann wieder ausliest usw....
Jetz will ich noch die anderen 2 Aufgaben mit integrieren, stehe aber 
an!

Mein Problem ist, dass ich nicht weiß wie ich jetzt die anderen 2 
Aufgaben da integrieren kann. Muss ich da im Hauptprogramm einfach einen 
Timer laufen lassen und bei jedem Timer Overflow wird dann ein Interrupt 
aufgerufen, dass eine meiner zu erfüllenden Aufgaben löst? Ich hab 
bisher noch nie was gemacht, was mehrere Sachen gleichzeitig erfüllt und 
stehe daher etwas auf dem Schlauch... Sowas wie ein Ablaufplan des 
Hauptprogrammes wäre Hilfreich!

mfg
Hannes

von peter (Gast)


Lesenswert?

In fast allen meinen Projekten ohne Betriebssystem benutze ich folgende 
Grundstruktur.
Ein Timer wird so programmiert, dass er einen festen Takt erzeugt (z.B. 
1 Millisekunde).
In der Timer Interruptroutine laufen dann verschiedene Zähler für die 
einzelnen Aufgaben. Sind diese Zähler abgelaufen rufen sie direkt 
Unterprogramme auf (wenn diese nur kurz brauchen, also deutlich kürzer 
als der Timertakt) oder setzen Signalbits für andere Aufgaben.
In der Endlosschleife in Main werden diese Signalbits dann abgefragt und 
wenn eines gesetzt ist die entsprechende Funktion aufgerufen (z.B. die 
AD Wandlung und Ausgabe auf Display). Nicht vergessen das Signalbit 
zurückzusetzen. In main wird also ständig kontrolliert obs was zu tun 
gibt und der Timerinterrupt löst über die Signalbits die Ausführung aus.
Die Signalbits kann man natürlich auch an anderen Stellen oder weiteren 
Interrupts setzen.
So kann man auch andere Ereignisse (wie z.B. Schnittstelle wie UART oder 
CAN) mit einbinden.

Ich hoffe das hilft die weiter und bringt dich auf neue Ideen.

von Hannes S. (hannestum)


Lesenswert?

Ok, das liest sich schonmal gut, und erscheint mir auch logisch und 
sinnvoll! Eigentlich genau das was ich brauche!

Dann werd ich mich mal etwas mit Timern und Interrupts beschäftigen!

Danke für die Hilfe!

von Tim R. (vref)


Lesenswert?

"Statemachine" ist auch sowas, womit man sich in diesem Zusammenhang mal 
beschäftigen könnte...
http://en.wikipedia.org/wiki/Automata-based_programming

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.