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!