Forum: Mikrocontroller und Digitale Elektronik SPI Problemchen


von afo (Gast)


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!

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.