Ich habe ein winziges 2.0-Board und versuche, damit dieses LCD über serielles TTL zu steuern.
Ich habe es mit meinem Arduino uno und einigen Arduino-Beispielcodes zum Laufen gebracht, aber ich möchte es mit der Teensy- und der C-Sprache machen.
Der Teensy verwendet den ATmega32u4 und hier ist das Datenblatt für diesen Chip.
Im Datenblatt ab Seite 186 befindet sich der Abschnitt über USART. Auf Seite 192 finden Sie einen Beispielcode in C-Sprache zum Initialisieren des USART. Ich bin in ein paar Zeilen verwirrt und könnte etwas Hilfe gebrauchen.
void USART_Init( unsigned int baud )
{
/* Set baud rate */
UBRRHn = (unsigned char)(baud>>8);
UBRRLn = (unsigned char)baud;
/*rest of code here*/
}
Erstens ist mir nicht klar, wie die Baudratenzahl lauten soll. Mein LCD fordert 9600 Baud mit 1 Startbit, 1 Stoppbit, kein Paritätsbit und 8 Datenbits. Auf Seite 189 des Datenblatts des ATmega32u4 habe ich die Berechnung durchgeführt, wie hoch die Baudrate sein sollte, die im Fall der Teensy- und LCD-Kombination 103 sein sollte, da die Chipfrequenz 16 MHz und die Baudrate 9600 beträgt. Dies entspricht auch der Zahl in das Diagramm auf Seite 213 des Datenblatts des ATmega32u4. Ist dies also die richtige Zahl, die an die USART_Init-Funktion für die Variable Baud übergeben würde?
Ich bin auch verwirrt über die beiden Zeilen, die die Baudrate einstellen. Ich verstehe, dass die Baudratenregister gemäß Seite 209 des Datenblatts des ATmega32u4 in ein niedriges und ein hohes Register aufgeteilt sind, aber nur die Bits 8:10 im hohen Register verwendet werden, was es zu einem kombinierten 12-Bit-Register macht. Also, zurück zum Code, ich verstehe einige Dinge nicht:
UBRRHn = (unsigned char)(baud>>8);<br/>
UBRRLn = (unsigned char)baud;
Außerdem habe ich auf der Teensy-Website einen Beispielcode (http://www.pjrc.com/teensy/uart.html) gefunden, der den UART einrichtet und die Baudrate wie folgt einrichtet:
void uart_init(uint32_t baud)
{
cli();
UBRR1 = (F_CPU / 4 / baud - 1) / 2;
/*rest of code here*/
}
Setze ich die Zahlen ein, sieht das so aus:
UBRR1 = (16000000 / 4 / 9600 - 1) / 2; /* Which would equal 208 */
Nun, ich freue mich darauf, diesen Buckel zu überwinden und meinen LCD-Bildschirm zum Tanzen zu bringen. :)
Um all diese Dinge zu verstehen, werfen Sie einen Blick auf "Tabelle 18-1. Gleichungen zur Berechnung der Baudratenregistereinstellung" aus dem Datenblatt auf Seite 189. Die Gleichung, die Sie vorgeschlagen haben, haben Sie in einem Beispielcode gefunden
UBRR1 = (F_CPU / 4 / baud - 1) / 2;
... kommt der Gleichung für den asynchronen Double-Speed-Modus (U2Xn = 1) ziemlich nahe ... aber nicht genau.
Wenn Sie die Baudrate und Quarzgeschwindigkeit kennen, mit der Sie arbeiten möchten, würde ich einfach die Registereinstellungen aus "Tabelle 18-9. Beispiele für UBRRn-Einstellungen für häufig verwendete Oszillatorfrequenzen" auf Datenblatt Seite 210 entnehmen und Schluss machen. Der einzige Grund, eine dieser Gleichungen zu verwenden, ist, wenn Sie die Einstellungen aus irgendeinem Grund zur Laufzeit dynamisch ändern möchten (oder wenn Sie dies "elegant" in der Software tun möchten, bevorzuge ich die Gewissheit der Kompilierzeit für so etwas wie dies, um Zweifel auszuräumen).
Für die Einstellungen, die Sie in Ihrer Frage skizziert haben, wären das:
UCSR1A = 0; // importantly U2X1 = 0
UCSR1B = 0; // interrupts enabled in here if you like
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); // no parity, 8 data bits, 1 stop bit
UCSR1D = 0; // no cts, no rts
UBRR1 = 103; // 9600 baud @ 16MHz XTAL with U2X1 = 0
Nebenbei bemerkt, während die Hardware das Baudratenregister (UBBRn) als zwei 8-Bit-Register speichert, muss es in der Software nicht als solches behandelt werden. Sie können auf die High- und Low-Register (z. B. UBRR1H bzw. UBRR1L) zugreifen, aber Sie können auch einfach dem benannten "kombinierten" Register zuweisen (oder daraus lesen), als wäre es ein 16-Bit-Register.
UBRR1 = 0x0343;
ist funktional äquivalent zuUBRR1H = 0x03; UBRR1L = 0x43;
Ein unsigned char
sollte immer 8 Bit oder ein einzelnes Byte sein. Vergessen Sie, dass es sich um ein "Zeichen" handelt, sondern nur um einen Zahlendatentyp, der die gleiche Größe wie unsere Register hat. Da wir eine Zahl übergeben, die möglicherweise 12 Bit groß sein könnte, akzeptiert unsere Funktion einen Datentyp, der groß genug für baud
( unsigned int
) ist. Dies kann je nach unserer Architektur entweder 32 oder 16 Bit sein (spielt in diesem Fall keine Rolle).
Für diese Architektur sind unsere UBRRHn
und UBRRLn
Register jeweils 1 Byte groß. Wir haben kein einziges Register, das groß genug ist, um diesen 12-Bit-Wert aufzunehmen, also haben wir zwei 8-Bit-Register, und wie Sie erwähnt haben, teilen wir diese 12-Bit-Zahl in jedes auf. UBRRHn
nimmt die oberen 4 Bits, während UBRRLn
die unteren 8 verwendet werden.
Wir verschieben die unsigned int
8 Positionen nach unten, um diese oberen 4 Bits zu erhalten. Nehmen wir ein triviales Beispiel mit allen '1'-Bits:
baud = 4095;
UBRRHn = (unsigned char)(baud>>8);
// our shift: 0b0000111111111111 >> 8 == 0b0000000000001111
// after cast & assignment, UBRRHn == 0b00001111
UBRRLn = (unsigned char)baud;
// after cast & assignment, UBRRLn == 0b11111111
Unsere Umwandlung in unsigned char
nimmt die unteren 8 Bits, da unsigned char
es sich um einen 8-Bit-Datentyp handelt.
Ich habe keine Zeit, den anderen Beispielcode durchzugehen, aber es könnte sein, dass er zur Kompilierzeit ein Makro oder etwas anderes verwendet, um ihn für ihn aufzuteilen. Sie könnten tiefer graben und herausfinden, wo UBBR1 definiert ist. Wenn Sie ihm nicht vertrauen, verwenden Sie ihn nicht. Tun Sie zuerst das, was Sie für Ihre Hardwarekonfiguration als wahr kennen, und testen Sie es.
dext0rb
rayjamesfun