SPI Problemchen

Gast #3259010
Lesenswert?

Hallo Leute,
Ich möchte ein Byte via SPI versenden...
SPI - Schieberegiste - grobe Einstellungen habe ich verstanden.

Jetzt ist das Problem, dass auf dem SPI-Dataregister einfach kein Wert 
hingeschrieben wird.

Controller: MC9S08AW60 (freescale)

SPIdriver.h
1
#ifndef _SPIDRIVER_H_
2
#define  _SPIDRIVER_H_
3

4
typedef int bool;
5
  /*!< Definition for boolean type. */
6
#ifdef __MISRA__ /* MISRA rule #18 */
7
  #define true  1u
8
    /*!< Definitioni for TRUE. */
9
  #define false 0u
10
    /*!< Definition for FALSE. */
11
#else
12
  #define true  1
13
    /*!< Definitioni for TRUE. */
14
  #define false 0
15
    /*!< Definition for FALSE. */
16
#endif
17

18
// Includes ----------------------------------------------------------------------------------------
19
#include <hidef.h> /* for EnableInterrupts macro */
20
#include "derivative.h" /* include peripheral declarations */
21

22
#define uint8 unsigned char
23

24
// SPI Clock Sample Polarity
25
typedef enum CLOCKPOL
26
{
27
  RisingEdge  = 0,
28
  FallingEdge = 1
29

30
} e_clockpol_t;
31

32
// SPI Clock Sample Phase
33
typedef enum CLOCKPHS
34
{
35
  LeadingEdge  = 0,
36
  TrailingEdge = 1
37

38
} e_clockphs_t;
39

40
// SPI Clock Prescaler (Master only)
41
typedef enum CLOCKPRSC
42
{
43
  
44
  div1  =  0x000b,
45
  div2  =  0x001b,
46
  div3  =  0x010b,
47
  div4  =  0x011b,
48
  div5  =  0x100b,
49
  div6  =  0x101b,
50
  div7  =  0x110b,
51
  div8  =  0x111b
52
} e_clockprsc_t;
53

54
//SPI Clock Rate Divisor (Master only)
55
typedef enum CLOCKRD 
56
{
57
  
58
  rdiv2    =  0x000b,
59
  rdiv4    =  0x001b,
60
  rdiv8    =  0x010b,
61
  rdiv16  =  0x011b,
62
  rdiv32  =  0x100b,
63
  rdiv64  =  0x101b,
64
  rdiv128  =  0x110b,
65
  rdiv256  =  0x111b
66
  
67
} e_clockrd_t;
68
 
69

70
// SPI Data Order
71
typedef enum DATAORDER
72
{
73
  MSBfirst  = 0,
74
  LSBfirst = 1
75

76
} e_dataorder_t;
77

78
typedef enum SPIMODE
79
{
80
  Slave = 0,
81
  Master = 1
82
} spi_Mode_t;
83

84

85
 /**************************************************************************************************/
86
__interrupt VectorNumber_Vspi1 void SPI_ISR();
87

88
/****************************************************************************************************
89
 * Initialisierung des SPI Interfaces mit Standard-Einstellungen (Slave)
90
 **************************************************************************************************/
91
extern void spi_init();
92

93
/***************************************************************************************************
94
 * Aktivierung des SPI Interrupts
95
 *
96
 * Wird der SPI Interrupt freigeschalten, muss sichergestellt sein, dass die Interrupt Service
97
 * Routine (SPI_STC_vect) auch gefuellt ist. Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
98
 *
99
 * b_Option  SPI Serial Transfer Complete Interrupt aktivieren/deaktivieren
100
 ***************************************************************************************************/
101
void spi_enableInterrupt(bool b_Option);
102

103
/***********************************************************************************************//**
104
 * SPI Einstellungen vornehmen
105
 *
106
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
107
 *
108
 * e_Mode        SPI in als Slave oder Master betreiben
109
 * e_ClockPolarity    SPI Clock Polaritiy festlegen (Standard RisingEdge)
110
 * e_ClockPhase    SPI Clock Phase festlegen (Standard LeadingEdge)
111
 * e_ClockPrescaler  SPI Clock Prescaler festlegen (Standard div4)
112
 * e_DataOrder      SPI Bit-Folge (Standard LDBfirst)
113
 **************************************************************************************************/
114
void spi_setMode(spi_Mode_t e_Mode, e_clockpol_t e_ClockPolarity, e_clockphs_t e_ClockPhase, e_clockprsc_t e_ClockPrescaler,e_clockrd_t e_ClockRateDivisor, e_dataorder_t e_DataOrder);
115

116
/***********************************************************************************************//**
117
 * Daten ueber SPI versenden
118
 *
119
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
120
 * Es wird empfohlen, vorher mittels spi_checkComplete() den Status des SPI zu pruefen.
121
 *
122
 * c_Data  Byte welches ueber SPI gesendet werden soll
123
 **************************************************************************************************/
124
void spi_sendData(byte c_Data);
125

126
/***********************************************************************************************//**
127
 * Daten aus SPI receive buffer lesen
128
 *
129
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
130
 *
131
 * Byte welches zuletzt ueber SPI empfangen wurde
132
 **************************************************************************************************/
133
uint8 spi_receiveData();
134

135
/***********************************************************************************************//**
136
 * Setzt Slave-Select-Pin des SPI auf low oder zurueck auf high (/SS ist low active)
137
 * 
138
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
139
 *
140
 * Enable  Setzte Pin auf low (true) oder auf high (false)
141
 **************************************************************************************************/
142
void spi_selectChip(bool Enable);
143

144
/***********************************************************************************************//**
145
 * Ueberprueft ob ein SPI Transfer komplett ist
146
 *
147
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
148
 *
149
 * Gibt true zurueck, wenn ein Transfer stattgefunden hat
150
 **************************************************************************************************/
151
bool spi_checkComplete();
152

153
/***********************************************************************************************//**
154
 * Ueberprueft ob beim Schreiben von SPI Daten eine Kollision entstanden ist
155
 *
156
 * Erfordert, dass spi_init() zuvor einmalig gerufen wurde.
157
 *
158
 * Gibt true zurueck, wenn eine Kollision stattgefunden hat
159
 **************************************************************************************************/
160
bool spi_checkCollision();
161

162

163
#endif        // _SPIDRIVER_H_
SPIdriver.c
1
// Includes ----------------------------------------------------------------------------------------
2
#include  "SPIDriver.h"
3
typedef int bool;
4
  /*!< Definition for boolean type. */
5
#ifdef __MISRA__ /* MISRA rule #18 */
6
  #define true  1u
7
    /*!< Definitioni for TRUE. */
8
  #define false 0u
9
    /*!< Definition for FALSE. */
10
#else
11
  #define true  1
12
    /*!< Definitioni for TRUE. */
13
  #define false 0
14
    /*!< Definition for FALSE. */
15
#endif
16
#include <hidef.h> /* for EnableInterrupts macro */
17
#include "derivative.h" /* include peripheral declarations */
18

19

20
// Makros ------------------------------------------------------------------------------------------
21
#define uint8 unsigned char
22
#define SPI_SS PTED_PTED4_MASK
23
#define SPI_MOSI PTED_PTED6_MASK
24
#define SPI_MISO PTED_PTED5_MASK
25
#define SPI_SCK PTED_PTED7_MASK
26
#define SPI_DDR PTEDD
27
#define SPI_PORT PTED
28

29

30
// Prototypen --------------------------------------------------------------------------------------
31
/***********************************************************************************************//**
32
 * Reinitialisiert die GPIO Belegung fuer den SPI (wird bereits durch Init gerufen)
33
 *
34
 * e_Mode        SPI in als Slave oder Master betreiben
35
 **************************************************************************************************/
36
void spi_initPorts(spi_Mode_t e_Mode);
37

38
// Funktionen --------------------------------------------------------------------------------------
39
void spi_init()
40
{
41
  // PortE konfigurieren
42
  spi_initPorts(Master);
43
  // Reset des SPI Control Registers
44
  SPI1C1 = 0x00;
45
  // Aktivieren des SPI
46
  SPI1C1 |= SPI1C1_SPE_MASK;
47
}
48

