Forum: Mikrocontroller und Digitale Elektronik timer und uart ist das richtig so?


von Fridolin O. (muebau)


Lesenswert?

Hi,
für einen RFID Versuch...

Ziel:
Bei 8 Mhz...
RS232:  9600 8n1
Timer0: 125kHz Nadelimpuls
1
#define BAUD 9600L // baud rate
2
3
#include <util/setbaud.h>
4
5
void uart_init(void) {
6
  DDRD |= (0 << PIND0) | (1 << PIND1); //set PD0, PD1 (RX, TX) to input, output
7
  UBRRL = UBRRL_VALUE; //set baud rate
8
  UBRRH = UBRRH_VALUE; //set baud rate
9
10
  UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //enable receive interrupt; receiver and transmitter
11
}
UBRRL_VALUE und UBRRH_VALUE bekomme ich von setbaud.h.

Nadelimpuls:
1
void pwm_init(void) {
2
  DDRB |= (1 << PINB2); //set PB2 (OC0A) to output
3
4
  OCR0A = 19;
5
  TCCR1B = (1 << CS02) | (1 << CS00); //timer 0 prescaler of 64; means 125 kHz @ 8 Mhz CPU clock
6
  TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (1 << WGM00); //PWM: (COM0Ax): set OC0A on compare match, clear OC0A at 0xff
7
}
Da der Timer0 alle 255 überläuft bekomme ich den Output zurückgesetzt 
und will ihn bei ca. 25 wieder setzen lassen. Ergibt: 125 kHz bei 1/10 
high.

Ist das OK so? Fehlt da was?
Ich bekomme weder RS232 output noch PWM output...

Tschüss muebau

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:

> Da der Timer0 alle 255 überläuft bekomme ich den Output zurückgesetzt
> und will ihn bei ca. 25 wieder setzen lassen.

Warum setzt du den OCR Wert dann auf 19?


  TCCR1B =
  TCCR0A =

Fällt dir was auf?
  TCCR_eins_B
  TCCR_null_A

(In der Nomenklatur steht die Ziffer für den Timer für den dieses 
Konfigurationsregister gilt)

> Ich bekomme weder RS232 output noch PWM output...

Dann solltest du ein Problem nach dem anderen angehen.

von Fridolin O. (muebau)


Lesenswert?

Hi,

>> Da der Timer0 alle 255 überläuft bekomme ich den Output zurückgesetzt
>> und will ihn bei ca. 25 wieder setzen lassen.
>
> Warum setzt du den OCR Wert dann auf 19?

Naja 25 ist hex 19. Ist diese Denkweise falsch?

>   TCCR1B =
>   TCCR0A =
>
> Fällt dir was auf?
>   TCCR_eins_B
>   TCCR_null_A
>
Danke.

> (In der Nomenklatur steht die Ziffer für den Timer für den dieses
> Konfigurationsregister gilt)
>
>> Ich bekomme weder RS232 output noch PWM output...
>
> Dann solltest du ein Problem nach dem anderen angehen.

Bin deshalb auch erst mal am PWM.

Tschüss muebau

von Grrrr (Gast)


Lesenswert?

Fridolin Onteca schrieb:
> Naja 25 ist hex 19. Ist diese Denkweise falsch?

Nein. Nur die Ausdrucksweise.
In C wird die der Text "25" als dezimal 25 interpretiert, "19" als 
dezimal 19. Wenn Du eine Zahl als hexadezimal interpretiert haben 
willst, musst Du "0x" davorschreiben. Also "0x19".

von Hc Z. (mizch)


Lesenswert?

Fridolin Onteca schrieb:
> DDRD |= (0 << PIND0) | (1 << PIND1); //set PD0, PD1 (RX, TX) to input, output

Der Kommentar ist falsch.  PD0 wird auf gar nichts gesetzt.  Damit meine 
ich: sollte er - warum auch immer - vorher schon Ouput gewesen sein, 
bleibt er das auch danach.

> > Warum setzt du den OCR Wert dann auf 19?

> Naja 25 ist hex 19. Ist diese Denkweise falsch?

25 ist schon hex 19.  Nur setzt Du OCR auf dezimal 19 (0x13).

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:
> Hi,
>
>>> Da der Timer0 alle 255 überläuft bekomme ich den Output zurückgesetzt
>>> und will ihn bei ca. 25 wieder setzen lassen.
>>
>> Warum setzt du den OCR Wert dann auf 19?
>
> Naja 25 ist hex 19. Ist diese Denkweise falsch?

Wenn du 25 willst, dann schreib auch 25.
Was für einen Sinn soll es haben, eine Zahl, für die es eine perfekte 
Erklärung in dezimaler Schreibweise gibt, in ihrer hexadezimalen 
Notation hinzuschreiben (die da 0x19 wäre).
Maximale Konfusion?

Was ist klarer:
1
   Sekunden_Pro_Stunde = 60 * 60;
oder
1
   Sekunden_Pro_Stunde = 0x3C * 0x3C;

