Forum: Mikrocontroller und Digitale Elektronik MCP3911 SPI-Interface funktioniert nicht


von Michael S. (the_mole)


Angehängte Dateien:

Lesenswert?

Um mich kurz zu fassen: Ich habe für meine Diplomarbeit die Aufgabe 
bekommen ein Messgerät für E-Autos zu bauen. Nach zahlreichen 
Fehlschlägen bei der Messung bin ich auf den MCP3911 gekommen.
Alles Klar. Testprogramm geschrieben und mit PICKIT2 Werte an den PC 
gesendet. Dann die enttäuschung: Es kommt je nach Versuch nur 0, 1, -1 
oder 255 am Terminal an.
Nochmal alles überprüft, Programm neu geschrieben, wieder nichts.
Dann habe ich einfach ein paar Register beschrieben und ausgelesen: aber 
es kommt nur 0 oder 255 raus.

Hatte schon mal jemand ein ähnliches Problem oder kann mir jemand 
helfen?
Sitze seit 3 Tagen ununterbrochen vorm Bildschirm aber es wird nicht 
besser.

Hier der größte Teil des Programms:
1
#include  "C:\Users\Michael\Documents\Schule\Microcontroller\PICC\Devices\18F2550.h"
2
#include  "C:\Users\Michael\Desktop\Netzanalyse\Programme\PIC18F2550\MCP3911 Test\Hardware.h"
3
#include  "C:\Users\Michael\Desktop\Netzanalyse\Programme\PIC18F2550\MCP3911 Test\MCP3911_EVB.h"
4
#device  ADC = 10
5
#fuses  NOWDT, NOPUT, HSPLL, PLL5, CPUDIV1, NOMCLR  
6
#use    delay(clock=48M)        
7
#use    rs232(Stream=PICKIT2,Baud = 38400, FORCE_SW, RCV = pin_b6, XMIT = pin_b7)
8
9
10
11
12
#define CS_delay      50
13
#define  VDD        4000
14
#define CH0_VAL_H      0x00      //READ-ONLY, ADC-Daten
15
#define CH0_VAL_M      0x01      //READ-ONLY, ADC-Daten
16
#define CH0_VAL_L      0x02      //READ-ONLY, ADC-Daten
17
#define CH1_VAL_H      0x03      //READ-ONLY, ADC-Daten
18
#define CH1_VAL_M      0x04      //READ-ONLY, ADC-Daten
19
#define CH1_VAL_L      0x05      //READ-ONLY, ADC-Daten
20
#define MOD         0x06      //Wegen ADC-Genauigkeit darf hier nicht geschrieben werden, Modulator-Daten
21
#define PHASE_H        0x07      //Bei WRITE --> RESET, Phasen-Delay: Bit 0-7
22
#define PHASE_L        0x08      //Bei WRITE --> RESET, Phasen-Delay: Bit 8-11 Bit 11-15 = 0
23
#define GAIN        0x09      // GAIN2: Bit 0-2 GAIN1: Bit 3-5 BOOST: Bit 6-7
24
#define STATUS_H       0x0A      
25
#define STATUS_L       0x0B      
26
#define CONFIG_H       0x0C      // CLKEXT: Bit 1  VREFEXT: Bit 2 SHUTDOWN: Bit 4-5 RESET: Bit 6-7
27
#define CONFIG_L       0x0D    //AZFREQ: Bit 8 DITHER: Bit 9-10 OSR Bit: 11-13 PRE: 14 -15
28
#define CH0_OFF_H      0x0E      // CH0 OFFSET: Bit 0-7
29
#define CH0_OFF_M      0x0F      // CH0 OFFSET: Bit 8-15
30
#define CH0_OFF_L      0x10      // CH0 OFFSET: Bit 16-23
31
#define CH0_GAIN_H      0x11      // CH0 GAIN-ERROR: Bit 0-7
32
#define CH0_GAIN_M      0x12      // CH0 GAIN-ERROR: Bit 7-15
33
#define CH0_GAIN_L      0x13      // CH0 GAIN-ERROR: Bit 15-23
34
#define CH1_OFF_H      0x14      // CH1 OFFSET: Bit 0-7
35
#define CH1_OFF_M      0x15      // CH1 OFFSET: Bit 8-15
36
#define CH1_OFF_L      0x16     // CH1 OFFSET: Bit 16-23
37
#define CH1_GAIN_H      0x17      // CH1 GAIN-ERROR: Bit 0-7
38
#define CH1_GAIN_M      0x18      // CH1 GAIN-ERROR: Bit 8-15
39
#define CH1_GAIN_L      0x19      // CH1 GAIN-ERROR: Bit 15-23
40
#define V_REF        0x1A      //READ-ONLY, VREF einstellen
41
42
43
unsigned char internal_registers[27];
44
45
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
46
/*****************************************************
47
* Local Prototypes
48
*****************************************************/
49
void Init_PIC(void);
50
void Write3911(unsigned char address, unsigned char data);
51
unsigned char Read3911(char addres);
52
void Read_Internal_Registers(void);
53
void Print_Internal_Registers(void);
54
55
56
57
58
int16  adcValueVDD;
59
int16   VoltA, VoltD;
60
int8    spidata;
61
62
// Hauptprogramm
63
void main() 
64
{
65
  delay_ms(2000);
66
  Init_PIC();
67
  
68
  output_low(SS_Pin);
69
  delay_us(CS_delay);
70
  spi_write(0b00011010);  // Adresse Config-2
71
  spi_write(0b11000000);  // CONFIG2: Beide ADC-Reset
72
  output_high(SS_Pin);
73
  delay_us(CS_delay);
74
  output_low(SS_Pin);
75
  delay_us(CS_delay);
76
  spi_write(0b00001110);  // Adresse Phase 
77
  spi_write(0b00000000);  // PHASE: Bit 15- 8 
78
  spi_write(0b00000000);  // PHASE: Bit 7- 0
79
  spi_write(0b10000000);   // GAIN: 
80
  spi_write(0b00011111);   // STATUSCOM2: Bit 15-8 
81
  spi_write(0b00100000);   // STATUSCOM1: Bit 7-0: immer das gleiche register lesen
82
  spi_write(0b00000110);  // CONFIG2:
83
  spi_write(0b00000000);  // CONFIG1: Beide ADC-Reset Ende
84
  output_high(SS_Pin);
85
  delay_us(CS_delay);
86
  Read_Internal_Registers();
87
  Print_Internal_Registers();
88
  
89
  while(1)
90
  {
91
    
92
  //  Read3911(CH0_VAL_M);
93
  //  Read3911(CH0_VAL_L);
94
  //  output_high(SS_Pin);
95
  //  delay_us(CS_delay);
96
  //  Write3911(GAIN,0b11111111);
97
  //  delay_ms(100);
98
  //  fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
99
  //  fprintf(PICKIT2,"SPI: %u",Read3911(GAIN));
100
101
  }
102
}  
103
104
void Init_PIC(void)        // Gibt die Spannungen über das PICKIT2-UART-Tool an den PC
105
{
106
  fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
107
  fprintf(PICKIT2,"Initialisierung");
108
  setup_adc(ADC_CLOCK_INTERNAL);    // ADC-Konfiguration
109
  setup_adc_ports(AN0_TO_AN1|VSS_VDD);
110
111
  set_adc_channel(AVDD);      // MCP3911-Steckbrett Spannungsmessung und ADC-Test
112
  delay_us(100);  
113
  adcValueVDD = read_adc();
114
  VoltA = (adcValueVDD / (double) 1023) * VDD;
115
  
116
  set_adc_channel(DVDD);
117
  delay_us(100);
118
  adcValueVDD = read_adc();
119
  VoltD = (adcValueVDD / (double) 1023) * VDD;
120
    
121
  delay_ms(2000);
122
  fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
123
  fprintf(PICKIT2,"Analog-Spannung: %LD", VoltA);
124
  
125
  fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
126
  fprintf(PICKIT2,"Digital-Spannung: %LD", VoltD);
127
  delay_ms(2000);
128
129
  setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);  // SPI-Master Einstellung
