Hallo, ich habe einen ATtiny, wo ich einen Qaurz mit 8Mhz drann habe. Desweiteren habe ich einen Prescaler von 64. Da dieser Quarz nicht optimal für UART ist, ist mir bewusst, allerdings brauche ich auch 8Mhz, damit ich genau Timer-INterrupts erstellen kann. Meine Frage bezieht sich auf den Prescaler. Wird der bei der Berechnung von UBBR mit einbezogen? Die Gleichung ist ja UBRR = (fOSC / (16*BAUD) ) - 1 ist fosc jetzt 8000000 oder 125000? Habe für den Uart eine Baud-Rate von 9600 genommen (fosc = 8Mhz), allerdings wird nichts richtiges empfangen. Marc
Wenn Du eine Prescaler von 64 für die Taktrate einstellst, dann läuft innerhalb des Kerns alles mit 125kHz, so auch der Eingangstakt der Peripherie.
Marc schrieb: > ich habe einen ATtiny, wo ich einen Qaurz mit 8Mhz drann habe. > Desweiteren habe ich einen Prescaler von 64. > Da dieser Quarz nicht optimal für UART ist, ist mir bewusst, allerdings > brauche ich auch 8Mhz, damit ich genau Timer-INterrupts erstellen kann. Was für ein Prescaler ist das? Systemtakt oder Timer? Wenn's der Timer-Prescaler ist, wird der Takt der UART davon nicht beeinflußt. Wenn's hingegen der Systemtakt ist, dann natürlich schon. Allerdings ergäbe das keinen Sinn, da dann auch für den Timer nur 125kHz verfügbar wären, womit deine Begründung für den 8MHz Quarz obsolet wäre...
für den Systemtakt gibt es beim ATTiny nur die CKDIV8-Fuse. 8 MHz intern/extern/Quarz ergeben 1 MHz, oder 8 MHz Systemtakt, je nach Fuse-Setting. Die CKDIV8-Fuse muss in deinem Fall AUSGESCHALTET werden. Bei den klassischen ATTinys gibt es nur den 2313 mit UART. - Ist wohl zuviel verlangt, dass du den µC-Typ mal nennst... Der Prescaler 64 ist also ein Rätsel für alle, die helfen sollen. Erste Frage: (CKDIV8) Hast du 1 MHz, oder 8 MHz Systemtakt? Ansonsten hängt UBRR H/L direkt am Systemtakt, bei 1 MHz: UBRR = (fOSC / (16*BAUD) ) - 1 = UBRR = 1 MHz / (16 * 9600) - 1 = UBRR = 1.000.000 / 153.600 = 6,5 UBRR = geht nicht, 6 zu klein, 7 zu groß! bei 8 MHz: UBRR = (fOSC / (16*BAUD) ) - 1 = UBRR = 8 MHz / (16 * 9600) - 1 = UBRR = 8.000.000 / 153.600 - 1 = 52,0833 - 1 UBRR = 51 -> 9615 Bd - kein Problem! OK!
Und wenn du zu blöd bist die CKDIV8-Fuse abzuschalten, kannst du bei 1 MHz noch den Double-Speed-Mode wählen, dazu ist das U2X-Bit im UCSRA-Register zu setzen. (Schaffst du das????) Dann gilt: bei 1 MHz: UBRR = (fOSC / (8*BAUD) ) - 1 = UBRR = 1 MHz / (8 * 9600) - 1 = UBRR = 1.000.000 / 76.800 - 1 = 13,0208333 - 1 UBRR = 12 -> 9615 Bd - kein Problem! OK!
Jakob schrieb: > Die CKDIV8-Fuse muss in deinem Fall AUSGESCHALTET werden. Naja, theoretisch muss sie "eingeschaltet" werden, im weitesten Sinne :-D Denn viele, war damals (tm) bei mir genauso: 0 = Bit nicht gesetzt = programmed / eingeschaltet 1 = Bit gesetzt = unprogrammed / ausgeschaltet Das sorgt schon ab und wann für Verunreinigungen. ;-)
Marc schrieb: > Habe für den Uart eine Baud-Rate von 9600 genommen (fosc = 8Mhz), > allerdings wird nichts richtiges empfangen. > Marc Hi, da gibt es unter Umständen andere Probs noch, wenn nichts empfangen/gesendet wird: "... Die Originaldokumentation für den Attiny 2313 (2543L-AVR-08/10) macht auf Seiten 129 bis 133 UART Controlregisterdefinitionen, die nicht stimmen, so dass die Assemblierung im Studio4 fehlschlägt. "UCSRC not defined on this target " Im Attiny 4313 gibt es in der "def.inc" den klärenden Hinweis auf Kompatibilität. ser in out init: ldi temp, bdrt ;Baudrate setzen out UBRR, temp ; .equ UBRR=UBRRL;for compatibility ldi temp, 0x18 ;(1<<RXEN)+(1<<TXEN) out UCR, temp ; .equ UCR=UCSRB;for compatibility ret ; tx: ;RS232-Ausgaberoutine sbis UCSRA, UDRE ; .equ USR=UCSRA;for compatibility rjmp senden out UDR, temp ret ciao gustav P.S.: verwende bei 4 MHZ als Baudratenteilerkonstante 25 bei 9k6
Jakob schrieb: > - Ist wohl zuviel verlangt, dass du den µC-Typ mal nennst... Nein, zu viel ist es nicht verlangt, aber es ging ja nicht primär um Uart, sondern darum, mit welchem Takt der Controller läuft. Jakob schrieb: > Und wenn du zu blöd bist danke
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define FOSC 8000000 |
5 | #define BAUD_UART 9600 |
6 | #define UBBR_UART (FOSC/ (16*BAUD_UART))-1 |
7 | |
8 | void setup(void); |
9 | |
10 | volatile unsigned int senduart = 0; |
11 | |
12 | int main(void) |
13 | { |
14 | setup(); |
15 | |
16 | sei(); /* enable Interrupt */ |
17 | while (1) |
18 | { |
19 | if(1 == senduart) |
20 | { |
21 | senduart = 0; |
22 | USART_Transmit("A"); |
23 | } |
24 | } |
25 | } |
26 | |
27 | void setup(void) |
28 | { |
29 | /* Pin Setup */ |
30 | DDRB |= (1 << PB0); /* PB0 -> Output */ |
31 | PORTB &= ~(1 << PB0); /* PB0 -> Low */ |
32 | |
33 | /* Timer Setup */ |
34 | TCCR0A |= (1 << WGM01); /*Modus: CTC; Top: ORC0A */ |
35 | TCCR0B |= (1 << CS00) | (1 << CS01); /* Prescaler 64 */ |
36 | OCR0A = 125-1; /* ((8000000/64)/1000) = 125 */ |
37 | |
38 | /* Usart Setup */ |
39 | UBRRH = (UBBR_UART >> 8); // Set Baud-Rate */ |
40 | UBRRL = UBBR_UART; /* Set Baud Rate */ |
41 | UCSRB = (1 << RXEN) | (1 << TXEN); /* Enable receiver and transmitter */ |
42 | UCSRC = (1 << USBS) | (1 << UCSZ0) | (1 << UCSZ1); /* Set frame format: 8data, 2stop bit */ |
43 | |
44 | /* Interrupt Setup */ |
45 | TIMSK |= (1<<OCIE0A); /* enable Compare Interrupt */ |
46 | } |
47 | |
48 | void USART_Transmit( unsigned char data ) |
49 | { |
50 | while ( !( UCSRA & (1<<UDRE)) );/* Wait for empty transmit buffer */ |
51 | UDR = data; /* Put data into buffer, sends the data */ |
52 | } |
53 | |
54 | ISR (TIMER0_COMPA_vect) |
55 | { |
56 | static uint16_t milliseconds = 0; |
57 | milliseconds++; |
58 | if(milliseconds >= 1000) |
59 | { |
60 | milliseconds = 0; |
61 | senduart = 1; |
62 | PORTB ^= ( 1 << PB0 ); /* Toggle PB0 */ |
63 | } |
64 | } |
In der Timer ISR lasse ich eine LED Toggeln. Dies läuft auch jede Sekunde. Allerdings funktioniert das mit dem UART noch nicht. Benutze dazu das Programm HTerm, Es kommt zwar was an, aber bei jedem Senden 0x00 und 0xC0. Die Fuses sind: Extended: oxFF; High: 0x9F; Low: 0xEC DraconiX schrieb: > 0 = Bit nicht gesetzt = programmed / eingeschaltet > 1 = Bit gesetzt = unprogrammed / ausgeschaltet CKDIV8 habe ich nicht gesetzt (nach deiner Aussage dann ja eingeschaltet), jedoch stimmt dann ja meine Berechnung für den Timer nicht, bzw. dann ist da noch ein anderer Fehler drinn, da die ISR wie berechnet jede millisekunde ausgeführt wird
mach mal dein senduart volatile, das ist vermutlich nicht die Fehlerursache, ist aber notwendig, damit es nicht irgendwann doch hängt. Und dann häng doch einfach ein Scope an den TxD Pin und sieh dir die Breite der Bits an. Damit kannst du sofort die Baudrate errechnen und bekommst einen Hinweis, wo es nicht passt.
Marc schrieb: > #define UBBR_UART (FOSC/ (16*BAUD_UART))-1 Da der Compiler per Definition mit 16 Bit Integer rechnet, kommst hier nicht das gewünschte Ergebnis. Ein Blick in das .lss File zeigt dir, was passiert ist.
:
Bearbeitet durch User
> kommst hier nicht das gewünschte Ergebnis. Benutze die Datei setbaud.h zum Berechnen der Registerwerte. http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html
Die Frage nach dem µC könnte z.B. helfen, um für Ratschläge das Handbuch-Kapitel zu nennen. - Naja, manche müssen aus dem µC-Typ ein grooooßes Geheimnis machen. Oder lesen nicht gern? CKDIV8 ist bei Auslieferung GESETZT, d.h. AKTIV. Ob NULL, oder EINS das aktivierende Logik-Potential ist, KÖNNTE man auch im Handbuch nachlesen. Ändert man nichts am Auslieferungszustand, arbeitet der µC halt mit 1/8 der wirksamen Frequenz... Symbolische Rechnung ist schön, kann aber auch zu unbrauchbaren Ergebnissen führen: bei 1 MHz: UBRR = (fOSC / (16*BAUD) ) - 1 = UBRR = 1 MHz / (16 * 9600) - 1 = UBRR = 1.000.000 / 153.600 - 1 = 5 (Ganzzahl) Test: BAUD = (fOSC / (UBRR + 1)) / 16 = 10.417 = 8,5% daneben! Funktioniert nicht.
Das Standardvorgehen ist das UART mit einer Konstante, zB 0x55, senden zu lassen und mit einem Oszilloskop die Baudrate zu messen. Dann muss man viel weniger raten.
Hi >Das Standardvorgehen ist das UART mit einer Konstante, zB 0x55, senden >zu lassen und mit einem Oszilloskop die Baudrate zu messen. Wieso ist das 'Standard'? Ich brauche dafür lediglich IO-Frequenz und Baudrate. MfG Spess
Hi
>Weil man nahezu gar nichts ueberlegen muss.
Aber man muss mit dem Oszi umgehen können. Sonst kommt noch größerer
Mist als beim Rechnen heraus. Abgesehen davon besitzt nicht jeder einen
Oszi.
MfG spess
spess53 schrieb: > Wieso ist das 'Standard'? Ich brauche dafür lediglich IO-Frequenz und > Baudrate. Weil die IO-Frequenz nicht konstant ist. AVR wird mit einem für UART Betrieb etwas zu ungenauen internem Oszillator ausgeliefert, den man erst per Fuse auf Quarz (so vorhanden) umstellen muss.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.