Beide Formen sind absolut gleichwertig (fast, aber das ist jetzt ein 
kleines Detail das hier keine Rolle spielt) und trotzdem ist dir als 
Mensch mit einer Uhr am Handgelenk die erste Form vertrauter und sofort 
einleuchtend während du bei der 2ten Form erst mal zum Taschenrechner 
greifen wirst.

von Karl H. (kbuchegg)


Lesenswert?

Hc Zimmerer schrieb:
> Fridolin Onteca schrieb:
>> DDRD |= (0 << PIND0) | (1 << PIND1); //set PD0, PD1 (RX, TX) to input, output
>
> Der Kommentar ist falsch.  PD0 wird auf gar nichts gesetzt.  Damit meine
> ich: sollte er - warum auch immer - vorher schon Ouput gewesen sein,
> bleibt er das auch danach.

Ist richtig, spielt hier allerdings keine Rolle. Durch
1
  UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //enable receive interrupt; receiver and transmitter

wird PD0 zwangsweise zum Input und PD1 zwangsweise zum Output.
UART ist so ein Fall, wo man sich nicht um die Pins im DDR Register 
kümmern muss.

von Hc Z. (mizch)


Lesenswert?

Ich bezog mich ausschließlich auf den Kommentar und auf das zitierte 
Statement.  Die schienen mir auf ein falsches Verständnis der 
Bitoperation hinzudeuten.

von Karl H. (kbuchegg)


Lesenswert?

Hc Zimmerer schrieb:
> Ich bezog mich ausschließlich auf den Kommentar und auf das zitierte
> Statement.  Die schienen mir auf ein falsches Verständnis der
> Bitoperation hinzudeuten.

Verzeih. Da hab ich mich dann wohl nicht so toll ausgedrückt.
Meine Anmerkung war eigentlich mehr für den TO gemünzt, das Datenblatt 
besser zu studieren. Dann hätte er sich das ganze Gepfriemel mit dem 
DDRD komplett gespart und so auch keinen Fehler machen können.

Dein zwischen den Zeilen lesen ist natürlich völlig korrekt. Der Hinweis 
auf ein Misverständnis ist nicht zu übersehen.

von Hc Z. (mizch)


Lesenswert?

Alles klar.

von Fridolin O. (muebau)


Lesenswert?

Hi,
danke fuer die vielen Antworten.

Zu der 19: Ich hatte das hier auch 0x19 geschrieben. Das das fuer mich 
auch der compiler uebernehmen kann ist mir nun klar.

Das mit dem DDRD und der RS232 hatte ich schon gelesen, spaeter als es 
nicht funktionierte dann trotzdem versucht.
Ich bin mir nicht ganz sicher ob ich das mit den Bits richtig verstanden 
habe. Ich dachte das ich mit:
1
DDRD |= (0 << PIND0) | (1 << PIND1);

durch |= dafuer sorge das ich nur "verodere" also nur setze was gesetzt 
werden soll:
Die Maske
0 bei Pin D0
1 bei Pin D1

Also nicht ob der Pin high oder low ist.

Ahh da haette ein & hingemusst da (0 | 1) = 1 .... Meintet ihr das?
Also:
1
DDRD |= (1 << PIND1);
2
DDRD &= (0 << PIND0);
Auch wenn es hier ja nicht noetig ist.

Wie bekomme ich den einen Pin dazu 125 kHz bei 8 Mhz zu machen?
Meine Idee einen Timer zu nehmen und PWM zu machen ist doch nicht 
schlecht!?

Tschuess und Danke
muebau

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:

> Ahh da haette ein & hingemusst da (0 | 1) = 1 .... Meintet ihr das?
> Also:
>
1
> DDRD |= (1 << PIND1);
2
> DDRD &= (0 << PIND0);
3
>
> Auch wenn es hier ja nicht noetig ist.

Merk dir eines als Eselsbrücke
Eine 0 kann man nach links schieben sooft man will, sie bleibt trotzdem 
eine 0.

Oder mathematisch ausgedrückt:
Für jedes beliebige x gilt:   0 * x -> 0

Daher kann dieser Ausdruck
1
(0 << PIND0)
niemals Sinn machen, denn:
1
(0 << PIND0) <==> (0 << PIND1) <==> (0 << PIND2) <==> ... <==> 0

> Wie bekomme ich den einen Pin dazu 125 kHz bei 8 Mhz zu machen?
> Meine Idee einen Timer zu nehmen und PWM zu machen ist doch nicht
> schlecht!?

Die ist schon ok.

von Fridolin O. (muebau)


Lesenswert?

Hi,

Danke fuer die Eselsbruecke. Ist jetzt klar.

>> Wie bekomme ich den einen Pin dazu 125 kHz bei 8 Mhz zu machen?
>> Meine Idee einen Timer zu nehmen und PWM zu machen ist doch nicht
>> schlecht!?
>
> Die ist schon ok.

