Forum: Mikrocontroller und Digitale Elektronik Zwei PIC18F2550 mit SPI koppeln


von FitzDaKat (Gast)


Lesenswert?

Hallo,

ich arbeite seit mehreren Tagen, an einem Teil von meinem Projekt. Ich 
möchte zwei PIC18F2550 über SPI verdrahten, damit diese Daten 
austauschen. An und für sich dachte ich, das wäre kein Problem. Nun 
stellt es sich aber doch sehr kniffelig heraus.


Die µCs sind nach folgendem Schema mit draht aneinander gekoppelt, 
Betriebsspannung ist vorhanden und zugeschaltet;): Der Master soll einen 
counter vom Slave auslesen und über LEDS an PORTA ausgeben.

Master:   Slave:
SCK--------->SCK
SDI<---------SDO
SDO--------->SDI
CS(RB2)----->SS(RA5)

Pull-Up oder Pull-Down Widerstände verwende ich bislang keine.Könnte das 
eine Fehlerquelle sein?

Der bisherige Quellcode des Masters sieht wie folgt aus:
1
//#include<p18f2550.h>
2
#include<p18cxxx.h>
3
#include<delays.h>
4
#include<portb.h>
5
#include<timers.h>
6
#include<adc.h>
7
#include<stdlib.h>
8
#include<spi.h>
9
10
11
12
#pragma config PLLDIV = 5        //PLL for 4Mhz
13
#pragma config CPUDIV = OSC1_PLL2    //Takt 
14
#pragma config FOSC = HS        //Interner Oszillator
15
#pragma config FCMEN = OFF        //keine Taktüberwachung
16
#pragma config PWRT = ON        //Poweruptimer on
17
#pragma config BOR = ON        //Kein Brown Out Reset
18
#pragma config WDT = OFF        //WatchDogTimer Off
19
#pragma config MCLRE = ON        //MCLR on
20
#pragma config PBADEN = OFF        //PortB digital I/Os
21
#pragma config STVREN = OFF        //Kein Stackreset
22
#pragma config LVP = OFF        //Kein LowPowerICSP
23
#pragma config DEBUG = OFF        //RB6,RB7 stehen zur Verfügung
24
#pragma config IESO = OFF        //IESO Off
25
26
27
28
/*
29
void high_isr(void);
30
31
#pragma code high_vector=0x08
32
void interrupt_at_high_vector(void){
33
    _asm goto high_isr _endasm
34
}*/
35
36
#pragma code
37
/*
38
#pragma interrupt high_isr
39
void high_isr (void)
40
{
41
42
}*/
43
44
void SPI_TR_Done(void);
45
char spi_read_write(char data);
46
47
48
void SPI_TR_Done(void)
49
{
50
  PORTBbits.RB3=1;
51
  while(SSPSTATbits.BF==0);
52
}//SPI_TR_Done()
53
54
55
char spi_read_write(char data)
56
{
57
  char dataReturn;
58
  SSPBUF = data;
59
  SPI_TR_Done();
60
  dataReturn=SSPBUF;
61
  return(dataReturn);
62
}//spi_write(char data)  
63
64
void main(void)
65
{
66
char i=0x0A;
67
68
69
ADCON1=0x0F;
70
71
72
PORTA=0;
73
TRISA=0;
74
75
PORTBbits.RB2=1;
76
PORTBbits.RB3=0;
77
PORTBbits.RB4=0;
78
79
//Enable MSSP
80
OpenSPI(SPI_FOSC_16, MODE_10, SMPMID);
81
82
DDRBbits.RB0=1;//SDI = Input
83
DDRBbits.RB1=0;//SCK=Output
84
DDRBbits.RB2=0;//CS=Output
85
DDRCbits.RC7=0;//SDO=Output
86
DDRBbits.RB3=0;
87
DDRBbits.RB4=0;
88
89
90
PORTA=i;
91
Delay10KTCYx(150);
92
93
94
while(1)
95
{
96
PORTBbits.RB2=0;
97
i=spi_read_write(0xFF);
98
PORTBbits.RB2=1;
99
LATA=i;
100
Delay10KTCYx(200);
101
}
102
103
104
}//end main