49
void spi_initPorts(spi_Mode_t e_Mode)
50
{
51
  if(e_Mode == Master)
52
  {
53
    // Master
54
    // GPIO Ausgabe fuer SPI Master konfigurieren (SS Pullup)
55
    SPI_PORT = SPI_PORT|(SPI_SS)&~(SPI_MOSI)&~(SPI_MISO)&~(SPI_SCK);
56
    // GPIO Pins fuer SPI Master konfigurieren (MISO Input)
57
    SPI_DDR = SPI_DDR|(SPI_SS)|(SPI_MOSI)&~(SPI_MISO)|(SPI_SCK);
58
  }
59
/*  else
60
  {
61
    // Slave
62
    // GPIO Ausgabe fuer SPI Slave konfigurieren (SS Pullup)
63
    SPI_PORT = SPI_PORT|(1<<SPI_SS)&~(1<<SPI_MOSI)&~(1<<SPI_MISO)&~(1<<SPI_SCK);
64
    // GPIO Pins fuer SPI Slave konfigurieren (MISO Output)
65
    SPI_DDR = SPI_DDR&~(1<<SPI_SS)&~(1<<SPI_MOSI)|(1<<SPI_MISO)&~(1<<SPI_SCK);
66
  }
67
  */
68
}
69

70
void spi_enableInterrupt(bool b_Option)
71
{
72
  if(b_Option == true)
73
  {
74
    // SPI Interrupt einschalten
75
    SPI1C1 = SPI1C1|(SPI1C1_SPIE_MASK);
76

77
    // Interrupts freigeben
78
    EnableInterrupts;
79
  }
80
  else
81
  {
82
    // SPI Interrupt abschalten
83
    SPI1C1 = SPI1C1&~(SPI1C1_SPIE_MASK);
84
  }
85
}
86

87
void spi_setMode(spi_Mode_t e_Mode, e_clockpol_t e_ClockPolarity, e_clockphs_t e_ClockPhase, e_clockprsc_t e_ClockPrescaler,e_clockrd_t e_ClockRateDivisor, e_dataorder_t e_DataOrder)
88
{
89
  // GPIO Ports neu konfigurieren
90
  spi_initPorts(e_Mode);
91

92
//  SPI1BR_SPPR = e_ClockPrescaler;
93
//  SPI1BR_SPR = e_ClockRateDivisor;
94
  
95
  
96
  // SPI Control Register teilweise loeschen und neu schreiben
97
//  SPI1C1 = SPI1C1&~(SPI1C1_SPE_MASK)&~(SPI1C1_LSBFE_MASK)&~(SPI1C1_MSTR_MASK)&~(SPI1C1_CPOL_MASK)&~(SPI1C1_CPHA_MASK);
98
//  SPI1C1 = SPI1C1|(SPI1C1_SPE_MASK)|(e_DataOrder<<SPI1C1_LSBFE_MASK)|(e_Mode<<SPI1C1_MSTR_MASK)|(e_ClockPolarity<<SPI1C1_CPOL_MASK)|(e_ClockPhase<<SPI1C1_CPHA_MASK);
99
    SPI1C1 = SPI1C1|(SPI1C1_SPE_MASK)| (SPI1C1_MSTR_MASK);
100
    SPI1BR = 0x04;
101

102
  // Dummy Daten senden um SPI1S_SPTEF zurueck zu setzen (moeglicher AVR Bug, Flag sollte hier 0 sein)
103
  spi_sendData(0x00);
104
}
105

106
void spi_sendData(byte c_Data)
107
{
108
  
109
  SPI1D = 0x001010b;
110
}
111

112
uint8 spi_receiveData()
113
{
114
  return SPI1D;
115
}
116

117
void spi_selectChip(bool Enable)
118
{
119
  if(Enable == true)
120
  {
121
    SPI_PORT = SPI_PORT&~(1<<SPI_SS);
122
  }
123
  else
124
  {
125
    SPI_PORT = SPI_PORT|(1<<SPI_SS);
126
  }
127
} //Mehrere Slaves vorhanden => muss noch verändert werden
128

129
bool spi_checkComplete()
130
{
131
  uint8 Temp;
132

133
  if((SPI1S&(SPI1S_SPTEF_MASK)) == 0)
134
  {
135
    return false;
136
  }
137
  else
138
  {
139
    // SPI Data Buffer lesen um Interrupt Bit zu leeren
140
    Temp = SPI1D;
141
    return true;
142
  }
143
}
144

