Hallo Leute - irgendwie wollte ich einfach nur über mein STK mit einem
AtMega16 ein Zeichen über die serielle Schnittstelle ans Hyperterminal
schicken da ich in weiterer Folge mehr mit der RS232 zu tun haben werde
und irgendwie funktioniert das schon nicht - ist mein Programm einfach
zu wenig oder ist da was Grundlegendes falsch? Header-File ist im
Anhang.
Dies ist das Hauptprogramm.
Larry wrote:
> zu wenig oder ist da was Grundlegendes falsch? Header-File ist im> Anhang.
Das ist kein Header, sondern astreiner Code.
Sowas *.h zu nennen und zu includieren, ist erlaubt, aber nicht ratsam,
wenn man auch noch in größeren Projekten die Übersicht behalten möchte.
Preisfrage:
Wozu ist wohl Init() da, wie wärs mal mit ausführen?
Peter
-.- Gute Idee zumindest mal die Init() zu verwenden, danke, vorlauter
herumprobieren den ganzen Tag sowas nit mal mehr sehen - jetzt spuckt
das Ganze zumindest irgendwelche Zeichen aus - wenn auch nicht die, die
ich mir vorstellen würde.
So jetzt hab ich das ganze umgeändert - nach Anleitung vom Datenblatt
wie vorgeschlagen und irgendwie erscheint immer noch nichts im
HyperTerminal...sieht irgendwer das Problem.
Im Header-File prototypen.h stehen auch nur eben diese drin.
> #define FOSC 3686400
Weiss der Atmega16, dass er mit 3686400 Hz zu laufen hat? Ab Werk macht
er das nämlich nicht.
Die Voraussetzungen sind
1/ Das STK500 stellt eine Taktquelle von 3686400 Hz bereit
2/ Die Taktquelle kommt am Atmega16 an den richtigen Pins an
3/ Der Atmega16 ist per AVR Fuses auf die Nutzung dieser Taktquelle
eingestellt
Keines von 1-3 macht die Definition des Taktes in dem Quellcode. Diese
Definition ist in obigem Fall nur dazu da die Parameter für die UART
Baudrate zu berechnen. Die Definition hilft allerdings garnichts, wenn
die UART mit einer anderen Taktrate betrieben wird.
Wenn du jetzt Zweifel hinsichtlich der Taktrate hast, versuche ein
Programm zu schreiben, bei dem eine LED im 10 Sekunden Takt blinkt. Eine
Abweichung von 37 s (Atmega16 hat Werkseinstellung 1 MHz) zu 10 s
(Wunschtakt funktioniert mit 3,686400 MHz) sollte offensichtlich sein.
Eine weitere "beliebte" Fehlerquelle ist die ZUordnung TX am AVR zum RX
am PC. Irgendwo muss diese Verbindung (und die Verbindung der
Masseleitung) vorhanden sein. Manchmal greift man ein vermeindlich
passendes RS232-Kabel aus der Kiste und es ist promt das falsche - also
1:1 Kabel (Modemkabel) statt Nullmodemkabel und umgekehrt.
Für das STK500 brauchst du ein 1:1 (Modem) RS232-Kabel zwischen dem
STK500 RS232-Port for Communication (nicht der RS232-Port for
Programming) und eine Verbindung zur zweiten Seriellen Schnittstelle am
PC. Die Kreuzung TX-RX ist bereits auf dem STK500 gemacht.
Und das Terminalprogramm muss auf die zweite serielle Schnittstelle
eingestellt sein.
Ausserdem brauchst du auf dem STK500 auch noch eine 2-Drahtverbindung
zwischen den I/O-Pins am Atmega16 (PD0=RXD und PD1=TXD) und den
RS232-Pins (RS232 SPARE) auf dem Board.
Zur Taktquelle würde ich sagen, dass der XTAL1 Jumper gesteckt sein
sollte und dass OSCSEL in Stellung 1-2 geschlossen ist. In diesem Fall
wird die software-generated clock benutzt, die per AVR Studio auf
3,686400 MHz eingestellt werden kann. Damit diese Taktquelle
anschliessend auch vom Atmega16 benutzt wird, muss der Atmega16 über
seine Fuses auf externe Taktquelle eingestellt werden.
Also bei den Fuses hab ich nur die Möglichkeiten von 1,2,4 und 8 MHz
jeweils + xx ms StartupTime, aber ich kann den ClockGenerator einstellen
auf 1,843 oder 3,686 MHz - viele Zwischenmöglichkeiten gibt er mir dabei
gar nicht.
Die 2-Drahtverbindung hab ich - das RS232-Kabel sollte auch passen.
XTAL1-Jumper ist gesteckt und OSCSEL auch auf 1-2 geschlossen.
Die Einstellung bei den Fuses hab ich jetzt auf Ext.Clock - StartupTime
6CK+0ms.
Da ich nur ein serielles Kabel momentan zur Verfügung habe ist das
Terminalprogramm auch auf die richtige Schnittstelle eingestellt.
Hab das ganze auch mit der Hälfte der Taktfrequenz 1,832MHz probiert und
es geht dennoch nicht.
Was wären jetzt die richtigen Pins für den Takt?
Clockgenerator auf 3,686 MHz einstellen. XTAL1 gesteckt. OSCSEL auf 1-2
geschlossen. Fuses sollte nach deiner Einstellung (Ext.Clock) OK sein.
Noch die
Hat der PC eine Chance etwas zu empfangen? Modemkabel an der seriellen
Schnittstelle des RS abziehen. Programm auf den AVR laufen lassen. Mit
Voltmeter zwei Spannungsmessungen machen:
GND = Pin 5 am 8-pol. Stecker des Modemkabels
Messung 1: Welche Spannung ist an Pin 2?
Messung 2: Welche Spannung ist an Pin 3?
Die Leitung, auf der eine deutliche Spannung (keine im mV-Bereich bei
einem auto range Voltmeter) zu messen ist, ist die auf RS232-Pegel
gebrachte Sendeleitung des AVR.
Wenn der AVR nicht sendet, sollte die Spannung an einem der beiden Pins
ca. -12V betragen. Beim Senden geht das aus dem negativen Bereich hoch
(Betrag sinkt). Wieviel ist davon abhängig, wie gesendet wird und wie
träge die Anzeige des Voltmeters ist. Ich kann keinen genauen Wert
angegeben.
Wenn von der RS232-Hardware her alles OK ist, solltest du die
Sendeleitung des AVR auf Pin 2 am Kabelende identifizieren können.
Also ich habe jetzt zuerst die serielle überprüft und ja auf PIN2 liegen
während das Programm zum Senden am µC ist -2V und habe jetzt das
URSEL-Bit auch noch gesetzt und mir scheint es funktioniert jetzt
endlich. Endlich mal ein Erfolgserlebnis dieses verlängerte Wochenende.
Ahja und die Reihenfolge in der Initialisierung ist jetzt zuerst
UBRRH->UBRRL->UCSRB->UCSRC.
Vielen vielen Dank Stefan für die vielen Tipps und die guten Erklärungen
- dann hoffe ich mal, dass ich beim Empfangen nicht wieder ähnliche
Probleme haben werde.
Viele Grüße Larry
Wollte noch kurz anmerken für diejenigen die den Code hier rauskopieren
und verwenden wollen: Bei mir hats das AVR-Studio erst richtig gemacht
als die Zeile
UCSRC = (3<<UCSZ0); //8bit - 1 Stopbit
in
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); //8bit - 1 Stopbit
geändert wurde. Sonst sendet es nur 7Bit Daten!
Jo wrote:
> Wollte noch kurz anmerken für diejenigen die den Code hier rauskopieren> und verwenden wollen: Bei mir hats das AVR-Studio erst richtig gemacht> als die Zeile> UCSRC = (3<<UCSZ0); //8bit - 1 Stopbit> in> UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); //8bit - 1 Stopbit> geändert wurde. Sonst sendet es nur 7Bit Daten!
Der ATMega16 (um den es hier bisher ging) hat aber erstens kein UCSR0C
sondern nur ein UCSRC und zweitens hat das nichts mit AVRStudio zu
tun, sondern wenn überhaupt, dann mit dem Compiler und drittens lässt
sich die zweite Version auch wie oben schreiben:
Hallo.
Ich habe folgendes Problem:
Ich habe die UART-Initialisierung wie im Datenblatt des ATmega16
beschrieben programmiert (STK500,AVR Studio,JTAGICE mkII zum
debuggen).Möchte einen Wert über den UART an HyperTerminal schicken.
void init_uart(uint16_t baudrate)
{
DDRD |= (1 << RXD) | (1 << TXD);
PORTD |= (1 << RXD) | (1 << TXD);// receive and transmit pin as output
UCSRC |= (1 << UCSZ1) | (1 << UCSZ0) | (1 << USBS);// 8 databits,1
stopbit(USBS=0)
UCSRB |= (1 << TXEN) | (1 << RXEN);// enable transmitter and receiver
UBRRH = baudrate >> 8; // extract high-byte from baudrate
value
UBRRL = baudrate & 0xFF; // extract low-byte from baudrate value
}
Wenn ich nun debugge,dann beschreibt es bei mir nur das Register UCSRB.
Im Register UCSRA steht wie im Datenblatt beschrieben das Bit UDRE auf
1.Ansonsten kann das Register ebenso wie UCRSC nicht beschrieben werden.
Hat jemand eine Idee woran das liegen kann?
Warum gräbst du dafür einen eineinhalb Jahre alten Thread aus?
Mike schrieb:
> DDRD |= (1 << RXD) | (1 << TXD);> PORTD |= (1 << RXD) | (1 << TXD);// receive and transmit pin as output
warum einen Eingang als Ausgang definieren?
> UCSRC |= (1 << UCSZ1) | (1 << UCSZ0) | (1 << USBS);// 8 databits,1> stopbit(USBS=0)
Was nun USBS = 1 oder 0?
Und vielleicht solltest du auch mal ins Datenblatt schauen, wie man auf
UCSRC zugreift...
> Warum gräbst du dafür einen eineinhalb Jahre alten Thread aus?
Warum Unmengen von Threads aufmachen,wenn dieser genau mein Anliegen
betrifft?
> DDRD |= (1 << TXD);> PORTD |= (1 << TXD);
Gut,hab ich vergessen rauszunehmen.Will sowieso nur senden. :)
>Was nun USBS = 1 oder 0?
O.k.!Ein stoppbit,also USBS = 0
>Und vielleicht solltest du auch mal ins Datenblatt schauen, wie man auf>UCSRC zugreift...
hatte ich vergessen: UCSRC |= (1 << URSEL); muss natürlich noch da
stehen.
Gut,die Hyperterminal-Kommunikation geht nun schon mal.Lag daran,dass
die Baudrate auf 115200 eingestellt werden muss.
Aber trotzdem kann ich die Register UCSRC und UCSRA immer noch nicht
beschreiben.
Im Terminalprogramm wird entweder ein Leerzeichen oder irgendein
ASCii-Zeichen ausgegeben?!?
Initialsierungscode sieht so aus:
void init_uart(uint16_t baudrate)
{
DDRD |= (1 << TXD);
PORTD |= (1 << TXD); // receive and transmit pin as output
UCSRC |= (1 << URSEL);
UCSRC |= (1 << UCSZ1) | (1 << UCSZ0);// 8 databits,1 stopbit(USBS=0)
UCSRB |= (1 << TXEN); // enable transmitter and receiver
UCSRC &= (1 << URSEL); // for write operation of UBRRH
UBRRH = baudrate >> 8; // extract high-byte from baudrate value
UBRRL = baudrate & 0xFF; // extract low-byte from baudrate value
}
Sorry, aber das ist Unsinn. URSEL muss gleichzeitig mit den anderen Bits
geschrieben werden. Und es muss auch nicht wieder gelöscht werden.
1
UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
Mal ganz davon abgesehen, dass dieses Schreiben nach UCSRC eh
überflüssig ist. Was du da reinschreiben willst ist eh schon der
Default-Inhalt.
PS: Und das gewöhn dir bitte ab:
> Warum Unmengen von Threads aufmachen,wenn dieser genau mein Anliegen> betrifft?
Neue Frage -> neuer Thread (auch wenn die Frage ähnlich ist)
Ja du hast recht.Das ist der default-Inhalt.Aber trotzdem sehe ich
diesen eben nicht in meinem view I/O-Fenster.
Dort setzt es nur das Bit meinen UCSRB-Registers,sonst nichts.Ist doch
schon komisch oder?
Mike schrieb:
> Ja du hast recht.Das ist der default-Inhalt.Aber trotzdem sehe ich> diesen eben nicht in meinem view I/O-Fenster.> Dort setzt es nur das Bit meinen UCSRB-Registers,sonst nichts.Ist doch> schon komisch oder?
Du kannst den Inhalt nicht direkt im Debugger sehen. Wenn der UCSRC
ausliest, liest er ja in Wirklichkeit UBRRH.