Forum: Mikrocontroller und Digitale Elektronik AD7798 & PIC SPI


von Stefan R. (stefanr86)


Lesenswert?

Hallo,
ich krame mich nun schon eine Zeit durch dieses Problem.

Ich habe einen 16F876 µC und einen AD7798 (3x16Bit SD-ADC) der an einen 
Drucksensor angeschlossen ist.

Nun möchte ich den 16Bit ADC-Wert auslesen, alle versuche bislang selbst 
die ID des IC's auszulesen  gingen schief. (Per USART/RS232)

Mein bisheriger code siegt wie folgt aus:

Init:
1
; ==========================================
2
; Ports Init.
3
; ==========================================
4
  clrf  PORTA
5
  clrf  PORTB
6
  clrf  PORTC
7
    BSF   STATUS, RP0 ; auf Bank 1 umschalten
8
    MOVLW   0x06        ; PCFG3..0 = '0110' (ADC's -> OFF)
9
    MOVWF   ADCON1
10
  movlw  B'11100110'  ; PortA SoftwareI²C
11
  movwf  TRISA
12
  movlw  B'00000000'  ; PortB LED's
13
  movwf  TRISB
14
  movlw  B'10001000'  ; RS232 & SPI
15
  movwf  TRISC
16
  bcf     STATUS, RP0  ; Bank 0
17
18
; ==========================================
19
; SPI-Bus initialisieren
20
; ==========================================
21
    clrf  SSPCON
22
  clrf  SSPSTAT
23
  
24
; ==========================================
25
; RS232 initialisieren
26
; ==========================================
27
  bcf    NewData
28
  clrf  ZeichenIN
29
  clrf  ZeichenOUT
30
    BSF     STATUS,RP0     ; Bank1
31
    MOVLW   0x20            ; Sender: RS232
32
    MOVWF   TXSTA           ;
33
    BCF     STATUS,RP0      ; Bank 0
34
     MOVLW   0x90            ; Empfänger: RS232
35
    MOVWF   RCSTA           ; 
36
    BSF     STATUS,RP0      ; Bank1
37
  MOVLW   D'64'      ; Set Baud rate 9,6 kBPS bei 10 MHz
38
    MOVWF   SPBRG
39
     BSF     TXSTA, BRGH     ; BRGH=1
40
     BCF     STATUS,RP0      ; Bank 0
41
42
  M_RS232Out '$'
43
  M_RS232Out 'H'
44
  M_RS232Out 'M'
45
  M_RS232Out '#'
46
  M_RS232Out 'B'
47
  M_RS232Out 'O'
48
  M_RS232Out 'O'
49
  M_RS232Out 'T'
50
  M_RS232Out 'I'
51
  M_RS232Out 'N'
52
  M_RS232Out 'G'
53
  M_RS232Out ';'
54
55
; ==========================================
56
; Lampentest und Status
57
; ==========================================
58
  bsf    LED_ERR
59
  bsf    LED_RTX
60
  
61
  M_wait D'250'
62
  M_wait D'250'
63
  M_wait D'250'
64
  M_wait D'250'
65
66
  bcf    LED_ERR
67
68
  M_wait D'250'
69
70
; ==========================================
71
; BUS-Systeme und andere Transmitter einschalten
72
; ==========================================
73
    clrf    PIR1               ; alle Interruptflags löschen
74
    clrf    PIR2  
75
  bsf     SSPCON, SSPEN   ; MSSP-Modul Ein
76
  BSF     STATUS,RP0      ; Bank1
77
    BSF     PIE1,RCIE       ; Enable receive interrupts
78
  ;BcF    PIE1,SSPIE    ; Enable SSP interrupts
79
    BCF     STATUS,RP0      ; Bank 0
80
  BSF    INTCON, PEIE
81
  BSF    INTCON, GIE    ; Enable global interrupts
82
83
  M_RS232Out '$'
84
  M_RS232Out 'H'
85
  M_RS232Out 'M'
86
  M_RS232Out '#'
87
  M_RS232Out 'R'
88
  M_RS232Out 'E'
89
  M_RS232Out 'A'
90
  M_RS232Out 'D'
91
  M_RS232Out 'Y'
92
  M_RS232Out ';'
93
  
94
  bcf    LED_RTX

Die SPI Funktion:
1
;*****************************************************
2
; SPI Datenverkehr
3
;*****************************************************
4
SPI_Data
5
  movf    SPIout,W                ; move outbyte into w
6
    movwf   SSPBUF                  ; place data in send buffer
7
SPIloop
8
    bsf     STATUS,RP0              ; set to bank 1
9
    btfss   SSPSTAT,BF              ; has data been received?
10
     goto    SPIloop                ; loop if not received yet
11
    bcf     STATUS,RP0              ; set to bank 0
12
    movf    SSPBUF,W                ; empty the receive buffer
13
  movwf  SPIin
14
  M_RS232Out '$'
15
  M_RS232Out 'H'
16
  M_RS232Out 'M'
17
  M_RS232Out '#'    
18
  M_RS232Out SPIin  
19
  M_RS232Out ';'
20
    return

(RS232 Only funktioniert)

Ich lieg doch richtig das ich z.B. die ID des ADC's mit folgenden Zeilen 
auslesen kann?
1
movlw B'01100000'  ; Sage Comm. Register das ich das ID_Register lesen möchte
2
movwf SPIout
3
call SPI_Data


Wär super wenn mir jmd helfen kann :)


Stefan

von Stefan R. (stefanr86)


Lesenswert?

sry der Init teil war der alte,

muss natürlich bei TRISC
1
movlw  B'10011000'  ; RS232 & SPI
heissen

von holger (Gast)


Lesenswert?

>movlw B'01100000'  ; Sage Comm. Register das ich das ID_Register lesen möchte
>movwf SPIout
>call SPI_Data

Und was machst du DANACH ?

von Stefan R. (stefanr86)


Lesenswert?

dannach erstmal garnichts mehr, weil ich als antwort  egal wobei immer 
nur das ascii char " bekomme (32)

von holger (Gast)


Lesenswert?

>dannach erstmal garnichts mehr

Du hast SPI nicht verstanden :(
Was glaubst du wie die ID aus dem Chip kommt ?
Mit dem senden des Befehls ? Geht nicht. Den muss er ja
erstmal empfangen. Danach musst du die ID aus dem Chip
rausholen !

von Stefan R. (stefanr86)


Lesenswert?

hmm...

hab den teil aus dem microchip appnotes, dafür (zum lesen)
sollte ja der folgende teil sein?

1
...
2
    btfss   SSPSTAT,BF              ; has data been received?
3
     goto    SPIloop                ; loop if not received yet
4
    bcf     STATUS,RP0              ; set to bank 0
5
    movf    SSPBUF,W                ; empty the receive buffer
6
...

oder lieg ich da total falsch?

von holger (Gast)


Lesenswert?

>oder lieg ich da total falsch?

Nicht ganz ;)

Denk nach! Du stellst eine Frage. Kommt die Antwort
schon während du die Frage stellst ? Nein, sie kommt
erst danach.

movlw B'01100000'  ; Sage Comm. Register das ich das ID_Register lesen 
möchte
movwf SPIout
call SPI_Data
movlw B'11111111'  ; Dummy write to clock out the answer
movwf SPIout
call SPI_Data

von Stefan R. (stefanr86)


Lesenswert?

ja sowas hatte ich auch schon versucht, Ohne erfolg.

Ich lassen nun den PIC nur als Schnittstellenwandler RS232 <-> SPI 
arbeiten.
Ich bekomme bei egal was ich per SPI sende die antwort ascii 34

UI> 96
HM> 34
UI> 0
HM> 34
UI> 96
HM> 34
UI> 255
HM> 34

HM -> Höhenmesser
UI -> UserInterface

es musst also noch etwas anderes sein?!

von Severino R. (severino)


Lesenswert?

Nur so aus Neugier: Welchen Drucksensor verwendest Du?

Hast Du den Drucksensor am AD-Wandler angeschlossen? Versuch es doch mal 
mit einem Potentiometer an Stelle des Sensors. So kannst Du die 
verschiedenen Werte simulieren ohne auf  schlechtes Wetter warten oder 
ohne auf den Hausberg steigen zu müssen.

