Forum: Compiler & IDEs ATMEGA168 Timer


von Andreas (Gast)


Lesenswert?

Hallo,

ich bin neu auf dem Gebiet µC und versuche mich gerade an den Timern. 
Dabei bin ich auf ein Problem gestoßen, was ich irgendwie nicht hin 
bekomme.
Letztendlich möchte ich einen Mikrokontroller dazu nutzen nacheinander 
Bits zu übertragen. Das Medium bzw. das Protokoll, das ich verwende ist 
KNX.
Hierbei muss im µs-Bereich ein PIN geschalten werden.

Nun zu meinem Problem. Ich möchte einen TimerIRQ alle 1µs auslösen, um 
meine Programmierung zu überprüfen habe ich mir eine Testschleife 
gebaut.

#include <avr/io.h>
#include <avr/interrupt.h>
//Variablen für die Zeit
volatile unsigned int timing=0;
volatile unsigned int count=0;

int main(void)
{
  DDRB = 0xf; //Port B Ausgang
  PORTB = 0x00; //Port B 00 setzten
  // Timer 0 konfigurieren
  TCCR0A = (1<<WGM01); // CTC Modus
  TCCR0B |= (1<<CS00); // Prescaler 1
  TIMSK0 |= (1<<OCIE0A);
  OCR0A = 7;
  sei();
  while(1)
  {
  }
}
ISR (TIMER0_COMPA_vect)
{
  timing++;
  if (timing==10000)
  {
    timing=0;
    count++;
    if (count==10)
    {
      count=0;
      PORTB = ~PORTB;
    }
  }
}

Leider ist das Resultat nicht wie erwartet. Der PORTB togglt im 
Intervall von 1s. Er müsste nach meiner Überlegung aber im 
100ms-Intervall togglen.
Ich verwende einen 8MHZ Quarz, Prescaler 1 und ORCA=7 == 1µs!?
Die Schleifen laufen bis 100000 und invertieren danach den PORTB aber 
wie gesagt nur alle 1s. Aber 1µs * 100000 = 100ms!?

Ich hoffe mir kann jemand helfen und mir sagen wo der Denk- oder 
Programmierfehler liegt.

Vielen Dank
Andreas

von Flo (Gast)


Lesenswert?

Überleg mal wieviele Takte du pro Interrupt hast, wenn der alle 1us 
losgeht.
(Antwort ist 8)
Du verpasst massig interrupts, weil deine ISR "zu lang" ist.

Vielleicht wärs besser du schaust dir mal z.B. Das SPI-Modul an, ob du 
das für deine Zwecke benutzen kannst, mit Pintogglen funktioniert das im 
us-Takt höchstens in Assembler, aber nicht in C.

von Hc Z. (mizch)


Lesenswert?

Ist Dir klar, dass bei einer Interruptrate von 1µs und 8 MHz Takt gerade 
mal 8 Takte pro Interrupt übrigbleiben, dann wäre schon der nächste 
dran?  Du musst schon berücksichtigen, dass Dein Programm auch Zeit zur 
Abarbeitung braucht und ihm diese auch geben.

von Falk B. (falk)


Lesenswert?

@  Andreas (Gast)

>Bits zu übertragen. Das Medium bzw. das Protokoll, das ich verwende ist
>KNX.

Ein Link wäre hilfreich.

>Hierbei muss im µs-Bereich ein PIN geschalten werden.

Geht.

>Nun zu meinem Problem. Ich möchte einen TimerIRQ alle 1µs auslösen, um

Ist dir klar, dass das schon SEHR oft ist? Das ist 1 MHz!!! 
Interruptfrequenz!

>Leider ist das Resultat nicht wie erwartet. Der PORTB togglt im
>Intervall von 1s.

Das ist noch fix.

>Ich verwende einen 8MHZ Quarz, Prescaler 1 und ORCA=7 == 1µs!?

Schom mal überlegt, dass dein AVR in 1s nur 8 Takte hat? Und amit soll 
dein Interrupt ausgeführt werden? Dream on ;-)

Solche kurzen Zeiten für Bitmustergenerierung erledigt man m,it 
_delay_us(), siehe Doku der libc.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29

MfG
Falk

von Andreas (Gast)


Lesenswert?

super vielen Dank für eure Hilfe.
Also ich nehme mit, dass ich die IRQs so kurz wie möglich halten sollte 
und nie länger als CPU-Takt-1/IRQ-Intervall.
Gibt es denn Eigentlich eine Beschreibung dafür, wie lange welcher 
gcc-Befehl braucht?