145
bool spi_checkCollision()
146
{
147
  uint8 Temp;
148

149
  if((SPI1S&(SPI1S_SPRF_MASK)) == 0)
150
  {
151
    return false;
152
  }
153
  else
154
  {
155
    // SPI Data Buffer lesen um Interrupt Bit zu leeren
156
    Temp = SPI1D;
157
    return true;
158
  }
159
}

main.c
1
#include <hidef.h> /* for EnableInterrupts macro */
2
#include "derivative.h" /* include peripheral declarations */
3
#include "MCUInit.h"     //Interrupts, IO-Ausgänge, SPI
4
#include "IOVerarbeitung.h"   //BCD-Schalter, DIL-Schalter, LEDS, SPI
5
#include "SPIDriver.h"
6

7
#define uint8 unsigned char
8

9
uint8 key_state_bcd;  // debounced and inverted key state:
10
          
11
uint8 key_press_bcd;  // bit = 1: key pressed
12

13
uint8 key_state_dil;  // debounced and inverted key state:
14
          
15
uint8 key_press_dil;  // bit = 1: key pressed
16

17
volatile bool status_bcd;
18
volatile bool status_dil;
19
volatile uint8 ISR_counter;
20

21

22

23
void main(void)
24
{
25
  PeriphInit();
26
  spi_init();
27
  spi_setMode(Master, RisingEdge, LeadingEdge, div2, rdiv8, LSBfirst);
28
  spi_enableInterrupt(true);
29
  for(;;) 
30
  {
31
    __RESET_WATCHDOG();
32
    
33
      if(status_bcd == true) {
34
      status_bcd = 0;
35
      PTAD_PTAD0 = 1;
36
      PTAD_PTAD1 = 0;
37
      spi_sendData(0x00111000b);
38
      } else{
39
      PTAD_PTAD1 = 1;
40
      PTAD_PTAD0 = 1;
41
      //Der BCD-Schalter wurde nicht verändert 
42
      }
43
      
44
      if(status_dil == true) {
45
      status_bcd = 0;
46
      PTAD_PTAD0 = 1;
47
      PTAD_PTAD1 = 0;
48
      } else{
49
      PTAD_PTAD1 = 1;
50
      PTAD_PTAD0 = 1;
51
      //Der DIL-Schalter wurde nicht verändert 
52
      }  
53
   }
54
}
55
 
56
 __interrupt VectorNumber_Vrti void Timer_ISR() {
57
 
58
   static uint8 ct0, ct1, ct2, ct3;
59
   uint8 i,j;
60
 
61
   SRTISC_RTIACK= 1;   
62
   
63
   
64
    
65
   ISR_counter++;
66
    if(ISR_counter == 4) {
67
       ISR_counter = 0;
68
    
69
       i = key_state_bcd ^ ~KEY_PIN_bcd;               // key changed ?
70
       ct0 = ~( ct0 & i );                             // reset or count ct0
71
       ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
72
       i &= ct0 & ct1;                                 // count until roll over ?
73
       key_state_bcd ^= i;                             // then toggle debounced state
74
       key_press_bcd |= key_state_bcd & i; 
75
   
76
   
77
       status_bcd = BCD_Verarbeiten(BCD_Auslesen());
78
      //Jetzt kann der Status des BCD Schalters abgefragt werden
79
      
80
       j = key_state_dil ^ ~KEY_PIN_dil;                       // key changed ?
81
       ct2 = ~( ct2 & j );                             // reset or count ct0
82
       ct3 = ct2 ^ (ct3 & j);                          // reset or count ct1
83
       j &= ct2 & ct3;                                 // count until roll over ?
84
       key_state_dil ^= j;                                 // then toggle debounced state
85
       key_press_dil |= key_state_dil & j; 
86
      
87
       status_dil = DIL_Verarbeiten(DIL_Auslesen());
88
       
89
       //Jetzt kann der Status des DIL Schalters abgefragt werden
90
   
91
    } 
92
   
93
}
94

95
__interrupt VectorNumber_Vspi1 void SPI_ISR(){
96
 
97
}

Ich simuliere es mit einem Simulator.
Ich weiß es ist so noch nicht alles richtig.
SS-Leitung passt noch nicht.
Im Simulator wird SPI1D einfach nicht verändert. Bleibt immer auf 0 und 
dadurch kann es nicht funktionieren. c-Data bleibt komischerweise immer 
auf 25...

Vielleicht habt ihr eine Idee!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren