Datum: 04.05.2008 15:07
Hallo zusammen. Ich versuche gerade über den USART meines NGW100 Zeichen
auszugeben. Doch irgendwie will das nicht so recht funktionieren. Das
ganze läuft als Standaloneapplikation.
Hiermal der Quellcode:
#ifndef IO_H
#include <avr32\io.h>
#endif
#include <stdint.h>
#define CPUHZ 24576000
int main(int argc, char** argv){
uint32_t i=0;
/* PIO Enable Register. Pin-Maske für die Pins, welche durch den
PIO-Controller gesteuert werden sollen. */
//UART
//UART-Reset
AVR32_USART1.idr = 0xffffffff;
AVR32_USART1.mr = 0;
AVR32_USART1.rtor = 0;
AVR32_USART1.ttgr = 0;
AVR32_USART1.cr = (1 << AVR32_USART_CR_RSTRX_OFFSET) |
(1 << AVR32_USART_CR_RSTTX_OFFSET) |
(1 << AVR32_USART_CR_RSTSTA_OFFSET) |
(1 << AVR32_USART_CR_RSTIT_OFFSET) |
(1 << AVR32_USART_CR_RSTNACK_OFFSET) |
(1 << AVR32_USART_CR_DTRDIS_OFFSET) |
(1 << AVR32_USART_CR_RTSDIS_OFFSET);
//Register initialisieren
AVR32_USART1.mr =0x800008C0;
AVR32_USART1.cr |= (1<<AVR32_USART_CR_TXEN_OFFSET);
//PIO-Mask
AVR32_PIOA.pdr|=(1<<17);
AVR32_PIOA.pudr|=(1<<17);
AVR32_PIOA.asr|=(1<<17);
AVR32_PIOA.pdr|=(1<<18);
AVR32_PIOA.pudr|=(1<<18);
AVR32_PIOA.asr|=(1<<18);
while(1){
for(i=0;i<1000000;i++);
AVR32_USART1.thr = 0x00000078;
}
return 0;
}
Das ganze soll bei 38400 baud laufen. Jemand eine Idee?
Datum: 04.05.2008 16:17
> Doch irgendwie will das nicht so recht funktionieren. Ist das deine Fehlerbeschreibung? PS: http://www.avrfreaks.net/ hat ein AVR32 Forum.
Datum: 04.05.2008 17:19
Naja, eine richtige Fehlerbeschreibung gibt es nicht. Im Hyperterminal, welches ich an den UART-Port angeschlossen habe, werden keine Zeichen ausgegeben. Woran kann das liegen?
Datum: 04.05.2008 19:08
André Schimschar wrote: > Naja, eine richtige Fehlerbeschreibung gibt es nicht. Dann solltest du dich damit abfinden können, dass es keine richtige Hilfe gibt. > Im Hyperterminal, > welches ich an den UART-Port angeschlossen habe, werden keine Zeichen > ausgegeben. Woran kann das liegen? Du hast etwas vergessen oder falsch gemacht :P Mal im Ernst: Entweder du gibst mehr Informationen (Hardwareaufbau, kompilierbares Programm, etc..) oder es wird wohl nichts mehr. Einfach ein bisschen Code reinhauen und andere Leute ans Fehlersuchen schicken ist nicht gerade eine beliebte Art der Fehlerbehebung.
Datum: 04.05.2008 19:33
Mit folgendem Codeschnispel läuft eine Standalone-Anwendung auf dem Grasshopper. Es ist nicht notwendig, den UART zu initialisieren, das kann die NEWLIB schon. Du weißt das es für Standalone-Anwendungen eine 2. Toolchain gibt? Wenn Du alles unter Windows installiert hast, ist glaube ich, beides (Linux / Standalone) installiert.
#include <stdio.h> #include <stdlib.h> #include <sys/cpu.h> #include <sys/usart.h> //--- Inform the newlib library about the CPU clock set_cpu_hz(20000000); // my board is clocked with 20MHz after reset //--- setup UART0 one for stdio (e.g. printf....) set_usart_base((void*)AVR32_USART0_ADDRESS); // init UART driver (set UART0 adress) usart_init(115200); // init UART0 with 115200 baud //--- We are finish to send the world a message printf("\r\nHello World\r\n"); |
Viel Spaß
Datum: 04.05.2008 21:50
Wow! DANKE,DANKE,DANKE! Gibt es so was einfaches auch für den SPI-Bus???
Datum: 04.05.2008 22:16
André Schimschar wrote: > Wow! > DANKE,DANKE,DANKE! Gerne doch :-) > Gibt es so was einfaches auch für den SPI-Bus??? Keine Ahnung. Ich habe in den Sourcen der Newlib gegraben, bis ich das mit dem UART gefunden habe. Es gibt keine Doku. Die lassen das den Kunden machen. Ist echt Schlamperei. Das einzige was es gibt, sind die Application-Nores. Die solltest Du Dir mal ansehen, vielleicht ist das etwas dabei.
Datum: 09.05.2008 13:41
#ifndef _IO_H_ #include <avr32\io.h> #endif #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/cpu.h> #include <sys/usart.h> int main(){ set_cpu_hz(20000000); set_usart_base((void*) AVR32_USART1_ADDRESS); usart_init(115200); while(1){ printf("Hello"); udelay(1000000); } return 0; } |
Diesen Quelltext habe ich nun mal getestet. USART1 musste ich nehmen, weil dieser derjenige für den Standard RS232-Stecker des ngw100 ist. Allerdings empfange ich immer noch keine Signale. Ich habe mal nachgemessen, die RX-Leitung des NGW ist 5,56V, und die TX bei 0V. Diese Potentiale verändern sich auch nicht. Beim Hyperterminal habe ich 115200 und 8-N-1 ohne Handshake eingestellt. Liegt es vielleicht auch daran, dass mein jtag ice mk II noch angesteckt ist. Ich bin mittlerweile ziemlich ratlos...
Datum: 09.05.2008 15:32
Ich kenne das NGW100 leider garnicht. Womit hast du denn geprüft, ob die Leitungen sich ändern? Also die Signalzustände sprechen dafür, dass etwas faul ist. An der RX-Leitung 5V? und an der TX 0V? Das sieht schon ziemlich falsch aus. Ich vermute es sind Levelkonverter auf dem NGW für die RS232. Dann sollten die Spannungen genau umgekehrt sein. Die 5V könnten auch noch mehr sein. An dem angesteckten JTAG ICE liegt es nicht. Mit dem könntest du ja sonst kein Programm debuggen. Wenn Signale bei TX zu sehen sind, ist aber noch nicht sichergestellt, ob die Baudrate (115200) stimmt, da ich nicht weiß, ob das NGW nach Reset mit 20MHz läuft. Die Zeile set_cpu_hz(20000000); informiert nur die NEWLIB Library, dass die Frequenz so ist. Die Frequenz der CPU wird damit nicht gesetzt. Mit diesem Faktor werden dann die Baudratenteiler eingestellt, wenn du die Baudrate setzt. Aber du mußt erstmal deine Hardware prüfen. Die Pegel sind nicht OK. Siehe auch: RS-232 oder http://de.wikipedia.org/wiki/Rs232 Edit: Habe gerade mal in das Schaltbild des NGW gesehen. Dort ist ein Level-Konverter (MAX-3232) drauf. Also hast Du wahrscheinlich beim messen RX/TX vertauscht? Und hast du ein Oszilloskop um zu messen, dass sich die Signale ändern? Das Hyperterminal ist richtig eingestellt, wenn denn dein Board mit 20MHz läuft.
Datum: 09.05.2008 20:43
Ein Oszi kann ich erst nächste Woche besorgen. Und wie lege ich jetzt den CPU-Takt fest. Wird das in irgendwelchen Registern festgelegt?
Datum: 09.05.2008 22:08
André Schimschar wrote: > Ein Oszi kann ich erst nächste Woche besorgen. Und wie lege ich jetzt > den CPU-Takt fest. Wird das in irgendwelchen Registern festgelegt? Der CPU-Takt ist solange nebensächlich, wie Du die Hardware nicht OK hast. Definitiv kann es so nicht funktionieren, da Deine Pegel faul sind. Es sei denn Du hast die Namen hier falsch angegeben oder was auch immer. Solange brauchst Du auch kein Oszi, der wird auch nichts anzeigen. Den CPU-Takt einzustellen muß mittels der PLLs auf der CPU gemacht werden. Hab ich auch auch noch nicht gemacht. Du mußt sehen, was für ein Quartz an CLK0 Eingang der CPU liegt, ich meine damit ist dann die CPU getaktet. Und den Frequenzwert übergibts Du der NEWLIB.
Datum: 14.05.2008 15:13
Juchu, ich hab es nun hinbekommen. Zuerst habe ich die CPU-Hz auf 20 MHZ gesetzt und das ganze über den PLL. Der PLL ist die Quelle der Masterclock. Und den CPU-Takt habe ich auf den Masterclock eingestellt.
AVR32_PM.pll0 = (1<<AVR32_PM_PLL0_PLLEN_OFFSET) |(0<<AVR32_PM_PLL0_PLLOSC_OFFSET) |(4<<AVR32_PM_PLL0_PLLOPT_OFFSET) |(1<<AVR32_PM_PLL0_PLLDIV_OFFSET) |(1<<AVR32_PM_PLL0_PLLMUL_OFFSET) |(16<<AVR32_PM_PLL0_PLLCOUNT_OFFSET); while (AVR32_PM.ISR.lock0 == 0); AVR32_PM.mcctrl = 1<<AVR32_PM_MCCTRL_PLLSEL_OFFSET; AVR32_PM.cksel=0x00000000; |
Das ganze habe ich mit udelay überprüft. Danach habe ich die einzelnen Register fürs USART1 eingestellt.
AVR32_USART1.idr = 0xFFFFffff; AVR32_USART1.mr = 0; AVR32_USART1.rtor = 0; AVR32_USART1.ttgr = 0; AVR32_USART1.cr = (1 << AVR32_USART_CR_RSTRX_OFFSET) | (1 << AVR32_USART_CR_RSTTX_OFFSET) | (1 << AVR32_USART_CR_RSTSTA_OFFSET) | (1 << AVR32_USART_CR_RSTIT_OFFSET) | (1 << AVR32_USART_CR_RSTNACK_OFFSET) | (1 << AVR32_USART_CR_DTRDIS_OFFSET) | (1 << AVR32_USART_CR_RTSDIS_OFFSET); if ( baudrate < (cpu_hz/16) ){ /* Use 8x oversampling */ AVR32_USART1.mr |= (1<<AVR32_USART_MR_OVER_OFFSET); cd = cpu_hz / (8*baudrate); AVR32_USART1.brgr = (cd << AVR32_USART_BRGR_CD_OFFSET); } else { /* Use 16x oversampling */ AVR32_USART1.mr &= ~(1<<AVR32_USART_MR_OVER_OFFSET); cd = cpu_hz / (16*baudrate); } AVR32_USART1.brgr = (cd << AVR32_USART_BRGR_CD_OFFSET); AVR32_USART1.mr |= ((charlength-5) << AVR32_USART_MR_CHRL_OFFSET); AVR32_USART1.mr |= (0 << AVR32_USART_MR_CHMODE_OFFSET) | (4 << AVR32_USART_MR_PAR_OFFSET); AVR32_USART1.mr |= (0 << AVR32_USART_MR_NBSTOP_OFFSET); AVR32_USART1.cr |= (1<<AVR32_USART_CR_TXEN_OFFSET) | (1<<AVR32_USART_CR_RXEN_OFFSET); AVR32_PIOA.pdr |= ( 1<<17 ); AVR32_PIOA.pdr |= ( 1<<18 ); AVR32_PIOA.pudr |= ( 1<<17 ); AVR32_PIOA.pudr |= ( 1<<18 ); AVR32_PIOA.asr |= ( 1<<17 ); AVR32_PIOA.asr |= ( 1<<18 ); if ((AVR32_USART1.csr & (1<<AVR32_USART_CSR_TXRDY_OFFSET)) != 0) { AVR32_USART1.thr = 0x00000000;} |
Anschließend konnte ich einzelne Zeichen ausgeben.
if ((AVR32_USART1.csr & (1<<AVR32_USART_CSR_TXRDY_OFFSET)) != 0) { AVR32_USART1.thr |= 0x58;} |
Und dann funktioniert plötzlich auch:
set_cpu_hz(20000000); set_usart_base((void*) AVR32_USART1_ADDRESS); usart_init(115200); printf("Hello"); |
Ich hoffe, dass dies jemanden weiterhilft...
Datum: 14.05.2008 16:21
Na meinen Glückwunsch :-)
Wie sieht es mit den Pegeln aus?
> nachgemessen, die RX-Leitung des NGW ist 5,56V, und die TX bei 0V. Diese
Hattest Du Dich da vertan? Und wo hattest Du gemessen?
Würde mich mal interessieren. Die Pegel sprechen wie gesagt für falsches
messen. Der Empfänger sollte keine Spannung haben (RX).
Funktioniert es auch, wenn Du folgendes machst?
1) Init. PLL mit 20MHz
2) set_cpu_hz(20000000);
3) set_usart_base((void*) AVR32_USART1_ADDRESS);
4) usart_init(115200);
5) printf("Hello");
Ich denke, dass geholfen hat, die PLL zu initialisieren. Darum geht es
dann später auch mit der Aufrufen 2-5 hier oben.
Wenn das nicht geht, hat die NEWLIB von ATMEL!! wohl einen Bug bzw. hast
Du auch die neuesten Versionen der Toolchain?
Datum: 15.05.2008 09:28
Genau, hatte RX und TX vertauscht, auch den - und + Pol hatte ich beim messen verdreht...
Datum: 15.05.2008 11:01
Ja wer mißt mißt Mist ;-) Hast Du noch die Sequenz aus meinem letzten Posting probiert? Sieht etwas eleganter aus :-) Aber denke ich, damit sollte es auch gehen. Aber eigentlich sollte es auch funktionieren, ohne die PLL zu initialisieren. Sie läuft nach Reset mit Defaulteinstellungen und das sollte der 1. Quartz für Clock am AVR32 sein. Diese Frequenz übergibts Du dann set_cpu_hz().
Datum: 15.05.2008 17:25
Ohne die PLL Sequenz gehts, aber nicht ohne die lange USART-Initialisierung. Komisch, oder?
Datum: 15.05.2008 22:17
Ja das finde ich auch sehr komisch. Dann fehlt der usart_init() wohl etwas. Nur merkwürdig, dass es bei dem Grasshopper funktioniert. Das will mir so garnicht in den Kopf. Aber ich kann das so schnell auch nicht überblicken, dafür kenne ich die UART-Register nicht. Müßte man mal das Datenblatt ansehen und auch den Source der usart_init(). Dann wird man sicher schlauer. Danke für die Info, fand ich auch interessant.
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel