Ich habe festgestellt, dass selbst bei den ganzen uart-Examples zum
LPCXpresso die Einstellung der Baudrate nur über die Register DLM/DLL
erfolgt und die Möglichkeiten der fractalen Baudratengeneration nicht
benutzt werden. Damit wird u.U. ein nicht nötiger Baudratenfehler in
Kauf genommen. Im Folgenden stelle ich mal einen kleinen Codeschnipsel
vor der diese Werte zur Laufzeit berechnet. Das mache ich mit der
Holzhammermethode in dem ich alle 54 Möglichkeiten der Register für die
fraktalen Werte mal 4 Möglichkeiten des Taktvorteilers durchrechne und
die Parameter mit der kleinsten Abweichung verwende. Wenn gleiche
Abweichungen zustande kommen, wird die mit dem größten Vorteiler
verwendet. Eventuell kann das ja jemand gebrauchen bzw. noch Fehler oder
Verbesserungen finden.
Und hier ein erweiterbares Beispiel der Verwendung:
1
LPC_UART_TypeDef*uart_init(intuartnr,intbaudrate)
2
{
3
structuartBaudRateParamaP;
4
5
// die gewünschte Baudrate setzen
6
aP.nBaudRate=baudrate;
7
8
// und die Systemfrequenz
9
aP.nSysClk=SystemFrequency;
10
11
// jetzt rechnen lassen
12
uartCalcBaudRate(&aP);
13
14
LPC_UART_TypeDef*LPC_UART;
15
switch(uartnr)
16
{
17
case0:
18
LPC_SC->PCONP|=(1<<3);
19
LPC_UART=LPC_UART0;
20
LPC_SC->PCLKSEL0&=~(0x03<<6);
21
LPC_SC->PCLKSEL0|=(aP.nPclkArg<<6);
22
GPIO_PINSEL(0,02,0x01);
23
GPIO_PINSEL(0,03,0x01);// rx0
24
GPIO_PINMODE_IN(0,01,GPIO_IN_FLOAT);// rx0 float
25
break;
26
27
case1:
28
LPC_SC->PCONP|=(1<<4);
29
// UART1 ist anders als die anderen, aber nicht
30
// an den hier relevanten Stellen. s.u.
31
LPC_UART=(LPC_UART_TypeDef*)LPC_UART1;
32
LPC_SC->PCLKSEL0&=~(0x03<<8);
33
LPC_SC->PCLKSEL0|=(aP.nPclkArg<<8);
34
GPIO_PINSEL(0,15,0x01);
35
GPIO_PINSEL(0,16,0x01);// rx1
36
GPIO_PINMODE_IN(0,16,GPIO_IN_FLOAT);// rx1 float
37
break;
38
39
case2:
40
LPC_SC->PCONP|=(1<<24);
41
LPC_UART=LPC_UART2;
42
LPC_SC->PCLKSEL1&=~(0x03<<16);
43
LPC_SC->PCLKSEL1|=(aP.nPclkArg<<16);
44
GPIO_PINSEL(0,10,0x01);
45
GPIO_PINSEL(0,11,0x01);// rx2
46
GPIO_PINMODE_IN(0,11,GPIO_IN_FLOAT);// rx2 float
47
break;
48
49
case3:
50
LPC_SC->PCONP|=(1<<25);
51
LPC_UART=LPC_UART3;
52
LPC_SC->PCLKSEL1&=~(0x03<<18);
53
LPC_SC->PCLKSEL1|=(aP.nPclkArg<<18);
54
GPIO_PINSEL(0,0,0x02);
55
GPIO_PINSEL(0,1,0x02);// rx3
56
GPIO_PINMODE_IN(0,1,GPIO_IN_FLOAT);// rx3 float
57
break;
58
}
59
60
// Zugrif auf das DLL und DLM Register
61
LPC_UART->LCR|=(1<<7);
62
LPC_UART->DLM=aP.nDlm;
63
LPC_UART->DLL=aP.nDll;
64
// Zugrif auf das DLL und DLM Register ausschalten
65
LPC_UART->LCR&=~(1<<7);
66
LPC_UART->FDR=aP.nMulVal<<4|aP.nDivAddVal;
67
68
LPC_UART->LCR=0x03;// 8bit 1Stopbit keine Parität
69
70
// rx tx-buffer reseten
71
LPC_UART->FCR=0x07;
72
returnLPC_UART;
73
}
Der Code ist an einer Stelle unsauber. Die Strukturen für UART0,2,3 sind
etwas anders als bei UART1. Da aber alle Register, die ich verwende, an
der selben stelle in den Structuren liegen kann ich den Pointer
LPC_UART1 auf (LPC_UART_TypeDef *) casten;
Die GPIO Macros sind von mir, wenn die noch einer benötigen sollte bitte
melden.
Ist es richtiger den Beitrag in dei Codesammlung zu stellen oder hier
her?
Jürgen Liegner schrieb:> Die GPIO Macros sind von mir, wenn die noch einer benötigen sollte bitte> melden.
Ja, wäre cool wenn Du die auch noch mit reinstellst...dann ist es
vollständig.
Grüße und Danke.
N. Müller
Hallo Jim Meba,
danke für deine Infos. Das wusste ich bisher noch nicht. Das Setzten von
PCLKSELx findet man in fast jedem Beispielcode. Ich denke in der Regel
immer nachdem die PLL0 gesetzt ist. Ich muss nochmal debuggen, ob bei
meinen Tests immer 0x00 für das Bitpaar (CLK/4) rauskam und es deshalb
nicht zum Fehler kam oder ob ich ICs habe bei denen das trotzdem geht.
Die "lpc17xx CMSIS driver" habe ich mir zwar schon mal angesehen aber
nicht den uart-Teil. Ich habe gesehen, daß das Setzen eines Bits bei den
Gpio Funktionen ganz schönen Overhead produziert (2 Function-Calls).
Deshalb wollte ich auf diese Lib ganz verzichten. Ausserdem will ich die
Register des MC verstehen und nicht nur wissen wie man entsprechende
Funktionen aufruft. Wenns um die Fehlersuche geht sind ja dann trotzdem
wieder die Register gefragt und ich muss eigentlich alles doppelt lernen
wenn ich die Lib für alles benutze.
Vor diesem gesamten Hintergrund hat meine Funktion der
Baudratenberechnung noch den Vorteil, dass man die Werte berechnen kann
bevor die PLL0 gesetzt und connectetd wird. Dann die PCLKSELx-Register
mit den berechnetetn Werten setzten, die PLL0 starten (oder den normalen
sysinit) und dann die UARTs mit den restlichen Parametern
initaialisieren.
Danke nochmal.