Dachte ich auch. Wenn ich 8 Mhz durch 64 teile bekomme ich 125 kHz. Aber 
die sind ja dann der Takt und nicht der "Ueberlauftakt". Der ist doch 
Input durch 255, also 125000/255.
Meine Idee: prescaler auf 8 setzen. Wenn ich jetzt bei 1 auf high setzte 
und bei 2 auf low und der Timer bei 8 resetet wird dann bekomme ich 1/8 
bei 125 kHz.
Gibt es einen Mode der sowas oder etwas aehnliches kann?
Ich will das nicht "zu Fuss" machen. Ich war so froh das der PWM-Mode 
ohne CPU-Last arbeitet.

Tschuess muebau

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:

> die sind ja dann der Takt und nicht der "Ueberlauftakt". Der ist doch
> Input durch 255, also 125000/255.

Aber nur, wenn du den Timer durchlaufen lässt.

> Meine Idee: prescaler auf 8 setzen. Wenn ich jetzt bei 1 auf high setzte
> und bei 2 auf low und der Timer bei 8 resetet wird dann bekomme ich 1/8
> bei 125 kHz.
> Gibt es einen Mode der sowas oder etwas aehnliches kann?

Entweder CTC mit eigener ISR
oder aber, das was du schon seit Anbeginn vorschlägst:
Timer 1, PWM, Modus 14 oder Modus 15
  Fast PWM mit einem TOP Wert in ICR1 oder OCR1A


Wenn du endlich mal bekannt geben würdest, welchen µC du benutzt, dann 
müsste man nicht raten, was deine Timer alles können.

von Fridolin O. (muebau)


Lesenswert?

Hi,
Entschuldigung.

Es handelt sich um einen attiny2313.

Die Idee:
Mit 125 kHz ueber einen Transistor einen Spule (Schwingkreis) anregen.
Nach einem Filter geht das Ganze an den Comparator des uC.

Jetzt muss nur noch der Manchester-Code dekodiert werden. Da gibt es das 
RFID-Tueroeffner Projekt. Die haben da schon C-Code fuer.

Es gibt den SF6107. Der macht das vermutlich auch so.

Tschuess muebau

von Fridolin O. (muebau)


Lesenswert?

Karl heinz Buchegger schrieb:
> Fridolin Onteca schrieb:
>
>> die sind ja dann der Takt und nicht der "Ueberlauftakt". Der ist doch
>> Input durch 255, also 125000/255.
>
> Aber nur, wenn du den Timer durchlaufen lässt.
>

Naja sonst muesste ich ihn immer bei 1 wieder loeschen.

>> Meine Idee: prescaler auf 8 setzen. Wenn ich jetzt bei 1 auf high setzte
>> und bei 2 auf low und der Timer bei 8 resetet wird dann bekomme ich 1/8
>> bei 125 kHz.
>> Gibt es einen Mode der sowas oder etwas aehnliches kann?
>
> Entweder CTC mit eigener ISR
> oder aber, das was du schon seit Anbeginn vorschlägst:
> Timer 1, PWM, Modus 14 oder Modus 15
>   Fast PWM mit einem TOP Wert in ICR1 oder OCR1A
>
Das mag sich so angehoert haben. Aber einen Plan hab/hatte ich nicht so 
wirklich. :-)

Mal die erste Idee:
Kein prescaler. 8 Mhz und bei 64 loeschen (inverted, also pin auf high). 
Compare bei 6 (pin auf low).
1
//clear at 64 (8 Mhz / 64 = 125 kHz)
2
ICR1 = 64;
3
4
//mode 14 (Fast PWM, ICR1 is TOP)
5
TCCR1A |= (1 << WGM10);
6
TCCR1B |= (1 << WGM13) | (1 << WGM12);
7
8
//no prescaler
9
TCCR1B |= (1 << CS10);
10
11
//compare match at 6 (means 1/10 high level)
12
OCR1AL = 6;

Das muesste es doch schon sein, oder?

Tschuess muebau

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:

> Das muesste es doch schon sein, oder?

Versuch macht Kluch

von Fridolin O. (muebau)


Lesenswert?

Hi,
ich habe nun auf dem Oszi Wellen. Ich hatte klare High/Low's erwartet. 
Habe ich da offene Kollektoren uebersehen?

Tschuess muebau

von Karl H. (kbuchegg)


Lesenswert?

Aus µC Sicht: nein
Was du am Pin hängen hast, weißt aber nur du selber

von Fridolin O. (muebau)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aus µC Sicht: nein
> Was du am Pin hängen hast, weißt aber nur du selber

Nein, Nein. Ich habe nur ISP + 16 MHz Quarz (mit den Kondensatoren).

Sonst ist nichts angeschlossen.

Wenn ich mit dem Oszi an den Pin "pieke" bekomme ich was (im Gegensatz 
zu anderen Pins). Es wirk fuer mich aber so als wenn da nur die 16 MHz 
"durchscheinen".
Sollten da nicht +5V und 0V abwechseln anliegen (eben mit den 125 kHz)?

Tschuess muebau

von Karl H. (kbuchegg)


Lesenswert?

Fridolin Onteca schrieb:

> Sollten da nicht +5V und 0V abwechseln anliegen (eben mit den 125 kHz)?

Jepp.
Sollten.

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.