Hi,
ich sitze hier vor meinem kleinen Board mit einem STM32F105 drauf. Ich
will jetzt mal meine Peripherie testen und hänge an der USART2. Ich
initialisiere die Schnittstelle wie in reference manual beschrieben. Das
klappt auch alles soweit - nur bekommen ich irgendwie nichts ins
Datenregister. Ich habs händig probiert und mit der DMA, aber keines von
beiden funktioniert. Das Register steht dauerhaft auf 0x00000000 und
dadurch kommt natürlich nichts raus.
Hier mein Code zur USART2:
void Usart2()
{
pUSART2->CR1 = 0x00002000; //Enable USART2: 1 Start bit, 8 bits
pUSART2->CR2 = 0x00002000; //2 stop bits
pUSART2->CR3 = 0x00000180; //RTS + DMA enabled
pUSART2->SR = 0x00000000;
Dma1Init();
pUSART2->BRR = 0x0000001A; //Clock/4=Baud rate
pUSART2->CR1 |= 0x00000009; //Transmission enable
//pUSART2->DR = 0x55;
while (!(pUSART2->SR & 0x00000040))
{
}
}
Und die DMA1 initialisier ich folgendermaßen:
void Dma1Init()
{
pDMA1->CPAR1 = 0x4004404; //Zieladresse Peripherie
pDMA1->CMAR1 = (uint32_t) &pSpeicher; //Zieladresse Speicher
pDMA1->CNDTR1 = 0x000000FF; //8 Daten-Bits
pDMA1->CCR1 = 0x00001010; //Priorität = mittel; vom
Speicher lesen
pDMA1->CCR1 |= 0x00000001; //enable
}
Hat da jemand eine idee was ich hier falsch mache?
Wäre super wenn mir jemand weiterhelfen könnte. Ich häng grad echt total
in der Luft.
Geht du davon aus, dass du (oder ein Debugger) aus dem Datenregister der
USART das wieder auslesen kannst, was du vorher reingeschrieben hast?
Dann hast du die Arbeitsweise einer U(S)ART und von dessen Datenregister
egal welchen Controllers nicht verstanden.
Das mag sein, aber wenn ich das Programm Schritt für Schritt debugge und
etwas in das Datenregister schreibe, dann muss ich das doch bevor ich
den den nächsten Schritt ausführe dort sehen können. Oder bin ich da
jetzt falsch gewickelt? Ich schreibe das doch parallel rein und es wird
dann seriell an die Schnittstelle weitergegeben. Aslo muss ich es doch
kurzfristig dort sehen können, oder nicht?
Benjamin Norenburg schrieb:
> Oder bin ich da jetzt falsch gewickelt?
Ja.
Das Datenregister gibt es zweimal, eins für Empfang (lesender Zugriff)
und eins für Senden (schreibender Zugriff), aber beide an der gleichen
Adresse. Und zu allem Überfluss verschwindet der Inhalt des ohnehin
nicht auslesbaren Datenregisters fürs Senden sofort im Schieberegister
(wenn frei).
In der Referenz findet man ein Prinzipschaltbild der USART (USART block
diagram), in dem das illustriert wird.
Aso, dass die Daten weitergegeben werden war mir klar. Ich habe nur
gedacht, dass ich sie im ersten Moment noch sehen müsste bevor der
nächste schritt ausgeführt wird. Ok, dann ist das nicht mein Problem,
danke schonmal. Da bleibt die Frage: Was mach ich dann falsch?
Ja, das war meine vermutung, dass es daran hängt. Du hast mir ja klar
gemacht, dass dem nicht so ist. Das Problem aller Probleme ist, dass
nicht rauskommt. Kein einziges Bit. Ich Schau nochmal nach ob ich den
Takt richtig initialisiert habe, aber ich denke schon.
Sieht gut aus, der Takt müsste da sein. Und ich gehe bei der
Initialisierung Schritt für Schritt wie im reference manual beschrieben
vor. Keine Ahnung warum das nicht geht. Ich steh grad voll auf dem
Schlauch.
Moment, Komando zurück. jetzt sind Sie alle so konfiguriert. Habe gerade
beim TX was falsch gemacht. jetzt klappts.
Danke für deine Hilfe. War ein dämlicher Fehler an dem ich ohne deinen
Schupser in die richtige Richtung warscheinlich noch einen Tag
rumgemacht hätte.
Hi,
weißt du was du da damals beim TX falsch gemacht hast? Ich fürchte, ich
steh grad vor dem selben Problem - komm aber irgendwie nicht drauf was
mir fehlt..
Das komische ist, dass es funktioniert, wenn ich den Kommentar am Ende
des Unterprogramms entferne...
Die Frage ist nur, warum funktionierts dann? Eigentlich konfiguriere ich
PA.9 ja oben schon als AF-Push-Pull..
aso, so weit mit ich garnicht gegangen. ich habe garnicht mit interupts
gearbeitet. mein entstand war, dass ich was über die serielle
schnittstelle empfange kurz zwischenspeicher und gleich wieder zurück
schick. es ging nur ums testen der hardware.
Philipp schrieb:
> Der Sende-Interrupt wird angestoßen?
Er hat Interruptbetrieb gar nicht konfiguriert, sonst müsste TXEIE in
USART1_CR1 gesetzt sein. Ergo reicht gepollter Versand.
@STM32 Neuling:
Du müsstest nach
Arne schrieb:
> @STM32 Neuling:> Du müsstest nachGPIOA->CRH |= (0x0BUL << 4); // Tx (PA9)
alt. out push-pull
> GPIOA->CRH |= (0x04UL << 8); // Rx (PA10) in floating> noch IOPAEN in RCC->APB2ENR anknipsen.> Könntest Du evtl. so machen:RCC->APB2ENR |= RCC_APB2ENR_USART1EN |
RCC_APB2ENR_IOPAEN; // enable clock for USART1
IOPAEN hab ich angeknipst - siehe 2.Zeile des Unterprogramms.
@thorstendb: In der STM32 FAQ hab ich zum Thema AFIO-clock folgendes
gefunden:
"If the application is mapping USART1 on the default port A, then there
is no need to enable the AFIO clock. If the application is remapping the
USART1 pins from port A to port B, then the AFIO clock should be
enabled."
So wie ich das sehe, brauche ich den AFIO-clock nicht, da ich eh den
Standard USART1 Port A verwende?
Hat noch jemand nen Tipp?
Langsam bin ich echt am Verzweifeln...
Ich find das Reference Manual von ST ein bisschen schwach - es werden
zwar viele Sachen angeschnitten, aber ne ausführliche Erklärung findet
man dann selten - zumindest ist das mein Eindruck.
Naja, es gibt schlimmere Manuals, als das RM0008 von ST ;) Zum Beispiel
die zum Coldfire :-O
Ansonsten könnte es sein, dass die Reihenfolge der ganzen Enablebits
entscheidend ist. Ich kann mich da düster entsinnen, hab meine UART Lib
vor ca. 1 Jahr geschrieben. Sonst schau mal im Debugger nach, ob durch
den auskommentierten Code ein Enablebit wieder angeknipst wird.
Denn mit dem auskommentierten bereich am Ende funktioniert es ja?!?
BTW: Du willst erstmal nur senden? Dein terminalprg. am anderen Ende
hast Du richtig konfiguriert? Die Baudrate im STM hast Du von den Werten
des USART1_BRR Mantissa/Fraction (wie in kap 24.3.4 beschrieben)
zurückgerechnet?
Genau, im Moment moecht ich nur mal Daten zum PC uebertragen. Wenn ich
den Kommentar am Ende entferne, dann funktionierts. Die Einstellungen im
Terminalprogramm passen. Wenn ich daheim bin, werd ich mir mal die
Enable-Bits anschauen. Danke fuer den Tipp!
Da ich ja nicht die ST-Lib nutze, habe ich meine Initialisierung hier
mal in 'Pseudocode' abgetippt:
1
RCC_APB2RSTR_USART1RST = 1 // reset des UART Moduls
2
RCC_APB2RSTR_USART1RST = 0
3
RCC_APB2ENR_USART1EN = 1 // enable UART1 im RCC
4
RCC_APB2ENR_IOPAEN = 1 // enable GPIO-A
5
GPIOA->CRH |= 0x0B << 4 // Portbits für UART definieren
6
GPIOA->CRH |= 0x04 << 8
7
USART1_BRR = ... // Baudrate (bei 72MHz steht bei mir das BRR auf 0x0271 für 115200bd)
8
USART1_CR1 = 0 // 8 databits, parity off
9
USART1_CR2 = 0
10
USART1_CR1 |= USART_CR1_UE // UART ein
11
USART1_CR1 |= USART_CR1_TE | USART_CR1_TE // Transm. & Receiv. ein
Zum Senden dann:
Solange auf dem USART_SR_TXE pollen, bis es 1 ist, dann einen Wert in
das USART1_DR poken.
Hoffe Du kannst was mit den Bitbezeichnungen anfangen.
Welche Entwicklungsumgebung nutzt Du? Keil, IAR, GCC,...?
Hi Arne,
erstmal danke für den Sourcecode Auszug. Ich hab mir den Code von dir
jetzt mal mit Hilfe des Reference Manuals durchgeschaut und ein paar
Kleinigkeiten übernommen. Wenn ich das Programm nun debugge (ich nutze
Keil uVision3 als IDE), dann bekomme ich im "Serial Window" innerhalb
der IDE die gesendeten Daten angezeigt. Beende ich nun den Debugmodus
und connecte mit einem Terminalprogramm, dann bekomm ich komischerweise
keine Daten...(die Baudrate, Start -und Stopbit, sowie Parity sind
korrekt eingestellt)
Was mach ich falsch?
Die IDE zeigt Dir über JTAG an, was rausgegangen sein sollte?
Für Analyse der RS232 PC-seitig setze ich das hier ein:
http://www.serial-port-monitor.com/Download/free-serial-port-monitor.exe
Der klemmt sich zwischen Anwendung und WindowsTreiber. Ab und an hängt
er bei mir die komplette Kiste weg, aber ist halt so :(
Ansonsten würde ich mal das Demoboard unter die Lupe nehmen: geht der
UART 1 auch auf Pegelwandler? Nicht, daß der TTL ausgibt. Müssen da
Lötbrücken (um-)gesetzt werden? Ich kenn Dein Board halt nicht - ich
selbst nehme ein IAR-Kit mit IAR IDE.
Da hat A.K. vollkommen recht!
Ich hab das bei mir in einer Funktion gekapselt, in der ich dann die
betreffenden 4 Bits ausnulle, bevor ich eine neue Bitmaske reinschreibe.
Hab ich im Pseudocode unterschlagen. Mea culpa ;)
Somit muss es heissen:
Arne schrieb:
> habe hoffentlich keinen neuen Fehler eingebaut.
Doch.
Erstens stimmen die Shiftcounts nicht, 4/4/8/8 statt 4/8/4/8 wäre
richtig.
Zweitens kriegst du einen Zwischenzustand von 0 (analog input), der bei
rein digitalen Pins möglicherweise nicht definiert ist. Besser:
CRH = CRH & ~(...) | ...;
Das 'Ausnullen' und neu Setzen der vier Bits mache ich in meiner Lib
über eine lokale Variable und schreibe die dann komplett als uint32_t am
Ende zurück.