Der des Slave so:
1
#include <p18F2550.h>
2
#include<p18cxxx.h>
3
#include<delays.h>
4
#include<math.h>
5
#include<capture.h>
6
#include<timers.h>
7
#include <stdlib.h>
8
#include<spi.h>
9
10
#define STATLEDDIR DDRCbits.RC6
11
#define STATLED PORTCbits.RC6
12
#pragma config PLLDIV = 1        //PLL for 20Mhz
13
#pragma config CPUDIV = OSC1_PLL2    //Takt = 12Mhz:1=12Mhz
14
#pragma config FOSC = HS        //bis 20MHz Taktung
15
#pragma config FCMEN = OFF        //keine Taktüberwachung
16
#pragma config PWRT = ON        //Poweruptimer on
17
#pragma config BOR = ON          //Kein Brown Out Reset
18
#pragma config WDT = OFF        //WatchDogTimer Off
19
#pragma config MCLRE = ON        //MCLR on
20
#pragma config PBADEN = OFF        //PortB digital I/Os
21
#pragma config STVREN = OFF        //Kein Stackreset
22
#pragma config LVP = OFF        //Kein LowPowerICSP
23
#pragma config DEBUG = OFF        //RB6,RB7 stehen zur Verfügung
24
#pragma config IESO = OFF        //IESO Off
25
#pragma config CCP2MX = ON        //CCP2 multiplexed mit RC1
26
27
unsigned char SPI_cnt=0;
28
29
void SPI_TR_Done(void);
30
char spi_read_write(char data);
31
32
void SPI_TR_Done(void)
33
{
34
  STATLED=0;
35
  while(!PIR1bits.SSPIF);
36
    PIR1bits.SSPIF = 0x00;
37
    SSPSTATbits.BF=0;
38
    SPI_cnt++;
39
    if(SPI_cnt>0x0F)SPI_cnt=0;
40
41
}//SPI_TR_Done()
42
43
44
char spi_read_write(char data)
45
{
46
  char dataReturn;
47
  dataReturn=SSPBUF;
48
  SSPBUF = data;
49
  return(dataReturn);
50
}//spi_write(char data)  
51
52
void main(void)
53
{
54
unsigned char i=0;
55
unsigned int j=0;
56
int Error = 0;
57
58
  ADCON1=0x0F;
59
  TRISA=0x0F;
60
  PORTC=0x00;
61
  TRISC = 0x06;
62
  INTCONbits.GIE=0;    //disable GLOBAL Interruts
63
  RCONbits.IPEN=1;    //set Priority scan
64
65
  M_DRIVER_Init();    //init dopple H-Bridge
66
  STATLEDDIR = 0;      //init Stauts LED
67
  STATLED = i;      //unleash LED
68
69
//SPI CONFIG
70
DDRBbits.RB0=1;//SDI=Input
71
DDRBbits.RB1=1;//SCK=Input
72
DDRCbits.RC7=0;//SDO=Output
73
DDRAbits.RA5=1;//SS=Input
74
75
//Open SPI
76
OpenSPI(SLV_SSON, MODE_10, SMPMID);
77
//End Open SPI
78
79
STATLED=1;
80
//Test for Serial Data Transport
81
j=0;
82
while(1)
83
{
84
if(j!=0xFF)
85
{
86
STATLED=STATLED^1;
87
Delay10KTCYx(10);
88
}
89
if(SSPSTATbits.BF==1)
90
{
91
j=spi_read_write(SPI_cnt);
92
SSPCON1bits.SSPOV=0;
93
Delay10KTCYx(100);
94
}
95
}
96
}

Wäre super, wenn sich mal jemand die Mühe macht über den Quellcode 
drüber zu lesen. Ich kann mir jetzt nicht erklären, warum die beiden 
Prozessoren nicht wollen. OSC_Master=20MHz, OSC_Slave=12MHz. Für jede 
Art von Anregung bin ich dankbar.

Gruß Fitz

von Jens M. (Gast)


Lesenswert?

FitzDaKat schrieb:
> Pull-Up oder Pull-Down Widerstände verwende ich bislang keine.Könnte das
> eine Fehlerquelle sein?

Nein, SPI verwendet keine. Es ist aber immer schwierig mit zwei 
unbekannten Controllern und einem Bus dazwischen zu debugggen.

Schlage daher vor SDI und SDO am Master brücken. Dann kannst du sehen ob 
das was evtl. rausgeht auch wieder reinkommt.

Wenn du irgendein Messgerät hast um Busaktivitäten zu sehen ist das sehr 
hilfreich. Ein Logiktester reicht da oft.

von FitzDaKat (Gast)


Lesenswert?

Werde deinem Tipp später mal nachgehen. Zum messen habe ich nur ein 
Nordmende Oszi BJ1933 oder so^^

Deshalb muss da mit einem Jain antworten...

von Jens M. (Gast)


Lesenswert?

FitzDaKat schrieb:
> Nordmende Oszi BJ1933 oder so^^

Baujahr 1933? ;-) Reicht aber völlig aus, musst nur Takt und Daten 
anschauen. Wenn das Oszi zu langsam ist setzt du halt den INTosc auf 
500kHz oder kleiner.

von Holger W. (holgerw)


Lesenswert?

Ich würde den Master zuerst programmieren, als Slave einen bekannten 
Baustein, z.b. EEprom. Wenn das sicher läuft dann durch den den Slave 
ersetzen, ansonsten hast du immer 2 Baustellen.

Holger

von FitzDaKat (Gast)


Lesenswert?

Hallo Jens Martin, hallo Holger!


zunächst danke für die Hinweise. Es wahr wohl auch etwas 
größenwahnsinnig gleich beide Devices zu programmieren.

@Jens Martin ich bin deinem Hinweis mal auf die Spur gegangen. Es 
scheint als würde der Master seinen Job machen. Was er sendet, bekommt 
er auch wieder rein, wenn ich SDO und SDI kurz schließe.


Ich werde mich die nächsten Tage dann mal mit dem Slave genauer 
beschäftigen. Es ist dann mit an Sicherheit grenzender 
Wahrscheinlichkeit davon aus zu gehen, dass das Ding nen knacks hat ;)

Danke soweit, ich halte euch auf dem Laufenden.
Schönen Abend :)

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.