Forum: Compiler & IDEs AVR ATMEGA32 - SPI in GCC - CODEPROBLEM, erbitte Hilfe


von Daniel B. (dont_care)


Lesenswert?

Hallo und schönen Sonntag allerseits,

ich versuche eine SPI Kommunikation zwischen einem Atmel ATMEGA32L (als 
Master) und einem bzw später mehreren Slaves zu implementieren.


Leider tat sich lt. Oszilloskop nicht das was ich mir erhofft habe. Habe 
ich etwas vergessen, übersehen oder falschgemacht?


Anbei mein C - Code mit der Bitte um Hilfe, Anregung und 
Lösungsvorschläge.


1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdbool.h>
4
#include <avr/interrupt.h>
5
6
// Prototypen
7
8
void SPI_MasterInit(void);
9
void SPI_MasterTransmit( int cData);
10
unsigned char SPI_MasterReceive(void);
11
12
13
14
15
int main(void)
16
{
17
    // Interrupts erlauben
18
    sei();
19
    //TestPin wechselt Zustand bei erfolgreichem Funktionsdurchlauf
20
    DDRD |= (1<<DDD7);
21
    
22
    unsigned char test= 0x54;
23
    unsigned char back;
24
    unsigned char end = false;
25
   
26
    while(end!=true)
27
    {
28
        SPI_MasterTransmit(test);
29
        back = SPI_MasterReceive();
30
     
31
    }
32
    
33
    
34
    return 0;               /* never reached */
35
}
36
37
38
39
void SPI_MasterInit(void)
40
41
{
42
43
    /* Set MOSI and SCK output, all others input */
44
    DDRB |= (1<<DDB5)|(1<<DDB7);
45
    // SET MISO als Eingang
46
    //DDRB &= ~(1<<DDB6);
47
    // MOSI, MISO und Takt auf LOW
48
    //PORTB &= ~((1<<PB5)|(1<<PB6)|(1<<PB7));
49
    // slave select als Ausgang
50
    DDRD |= (1<<DDD4);
51
    // SS auf High
52
    PORTD |= (1<<PD4);
53
    
54
    /* SPI Kontrollregister */
55
    
56
    // SPI Interrupt enable , SPI aktivieren, Mastermode
57
    SPCR |= ((1<<SPE)|(1<<MSTR));
58
    
59
   //Taktbasis low, steigende flanke MO, fallende flanke MI, SPI Takt = /4 -> 1 MHz / 4 = 250 KHZ = 250.000 Hz
60
    //SPCR &= ~((1<<SPIE)|(1<<CPOL)|(1<<CPHA)|(1<<SPR0)|(1<<SPR1));
61
   
62
    /*SPI  Status Register*/
63
    
64
    //Kontrollflag setzen
65
    
66
    PORTD |= (1 <<PD7);
67
    
68
}
69
70
void SPI_MasterTransmit( int cData)
71
72
{
73
    //testflag löschen
74
    PORTD &= ~(1<<PD7);
75
76
    //Slaveselect auf Masse
77
    PORTD &= ~(1<<PD4);
78
    
79
    
80
    /* Start transmission */
81
    SPDR = cData;
82
    /* Wait for transmission complete */
83
    while(!(SPSR & (1<<SPIF)));
84
    
85
    PORTD |= (1<<PD4);
86
    
87
    //testflag setzen
88
    PORTD |= (1 <<PD7);
89
    
90
    
91
    
92
    
93
}
94
95
  unsigned char SPI_MasterReceive(void)
96
{
97
    //testflag löschen
98
    PORTD &= ~(1<<PD7);
99
    
100
    _delay_ms(10);
101
    //testflag setzen
102
    PORTD |= (1 <<PD7);
103
    //
104
    return SPDR;
105
    
106
    
107
}

1
Fuse high byte:
2
# 0xB9 = 1 0 1 1   1 0 0 1
3
Fuse low byte:
4
# 0x81 = 1 0 0 0   0 0 0 1

von Martin (Gast)


Lesenswert?

Der Slave Select ist doch PB4 und nicht PD4 oder?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdbool.h>
4
#include <avr/interrupt.h>
5
6
// Prototypen
7
8
void SPI_MasterInit(void);
9
uint8_t SPI_MasterTransmit(uint8_t cData);
10
11
12
int main(void)
13
{    
14
    uint8_t test= 0x54;
15
    uint8_t back;
16
    unsigned char end = false;
17
   
18
    while(end!=true)
19
    {
20
        back = SPI_MasterTransmit(test);   
21
    }
22
    
23
    
24
    return 0;               /* never reached */
25
}
26
27
28
29
void SPI_MasterInit(void)
30
{
31
    // SS auf High
32
    PORTD |= (1<<PB4);
33
34
    /* Set MOSI and SCK output, all others input */
35
    DDRB |= (1<<DDB4)|(1<<DDB5)|(1<<DDB7);
36
    
37
    // SPI Interrupt enable , SPI aktivieren, Mastermode
38
    SPCR |= ((1<<SPE)|(1<<MSTR)); 
39
}
40
41
uint8_t SPI_MasterTransmit(uint8_t cData)
42
{
43
    //Slaveselect auf Masse
44
    PORTB &= ~(1<<PB4);
45
    
46
    
47
    /* Start transmission */
48
    SPDR = cData;
49
    /* Wait for transmission complete */
50
    while(!(SPSR & (1<<SPIF)));
51
    
52
    PORTB |= (1<<PB4);
53
    
54
    return SPDR;
55
}

von Martin (Gast)


Lesenswert?

OOh da hatte sich noch ein Fehler eingeschlichen
1
void SPI_MasterInit(void)
2
{
3
    // SS auf High
4
    PORTB |= (1<<PB4);
5
6
    /* Set MOSI and SCK output, all others input */
7
    DDRB |= (1<<DDB4)|(1<<DDB5)|(1<<DDB7);
8
    
9
    // SPI Interrupt enable , SPI aktivieren, Mastermode
10
    SPCR |= ((1<<SPE)|(1<<MSTR)); 
11
}

von Nil (nilsnilss)


Lesenswert?

Du solltest deine Init Methode schon aufrufen.

von Daniel B. (dont_care)


Lesenswert?

Hallo und vielen Dank. Es funktioniert jetzt so wie es soll!

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.