Bezügkich der Frage nach dem Link. Das ist so ne Sache mit dem EIB/KNX. 
Es war mir nur durch mühselige Suche im Netzt möglich, spezifische Daten 
zur Datenübertragung zusammen zu bekommen. Falls jemannd nicht weiß was 
KNX ist: http://www.knx.de/

Wesentlich ist auf jeden Fall, dass ein Bit in einem Frame von 104µs 
übertragen wird. Jedoch eine Null für maximal 35µs bestehen darf. Die 
restlichen 70µs muss wieder eins anliegen.

Aber eventuell hat ja jemand ne clevere Lösung dafür, wie ich ein Byte 
seriell folgendermaßen übertragen kann:

  104µ 104µ 104µ 104µ 104µ 104µ 104µ 104µ 104µ  104µ   104µ  104µ  104µ
 ----------------------------------------------------------------------
|     |    |    |    |    |    |    |    |    |       |    |     |     |
|Start|Bit0|Bit1|Bit2|Bit3|Bit4|Bit5|Bit6|Bit7|Pritäts|Stop|Pause|Pause|
| Bit |    |    |    |    |    |    |    |    |  Bit  | Bit| Bit | Bit |
 ----------------------------------------------------------------------

Die Übertragung eines Bytes erfolgt indem zuerst ein Startbit(NULL) 
gesendet wird, danach LSB bis MSB ein Paritätsbit und Stopbit. Alles 
jeweils 104µs lang, wobei wie gesagt zu beachten ist, dass eine Null max 
35µs gesendet wird. Zum Schluss noch 2 Bit Pause (208 µs)

Gibts irgendeine Möglichkeit das mit nem µC zeitkritisch zu übertragen?
Kann ich eventuell den UART dafür bemühen?

Gruß
Andreas

von Dr.PillePalle (Gast)


Lesenswert?

moin

– des weltweit einzigen offenen STANDARDS für alle Anwendungen im 
Bereich Haus- und Gebäudesystemtechnik....

Falls Sie kein Mitglied sind, gibt’s zwei Möglichkeiten:

    * Kaufen Sie ein Exemplar der KNX Specifications bei KNX 
Association, mit KNX Online Shop.
          o € 1.000 – ohne Updateservice
          o Der obige Betrag ist des ersten Mitgliedsgeld absetzbar, 
falls der Hersteller KNX Mitgliedschaft beantragt innerhalb von sechs 
Monaten.


    * Kaufen Sie ein Exemplar des EN 50090 Standards bei dem nationalen 
Normierungsinstanz.

Ein Satz mit X : War wohl nix.

mfg

von Falk B. (falk)


Lesenswert?

@  Andreas (Gast)

>Gibt es denn Eigentlich eine Beschreibung dafür, wie lange welcher
>gcc-Befehl braucht?

Nöö, schon aml deshalb, weil es keine gcc-Befehle gibt. Nur 
C-Anweisungen. Und die sind nur bedingt auf ASM-Code 1:1 umrechenbar. Im 
Ersntfall muss man sich den erzeugten ASM-Code im *.lss File anschauen.

>Wesentlich ist auf jeden Fall, dass ein Bit in einem Frame von 104µs
>übertragen wird. Jedoch eine Null für maximal 35µs bestehen darf. Die
>restlichen 70µs muss wieder eins anliegen.

Klingt ähnlich zu One Wire. Und warum machst du dann einen 1µs 
Interrupt?

>Aber eventuell hat ja jemand ne clevere Lösung dafür, wie ich ein Byte
>seriell folgendermaßen übertragen kann:

Ganz einfach. Mit einem Timer und der Output Compare Funktion sowie dem 
dazugehörigen Interrupt.

>Gibts irgendeine Möglichkeit das mit nem µC zeitkritisch zu übertragen?
>Kann ich eventuell den UART dafür bemühen?

Nö.

MfG
Falk

von Andreas (Gast)


Lesenswert?

sag ich ja, da ist nix zu holen. das ist das einzige was ich gefunden 
habe. und nur zu hobbyzwecken lege ich da keine 1000€ aufn tisch. die 
gehen ja auch davon aus, dass ich das alles gleich kommerziell mache.
bin auch noch nicht mal sicher ob das was ich zusammen gesucht habe 
alles so stimmt.
also wenn jemannd näheres weiß, wäre ich sehr interessiert.

gruß andreas

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.