130
  output_high(SS_Pin);
131
  delay_us(1000);
132
}  
133
134
//>>>>>>> Read the registers from MCP3911
135
unsigned char Read3911(char address)
136
{
137
  char data;
138
  address=(address<<1)+1;
139
140
  output_low(SS_Pin);
141
  delay_us(CS_delay);
142
  spi_write(address);
143
      data=spi_read();
144
  delay_us(CS_delay);
145
  output_high(SS_Pin);
146
  
147
  return(data);
148
}
149
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
150
//  Reads the all the registers from MCP3911
151
152
void Read_Internal_Registers(void)
153
{
154
  unsigned char i, address;
155
  for(i=0; i<=26; i++)
156
  {
157
    internal_registers[i]=Read3911(i);
158
  }
159
160
}
161
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
162
//   Write each register from MCP3911
163
164
void Write3911(unsigned char address, unsigned char data)
165
{
166
  address=(address<<1);
167
  
168
     output_low(SS_Pin);
169
     delay_us(CS_delay);
170
  spi_write(address);
171
  spi_write(data);
172
  delay_us(CS_delay);
173
    output_high(SS_Pin);
174
}
175
176
void Print_Internal_Registers(void)
177
{
178
  int8 i = 0;
179
  fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
180
  for(i = 0;i <= 26;i++)
181
  {
182
    fprintf(PICKIT2,"Register %d: %u",i,internal_registers[i]);
183
    fprintf(PICKIT2,"%c%c", 0x0D, 0x0A);
184
    delay_ms(1);
185
  }  
186
}

