mikrocontroller.net

Forum: Compiler & IDEs Umstieg zu Atmelstudio (hilfe beim Coden mit TimerInterrupt)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Sören G. (xasir)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo erstmal.

Ich bin gerade dabei von der gut vorgekauten Arduino-IDE auf Atmelstudio
umzusteigen.

Die ersten Hürden konnte ich noch gut überwinden und verstehen, doch nun 
die Erste die ich zwar überwunden habe aber nicht verstehe.

Da ich viel mit Arduino gemacht habe, laufen meine ersten schritte auf 
einem Arduino-uno (ATMega328).

Nun war nach den ersten timer und pwm versuchen der Wunsch geweckt auch 
ein LED blinken ohne delay zu bauen. Hier erstmal der Code der sogar 
funktioniert.
#define F_CPU 16000L
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
uint64_t millis = 0;
uint64_t last;
uint64_t micros;
uint64_t pos;
int main(void)
{
  DDRB = 0b00100000;
  PORTB = 0b00010000;
  DDRD = 255;
  PORTD = 0;
  TCCR0A = 0b10000011;
  TCCR0B = (1<<CS00);
  TIMSK0 = 0b00000001;
  sei();
  while (1)
  {
    OCR0A = 0;
    if(micros - last > 1000000){
      last = micros;
      PORTB ^= (1<<5);
    }
  }
}
ISR(TIMER0_OVF_vect){
  micros+=16;
}

Nun das Problem.
Wenn ich die Zeile mit "OCR0A = 0;" aus der while schleife schiebe oder 
lösche, blinkt PB5 nicht mehr. und trotz der 0 leuchtet die LED am Pin 
(PD6) an dem die Waveform ausgegeben wird ganz schwach.

Habe ich hier was falsch verstanden oder ist das die komplett falsche 
Herangehensweise?

Autor: Carl D. (jcw2)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Da micros in der ISR geändert wird, muß volatile davor stehen:
volatile int64_t micros;

Edit: und offenbar reicht die eine Zeile genug Register zu brauchen, 
damit der Wert micros nachgeladen wird.

: Bearbeitet durch User
Autor: Sören G. (xasir)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok danke klappt. und auch verstanden. :)

Das muss ich dann bei jeder anderen Variablen machen die ich außerhalb 
der main verändere und in der main verarbeiten möchte?
und gibt es in meinem Code groben Optimierungsbedarf?
und woher kommt das "Glimmen" der LED an PD6?

: Bearbeitet durch User
Autor: Holger L. (max5v)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
#define F_CPU 16000L scheint mir verkehrt zu sein, der Prozessor läuft 
wohl eher mit 16MHz.

Bei den Registerzuweisungen sollte man sich schon eine einheitliche 
Schreibweise angewöhnen, das bringt Übersichtlichkeit.

Die uint64_t Variablen könnte man sich sparen in dem man den Prescaler 
erhöht z.B. 64, und den CTC statt dem PWM Modus wählt.

Da die Led im Code selber geschaltet wird bietet sich CTC sowieso an.

PD6 ist der OC0A Pin der PWM...

: Bearbeitet durch User
Autor: Sören G. (xasir)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Für die Schreibweisentipps.
die LED will ich später noch in verschiedenen Dimmstufen leuchten 
lassen.
deswegen fast PWM.
mich wundert nur das wenn ich "OC0A = 0" mache die LED trotzdem etwas am 
"glimmen" ist.

: Bearbeitet durch User
Autor: Karl M. (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Sören G. schrieb:
> while (1)
>   {
>     OCR0A = 0;
>     if(micros - last > 1000000){
>       last = micros;
>       PORTB ^= (1<<5);
>     }
>   }

Hallo, frage Dich bitte mit welcher Zahl die Differez (micros - last) 
verglichen wird.

Dass
PB5 = 5
 ist, weißt Du, es liest sich besser, dies umzuschreiben.
DDRB = 0b00100000; PORTB = 0b00010000;

Neu
DDRB = (1<<PB5); PORTB = (1<<PB5);

Ich nutze eine noch etwas andere Funktionalität, die Defines.
#define LED (1<<PB5)

Dadurch wird der Ausdruck noch leserlicher:
DDRB = LED; PORTB = LED;

Dass kann man weiter Abstrahieren, so dass dies möglich wird:
LED_DDR=1; LED=1;

Autor: Holger L. (max5v)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Sören G. schrieb:
> mich wundert nur das wenn ich "OC0A = 0" mache die LED trotzdem etwas am
> "glimmen" ist.

Ich hoffe das ich mich nun nicht hineinsetze, aber ich meine des der Pin 
im nicht invertierten Modus für sehr kurze Zeit eingeschaltet wird.
Abhilfe sollte da der invertierte Modus schaffen, welcher (glaube dann 
allerdings keine maximale "helligkeit" mehr zuläßt)
TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (1 << WGM00);

Set OC0A on Compare Match, clear OC0A at BOTTOM,
(inverting mode). Für Fast PWM Modus.

Die alte Initialisierung nur nochmal falls die obere unverständlich 
seien sollte
TCCR0A = 0b10000011;
  wäre das selbe wie
TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00);