Muss der A/D-Wandler irgendwie speziell initialisiert werden?

von Stefan R. (stefanr86)


Lesenswert?

das mit dem poti  wäre  ne möglichkeit wenn ich  nen falschen wert 
bekommen würde ja. aber ich hab ja irgend ein anderes Problem, der ADC 
hat mehrere register die anfangs beschrieben werden müssten zur 
taktrate des SD-ADC's kalibrierung ect.
hab eben mal  in mühevoller arbeit den adc abgelötet  und bekomme 
trotzdem noch 34 - muss also softwaremäßig  sein das prob.

Als Drucksensor verwendet ich den MPXA4100(A6U) von Motorola.

von Stefan R. (stefanr86)


Lesenswert?

also ich habs bislang net hinbekommen per Hardware SPI Schnittstelle, 
nun versuche ichs über ne eigen Softwareschnittstelle, ist das Konzept 
soweit ok?
1
SPI_out
2
  movfw  SPIout    ; SPI daten zum schreiben in den Buffer legen
3
  movwf  SPIBuffer
4
  bcf    INTCON, GIE  ; Interrupts aus
5
  clrf  temp    ; Temp. Register leeren (Zählreg)
6
SPI_outLoop
7
  rlf    SPIBuffer, 1; SPIBuffer  nach und nach nach links verschieben das MSB landet dabei im Carray
8
  btfsc  STATUS, C  ; Ist das Carrybit = 1 ?
9
   bsf  SPIo    ; ja, SPI übermittelt auch eine 1
10
  btfss  STATUS, C  ; Ist das Carrybit = 0 ?
11
   bcf  SPIo    ; ja, SPI übermittelt auch eine 0
12
  bcf    SPIclk    ; clock 0
13
  nop          ; Kurz warten
14
  bsf    SPIclk    ; Clock geht wieder  auf HI
15
  incf  temp,1    ; Weiteres bit wurde übertragen
16
  movwf  temp
17
  sublw  D'8'    ; wurden 8 bit übertragen?
18
  btfsc  STATUS, Z  
19
   goto   SPI_outLoop
20
  bsf    INTCON, GIE  ; Interrupts wieder an
21
  return
22
  
23
SPI_in
24
  bsf    LED_RTX
25
  bcf    INTCON, GIE  ; Interrupts aus
26
  clrf  SPIBuffer  ; Buffer leeren
27
  clrf  temp    ; Temp. Zählregister leeren
28
SPI_inpreLoop
29
  btfsc  SPIi    ; Ist SDI 0 ? (ADC= RDY)
30
   goto  SPI_inpreLoop
31
SPI_inLoop
32
  bcf    SPIclk    ; Clock 0
33
  nop
34
  nop
35
  nop          ; warten
36
  btfsc  SPIi    ; Sendet ADC ein Hi signal?
37
   bsf  SPIBuffer,0  ; ja, Bit = 1
38
  rlf    SPIBuffer,1  ; Buffer nach Links verschieben, da vom MSB zum LSB gesendet wird
39
  bsf    SPIclk    ; Clock wieder 1
40
  incf  temp,1    ; Weiteres bit wurde empfangen
41
  movwf  temp
42
  sublw  D'8'    ; wurden 8 bit empfangen?
43
  btfsc  STATUS, Z  
44
   goto   SPI_inLoop
45
  movfw  SPIBuffer  ; Buffer in Ausgabebyte schreiben
46
  movwf  SPIin
47
  bsf    INTCON, GIE  ; Interrupts wieder an
48
  bcf    LED_RTX
49
  return

von Arc N. (arc)


Lesenswert?

Arbeite zwar normalerweise nicht mit PICs, im Datenblatt steht 
allerdings unter 9.1 "SCK (Master mode) must have TRISC<3> cleared" also 
nicht gesetzt d.h. beim ADC kommt z.Z. kein Takt an.

> movlw  B'10011000'  ; RS232 & SPI
> movwf  TRISC

von Stefan R. (stefanr86)


Lesenswert?