Raus komm das:

Initialisierung
Analog-Spannung: 3061
Digital-Spannung: 3053
Register 0: 255
Register 1: 0
Register 2: 0
Register 3: 0
Register 4: 0
Register 5: 0
Register 6: 0
Register 7: 0
Register 8: 0
Register 9: 0
Register 10: 255
Register 11: 0
Register 12: 0
Register 13: 0
Register 14: 0
Register 15: 0
Register 16: 0
Register 17: 0
Register 18: 0
Register 19: 0
Register 20: 0
Register 21: 0
Register 22: 0
Register 23: 0
Register 24: 0
Register 25: 0
Register 26: 0

von Andre (Gast)


Lesenswert?

Hallo Michael

Bevoor ich den ganzen Code lese, doch zwei wichtige Fragen:

1)
Wie sieht die Gegenstelle aus, die mit dem MCP kommuniziert? Beschaltung 
richtig?

2)
Hast Du mal einen Logic Analyzer benutzt um auszuwerten, ob auch 
wirklich die richtigen Informationen gesendet werden, wie du es 
erwartest?

VG

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael S. schrieb:
> Dann habe ich einfach ein paar Register beschrieben und ausgelesen: aber
> es kommt nur 0 oder 255 raus.
Stichwort: Oszilloskop.
Damit kann man sich Signale ansehen und kontrollieren, ob sie mit den im 
Datenblatt angegebenen Zeiten und Timings (Taktfrequenz, Polarität und 
Phase) zusammenpassen.

> Hatte schon mal jemand ein ähnliches Problem oder kann mir jemand
> helfen?
Schließt sich das aus?

Noch ein Tipp:
>  setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
Den SPI zu Beginn ruhig erst mal langsam anfahren, und nicht mit der 
/maximal/erlaubten Geschwindigkeit...

BTW:
Wie sieht der Hardwareaufbau aus?

: Bearbeitet durch Moderator
von Michael S. (the_mole)


Lesenswert?

Andre schrieb:
>
> 1)
> Wie sieht die Gegenstelle aus, die mit dem MCP kommuniziert? Beschaltung
> richtig?

Die Beschaltung ist ganz simpel:
1
      
2
3
          VDD
4
    MCLR  I
5
     I  __I___
6
     I-I      I---TX                        I
7
  I    I   1  I---RX          _________  15pF
8
 15pF  I   8  I---DR   DR----I         I   _I_
9
 _I_   I   F  I---CS   CS----I         I--I 2 I
10
I 2 I--I   2  I---CLK  CLK---I MCP3911 I--I_0_I
11
I_0_I--I   5  I---SDO  SDI---I         I    I
12
  I    I   5  I---SDI  SDO---I_________I   15pF   
13
 15pF  I   0  I                             I
14
  I    I______I
15
           I
16
           I
17
         VSS
20MHz Quarz 15pF Kondis, am PIC sowie auch am MCP3911

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael S. schrieb:
> Die Beschaltung ist ganz simpel:
Das ist ja mal eine grausige ASCII-Grafik  :-o
Kleiner Tipp: mit den passenden Tags (siehe unter 
https://www.mikrocontroller.net/articles/Formatierung_im_Forum) lässt 
sich die Darstellung nicht von Formatierungen durcheinanderbringen...

Seis drum:
> 20MHz Quarz 15pF Kondis, am PIC sowie auch am MCP3911
Sonst nix? Ich sehe da keine Blockkondensatoren und tu mir auch schwer, 
den tatsächlichen Hardwareaufbau vorzustellen (Leitungslängen usw.).


BTW: SPI kennt auch keine SDO und SDI, sondern nur MISO und MOSI...

: Bearbeitet durch Moderator
von Michael S. (the_mole)


Angehängte Dateien:

Lesenswert?

> Seis drum:
>> 20MHz Quarz 15pF Kondis, am PIC sowie auch am MCP3911
> Sonst nix? Ich sehe da keine Blockkondensatoren und tu mir auch schwer,
> den tatsächlichen Hardwareaufbau vorzustellen (Leitungslängen usw.).
>
Kabel so kurz wie möglich. 2 separate 3.3V-Spannungsregler, 
Pufferkondensatoren 10uF, mehr Bauteile gibts nicht(siehe Bild)

von Michael S. (the_mole)


Lesenswert?

JAAA! Problem gelöst:
ohne Daten im
1
 spi_read(data);
gibts keine Clock, also kann er auch nichts lesen.
1
unsigned char Read3911(char address)
2
{
3
  char data;
4
  address=(address<<1)+1;
5
6
  output_low(SS_Pin);
7
  delay_us(CS_delay);
8
  spi_write(address);
9
      data=spi_read(); /// hier fehlt die 0 im spi_read(0);
10
  delay_us(CS_delay);
11
  output_high(SS_Pin);
12
  
13
  return(data);
14
}

von Frank K. (fchk)


Lesenswert?

Michael S. schrieb:
>> Seis drum:
>>> 20MHz Quarz 15pF Kondis, am PIC sowie auch am MCP3911
>> Sonst nix? Ich sehe da keine Blockkondensatoren und tu mir auch schwer,
>> den tatsächlichen Hardwareaufbau vorzustellen (Leitungslängen usw.).
>>
> Kabel so kurz wie möglich. 2 separate 3.3V-Spannungsregler,
> Pufferkondensatoren 10uF, mehr Bauteile gibts nicht(siehe Bild)

Grundregel 1: an jedes VCC-GND-Pärchen gehört immer ein 100n keramisch 
DIREKT am Pinpaar
Grundregel 2: keine offenen Eingänge

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael S. schrieb:
> data=spi_read(); /// hier fehlt die 0 im spi_read(0);
Und wie war nochmal die Warnung, die der Compiler für diesen leeren 
Funktionsaufruf ausgespuckt hat?

von Michael S. (the_mole)


Lesenswert?

Es gab keine Warnung. hat mich auch sehr gewundert...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael S. schrieb:
> Es gab keine Warnung.
Hoppla, lausiger Compiler...
Oder hast du Warnungen abgeschaltet?

von Michael S. (the_mole)


Lesenswert?

Nein. Sowas mache ich nicht. So ist er halt der CCS Compiler

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.