Forum: Mikrocontroller und Digitale Elektronik AD7680 (SPI) + STM32F4Discovery


von opcode (Gast)


Angehängte Dateien:

Lesenswert?

Sehr geehrte Forumuser,

zur Zeit versuche ich den Analog Digital Umsetzer AD7680 mit dem 
STM32F4Discovery zum "Laufen" zu bringen. Ich möchte die Samples von dem 
AD7680 auslesen. Ich habe hier leider kein DSO oder ein Logic 
Analyzer,so dass ich eben die Ausgänge messen kann... Ich würde gerne 
wissen wollen, ob die Konfiguration des SPI's soweit "richtig" ist. Wie 
kann ich, bevor ich mit DMA die Daten speichere, schnell überprüfen ob 
überhaupt irgendwas vom AD7680 ankommt ? Die Frequenz der SCLK ist 
656.25 kHz.
Auch mit den Interrupt komme ich bei dem SPI noch nicht so klar.


Ich habe den STM32F4 mit dem AD7680 wie folgt verbunden:

AD7680   STM32F4Discovery
-------------------------
Vs     =  3V Leitung
GND    =  GND
SCLK   =  PC13
CS     =  PC14
SDATA  =  PC15
Vin    =  Nicht verbunden, aber dennoch müsste man ja "Rauschen" messen 
können oder?

Hier der bisherige C-Code:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_dma.h"
3
#include "stm32f4xx_rcc.h"
4
#include "stm32f4xx_spi.h"
5
#include "stm32f4xx_gpio.h"
6
#include "misc.h"
7
8
/* Prototypes */
9
void SPIConfig(void);
10
void GPIOConfig(void);
11
void EnableRCC(void);
12
13
14
/* Defines */
15
#define SCLK    GPIO_Pin_13    /* Takt-Pin für den SPI Datentransfer */
16
#define CS    GPIO_Pin_14    /* ChipSelect-Pin für den AD7680     */
17
#define SDATA    GPIO_Pin_15    /* Datenleitung für die Samples, MISO */
18
#define MOSI    GPIO_Pin_3    /* Datenleitung zum Senden, MOSI */
19
20
#define LED_Green   GPIO_Pin_12
21
#define LED_Orange   GPIO_Pin_13
22
#define LED_Red   GPIO_Pin_14
23
#define LED_Blue   GPIO_Pin_15
24
25
26
int main(void)
27
{
28
29
30
  SystemInit();          /* Wichtig, damit die korrekten Frequenz-Einstellungen wirksam werden */
31
  EnableRCC();          /* RCC (Takt für die Peripherie) aktivieren */
32
  GPIOConfig();          /* GPIO Einstellungen übernehmen: SPI, LED, ... Pins */
33
  SPIConfig();
34
35
  GPIO_SetBits(GPIOD,LED_Green);      /* Grüne LED einschalten, um zu sehen ob µC bzw. Programm lebt :-) */
36
37
  //GPIO_SetBits(GPIOD,CS);
38
39
  GPIO_ResetBits(GPIOC,CS);
40
41
42
    while(1)
43
    {
44
    
45
    }
46
47
  
48
}
49
50
51
void SPIConfig(void)
52
{
53
54
    SPI_InitTypeDef SPI_InitStructure;
55
56
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  /* Eine Datenleitung, nur Empfangen... */
57
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       /* STM32F407VGT ist der Master und AD7680 der Slace */
58
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;      /* Es werden 24 Bit's vom AD7680 ausgegeben 000016BitDaten0000, daher 3x8 Bit übertragen */
59
    SPI_InitStructure.SPI_DataSize = SPI_FirstBit_MSB;      /* Der AD7680 überträgt die Daten als "MSB first" */
60
    SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_64;  /* SCLK=42MHz/64=656.2kHz APB1=42 MHz, SYSCLK=168 MHz */
61
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        /* CPOL=1 */
62
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;      /* CPHA=1 */
63
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        /* NSS Pin als GPIO Pin einstellen */
64
    SPI_InitStructure.SPI_CRCPolynomial = 0;        /* kein CRC bilden */
65
66
    SPI_Init(SPI2, &SPI_InitStructure);          /* SPI2 Interface initialisieren */
67
    SPI_SSOutputCmd(SPI2, ENABLE);
68
    SPI_Cmd(SPI2,ENABLE);                        /* SPI2 Interface aktivieren*/
69
70
71
}
72
73
74
void GPIOConfig(void)
75
{
76
  GPIO_InitTypeDef GPIOLEDs_InitStructure;
77
  GPIO_InitTypeDef GPIO_InitStructure;
78
79
  GPIOLEDs_InitStructure.GPIO_Pin = LED_Green;
80
  GPIOLEDs_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
81
  GPIOLEDs_InitStructure.GPIO_OType = GPIO_OType_PP;
82
  GPIOLEDs_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
83
  GPIOLEDs_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
84
  GPIO_Init(GPIOD,&GPIOLEDs_InitStructure);
85
86
  GPIO_InitStructure.GPIO_Pin = SCLK | SDATA | GPIO_Pin_3;
87
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
88
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
89
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
90
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
91
  GPIO_Init(GPIOC, &GPIO_InitStructure);
92
93
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource13, GPIO_AF_SPI2);
94
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource15, GPIO_AF_SPI2);
95
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2);
96
97
98
  GPIO_InitStructure.GPIO_Pin = CS;
99
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
100
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
101
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
102
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
103
  GPIO_Init(GPIOC, &GPIO_InitStructure);
104
105
}
106
107
108
void EnableRCC(void)
109
{
110
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
111
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
112
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
113
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
114
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);     /* Takt für den SPI2 aktivieren */
115
}

Im Anhang befindet sich das Datenblatt des AD7680's

Ich würde mich über Starthilfe sehr freuen.
Vielen Dank

mfGruß,
opcode

von opcode (Gast)


Lesenswert?

Oh weia... ich glaube, dass ich die Pins total durcheinander gebracht 
habe :-(. Ich korrigiere das und melde mich nochmal !

Sorry.

von F. F. (foldi)


Lesenswert?

opcode schrieb:
> Oh weia... ich glaube, dass ich die Pins total durcheinander gebracht
> habe :-(. Ich korrigiere das und melde mich nochmal !
>
> Sorry.

In Amerika glaub ich wars, da gibt es eine Uni in der die Studenten 
erstmal einem Stoffteddy ihr Problem erzählen müssen und erst dann 
dürfen sie zum Prof.
Passt doch dazu, oder?

von opcode (Gast)


Lesenswert?

Scheisse... war der lustig !

von opcode (Gast)


Lesenswert?

Die Pin Konfiguration soweit korrigiert:

SCK=PB10
CS=PA3
SDATA=PC2

Ich bekomme nun auch Daten an, aber leider ist das erste Byte immer 0.
1
int main()
2
{
3
....
4
5
        GPIO_ResetBits(GPIOA,CS);
6
  Delay(1000L);
7
  /*
8
  //SPI2->DR = 0;
9
  while(!(SPI2->SR & SPI_I2S_FLAG_RXNE));
10
  byte1=SPI2->DR;
11
  //SPI2->DR = 0;
12
  while(!(SPI2->SR & SPI_I2S_FLAG_RXNE));
13
  byte2=SPI2->DR;
14
  //SPI2->DR = 0;
15
  while(!(SPI2->SR & SPI_I2S_FLAG_RXNE));
16
  byte3=SPI2->DR;
17
  GPIO_SetBits(GPIOA,CS);

Würde mich über Hilfe sehr freuen.

von opcode (Gast)


Lesenswert?

----

von holger (Gast)


Lesenswert?

>----

Alles auskommentiert was wichtig für die Funktion von SPI
ist. Mehr sag ich dazu nicht.

von Manfred B. (manib)


Lesenswert?

Hallo opcode,

bitte nicht entmutigen lassen von den lustigen Kommentaren hier - 
sondern Lektion lernen: erst denken, dann posten.

Zu deinem AD7680 habe ich jetzt auf die Schnelle auch keinen 
Beispielcode gefunden, aber ich empfehle dir wärmstens die Seite von Uwe 
anzusehen. Da gibt's inzwischen 64 Libraries für das STM32F4 Discovery 
Board.

Folgende drei sind zum Thema SPI, und die Library 16 bindet den DAC 
MAX5250 ein:

Library 15 = SPI-LoLevel (zum benutzen der 3 SPI-Schnittstellen)
http://mikrocontroller.bplaced.net/wordpress/?page_id=683

Library 16 = SPI-MAX5250 (um ein 4fach DAC MAX5250 anzusteuern)
http://mikrocontroller.bplaced.net/wordpress/?page_id=689

Library 17 = SPI-LIS302DL (für den 3Achs-Beschleunigungs-Sensor auf dem 
Discovery)
http://mikrocontroller.bplaced.net/wordpress/?page_id=705

Das sollte als Grundlage mehr als ausreichen;)

Viel Erfolg!
ManiB

Nachtrag: Fallst du die CooCox IDE noch nicht nutzen solltes, dann 
unbedingt installieren und bei Uwe die jeweils kompletten 
CooCox-Projektordner herunterladen, starten und staunen!

Hier gibt's von Uwe die detaillierte Installationsanleitung:
http://mikrocontroller.bplaced.net/wordpress/?page_id=58

: Bearbeitet durch User
von Op C. (opcode_x64)


Lesenswert?

Guten Tag  Manfred Becker,

ich lass mich nicht von diesen Kommentaren entmutigen.

Ich habs gestern doch noch hinbekommen. Zum Testen habe ich den ADU 
Eingang auf Vdd, auf Masse und noch mal auf einen Spannungsteiler gelegt 
und alle Werte/Samples (Bits) stimmen mit sehr hoher Genauigkeit 
überein.

Folgendes konnte ich messen:

Spannung am ADU Eingang | Sample Wert | Sample Wert in Spannung
---------------------------------------------------------------
Vdd=2.94V                    65535         2.94V
GND                            0            0V
0.94V                     (Vergessen)      0.9382V

Die 0.94V habe ich mit einem Spannungsteiler erzeigt (100k/147k=0.68).
Ob die 0.94V oder die 0.9382V stimmen ist nicht klar, denn ich habe die 
0.94V mit einem standard Multimeter (VC150) gemessen.

Sobald ich den Code "sauber" geschrieben und kommentiert habe, werde ich 
diesen hier posten (inklusive Beschaltung). Vielleicht hilft das ja 
jemanden anderen weiter.

Vielen Dank für die Links ! Werde ich mir alle anschauen.

mfGruß,
opcode

: Bearbeitet durch User
von Manfred B. (manib)


Lesenswert?

Hi opcode,

herzlichen Glückwunsch - und weiter so!

Über deinem fertigen C-Quelltext hier als Abschluß werden sich 
sicherlich noch viele interessierte Leser freuen.

Ciao,
ManiB

von Op C. (opcode_x64)


Angehängte Dateien:

Lesenswert?

Sehr geehrte Forumuser,

ich habe nun das Programm bzw. den Projektordner für CooCox CoIDE 
inklusive Bild des Aufbaus dem Anhang angefügt.

Anschlussplan ist dem Hauptkommentar in main.c zu entnehmen.

Hier ist noch einmal der Inhalt der main.c Datei:
*(Achtung: SystemInit(); muss in int main() ausgeführt werden. Kommentar 
entfernen !)*
1
//------------------------------------------------------------------------------------------------------------
2
//
3
//       Programmname: STM32F4_AD7680
4
//              Datum: 09.10.2013
5
//                IDE: CooCox COIDE V. 1.7.5
6
//              Autor: T. Öztürk
7
//
8
//
9
//
10
//    Takt-Einstellungen: HSE=8 MHz, HCLK=168MHz, SYSCLK=168 MHz, PCLK1=42 MHz (Taktquelle für SPI2)
11
//              PLL_N=336
12
//              PLL_M=25
13
//              PLL_Q=7
14
//              PLL_P=2
15
//
16
//    Beschreibung: Dieses Programm steuert über Serial Peripheral Interface (SPI) den externen
17
//                  Analog-Digital Umsetzer AD7680 an und empfängt die Abtastwerte.        Der AD7680
18
//                  hat eine Auflösung von 16 Bit, also 65535 Abstufungen. Der 16-Bit Abtastwert
19
//                  wird nicht "direkt" als 16-Bit geschickt, sondern in 24 Bits, d.h. der AD7680
20
//                  füllt die restlichen Bit-Stellen mit Nullen auf. Der SPI wurde daher auf 8 Bit,
21
//                  also 1 Byte, Datenpakete eingestellt. Es werden somit drei Byte Pakete empfangen,
22
//                  aus denen der 16 Bit Abtastwert durch Bit-Verschiebung zusammengestellt wird.
23
//                  Der Abtastvorgang beginnt mit der fallenden Flanke des Chip Select Signals.
24
//                  Die Taktgeschwindigkeit SCLK des SPI's bestimmt auch die Abtastrate des  AD7680.
25
//                  Weitere Informationen sind dem Datenblatt des AD7680 zu entnehmen:
26
//                  http://www.analog.com/static/imported-files/data_sheets/AD7680.pdf
27
//                  (In CooCox CoIDE: STRG gedrückt halten und mit linken Mauszeiger auf Link klicken)
28
29
//                  In diesem Beispiel wird der SPI2 Controller des STM32F4 verwendet.  Die jeweiligen
30
//                  Pin-Zuordnungen sind dem Datenblatt des STM32F4 zu entnehmen. (Abschnitt 3, Tab. 6):
31
//                  http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00037051.pdf
32
//
33
//                  Eine weitere wichtige Quelle bzw. die einzige, die ich gefunden habe, wo der AD7680 eingesetzt wird:
34
//                  http://abieneman.wordpress.com/2010/04/04/punch-acceleration-sensor/
35
//
36
//
37
//          Anschlussplan:
38
//
39
//          AD7860             |    STM32F4 Discovery Board
40
//------------------------------------------------------------------------------------------------------------
41
//          VDD   (Pin 1)        VDD
42
//          GND   (Pin2,Pin3)    GND
43
//          VIN   (Pin4)         zu Messende Spannung z.B. VDD, Auf max. Spannung achten !
44
//          SCLK  (Pin5)         PB10
45
//          NC    (Pin6)          -
46
//          SDATA (Pin7)         PC2
47
//          ~CS   (Pin8)         PA3
48
//------------------------------------------------------------------------------------------------------------
49
//
50
//          Ich habe keine Kondensatoren zum Glätten bzw. Entstören verwendet. Dies ist lediglich ein
51
//          Minimalbeispiel. Eine Beispiel-Schaltung nach Analog Devices befindet sich im Datenblatt
52
//          des AD7680 auf S. 13 (inklusive "saubere" Versorgungs- bzw. Referenzspannung)
53
//
54
//          Ich bin kein "langjähriger" C-Programmierer, daher entschuldigt den nicht sauberen
55
//          bzw. nicht professionellen Code !
56
//
57
//
58
//          Viel Spass und Erfolg !
59
//
60
//------------------------------------------------------------------------------------------------------------
61
62
63
64
//---------------------------------------------------------------------------------------------------
65
// Includes
66
//---------------------------------------------------------------------------------------------------
67
#include "stm32f4xx_rcc.h"
68
#include "stm32f4xx_gpio.h"
69
#include "stm32f4xx_spi.h"
70
71
72
73
//---------------------------------------------------------------------------------------------------
74
// Defines
75
//---------------------------------------------------------------------------------------------------
76
#define LED_Green     GPIO_Pin_12   // selbsterklärend
77
#define LED_Orange    GPIO_Pin_13   //     ""
78
#define LED_Red       GPIO_Pin_14   //    ""
79
#define LED_Blue      GPIO_Pin_15   //     ""
80
81
#define SCLK          GPIO_Pin_10   //PB10  // Takt-Ausgang für SPI
82
#define SDATA         GPIO_Pin_2    //PC2   // Datenleitung für die Samples bzw. MISO
83
#define MOSI          GPIO_Pin_3    //PC3   // MOSI; existiert in diesem Beispiel nicht
84
#define CS            GPIO_Pin_3    //PA3   // ChipSelect (auch SlaveSelect genannt)
85
86
#define ADC_RES       65535    // Der AD7680 hat eine Auflösung von 16 Bit: (2^16)-1=65535 Abstufungen
87
#define Vref          2.94     // Referenzsspannung des A-D Umsetzer ist bei beim AD7680 die Versorgungsspannung Vss
88
                               // Die Versorgungsspannung des AD-Umsetzer wird dem Vdd Pin des STM32F4 Discovery Boards
89
                               // entnommen, die bei USB Speisung c.a. 2.94 V beträgt (Schutzdioden auf dem Board...).
90
91
//---------------------------------------------------------------------------------------------------
92
// Prototpes
93
//---------------------------------------------------------------------------------------------------
94
void EnableRCC(void);
95
void ConfigGPIO(void);
96
void ConfigSPI(void);
97
uint8_t ReadSPI(void);
98
99
100
int main(void)
101
{
102
103
  uint8_t  raw_bytes[3];        // Ein Array wo die drei "Roh-Bytes" gespeichert werden. "Roh-Bytes" sind die mit den Nullen aufgefüllten Bytes, die  vom AD7680 gesendet werden
104
  unsigned sample_value = 0;    // Hier wird der 16 Bit Abtastwert gespeichert
105
  float voltage_value = 0;      // Der berechnete Spannungswert wird hier gespeichert
106
  int i = 0;
107
108
  SystemInit();            // ggf. nötig, damit die Takteinstellungen richtig übernommen werden
109
  EnableRCC();             // Takt für die benötigten Peripherien einschalten
110
  ConfigGPIO();            // Die GPIO Pins konfigurieren
111
  ConfigSPI();             // SPI2 Controller konfigurieren
112
  GPIO_SetBits(GPIOD,LED_Blue);  // blaue LED einschalten (Lebenszeichen)
113
114
    while(1)
115
    {
116
      GPIO_ResetBits(GPIOA,CS);  // ChipSelect Ausgang auf Low setzen, damit der AD7680 mit Abtastvorgang anfängt
117
      for(i=0; i<3; i++)
118
      {
119
        raw_bytes[i]=ReadSPI();  // Alle drei "Roh-Bytes" in das Array speichern
120
      }
121
      GPIO_SetBits(GPIOA,CS);    // ChipSelect Ausgang auf High setzen, damit der AD7680 mit Abtastvorgang aufhört
122
123
124
      sample_value = (raw_bytes[0] << 11) | (raw_bytes[1] << 3) | (raw_bytes[2] >> 5);   // Da wir 3 Bytes (24 Bit) erhalten, müssen wir Bits verschieben um an die
125
                                                // relevanten 16 Bit Daten (Abtastwert) heranzukommen.
126
127
      voltage_value=(Vref/ADC_RES)*sample_value;  // Spannungswert aus dem Abtastwert (16 Bit ADC Wert) berechnen
128
    }
129
}
130
131
132
uint8_t ReadSPI(void)
133
{
134
    SPI2->DR = 0xAA;                           // "dummy" Daten schreiben, dies ist nötig, damit überhaupt Empfangen werden kann.
135
    while( !(SPI2->SR & SPI_I2S_FLAG_TXE) );   // warten bis der Sendevorgang abgeschlossen ist
136
    while( !(SPI2->SR & SPI_I2S_FLAG_RXNE) );  // warten bis der Datenempfang abgeschlossen ist
137
    while( SPI2->SR & SPI_I2S_FLAG_BSY );      // warten bis der SPI2 nicht mehr "beschäftigt" ist.
138
    return SPI2->DR;                           // Daten im SPI2 Datenregister als Rückgabewert ausgeben
139
}
140
141
142
void ConfigSPI()
143
{
144
145
  SPI_InitTypeDef SPI_InitStructure;
146
147
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;      // Daten empfangen und senden
148
  SPI_InitStructure.SPI_Mode    = SPI_Mode_Master;               // STM32F407VGT ist der Master und AD7680 der Slace
149
  SPI_InitStructure.SPI_DataSize   = SPI_DataSize_8b;           // Es werden 24 Bit's vom AD7680 ausgegeben 000016_Bit_Sample_Value0000, daher 3 x 8 Bit Packete
150
  SPI_InitStructure.SPI_DataSize   = SPI_FirstBit_MSB;          // Der AD7680 überträgt die Daten als "MSB first"
151
  SPI_InitStructure.SPI_CPOL     = SPI_CPOL_High;               // Clock Polarity (CPOL) = 1
152
  SPI_InitStructure.SPI_CPHA     = SPI_CPHA_2Edge;              // Clock Phase (CPHA) = 1 (entspricht hier CPHA_2Edge !)
153
  SPI_InitStructure.SPI_NSS     = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;  // NSS Pin als GPIO Pin einstellen und intern auf High setzen
154
155
  SPI_InitStructure.SPI_BaudRatePrescaler  =SPI_BaudRatePrescaler_64;      // SCLK=42MHz/64=656.2kHz APB1=42 MHz, SYSCLK=168 MHz
156
  SPI_InitStructure.SPI_CRCPolynomial   = 0;                   // kein CRC bilden
157
158
  SPI_Init(SPI2, &SPI_InitStructure);                          // SPI2 Interface initialisieren
159
  SPI_CalculateCRC(SPI2, DISABLE);                             // CRC Berechnung deaktivieren
160
161
  SPI_Cmd(SPI2,ENABLE);                                        // SPI2 Interface aktivieren
162
}
163
164
165
void EnableRCC(void)
166
{
167
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  // Takt für die GPIOA's aktivieren
168
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);  // Takt für die GPIOB's aktivieren
169
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);  // Takt für die GPIOC's aktivieren
170
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);  // Takt für die GPIOD's aktivieren
171
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,  ENABLE);  // Takt für den SPI2 aktivieren
172
}
173
174
175
void ConfigGPIO(void)
176
{
177
178
  GPIO_InitTypeDef GPIO_InitStructure;
179
180
181
  //---------------------------------------------------------------------------------------------------
182
  // Pin für die blaue LED (PD15) konfigurieren
183
  //---------------------------------------------------------------------------------------------------
184
  GPIO_InitStructure.GPIO_Pin   = LED_Blue;
185
  GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_OUT;
186
  GPIO_InitStructure.GPIO_OType  = GPIO_OType_PP;
187
  GPIO_InitStructure.GPIO_PuPd   = GPIO_PuPd_NOPULL;
188
  GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
189
190
  GPIO_Init(GPIOD, &GPIO_InitStructure);
191
  //---------------------------------------------------------------------------------------------------
192
193
194
195
  //---------------------------------------------------------------------------------------------------
196
  // SCLK Ausgang konfigurieren
197
  // -restliche Einstellungen können aus der LED Konfiguration übernommen werden.
198
  //---------------------------------------------------------------------------------------------------
199
  GPIO_InitStructure.GPIO_Pin   = SCLK;
200
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;       // SCLK, also PB10, auf Alternativ-Modus umschalten
201
202
  GPIO_Init(GPIOB, &GPIO_InitStructure);
203
204
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);   // PB10 mit dem SPI2 Controller verbinden
205
                                 // PB10 ist nun die SCLK Quelle
206
  //---------------------------------------------------------------------------------------------------
207
208
209
210
  //---------------------------------------------------------------------------------------------------
211
  // SDATA (MISO) und MOSI konfigurieren
212
  //---------------------------------------------------------------------------------------------------
213
  GPIO_InitStructure.GPIO_Pin   = SDATA | MOSI;
214
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;      // PC2 und PC3 auf Alternativ-Modus umschalten
215
216
  GPIO_Init(GPIOC, &GPIO_InitStructure);
217
218
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_SPI2); // PC2 mit SDATA(MISO) von SPI2 verbinden
219
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2); // PC3 mit MOSI von SPI2 verbinden
220
  //---------------------------------------------------------------------------------------------------
221
222
223
224
  //---------------------------------------------------------------------------------------------------
225
  // ChipSelect(CS) bzw. SlaveSelect(SS) konfigurieren
226
  //---------------------------------------------------------------------------------------------------
227
  GPIO_InitStructure.GPIO_Pin   = CS;
228
  GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_OUT;    // Normaler Ausgang...
229
  GPIO_InitStructure.GPIO_PuPd   = GPIO_PuPd_UP;     // PullUp aktivieren
230
  GPIO_Init(GPIOA, &GPIO_InitStructure);
231
232
  GPIO_SetBits(GPIOA,CS);                            // ChipSelect sofort auf High setzen,
233
                                                     // damit der AD7680 nicht gleich anfängt
234
                                                     // zu "arbeiten".
235
  //---------------------------------------------------------------------------------------------------
236
}

viel Spass und Erfolg !

mfGruß,
opcode

: Bearbeitet durch User
von F. F. (foldi)


Lesenswert?

Vielen Dank!

von Op C. (opcode_x64)


Lesenswert?

Ich würde mich sehr freuen, wenn Fehler oder Verbesserungsvorschläge 
erwähnt werden.

Danke !

von Op C. (opcode_x64)


Lesenswert?

Ein wichtiger Nachtrag:

In dem Programm habe ich kommentiert, dass die Abtastwerte des AD7680 
als 24 Bit übertragen werden. Das Datenframe sieht so aus:

"0 0 0 0 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 0 0 0 0"

Wird der SPI2 so eingestellt, dass die Daten bei der zweiten Flanke 
gelesen bzw. gesendet werden, also der ClockPhase CPHA=1, dann muss das 
Bit-Shifting wie folgt erfolgen, damit der eigentliche 16 Bit Wert 
extrahiert wird:
1
sample_value = (raw_bytes[0] << 12) | (raw_bytes[1] << 4) | (raw_bytes[2] >> 4);

Wird der Clockphase auf CPHA=2 gesetzt, werden die Daten bei der zweiten 
Flanke, hier die steigende Flanke von SCLK, gelesen bzw. gesendet. Dann 
muss das Bit-Shifting so erfolgen, wie es auch im Code oben ist, also:
1
sample_value = (raw_bytes[0] << 11) | (raw_bytes[1] << 3) | (raw_bytes[2] >> 5);

Das liegt daran, dass bei der steigenden Flanke die erste Null ignoriert 
wird und am Ende eine Null hinzukommt, das Datenframe ist dann wie folgt 
zu betrachten:
"0 0 0 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 0 0 0 0 0"

Ich habe das Bit-Shiften für den AD7680 aus einer Internetquelle (siehe 
dritten Link im Hauptkommentar) übernommen. Der Autor dieser Quelle 
begründet dies damit, das zum Lesen und Schreiben bei fallender Flanke 
nur 10ns zur Verfügung stehen (siehe t_{7} im Datenblatt). Für das Lesen 
und Schreiben bei steigener Flanke hat man deutlicher mehr Zeit, bis die 
Daten "invalid" werden. (siehe Fig. 20 bzw. 21, S.17 Datenblatt AD7680).


mfGruß,
opcode

von Manfred B. (manib)


Lesenswert?

Prima Beispiel, und super kommentiert.

Danke!

ManiB

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
Noch kein Account? Hier anmelden.