Forum: Mikrocontroller und Digitale Elektronik Frage zu SPI und SCKL


von Sneim (Gast)


Lesenswert?

Hallo,

ich habe das SPI am Atmega32 wie nach Datenblatt beschrieben in Betrieb 
genommen. Leider antwortet der Slave nicht und der Controller steckt in 
der while Schleife fest, die Schaltung dürfte aber stimmen. Jetzt bin 
ich dazu übergegangen mir die Signale mit dem Oszi anzuschauen.

Leider sieht man außer dem korrekten Verhalten con Chip Select nichts. 
Der Code für das Spi ist aus dem Datenblatt des Atmega:
1
uint8_t SPI_transmit(uint8_t data)
2
{
3
4
  PORTB &= ~(1<<PB2); //Select CS5643
5
6
  // Start transmission
7
  SPDR = data; 
8
9
  // Wait for transmission complete
10
  while(!(SPSR & (1<<SPIF)));
11
12
  data = SPDR;
13
14
  PORTB |= (1<<PB2);
15
16
  return(data);
17
18
}

Meine Frage daher, wenn ich das Datum in SPDR schreibe, müsste ich dann 
nich zumindest den SCKL auf der Leitung sehen? Ich meine völlig 
unabhängig davon ob der Slave antworten wird oder nicht? Es macht mich 
stutzig das garnichts passiert.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Wie sieht denn die Initialisierung aus?

von Sneim (Gast)


Lesenswert?

So:
1
void init_SPI(void)
2
{
3
4
  DDRB |= (1<<PB5);     // MOSI als Ausgang
5
  DDRB |= (1<<PB4);    //SS Pin als Output                       
6
  DDRB |= (1<<PB7);   // SCK als Ausgang
7
  DDRB &= ~(1<<PB6); //MISO als Eingang
8
9
  SPCR |= (1<<MSTR);   //µC als Master
10
  SPCR |= (1<<SPE);   //Spi aktivieren
11
  SPCR |= (1<<SPR1); //Takt = 250kHz
12
13
}

Hinzu kommt eine initialisierung der restlichen I/O Ports für Taster und 
LCD. Davon hängt aber nichts an PORTB, der ist allein für die SPI 
Kommunikation reserviert

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Spontan fällt mir der Standardfehler ein: SS wird irgendwo als Eingang 
deklariert und schaltet dann das Modul auf Slave. Vielleicht fehlt 
irgendwo eine Veroderung beim Setzten von DDRB.

Grüße,

Peter

von Sneim (Gast)


Lesenswert?

Danke für die Antwort.

Mein Programm ist schon relativ groß geworden, da es eine komplette 
Menüführung enthält und auch eine SD Karte ansteuert. Hierzu habe ich 
aber eine fertige Bibliothek verwendet. Der andere IC ist ein Metering 
IC, CS5463 und ebenfalls Slave am SPI. Die SD Karte funktioniert 
wunderbar, zum Testen des CS5463 habe ich sie aber komplett vom SPI-Bus 
abgetrennt.

Ich schreibe gerade ein neues Testprogramm um Programmierfehler 
auszuschließen.

Du sagst wenn ich garantiere das SS immer als Output geschaltet wurde, 
dann garantiere ich auch das der µC Master bleibt? Ich muss ihn aber 
nicht noch auf High oder Low setzen?

Zeigt der Master dann das Verhalten, dass beim schreiben in SDR auf 
jeden Fall das Clock Signal gesendet wird?

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>Du sagst wenn ich garantiere das SS immer als Output geschaltet wurde,
>dann garantiere ich auch das der µC Master bleibt? Ich muss ihn aber
>nicht noch auf High oder Low setzen?
Richtig.

>Zeigt der Master dann das Verhalten, dass beim schreiben in SDR auf
                                                             ^^SPDR
>jeden Fall das Clock Signal gesendet wird?
Wenn er Master ist, ja.

Grüße,

Peter

von Sneim (Gast)


Lesenswert?

Sorry, hab mich verschrieben. Im Code stimmt es schon ;)

Danke für deine Hilfe, dann kann ich mal schaun ob ich ihm das richtige 
Verhalten abverlangen kann :)

von Sneim (Gast)


Lesenswert?

Es kommt etwas zurück und der uC steckt nicht mehr in der Schleife fest 
;)

Der Code dürfte so passen?
1
/*
2
 * main.c
3
 *
4
 *  Created on: 23.08.2011
5
 *      Author: weinmann
6
 */
7
       //Wird benötigt für sprintf() Funktion
8
#include <avr/io.h>        //Standard AVR I/O Library (enthält Makrodefinitionen)
9
#include "lcd_routines.h"      //Header Datei der LCD Routinen einbinden
10
#include <util/delay.h>
11
#include <stdio.h>
12
13
void init_uC(void)
14
{
15
  DDRA = 0x3F;   //Setze PA0 bis PA5 als Ausgang (LCD)
16
17
  DDRC |= 0x03;      //SCL und SDA als Ausgang konfigurieren! (TWI Interface)
18
19
  DDRD &= ~(1<<PD6);  //PD6 und PD7 als Eingang konfigurieren
20
  DDRD &= ~(1<<PD7); //(Writeprotection bzw. Carddetection)
21
22
  PORTD |= ((1<<PD6)|(1<<PD7)); //Interne Pull ups an PD6 und PD7 aktivieren!
23
  //////
24
25
  DDRB |= (1<<PB3);   //Tristate Adum aus
26
  PORTB |= (1<<PB3); // ""
27
28
  DDRB |= (1<<PB2); //CS5463 deselect
29
  PORTB |= (1<<PB2);
30
31
}
32
33
void init_SPI(void)
34
{
35
36
  DDRB |= (1<<PB5);    // MOSI als Ausgang
37
  DDRB |= (1<<PB4);    //SS Pin als Output konfigurieren um µC als Master zu garantieren
38
  DDRB |= (1<<PB7);   // SCK als Ausgang
39
  DDRB &= ~(1<<PB6); //MISO als Eingang
40
41
  SPCR |= (1<<MSTR);   //µC als Master
42
  SPCR |= (1<<SPE);   //Spi aktivieren
43
  SPCR |= (1<<SPR1); //Takt = 250kHz
44
45
}
46
47
uint8_t SPI_transmit(uint8_t data)
48
{
49
  PORTB &= ~(1<<PB2);
50
  _delay_ms(1);
51
  PORTB |= (1<<PB2);
52
  _delay_ms(1);
53
  PORTB &= ~(1<<PB2); //Select CS5643
54
  _delay_ms(1);
55
  // Start transmission
56
  SPDR = data;
57
58
  // Wait for transmission complete
59
  while(!(SPSR & (1<<SPIF)));
60
61
  data = SPDR;
62
63
  PORTB |= (1<<PB2);
64
65
  return(data);
66
67
}
68
69
int main(void)
70
{
71
  char rcv[4] = {0,0,0,0};
72
  char result_string[17];
73
74
  init_uC();
75
  lcd_init();
76
  init_SPI();
77
  uint8_t init = 1;
78
79
  lcd_setcursor(0,1);
80
  lcd_string("Test");
81
82
  while(1)
83
  {
84
    _delay_ms(1000);
85
86
    if(init)
87
    {
88
    rcv[0]=SPI_transmit(0xFF);
89
    rcv[1]=SPI_transmit(0xFF);
90
    rcv[2]=SPI_transmit(0xFF);
91
    rcv[3]=SPI_transmit(0xFE);
92
    sprintf(result_string,"Res:x%02Xx%02Xx%02Xx%02X",rcv[0],rcv[1],rcv[2],rcv[3]);
93
    lcd_setcursor(0,2);
94
    lcd_string(result_string);
95
    init=0;
96
    }
97
  }
98
99
}

Es wird nur einmal ein Übertragungsversuch gestartet, deswegen init als 
Hilfsvariable.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Sollte funktionieren.

  PORTB &= ~(1<<PB2);
  _delay_ms(1);
  PORTB |= (1<<PB2);
  _delay_ms(1);
  PORTB &= ~(1<<PB2); //Select CS5643
  _delay_ms(1);

Das ist nur ein Test, nehme ich an. Verzögerung braucht man normal keine 
zwischen CS und Senden.

Grüße,

Peter

von Sneim (Gast)


Lesenswert?

Ja, ist es ;)

Das Problem ist dass der CS5463 von der restlichen Schaltung 
potentialgetrennt ist. Daher muss ich das SPI vom uC mit einem Isolator 
an den IC koppeln. Hierzu habe ich einen ADUM1401 (reichelt) verwendet. 
Dessen "Geschwindigkeit" ist aber begrenzt, im Prinzip verzögert er das 
Signal etwas. D.h. wenn der Puls zu schnell ist kann es sein dass er 
nicht oder falsch erkannt wird.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Aber doch nicht 1 ms. Als propagation delay sind Zeiten von etwa 65 ns 
im Datenblatt angegeben. Das kann man vernachlässigen. Zudem werden ja 
alle Signale verzögert, wenn man sie ohne Verzögerung in der richtigen 
Abfolge losschickt, kommen sie auch richtig auf der anderen Seite an.

Grüße,

Peter

von Sneim (Gast)


Lesenswert?

Macht Sinn ;)

von Sneim (Gast)


Lesenswert?

So, nun habe ich ein neues Problem.

Das SPI hängt nun nicht mehr. Allerdings empfange ich immer nur 0xFF, 
selbst nach der im Datenblatt beschriebenen SPI synchronisierung.

Jemand noch eine Idee ? :(

von J.-u. G. (juwe)


Lesenswert?

Sneim schrieb:
> Jemand noch eine Idee ? :(

Was wird denn gesendet (Oszi an MISO)?

von Sneim (Gast)


Lesenswert?

Allein der Vollständigkeit wegen....


Ich habe alle Probleme gelöst. Da es nicht ganz unwahrscheinlich ist, 
dass jemand diesen IC (CS5463) zusammen mit dem ADUM1401-ARW verwenden 
wird möchte ich darauf hinweisen, dass es trotz Datenblatt notwendig ist 
die beiden Pins VE1/VE2 auf High zu halten wenn eine Übertragung 
gewünscht ist.

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.