1 | // Variablen werden in der Funktion Seriell_CalcBaudrate() beschreiben
|
2 | float fSeriellAbw;
|
3 | int iSeriellDL, iSeriellFDR;
|
4 |
|
5 | // Diese Funktion ermittelt die mögliche Baudrate des Prozessors
|
6 | // Rückgabe: Aktuelle Baudrate
|
7 | int Seriell_CalcBaudrate(int iBaud) {
|
8 | int iBestDL, iBestDiv, iBestMul;
|
9 | int iDivV, iMulV, iDL;
|
10 | float fBestAbw, fAbw1, fAbw2, fDiv, fMul, fMulDiv, fBaudAbw;
|
11 | volatile int iRegister= PCLKSEL0;
|
12 | if (iBaud <= 0)
|
13 | return 0;
|
14 | fBestAbw = 1000;
|
15 | iBestDL = iBestDiv = iBestMul = 0;
|
16 | for (iDivV = 0; iDivV < 15; iDivV++) {
|
17 | fDiv = (float)iDivV;
|
18 | for (iMulV = iDivV + 1; iMulV < 16; iMulV++) {
|
19 | fMul = (float)iMulV;
|
20 | fMulDiv = (1 + (fDiv / fMul)) * 16.0;
|
21 | iDL = Fpclk / (int)((float)iBaud * fMulDiv); // Divisor DL ermitteln
|
22 | if (iDL >= 70000)
|
23 | break;
|
24 | if (iDL > 65535) // Begrenzung auch maximale Möglichkeit des Registers
|
25 | iDL = 65535;
|
26 | fBaudAbw = (((float)Fpclk / ((float)iDL * fMulDiv)));
|
27 | fAbw1 = (fBaudAbw * 100) / (float)iBaud - 100.0; // Gegenrechnung Abweichung in %
|
28 | if (fAbw1 < 0) // Abweichung nur Positiv
|
29 | fAbw1 *= -1;
|
30 | if (iDL < 65535) // Ein Count erhöhen und nochmal rechnen, wenn nicht schon max-Grenze
|
31 | {
|
32 | fBaudAbw = (((float)Fpclk / ((float)(iDL + 1) * fMulDiv)));
|
33 | fAbw2 = (fBaudAbw * 100) / (float)iBaud - 100.0; // Gegenrechnung Abweichung in %
|
34 | if (fAbw2 < 0)
|
35 | fAbw2 *= -1;
|
36 | if (fAbw2 < fAbw1) // Zweite Rechnung ist besser
|
37 | {
|
38 | fAbw1 = fAbw2;
|
39 | iDL++;
|
40 | }
|
41 | }
|
42 | if (fAbw1 < fBestAbw) // Neue Abweichung ist kleiner, Ergebnisse merken
|
43 | {
|
44 | fBestAbw = fAbw1;
|
45 | iBestDL = iDL;
|
46 | iBestDiv = iDivV;
|
47 | iBestMul = iMulV;
|
48 | if (fBestAbw == 0) // Optimales Ergebnis bereits gefunden
|
49 | break;
|
50 | }
|
51 | if (!iDivV) // Schleife bei iDivV = 0 nur ein mal berechnen
|
52 | break;
|
53 | }
|
54 | if (fBestAbw == 0) // Optimales Ergebnis bereits gefunden
|
55 | break;
|
56 | }
|
57 | iSeriellDL = iBestDL;
|
58 | iSeriellFDR = (iBestMul << 4) + iBestDiv;
|
59 | fSeriellAbw = fBestAbw;
|
60 | iRegister++;
|
61 | if (fBestAbw == 0) // Keine Abweichung
|
62 | return iBaud;
|
63 | fDiv = (float)iBestDiv;
|
64 | fMul = (float)iBestMul;
|
65 | fMulDiv = 1 + (fDiv / fMul);
|
66 | // In den Variablen iSeriellDL und iSeriellFDR ist die Einstellung des Baudraten-Teilers
|
67 | return (int)((float)Fpclk / (16.0 * (float)iBestDL * fMulDiv));
|
68 | }
|
69 |
|
70 |
|
71 | Der Aufruf:
|
72 | (*(volatile unsigned int *)(UartBase + 0x03)) |= 0x80; // U0LCR |= 0x80; // Baudrate errechnen
|
73 | Seriell_CalcBaudrate(iBaudrate[Port]);
|
74 | (*(volatile unsigned int *)(UartBase + 0x00)) = iSeriellDL & 0xFF; // U0DLL = iSeriellDL & 0xFF;
|
75 | (*(volatile unsigned int *)(UartBase + 0x01)) = iSeriellDL >> 8; // U0DLM = iSeriellDL >> 8;
|
76 | (*(volatile unsigned int *)(UartBase + 0x0A)) = iSeriellFDR; // U0FDR = iSeriellFDR;
|