den code hatte ich überarbeitet und viele kleine fehlerchen tz 
ausgemärzt. ich hatte ihn nun soweit das mal etwas anderes ankam aber 
nie das was ich "haben" wollte.

Mein Init mit Hardware SPI sieht wie folgt aus nun:
1
...
2
  movlw  B'10010000'  ; RS232 & SPI
3
  movwf  TRISC
4
...
1
...
2
  movlw  B'00110010'  
3
  movwf  SSPCON
4
  BSF     STATUS,RP0      ; Bank1
5
  clrf  SSPSTAT
6
  movlw  B'01000000'
7
  movwf  SSPSTAT
8
...


Sende/Empfangsroutine:
1
;*****************************************************
2
; SPI Datenverkehr
3
;*****************************************************
4
SPI_Data
5
  bsf    LED_RTX
6
  movlw  D'255'
7
  movwf  loops
8
  movlw  D'255'
9
  movwf  loops2
10
  movfw    SPIout                ; move outbyte into w
11
    movwf   SSPBUF                  ; place data in send buffer
12
  bcf    INTCON, GIE
13
SPIloop
14
    bcf     STATUS,RP0              ; set to bank 0
15
  decf  loops,1
16
  movfw  loops
17
  sublw  '0'
18
  btfsc  STATUS,Z
19
   decf  loops2,1
20
  movfw  loops2
21
  sublw  '0'
22
  btfsc  STATUS,Z
23
   goto  SPIError
24
25
    bsf     STATUS,RP0              ; set to bank 1
26
    btfss   SSPSTAT,BF              ; has data been received?
27
     goto    SPIloop                ; loop if not received yet
28
    bcf     STATUS,RP0              ; set to bank 0
29
    movf    SSPBUF,W               ; empty the receive buffer
30
  movwf  SPIin
31
  bcf    LED_RTX
32
  bcf    INTCON, GIE
33
    return
34
SPIError
35
  bsf    LEDCON, LEDERREN
36
  bsf    LEDCON, BLINKERREN
37
  goto  SPIloop

von Arc N. (arc)


Lesenswert?

Ist denn der Rest so initialisiert wie im Datenblatt?
CKE = 0 getestet? Z.Z. müsste auf der falschen Flanke übertragen werden.
Wo wird der ADC selektiert oder liegt /CS immer auf Low, Pull-Up?
Pseudocode:
1
InitPorts()
2
SPIInit(mode)
3
4
SelectADC()
5
6
dummy = SPITransceive(ADCReadIDReg)
7
res = SPITransceive(0x00)
8
9
DeselectADC()

U.U. auch mal "SS must have TRISA<5> set and register
ADCON1 (see Section 11.0: A/D Module) must be
set in a way that pin RA5 is configured as a digital
I/O" umsetzen.

von Stefan R. (stefanr86)


Lesenswert?

ADC Datenblatt Seite 6 (kleingedruckte):
SCLK active edge is falling SCLK

PIC Datenblatt seite 64:
SSPSTAT CKE: SPI Clock Edge Select
(Figure 9-4, Figure 9-5 and Figure 9-6),CKP = 1
1 = Data transmitted on falling edge of SCK
0 = Data transmitted on rising edge of SCK

Also CKP = 1; CKE = 1

CKP wäre:
CKP: Clock Polarity Select bit/
In SPI mode/
1 = Idle state for clock is a high level
0 = Idle state for clock is a low level


Hab alle möglichkeiten mit SMP,CKE,CKP durchgetestet....

werde nun mal das mit dem SlaveSelect testen, wobei das normalerweise ja 
nicht sein kann, man weiss ja nie

EDIT, Das SlaveSelect wird nur im Slave Modus verwendet

von Stefan R. (stefanr86)


Lesenswert?

ich glaub ich habs :-)


da hab ich wohl was überlesen ...
To reset or reconfigure SPI
mode, clear bit SSPEN, re-initialize the SSPCON registers,
and then set bit SSPEN.

ich hab immer alles gleichzeitig gemacht, nun erst  alles bis auf sspen 
dann sspen.

zumindest überträgt er nun  die ID (48) was stimmen könnte ....


Danke erstmal :)

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.