Atmega SPI will nicht

OP #2372486
Lesenswert?

Hallo

Ich probiere mich gerade an der SPI Schnittstelle auf einem Atmega 2560 
für mein Projekt. Habe einen Quellcode vom Lehrer erhalten doch leider 
will die SPI Schnittstelle nicht so wie wir.

Vieleicht kann ja jemand einmal über den Code schauen.
1
/**************************************************************
2
Es soll alle halbe Sekunde im Wechsel 0 bzw. 1 gesendet werden.
3
Am korrespondierenden Slave soll zur Indikation jeweils die 
4
LEDs an bzw. aus gehen
5
Verdrahtung:  MISO(Master) --> MISO(Slave)
6
        MOSI(Master) --> MOSI(Slave)
7
        SCK(Master)  --> SCK(Slave)
8
        PB0(Master)   --> SS(Slave)
9
**************************************************************/
10

11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <avr/signal.h>
14

15
unsigned char status = 0;
16
volatile unsigned char count;
17

18
void timer1 (void);
19
void master_init (void);
20
void master_transmit (unsigned char data);
21

22
SIGNAL (SIG_SPI) {
23
  return;
24
}
25

26
SIGNAL (SIG_OVERFLOW1) {            //Senderoutine
27
  if (count == 1) {
28
    master_transmit ('1');
29
    count--;
30
    PORTL   = 0xFF;    
31
    return;
32
  }
33
  if (count == 0) {
34
    master_transmit ('0');
35
    PORTL   = 0x00;    
36
    count++;
37
  }
38
}
39

40
void timer1 (void) {
41
  TIMSK1 |= (1<<TOIE1);                   //Timer Overflow Interrupt enable
42
  TCNT1 = 0;                          //Rücksetzen des Timers
43
  TCCR1B = (1<<CS10) | (1<<CS11);      //8MHz/65536/64 = 1,91Hz --> 0,5s
44
}
45

46
void master_init (void) {
47
  DDRB = (1<<PB1) | (1<<PB2) | (1<<PB0);    // setze SCK,MOSI,PB0 (SS) als Ausgang
48
  PORTB = (1<<PB1) | (1<<PB0);        // SCK und PB0 high (ist mit SS am Slave verbunden)
49
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);  //Aktivierung des SPI, Master, Taktrate fck/16
50
  status = SPSR;                //Status löschen
51
}
52

53
void master_transmit (unsigned char data) {
54
  PORTB &= ~(1<<PB0);            //SS am Slave Low --> Beginn der Übertragung
55
  SPDR = data;                //Schreiben der Daten
56
  while (!(SPSR & (1<<SPIF)));
57
  PORTB |= (1<<PB0);              //SS High --> Ende der Übertragung
58
}
59

60
int main (void) {
61
  DDRL   = 0xFF;    
62
  master_init ();
63
  timer1 ();
64
  sei ();
65

66
  for (;;);
67
  return 0;
68
}
#2372538
Lesenswert?

Ev. Triggerproblem?
SCK ist nur aktiv, wenn Daten gesendet werden.

Wofür ist das?
1
status = SPSR;                //Status löschen

Also bei mir läuft dies auf einem ATmega32 mit 4MHz:
1
void SPI_MasterInit(void){
2
  /* Set MOSI and SCK output, all others input */
3
  DDR_SPI = (1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_SS);
4
  /* Enable SPI, Master, set clock rate fck/2 */
5
  SPCR = (1 << SPE) | (1 << MSTR);
6
  SPSR = (1 << SPI2X);
7
}
8

9
void SPI_MasterTransmit(char cData){
10
  /* Start transmission */
11
  SPDR = cData;
12
  /* Wait for transmission complete */
13
  while(!(SPSR & (1 << SPIF)));
14
}

Triggere mal auf SS (oder bleibt dieser immer auf High?).

Martin schrieb:
> Muss MISO nicht auf MOSI gehen? (Serial Input/ Serial Output)

Nö, passt schon. Master Out auf Master Out beim Slave. Die können gerade 
verbunden werden. Der Slave muss dann natürlich auf Slave eingestellt 
sein.
OP #2374698
Lesenswert?

Es war irgendein komisches Problem mit dem AVR Studio 5. Habe zum Test 
nochmal Studio 4 installiert und siehe da SPI klappt.
Danach habe ich nochmal Version 5 installiert und auch da klappt nun 
SPI.

Ich kann ja max 255 verschiedene Werte übertragen. (8Bit) Würde jetzt 
gerne z.B. "PC4_1" für PortC LED1 On usw übertragen. Später muss ich 
über SPI die PWM des anderen Atmega steuern können.

Hast du zufällig ein Beispiel wie man das anstellt.

MFG Christoph
Gast #2378711
Lesenswert?

Denk dir nen Protokol aus z.B. :

1. Byte Adresse des Empfängers
2. Byte Befehl
3. Byte Länge der Daten bzw. Parameter
4. n Byte Daten
5. Checksum

Und zerlege alle Variablen in 8Bit und bau Sie danach wieder Zusammen.
OP #2386153
Lesenswert?

Hallo

Habe es jetzt hinbekommen das ich mehrer Bytes über SPI sende. ( 
verwende ein Array)

Das Problem ist das nicht genau weiß wie der Slave das auswertet.
Leider stimmt die Auswertung noch nicht.

Anbei auch ein Beispiel wie die Sende Daten ausschauen.

Quellcode.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/signal.h>
4

5
volatile unsigned char data;
6
unsigned char status;
7
unsigned char data_IN[10];
8
unsigned int ADC_16;
9
i=0;
10

11
SIGNAL (SIG_SPI) {
12
  data_IN[i] = SPDR;
13
  i++;
14
  if (i=10)
15
  {
16
    ADC_16=data_IN[2]*256+data_IN[1];
17
    i=0;
18
  }
19
  
20
  
21
  if (ADC_16 == 'O','N')  PORTC = 0xFF;      //LEDs an
22
  if (ADC_16 == 'O','F')  PORTC = 0x00;      //LEDs aus
23
  
24
  if (ADC_16 == 'ON')  PORTC = 0xFF;      //LEDs an
25
  if (ADC_16 == 'OF')  PORTC = 0x00;      //LEDs aus
26
}
27

28

29

30
void slave_init (void) {
31
  DDRB |= _BV(PB6);              //MISO als Ausgang, der Rest als Eingang
32
  SPCR = _BV(SPE) | _BV(SPIE);        //Aktivierung des SPI + Interrupt
33
  status = SPSR;                //Status löschen
34
}
35

36
int main (void) {
37

38
  DDRC = 0xff;
39
  slave_init ();
40
  sei ();
41
  for (;;);
42
  
43
}

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