AVR UART
Transcrição
AVR UART
27.03.2011 AVR UART 1. Einleitung In dieser Anleitung soll beispielhaft gezeigt werden, wie die serielle Kommunikation zwischen einem AVR Mikroprozessor und dem PC aufgebaut wird. Hierbei wird erst der einfache Fall behandelt, in dem nur Daten vom Mikroprozessor zum PC gesendet werden, um Messdaten zu erfassen. Der zweite Teil beschreibt anschließend, wie sich Befehle zum Prozessor senden lassen und per Interrupt verarbeitet werden können, um den zu steuernden Aufbau zu kontrollieren. 2. Hardware Diese Anleitung beschränkt sich auf die kleineren Prozessoren der AVR Familie vom Hersteller Atmel. Die unten verwendeten Bibliotheken wurden auf einem Atmega16 Prozessor getestet, welcher für viele Anwendungszwecke mehr als ausreichend ist. Die folgende Schaltung soll als Beispielaufbau dienen. Die Pegelwandlung auf den vom PC verwendeten seriellen Anschluss wird im Beispiel über einen MAX232 IC realisiert. Dies kann jedoch auch einfacher über einen UART zu USB Controller gebaut werden, da moderne PCs nur noch selten einen herausgeführten COM Port verfügen. Hier links zu Fertigbausteinen: ELV Modul: http://www.elv.de/output/controller.aspx?cid=74&detail=10&detail2=28776&flv=1&berei ch=&marke= FTDI Kabel: http://de.farnell.com/ftdi/ttl-232r-3v3/kabel-usb-ttl-level-ser-konverter/dp/1329311 Eine Suche nach den Schlagworten UART TTL USB Converter sollte jedoch für jeden Anwendungsfall eine passende Fertiglösung bieten. Diese UART TTL zu USB Konverter erlauben eine einfache und wenig fehleranfällige Verbindung zwischen MCU und PC. Sie werden an den Pins PD0(RXD) und PD1(TXD) angeschlossen und ersetzen die Pegelwandlerschaltung des MAX232 ICs. 1 27.03.2011 !!!Pinbelegung für Atmega16 im TQFP Gehäuse!!! !!!Für eigene Schaltung bitte selbst prüfen!!! Abbildung 1: Beispielschaltung Atmega16 (Pinbelegung für TQFP Gehäuse!) mit MAX232 Abbildung 2: RS232 Stecker Bei der Verbindung vom Stecker zum Pegelwandler müssen RX und TX vertauscht werden, d.h. PIN1 im Schaltplan auf PIN2 am Stecker, PIN2 im Schaltplan PIN3 und PIN 3 im Schaltplan auf PIN5. Die Verbleibenden Pins können offen gelassen werden (wenn keine Flusssteuerung gewünscht ist, Normalfall). 2 27.03.2011 3. Software Um die UART Schnittstelle der MCU verwenden zu können, muss sie erst initialisiert werden. Dies wird durch Einstellen der verwendeten Baudrate (9600Baud sollte immer gehen) im Headerfile des Projekts und durch den Aufruf der Funktion void uart_init(void) vor der Verwendung erledigt. To Do: a. CPU Takt definieren (AVR Studio, Rechtsklick aufs Projekt, Edit Configuration Options, Frequency in Hz eintragen) b. Einfügen der Baudratenberechnung ins Headerfile #include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> //USART DEFS #define BAUD 9600UL // Baudrate #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) c. Einfügen der Datei usart.c ins Projekt (.c Datei aus Quellcode unten erstellen) d. Aufrufen der Funktion uart_init(void); im Hauptprogramm e. Sollen auch Daten empfangen werden können, muss noch folgende ISR (Interrupt Service Routine) eingebaut werden (vor dem Hauptprogramm) und der Interrupt global eingeschalten werden mit der Funktion sei();. Sie liefert die empfangenen Werte als String in uart_string[]. #define uart_maxstrlen 10 // Definiere maximale Laenge für Empfang volatile uint8_t uart_str_complete=0; volatile uint8_t uart_str_count=0; volatile char uart_string[uart_maxstrlen+1]="X"; ISR(USART_RXC_vect) { unsigned char buffer; } buffer = UDR; if ( uart_str_complete==0 ) { if (buffer!='\n' && buffer!='\r' && uart_str_count<uart_maxstrlen-1) { uart_string[uart_str_count]=buffer; uart_str_count++; } else { uart_string[uart_str_count]='\0'; uart_str_count=0; uart_str_complete=1; } } Rücksetzen der Variable uart_str_complete in main(), wenn der String empfangen wurde. 3 27.03.2011 Die Datei usart.c enthält folgende Funktionen die für die Projekte relevant sind: • • • uart_init(); wird benötigt, um UART zu initialisieren uart_putc(); sendet einzelnes Zeichen an PC uart_puts(char* s); sendet String an PC bis Null erreicht wird Die folgenden Funktionen sollten besser über die Interrupt Lösung realisiert werden: • • uart_getc(); empfängt einzelnes Zeichen vom PC uart_gets(char* Buffer, uint8_t MaxLen); empfängt String Um den einfachen Fall zu betrachten, wird nun eine Terminal Verbindung aufgebaut. Da Windows Vista / 7 nicht mehr über das bekannte HyperTerminal mehr verfügen, wird empfohlen sich folgende Programme anzusehen. Termite: http://www.compuphase.com/software_termite.htm HTerm: http://www.der-hammer.info/terminal/index.htm Im hier gezeigten Beispiel wird das Terminal Programm Termite verwendet. 4 27.03.2011 4. Verbindungsaufbau und Datenübertragung Diese kleine Demo soll zeigen, wie die oben gezeigten Funktionen in einem Aufbau funktionieren. Die folgende Abbildung zeigt schematisch den Aufbau RX TX ISP bzw. JTAG ELV USB Konverter Atmega16 Versorgungsspannung (5V) RX TX NICHT ÜBER USB VERSORGEN UND AUSLESEN GLEICHZEITIG Abbildung 3: Schematischer Aufbau und Testaufbau 5 USB PC 27.03.2011 Nun kann die Entwicklungsumgebung gestartet und das Testprojekt erstellt werden. In diesem Fall wird AVR Studio 4.18 SP1 verwendet und als Programmer der AVR Dragon. Ist AVR Studio gestartet, wird ein neues AVR GCC Projekt angelegt und die für das System entsprechenden Einstellungen für den Prozessor und Debugger festgelegt (Atmega16 und AVR Dragon). mit einem Klick auf Finish wird das Projekt erstellt. 8 Mhz eintragen und mit OK bestätigen. 6 27.03.2011 Nun folgendes Testprogramm in die UART_ELV_MODUL.c Datei einfügen #include #include #include #include <avr/io.h> <inttypes.h> <avr/interrupt.h> <util/delay.h> #define F_CPU 8000000UL //USART DEFS #define BAUD 9600UL // Baudrate #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) #define uart_maxstrlen 25 // Definiere maximale Laenge für Empfang volatile uint8_t uart_str_complete=0; volatile uint8_t uart_str_count=0; volatile char uart_string[uart_maxstrlen+1]="Test"; ISR(USART_RXC_vect) { unsigned char buffer; buffer = UDR; if ( uart_str_complete==0 ) { if (buffer!='\n' && buffer!='\r' && uart_str_count<uart_maxstrlen-1) { uart_string[uart_str_count]=buffer; uart_str_count++; } else { uart_string[uart_str_count]='\0'; uart_str_count=0; uart_str_complete=1; } } uart_str_complete=0; } void uart_init(void) { UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); // UART RX, TX und RX Interrupt einschalten UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchron 8N1 UBRRH = UBRR_VAL >> 8; UBRRL = UBRR_VAL & 0xFF; } int uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))) { } UDR = c; return 0; } 7 27.03.2011 void uart_puts (char *s) { while (*s) { uart_putc(*s); s++; } } uint8_t uart_getc(void) { while (!(UCSRA & (1<<RXC))) ; return UDR; } // warten bis Zeichen verfuegbar // Zeichen aus UDR an Aufrufer zurueckgeben void uart_gets( char* Buffer, uint8_t MaxLen ) { uint8_t NextChar; uint8_t StringLen = 0; NextChar = uart_getc(); // Warte auf und empfange das nächste Zeichen // Sammle solange Zeichen, bis: // * entweder das String Ende Zeichen kam // * oder das aufnehmende Array voll ist while( NextChar != '\n' && StringLen < MaxLen - 1 ) { *Buffer++ = NextChar; StringLen++; NextChar = uart_getc(); } // Noch ein '\0' anhängen um einen Standard // C-String daraus zu machen *Buffer = '\0'; } int main (void) { uart_init(); sei(); while(1) { uart_puts(uart_string); uart_puts("\n"); _delay_ms(500); } } In dem oben angegebenen Programm wurden Teile des auf www.mikrocontroller.net veröffentlichten Tutorials verwendet. 8 27.03.2011 Im Anschluss kann das Projekt kompiliert und auf das Zielgerät (Atmega16) übertragen werden. Programmiermodus wählen und Signatur abgleichen. 9 27.03.2011 Nun FUSES setzen. LOW FUSE auf 0xE4 setzen den HIGH FUSE auf default (nicht JTAG abschalten !). HEX Datei wählen aus dem Ordner Default des Projekt. ACHTUNG, wird nicht automatisch aus aktuellem Projekt gewählt!!! Flashen mit klicken auf Programm. 10 27.03.2011 Nun kann AVR Studio geschlossen und das Terminal Programm Termite gestartet werden. Mit Settings nun Parameter einstellen Kann im Gerätemanager eingesehen werden Ist die Verbindung, korrekt sollte der Teststring ankommen. 11 27.03.2011 Um den Interrupt zu testen, senden wir nun einen String, den der Prozessor wie im Programm definiert, wieder als Endlosschleife zurück sendet. HIER TEXT EINGEBEN und Senden! Zur Messwertübertragung weitere brauchbare Funktionen sind: itoa: http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ atoi: http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/ dtostrf(float,int,int,char*) float -> string Viel Spaß bei den Projekten! Hilfe zum Thema: [email protected] 12