Hallo, ich habe mal eine Verständnisfrage zu diesem, im Betreff genannten, Befehl. Was passiert, wenn ich dem Befehl, mit der Variabel data, ein 8 Bit langes Wort (Byte) übergebe? Beipielsweise so etwas hier 00100010. Wird dieses unverändert übertragen oder werden da Bits vorne oder hinten angehängt, da etwa nur eine bestimmte Wortlänge z.B.: 16 Bit (Word) übertragen werden kann. MfG Scipio
Use the source, luke. Die Peripherial Lib wird als C Code ausgeliefert, da kann man einfach mal reinschauen und mit dem dicken Manual vergleichen. Mir scheint außerdem, dass Du mal in ein gutes C Buch reinschauen solltest, denn 00100010 wird als oktaler Wert in C behandelt und entspricht 32776. Das passt nicht in ein Byte. Zu Deiner Frage mal eine Gegenfrage: Was passiert denn in C, wenn man eine Byte (char) Variable einem Integer (int) zuweist?
Hi, erst einmal danke für deine Antwort. Ich sollte vielleicht etwas mehr darüber verraten, was ich eigentlich vor habe. Ich möchte mit der einer der SPI-Schnittstellen eine STM32L152RBT6 eine Phase Lock Loop (ADF4360-4) Konfigurieren. (Ich hänge das Datenblatt an) Dieser Chip hat 3 24 Bit Latches. Diese müssen über eine SPI Schnittstelle mit Werten geladen werden. (Als Information zum Nachschlagen, die Latches hießen R-Counter, N-counter und Control) Um die ganze Sache noch etwas schwieriger zu machen, scheint die SPI-Schnittstelle der ADF4360-4 keine Standartausführung zu sein. Sie verfügt, wie im Datenblatt zu sehen ist, über einen mit LE bezeichneten Pin. Mit diesem komme ich nicht wirklich zurecht. Auf diesen Pin muss ich, jedesmal, wenn ein Register fertig geladen ist, kurz mit High belegt werden. Dies scheint mir nicht unbedingt zum Standard einer SPI-Schnittstelle zu gehören. Im Forum von Analog Divices will mir keiner antworten.... Ich gebe es offen zu, dass ich nicht sonderlich bewandert in solchen Dingen bin. Ich habe leider auch einiges wieder vergessen. Das ändert aber nichts an der Tatsache, dass für das Problem eine Lösung her muss. Nun zu deiner Frage: Laut meinem C-Buch "C kurz und gut" wird, wenn eine Variable mit dem Typ char den Typ int zuweist, wird eine Ganzzahl-Erweiterung durchgeführt. Da der Datentyp char einen kleineren Umfang hat als der Datentyp int. Andersherum können Informationen verloren gehen. Die zusätzliche Bytes werden als höherwertige Bytes angefügt.
Alex W. schrieb: > Um die ganze Sache noch etwas schwieriger zu machen, scheint die > SPI-Schnittstelle der ADF4360-4 keine Standartausführung zu sein. Sie > verfügt, wie im Datenblatt zu sehen ist, über einen mit LE bezeichneten > Pin. Das ist nicht schwierig. Wenn du Zugriff auf den SS (Slave Select) deines Controllers hast dann benutze ihn dazu den LE zu betätigen. Das bedeutet (für jeden 24-Bit Registerzugriff): - LE low - SPI Daten 24 Bit senden - LE high - Minimalzeit für LE warten (siehe ADF4360) - LE Low Der CE (Chip enable) muss während dieses Zyklus aktiv high sein, kann aber auch statisch immer high bleiben. Damit hast du ein ADF4360 Register gültig beschrieben. Falls es diese Möglichkeit (den SS zu "misbrauchen") nicht gibt musst du einen anderen Portpin als Ausgang definieren und diesen benutzen um LE auf die oben angegebene Weise zu steuern.
@isidor: Sehr schön, das klinkt schon nach dem, was ich in mein Programm geschrieben habe. Oder wenigstens nach dem was ich beabsichtigt habe. Aber machen wir es doch einfach mal konkret:
1 | |
2 | // Zu beginn erst einmal die Zuweisung der Pins (sind in einem eigenen Header untergebracht)
|
3 | |
4 | #define LE GPIO_Pin_10 //PA10 SPI-PLL
|
5 | #define DATA GPIO_Pin_7 //PA7 SPI-PLL
|
6 | #define CLK GPIO_Pin_5 //PA5 SPI-PLL
|
7 | #define CE GPIO_Pin_0 //PC0 PLL-Aktiv
|
8 | |
9 | |
10 | // Es folgt die Initialiesierung der
|
11 | void SPI3_Init() |
12 | {
|
13 | GPIO_InitTypeDef GPIO_InitStructure; |
14 | NVIC_InitTypeDef NVIC_InitStructure; |
15 | SPI_InitTypeDef SPI_InitStructure; |
16 | DMA_InitTypeDef DMA_InitStructure; |
17 | |
18 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // |
19 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); |
20 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); |
21 | |
22 | GPIO_InitStructure.GPIO_Pin = CE; |
23 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; |
24 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
25 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz; |
26 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; |
27 | GPIO_Init(GPIOC, &GPIO_InitStructure); |
28 | GPIO_ResetBits(GPIOC, CE); |
29 | |
30 | GPIO_InitStructure.GPIO_Pin = (MUXOUT); |
31 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; |
32 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; |
33 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz; |
34 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; |
35 | GPIO_Init(GPIOC, &GPIO_InitStructure); |
36 | |
37 | GPIO_InitStructure.GPIO_Pin = (LE|DATA|CLK); |
38 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //output mode |
39 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //output type: push pull |
40 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz; |
41 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; |
42 | GPIO_Init(GPIOB, &GPIO_InitStructure); |
43 | |
44 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI1); |
45 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI1); |
46 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI1); |
47 | |
48 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; |
49 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; |
50 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; |
51 | SPI_InitStructure.SPI_CRCPolynomial = 0; |
52 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; |
53 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
54 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; |
55 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; |
56 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; |
57 | SPI_Init(SPI1, &SPI_InitStructure); |
58 | |
59 | SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); |
60 | }
|
61 | |
62 | void ConfigPLL(){ |
63 | |
64 | /*Dieses Array enthält die Registerbelegung in 9 Abschnitten mit je 8 Bit. Ich bin mir mittlerweile nicht mal mehr sicher, ob ich die einzelnen Register wirklich in 8 Bit große Einheiten aufteilen muss.
|
65 | */
|
66 | uint8_t x[9] = {00100000, 00001010, 00000110, 01000001, 11000100, 00101000, 00010000, 00001010, 00000110}; |
67 | |
68 | SPI_Cmd(SPI3, ENABLE); |
69 | |
70 | GPIO_WriteBit(GPIOB, CE, SET); |
71 | |
72 | int t; |
73 | t=0; |
74 | int ti; |
75 | ti=1; |
76 | |
77 | |
78 | while(t < sizeof(x)); |
79 | {
|
80 | //Im Example, welches ich finden konnte war dies so angegeben, aber brauch ich dass, was hier im auskommentierten Bereich steht wirklich?
|
81 | //Es scheint sich um eine Art Adressierung zu handeln
|
82 | /*SPI_I2S_SendData(SPI3, 0x3);
|
83 | |
84 | while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET)
|
85 | ;
|
86 | |
87 | SPI_I2S_SendData(SPI3, 0x4);
|
88 | |
89 | while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET)
|
90 | ;
|
91 | */
|
92 | SPI_I2S_SendData(SPI3, x[t]); |
93 | |
94 | t++; |
95 | |
96 | if(ti > 2){ |
97 | //nach jedem dritten 8Bit block soll der LE Pin kurz aktiviert werden, die Zeit soll 20 ns betragen.
|
98 | //Da ich keinen so kleinen Timer finden konnte, hoffe ich dass dies ausreicht.
|
99 | GPIO_WriteBit(GPIOB, LE,SET); |
100 | |
101 | GPIO_WriteBit(GPIOB,LE, RESET); |
102 | ti = 0; |
103 | }
|
104 | ti++; |
105 | }
|
106 | ti++; |
107 | SPI_Cmd(SPI3, DISABLE); |
108 | |
109 | |
110 | }
|
Das ist die Funktion, wie ich sie geschrieben habe, samt Initialisierung der SPI-Schnittstelle und Pin-Belegung. Die bei gelegten Dokumente sind das Manual des Mikrocontrollers, aus welchem sich die Pin-Belegung ableitet, eines welches das Evaluationboard zeigt, welches ich verwende, und zuletzt noch das Datenblatt der ADF4360-4. Die SPI-Schnittstelle ist zum senden initialisiert, sie braucht keine Daten zu empfangen.
Alex W. schrieb: > /*Dieses Array enthält die Registerbelegung in 9 Abschnitten mit je 8 > Bit. Ich bin mir mittlerweile nicht mal mehr sicher, ob ich die > einzelnen Register wirklich in 8 Bit große Einheiten aufteilen muss. > */ > uint8_t x[9] = {00100000, 00001010, 00000110, 01000001, 11000100, > 00101000, 00010000, 00001010, 00000110}; Auch wenn da nur Nullen und Einsen stehen, sind das noch lange keine Binärwerte. Bei den führenden Nullen interpretiert der Compiler Oktalwerte, bei führenden Einsen Dezimalwerte. Lies endlich ein C-Buch! Viele der Zahlen passen nicht in 8 Bits. Gewöhne Dir besser mal an, Binärwerte als Hex aufzuschreiben, z.B: 0b00100000 = 0x2F Binärwerte sind oft scheisse zu lesen, weil man zuviele Stellen überblicken muss. Bei Hex hat man für jedes Nibble eine eigene Zahl. Das bedeutet auch, dass man mit etwas Übung den Wert jedes einzelnen Bits direkt ablesen kann. Was mir auch einfällt: Schau nach, ob SPI_I2S_SendData() überhaupt bis zum Ende der Übertragung wartet. Oftmals kommen solche Funktionen schon nach dem Schreiben des DR Registers zurück, das wäre zu früh - die Übertagung läuft dann noch.
@Jim Meba: Ich habe schon verstanden, was du mir gesagt hast. Ich hatte die Änderung der Werte erst vorgenommen, nach dem ich den Code hier eingestellt habe. Mittlerweile funktioniert die PLL einwandfrei. Danke für deine Hilfe.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.