Habe folgende Probleme mit der Seriellen bzw. dem Hyperterminal:
Verwende das Crumb8USB-Board (Dev.board mit einem ATmega8) und verbinde
mich dabei mittels USB-Kabel zum PC. Den zugehörigen Treiber hab ich
installiert. Das folgende Programm müsste doch funktionieren, wenn ich
ein Zeichen im Hyp.terminal runterschicke und anschließend ein Zeichen
(0x02) zurückbekomme, oder? wo hab ich den Fehler eingebaut?
1
#include<inttypes.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<util/delay.h>
5
6
#define USART_RXC_vect _VECTOR(11)
7
8
#ifndef F_CPU
9
#define F_CPU 1000000 /* Oszillator-Frequenz in Hz */
10
#endif
11
12
#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1) //Hilfsmakro zur UBRR-Berechnung ("Formel" laut Datenblatt)
13
#define UART_BAUD_RATE 9600
14
15
16
17
volatileuint16_tcontrol_sign;//Steuerzeichen (Protokoll) von SS
18
19
20
voidSend(intsign)
21
{
22
while(!(UCSRA&(1<<UDRE)));/* warten bis Senden moeglich, Usart Data Register Empty (!!) */
23
UDR=sign;/* schreibt das Zeichen x auf die Schnittstelle */
24
}
25
26
27
ISR(USART_RXC_vect)
28
{
29
control_sign=UDR;//?????
30
Send(0x02);
31
}
32
33
voidinit_serial()
34
{
35
//Serielle:
36
//Baudrate: 9600
37
//Frame: 8 Datenbits, 1 Stoppbit, 1 Parity (even)
38
39
cli();//Nur während der Initialisierung der Seriellen SS
40
41
UCSRB|=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);// UART TX und RX einschalten, RX Complete Interrupt Enable
Das Problem ist bestimmt die Baudrate (wenn 9600, 8E1 überhaupt das ist,
was du willst), schau mal in die Tabelle im Datenblatt mit den
UBRR-Beispielen (Tipp: Abweichungen von mehr als 2% funktieren kaum).
und überleg, ob du für dem Atmega nicht besser einen (Baudraten-) Quarz
nimmst, der interne RC-Oszillator ist Glückssache (+- 3%)
ps.: das "#define USART_RXC_vect" ist sinnlos (steht ja auch genauso in
der iom8.h, die der Compiler einbindet)
Joerg X. wrote:
> schau mal in die Tabelle im Datenblatt mit den> UBRR-Beispielen (Tipp: Abweichungen von mehr als 2% funktieren kaum).> und überleg, ob du für dem Atmega nicht besser einen (Baudraten-) Quarz> nimmst, der interne RC-Oszillator ist Glückssache (+- 3%)
Naja, sie sollte noch U2X setzen und dann in der Formel durch 8 statt
16 teilen, dann gibt's keinen Grund, warum das nicht zumindest erst
einmal bei Vcc = 5 V (Werkskalibrierung des RC-Oszillators) nicht
funktionieren würde.
Birgit wrote:
> mach ich vielleich einen Fehler mit dem hyperterminal?
Hyperterminal ist verrufen. Ich nehme aber kein Windows, ich kann dir
da zu nicht viel aus eigener Erfahrung raten.
> stimmt ansich der code?
Vom groben Drübergucken stimmt er.
Jörg Wunsch wrote:
> Birgit wrote:>>> mach ich vielleich einen Fehler mit dem hyperterminal?>> Hyperterminal ist verrufen. Ich nehme aber kein Windows, ich kann dir> da zu nicht viel aus eigener Erfahrung raten.
Für ein Terminal ist das gar nicht so schlecht.
Wenn es richtig konfiguriert ist, macht es eigentlich
alles was ich von einem Terminal erarten würde.
@Birgit
Ich würde aber kein
Send (0x02);
machen. 0x02 ist ein Steuerzeichen, dass von Hyperterminal
nich angezeigt wird. Lass dir doch einfach mal
ein 'x' zurückschicken (oder noch besser: Das Zeichen
das empfangen wurde).
Wenn du den internen RC-Oszillator verwenden möchtest, musst du beim
Programmstart das Calibration-Byte in das OSCCAL-Register schreiben.
Nur dann und nur bei 5 V Betriebsspannung läuft der Oszillator
innerhalb der im Datenblatt angegebenen Toleranz. Ohne das Beschreiben
des OSCCAL-Registers ist die Frequenzabweichung viel zu groß, um damit
RS-232 machen zu können.
Das Calibration-Byte steht bei nagelneuen (noch nie gelöschten) AVRs
am Ende des Flash-Speichers und kann vom Programm ausgelesen werden.
Ansonsten (d.h. in den meisten Fällen) muss es über das
Programmiergerät aus einem für das Programm unzugänglichen
Speicherbereich gelesen und entweder direkt in den Flashspeicher
zurückgeschrieben oder in den Sourcecode eingetragen werden.
Wie das Calibration-Byte per ISP-Programmer gelesen wird, verrät die
die Bedienungsanleitung desselben bzw. der zugehörigen PC-Software.
Quatsch!
Ich nehme alles zurück, was ich irrigerweise in meinem vorigen Post
geschrieben habe. Der ATmega8 lädt das Calibration-Byte automatisch
beim Reset. Lediglich bei älteren AVRs (zb.B: ATtiny15L) muss der
Programmierer noch selbst dafür sorgen.
Wenn's unbedingt mit R/C-Oszillator sein soll, dann sollte man die
Oszillatorfrequenz trotzdem nochmal nachkalibirieren. Ich hab das mal
gebraucht, als ich nicht extra für ein paar Debug-Ausgaben während der
Entwicklung einen Quarz einbauen wollte.
Einfach ein kleines Testprogramm schreiben, das z.B. einmal pro Sekunde
blinkt. Das läßt man für eine Minute laufen und zählt, wie oft es
geblunken hat. Dann versucht man das Spielchen so oft mit entsprechend
verändertem OSCCAL, bis man möglichst nahe am richtigen Wert ist.
Ich habe schon erlebt, daß ohne diese Maßnahme nur Datenmüll ankam.
> Nur dann und nur bei 5 V Betriebsspannung läuft der Oszillator> innerhalb der im Datenblatt angegebenen Toleranz.
Auch die Temperatur spielt eine Rolle. Die Werte gelten für +25°C.
> Der ATmega8 lädt das Calibration-Byte automatisch beim Reset.
Wobei es sich immer um das für 1Mhz handelt. Wenn man ihn mit einem
anderen Takt betreibt, muß man OSCCAL manuell laden.
Rolf Magnus wrote:
> Wenn's unbedingt mit R/C-Oszillator sein soll, dann sollte man die> Oszillatorfrequenz trotzdem nochmal nachkalibirieren.
Bei den neueren AVRs ist der RC-Oszillator recht gut geworden. Dort
bekommt man sogar noch eine benutzbare RS-232-Kommunikation ohne
Nachkalibrieren, wenn man von 5 V auf 3 V runtergeht. (Mit einem
ATmega128 hat das nie funktioniert, mit einem ATmega1281 praktisch
immer.)
Cliff Lawson hat auf avrfreaks.net mal eine interessante Version
beschrieben (wobei ich nicht weiß, ob er auch den Code veröffentlicht
hat): der Benutzer muss zu Beginn der Kommunikation ein paar Mal
<Enter> drücken, das gibt ein Zeichen 0x0d (carriage return). Dessen
Bitzeiten misst er dann und kalibriert danach den RC-Oszillator nach.
>> Der ATmega8 lädt das Calibration-Byte automatisch beim Reset.> Wobei es sich immer um das für 1Mhz handelt. Wenn man ihn mit> einem anderen Takt betreibt, muß man OSCCAL manuell laden.
Auch hier sind die neueren AVRs im Vorteil: die haben nur noch einen
RC-Oszillator. Der schwingt auf 8 MHz, wird aber im
Auslieferungszustand via CKDIV8 und CLKPR auf 1 MHz geteilt. Damit
gibt's aber auch nur noch ein Kalibrierungsbyte, das wird beim
power-on automatisch geladen.
Es gibt sogar eine Appnote, die sich nur mit den verschiedenen in AVRs
verbauten Oszillator-Varianten beschäftigt. Ich glaube, es gibt
mittlerweile 4 oder 5 verschiedene.
Die Butterfly Programme arbeiten oft auch mit einer Kalibrierung durch
den Uhrenquarz. Auf http://butterflylogger.sourceforge.net/ wurde der 8
MHz Oszillator auf 7.3728 MHZ getrimmt um mit 115200bps zu
kommunizieren. Ich hab's probiert und kann die kompletten Daten aus dem
Dataflash ohne Störung übertragen. Der Butterfly lief schon mehrere Tage
ohne Neustart (und erneutes Kalibrieren) mit drei AA Batterien bei
unterschiedlichsten Temperaturen. Keine Probleme mit dem UART Timing.
Terminal Programm war SuperTerm 2.14.