Clear OC0A on Compare Match, set OC0A at BOTTOM,
(non-inverting mode) Für Fast PWM Modus.


So Pi mal Daumen, ist ungetestet. Es gibt bestimmt eine deutlich 
bessere, fachlich versiertere, Erklärung.

Autor: Veit D. (devil-elec)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sören G. schrieb:

>     if(micros - last > 1000000) {
>       last = micros;
>       ...
>       ...
>     }

Hallo,

nur so nebenbei. Den Codeausschnitt hättest du in der Arduino IDE auch 
mit micros() oder millis() erledigen können. Das nur zur reinen Info.

> Da ich viel mit Arduino gemacht habe, laufen meine ersten schritte auf
> einem Arduino-uno (ATMega328).
Korrektur: Atmega328P - "P" nicht das du das falsche Datenblatt 
verwendest

Weitermachen.  :-)

Autor: Sören G. (xasir)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl M. schrieb:

> Ich nutze eine noch etwas andere Funktionalität, die Defines.
>
#define LED (1<<PB5)
>
> Dadurch wird der Ausdruck noch leserlicher:
>
DDRB = LED; PORTB = LED;

Bis hier hin komm ich noch mit.

> Dass kann man weiter Abstrahieren, so dass dies möglich wird:
>
LED_DDR=1; LED=1;

Da wirds für mich interessant, weil ich grad keine Ahnung hab wie ich 
das mit nem einfachen #define machen soll.


Veit D. schrieb:
>nur so nebenbei. Den Codeausschnitt hättest du in der Arduino IDE auch
>mit micros() oder millis() erledigen können. Das nur zur reinen Info.

Jap weiss ich, aber da ich die Arduinoumgebung gerade verlassen habe, 
steht mir diese nützliche Funktion leider nicht zur Verfügung und muss 
sie selbst bauen.

@ Holger
ich werds mal probieren.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei dem entlehnten Verb "coden" dreht sich mir immer der Magen um, weil 
ich da an was anderes denke. Steht zwar auch so im Wictionary, doch 
[ck]odieren oder coding erscheint mit irgendwie natürlicher, wobei koten 
(s.o.) natürlich auch ein natürlicher Vorgang ist ;-)

Autor: Carl D. (jcw2)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Bei dem entlehnten Verb "coden" dreht sich mir immer der Magen um, weil
> ich da an was anderes denke. Steht zwar auch so im Wictionary, doch
> [ck]odieren oder coding erscheint mit irgendwie natürlicher, wobei koten
> (s.o.) natürlich auch ein natürlicher Vorgang ist ;-)

Mit den Jahren und dank vieler junge Kollegen (jeder Bauart), hab ich 
eine gewisse Milde gegenüber Neuzeitsprech entwickelt. Sprachliche 
Korrektheit kann man ja immer noch in den Bereichen verlangen, in denen 
es wirklich wichtig ist. Z.B. weil Compiler nicht so rücksichtsvoll 
sind.

Wir waren schließlich auch nicht besser ;-)

Autor: Sören G. (xasir)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Gut das wir alle einen Verstand haben und Wörter auch im Kontext 
verstehen...

Sören G. schrieb:
> Da wirds für mich interessant, weil ich grad keine Ahnung hab wie ich
> das mit nem einfachen #define machen soll.

Ok da sind wir stehen geblieben....

Autor: Veit D. (devil-elec)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sören G. schrieb:

>> Da wirds für mich interessant, weil ich grad keine Ahnung hab wie ich
>> das mit nem einfachen #define machen soll.

Du bemerkst jetzt dass das Arduino Framework gar nicht so blöd ist. Denn 
#define ist dafür ein klarer Rückschritt. In C scheinbar nicht anders 
möglich. Ich empfehle dir bleibe bei C++, baue dir Klassen usw., dann 
kannste das ähnlich wie mit dem Arduino Framework machen.

Wenn du unbedingt #define möchtest lese dir das AVR Tutorial hier im 
Forum durch. Als Einstieg ein Bsp. ...
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))  
#endif

#define P1_OUT  sbi (DDRA,3)  // PA3 Ausgang
#define P2_OUT  sbi (DDRA,4)  // PA4 Ausgang

#define P1_ON  sbi (PORTA,3)  // PA3 einschalten
#define P2_ON  sbi (PORTA,4)  // PA4 einschalten

#define P1_OFF  cbi (PORTA,3)  // PA3 ausschalten
#define P2_OFF  cbi (PORTA,4)  // PA4 ausschalten

Was du vielleicht auch machen kannst ist folgendes. Atmel Studio mit 
https://www.visualmicro.com/  Plugin. Du stehst damit nicht völlig auf 
verlorenen Posten. Kannst weiterhin das Arduino Framework nutzen und 
baust Stück für Stück eigenen Klassen bis du das Arduino Framework 
vielleicht nicht mehr benötigst, falls das dein Ziel sein sollte. Man 
kann aber auch weiterhin das Arduino Framework nutzen und nur das selbst 
neu schreiben was einem vielleicht stört. Das bleibt jeden selbst 
überlassen.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für den leserlichen Zugriff auf IO-Pins:

Beitrag "Re: Port als Variable"

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.