SPI Geräte stören sich gegenseitig. ILI9341 regiert auf ENC28J60 Befehle. Was tun

OP #4800024
Lesenswert?

Hallo Community,

Ich habe zurzeit ein kleines Problem. Und zwar habe ich seit länger Zeit 
ein kleinen Webserver auf dem ATMega644 mit dem ENC28J60 laufen.
Der ENC28J60 wird über das SPI Interface angesteuert. Nun wollte ich 
mein Projekt gerne weiter ausbauen mit einen TFT Display, um Information 
über den Server dort anzuzeigen.

Das Display ist ein 240x320 2.2 Zoll QVGA SPI Display mit dem ILI9341 
Treiber.

Dieses Display habe ich dann auch mit dem SPI Bus verbunden anstatt denn 
SS Pin(Nutzt der ENC) habe ich ihm Pin 2 gegeben.

Wenn ich nun an das Display ein Text schreibe. Wird dieser Text auch 
nach dem Einschalten angezeigt. Jedoch wenn ich dann meinen Webserver im 
Internet aufrufe dann wird mir die Webseite, im Browser dargestellt, und 
zudem wird das TFT Display weiß.

Wenn ich aber nach dem Init des Display die CS Leitung vom TFT Display 
abziehe, und dann Webseite öffne bleibt der Text auf dem Display stehen. 
Also müssen sich die beiden Geräte gegenseitig stören, oder?

Da beide die SPI Kommunikation nutzten. Habe ich eine Klasse 
erstellt(SPI.c/h) um dort das SPI zu Initialisieren.

SPI.c:
1
#include "processor.h" //Enthält F_CPU und BAUD
2
#include "SPI.h" //Dort sind die Macros festlegt: SPI_CONTROL_DDR=DDRB; SPI_CONTROL_PORT=PORTB; MOSI=PORTB5; MISO=PORTB6; SCK=PORTB7; SS=PORTB4
3

4
void init_SPI_Interface(void) {
5
  SPI_CONTROL_DDR |= (1<<SPI_CONTROL_MOSI) | (1<<SPI_CONTROL_SCK) | (1<<SPI_CONTROL_SS); // MOSI, SCK, SS output
6
  SPI_CONTROL_DDR &= ~(1<<SPI_CONTROL_MISO); // MISO input
7

8
  SPI_CONTROL_PORT &= ~(1<<SPI_CONTROL_MOSI); // MOSI Low
9
  SPI_CONTROL_PORT &= ~(1<<SPI_CONTROL_SCK); // SCK Low
10
  SPI_CONTROL_PORT |= (1<<SPI_CONTROL_SS); //SS High
11

12
  SPCR = (1<<SPE) | (1<<MSTR);
13
  SPSR |= (1<<SPI2X);
14

15
}

Der ENC28J60 nutzt als CS Pin: Port B 4
Das TFT Display nutzt als CS Pin: Port B 2

Was könnte da das Problem sein. Denn nachdem senden des Textes wird die 
CS Leitung vom TFT Display wieder auf HIGH gelegt. Und dürfte somit 
nicht auf Daten die an denn ENC28J60 gesendet werden reagieren, oder?

Lg Jan.
OP #4800090
Lesenswert?

Lothar M. schrieb:
> Richtig,  dafür ist der Slaveselect da. Wird er tatsächlich auf high
> gelegt? Hast du das gemessen?

Messen wird denk ich schwer, da ich an der CS leitung ein 10K Pullup 
Widerstand habe.

So werden die Codes beim TFT gesendet:
1
void ili9341_writecommand8(uint8_t com)//command write
2
{
3
  controlport &=~((1<<dc)|(1<<cs));//dc and cs both low to send command
4
  _delay_us(5);//little delay
5
  ili9341_spi_send(com);
6
  controlport |=(1<<cs);//pull high cs
7
}
8

9

10
void ili9341_writedata8(uint8_t data)//data write
11
{
12
  controlport |=(1<<dc);//st dc high for data
13
  _delay_us(1);//delay
14
  controlport &=~(1<<cs);//set cs low for operation
15
  ili9341_spi_send(data);
16
  controlport |=(1<<cs);
17
}

Und beim ENC auch über all CSACTIVE; dann SPI und dann CSPASSIV;
1
// set CS to 0 = active
2
#define CSACTIVE ENC28J60_CONTROL_PORT&=~(1<<ENC28J60_CONTROL_CS)
3
// set CS to 1 = passive
4
#define CSPASSIVE ENC28J60_CONTROL_PORT|=(1<<ENC28J60_CONTROL_CS)

Der ENC hat auch ein 10K Pullup Widerstand an der CS leitung

Lg Jan.
Gast #4800095
Lesenswert?

Jan H. schrieb:
> Lothar M. schrieb:
>> Richtig,  dafür ist der Slaveselect da. Wird er tatsächlich auf high
>> gelegt? Hast du das gemessen?
>
> Messen wird denk ich schwer, da ich an der CS leitung ein 10K Pullup
> Widerstand habe.

Ja und? Pegel ist Pegel egal ob Pullup oder nicht. Den SPI Teilnehmer 
interessiert das nicht.

Was soll der Pullup überhaupt? Dein Ausgangspin für das CS ist jeweils 
eine Push Pull Stufe. Was soll der Pullup? Unnötig den CS Ausgangspin 
belasten? Oder hast du Angst, dass im Reset während der CS Ausgangspin 
floatend ist irgendwas passiert?
OP #4800146
Lesenswert?

GHD schrieb:
> Ja und? Pegel ist Pegel egal ob Pullup oder nicht. Den SPI Teilnehmer
> interessiert das nicht.
>
> Was soll der Pullup überhaupt? Dein Ausgangspin für das CS ist jeweils
> eine Push Pull Stufe. Was soll der Pullup? Unnötig den CS Ausgangspin
> belasten? Oder hast du Angst, dass im Reset während der CS Ausgangspin
> floatend ist irgendwas passiert?

Habe mir mal die CS Leitung mit meinen Oszi angeschaut. Wenn ich nur 
denn Text setzte habe ich nach dem Init genau 5 CS Low. Für set_cursor, 
set_rotation, set_textSize, set_TextColor, clearScreen. Danach nur noch 
HIGH 3,3 Volt. Beim ENC28J60 genau so. Also auch HIGH wenn nix passiert 
und LOW beim Empfänger habe getestet in dem ich die Webseite aufgerufen 
habe und aufs Oszi geschaut habe.

Kann es vllt. passieren das eine Anfrage an denn ENC28J60 geht dieser 
denn CS auf Low schreibt und gleichzeitig im TFT Display noch was 
gemacht wird? So das das TFT auch gleichzeitig low ist?

Lg Jan.
#4800160
Lesenswert?

Jan H. schrieb:
>   controlport &=~((1<<dc)|(1<<cs));//dc and cs both low to send command

Um beim AVR 2 Bits auf einmal zu setzen/löschen, ohne einem Interrupt 
eine Lücke zu öffnen, kann man nicht die PORTx Register verwenden. So 
wie hier besteht die Möglichkeit, dass ein Interrupt, der den gleichen 
Port bedient, zwischenrein funkt. Alternative: einzelbitweise bei Ports, 
die bitadressierbar sind, oder die Toggle-Funktion von PINx verwenden.

https://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff
Gast #4800813
Lesenswert?

Lothar M. schrieb:
> Richtig,  dafür ist der Slaveselect da.

Als Chip-Select Ausgang ist der SlaveSelect-Eingang eben nicht da.
Aber da man den Pin sowieso auf Ausgang setzen muss wenn man SPI benutzt 
und nicht die SlaveSelect Funktionalität haben will, drängt sich die 
Verwendung als Chip-Select quasi auf, ja. :-)

Die Informationen sind auf jeden Fall noch zu dünn.
Weder ist die Hardware ausreichend beschrieben, noch die Software.
Ich tippe da auf einen Software-Fehler.

Aber das könnte auch ein falsch angeschlossener Pegel-Wandler sein, das 
war so der einzige Fehler den ich bisher auf dem SPI hatte mit mehreren 
Slaves.

Versuch mal, das Programm auf ein Minimum zu reduzieren.
OP #4800866
Lesenswert?

Rudolph schrieb:
> Versuch mal, das Programm auf ein Minimum zu reduzieren.

Ich habe habe mal alles unnötige aus mein Programm entfernt. So das nur 
noch die Klassen drin sind wo mit SPI gearbeitet wird. Dieses sind 
ili9341.c/h, enc28j60.c/h, main.c, SPI.c/h und processor.h. Andere 
Sachen wie ADC, USART, DS18B20 TFT Grafik IP ARP habe ich raus gelassen.

Mal so ne Andere Frage. Was wäre wenn man bevor man ein CS Aktiv macht 
ein Status setzt(w. encSPI=1) und dann beim display spi vorher abfragt:
1
if(encSPI == 1) {
2
   while(encSPI != 0) {
3
     //Wait for encSPI equals 0 
4
     if(encSPI == 0) break;
5
  }
6
  tftSPI = 1; //Not Ready to use ENC SPI
7
  TFT_CS == LOW //Enable TFT CS
8
  Command ... //Write Command
9
  TFT_CS == HIGH //Disable TFT CS
10
  tftSPI = 0; //Ready to use ENC SPI
11
}else{
12
  tftSPI = 1; //Not Ready to use ENC SPI
13
  TFT_CS == LOW //Enable TFT CS
14
  Command ... //Write Command
15
  TFT_CS == HIGH //Disable TFT CS
16
  tftSPI = 0; //Ready to use ENC SPI
17
}
und halt umgekernt. Dann müsste es doch auch gehen. Bin mir nur nicht so 
sicher bei dem while()

lg jan.
Angehängte Dateien:
Gast #4800899
Lesenswert?

Nur kurz drüber geschaut, weder das Display noch der ENC28J werden im 
Interrupt bedient, oder etwa doch?

So können die sich doch regulär gar nicht in die Quere kommen und die 
Status-Variablen sind überflüssig.
Mit Interrupts wäre das while() auf jeden Fall tödlich, wenn gerade auf 
dem SPI gesendet wird und der IRQ aufgerufen wird der auch senden 
soll...

Und das manipuliert immer noch am Display rum?
Also es gibt einen Unterschied zwischen dem geposteten Code und
einer Version die iniEthernet() und ethernet_arp_request() 
auskommentiert hat?

Wie sieht denn die Hardware dazu aus?
Gast #4800917
Lesenswert?

Rudolph schrieb:
> Nur kurz drüber geschaut, weder das Display noch der ENC28J werden im
> Interrupt bedient, oder etwa doch?

Eigentlich müsste man mit einem Oszilloskop per Zufallstreffer
sehen dass beide Chip Selects irgendwann gleichzeitig aktiv
sind.

Jan H. schrieb:
> Da beide die SPI Kommunikation nutzten. Habe ich eine Klasse
> erstellt(SPI.c/h)

1
void init_SPI_Interface(void)
ist aber nicht Member irgendeiner Klasse. Insofern verstehe
ich das mit der Klasse nicht .....
OP #4801062
Lesenswert?

Rudolph schrieb:
> Interrupt bedient, oder etwa doch?

Nein. Im Interrupt(habe ich entfernt in diesen Code) wird nur die 
Temperatur eines LM35 ausgelesen und die Temperaturen des DS18B20.

Rudolph schrieb:
> Und das manipuliert immer noch am Display rum?

Also falls du damit meinst wo das Display immer noch rum spinnt. Janein. 
Also wenn ich die ganze Zeit mit ein Delay(nicht _delay_ms() Methode 
sondern mit Timer2 Overflow gereget) 100 ms ein Punkt auf dem Display 
löse und setzte. Und dann die Webseite aufrufe, dann bleibt das Display 
stehen und reagiert nicht mehr. ENC reagiert ebenfalls nicht mehr.
Wenn ich aber was auf Display schreibe und dann die Webseite aufrufe 
bleibt der Punkt auf dem Display stehen. Es seiden man kommt an die +5V 
oder GND Kabel.

Rudolph schrieb:
> Wie sieht denn die Hardware dazu aus?

Ich habe mal ein Schaltplan erstellt von meiner Hardware. Das ist 
wirklich nur der Controller und der Reset die Spannungversorgung ist 
dort nicht mit drin.

Arduinoquäler schrieb:
> ist aber nicht Member irgendeiner Klasse. Insofern verstehe
> ich das mit der Klasse nicht .....

Klar, ich hätte das mit dem SPI Interface auch in der main.c Klasse 
machen können jedoch finde ich es so übersichtlicher.

Lg Jan.
Angehängte Dateien:
Gast #4801073
Lesenswert?

Die Leitungen gehen sicher nicht direkt ohne andere Teile dazwischen auf 
den ILI9341 von dem Display und den ENC28J60, da zumindest der ENC28J60 
ja für 3,3V ist.
Wenn ich das richtig interpretiere geht auch der ILI9341 nur bis 3,3V.

Und wenn Du den Schaltplan erst erstellen musstest, ist das Teil auf dem 
Steckbrett aufgebaut?
Gast #4801077
Lesenswert?

Jan H. schrieb:
> Ich habe mal ein Schaltplan erstellt von meiner Hardware. Das ist
> wirklich nur der Controller und der Reset die Spannungversorgung ist
> dort nicht mit drin.

Der ENC28J60 braucht vergleichsweise (zum Controller) viel Strom
und könnte bei schwachen oder fehlenden Abblock-Massnahmen auf
der Versorgung die anderen Schaltungsteile stören.
OP #4801083
Lesenswert?

Rudolph schrieb:
> ja für 3,3V ist.
> Wenn ich das richtig interpretiere geht auch der ILI9341 nur bis 3,3V.

Ja das ist richtig. Die CS, MOSI, SCK DC, RESET Leitung gehen auf denn 
CD4050 Converter der mit 3,3 Volt betrieben wird. Dadurch kommen nur 3.3 
Volt auf denn Steuerleitungen an.

Rudolph schrieb:
> Und wenn Du den Schaltplan erst erstellen musstest, ist das Teil auf dem
> Steckbrett aufgebaut?

Also der ENC28J60 ist mit einer Ethernet Buchse auf einer 
Lochrasterplatine aufgelötet. Mit einen Pin Header(Vcc, Gnd, Sck, miso, 
mosi, cs, adc(lm35)).

Und das TFT Display habe ich auf eine Platine gemacht. Diese passt genau 
auf denn Arduino UNO. Ist also ein "Arduino Shield". Dort drauf ist ein 
3,3 Regler. 2 CD4050 Converter 1 für TFT ILI9341 und einer für denn SD 
Karten Slot.

Arduinoquäler schrieb:
> Der ENC28J60 braucht vergleichsweise (zum Controller) viel Strom
> und könnte bei schwachen oder fehlenden Abblock-Massnahmen auf
> der Versorgung die anderen Schaltungsteile stören.

Die Spannungversorgung wäre eigentlich mit ein 7805 gemacht. Jedoch 
Powerere ich das ganze mit mein Labornetzteil. Das auf 5V eingestellt 
ist. Die Schaltung zieht 245 mA. Ohne ENC und TFT nur 40 mA.

Lg Jan.
Gast #4801103
Lesenswert?

Jan H. schrieb:
> Die Spannungversorgung wäre eigentlich mit ein 7805 gemacht. Jedoch
> Powerere ich das ganze mit mein Labornetzteil. Das auf 5V eingestellt
> ist. Die Schaltung zieht 245 mA. Ohne ENC und TFT nur 40 mA.

Du hast es wieder nicht verstanden (wie bei der Klasssen-
Programmierung).
Ein Labornetzteil garantiert noch keine zuverlässige Abblockung.

Ausserdem ist auch der Aufbau entscheidend für die korrekte
Funktion. Aus den bisherigen Verlauf entnehme ich dass du uns
deinen Aufbau nicht zeigen willst.
#4801187
Lesenswert?

Jan H. schrieb:
> Ja das ist richtig. Die CS, MOSI, SCK DC, RESET Leitung gehen auf denn
> CD4050 Converter der mit 3,3 Volt betrieben wird. Dadurch kommen nur 3.3
> Volt auf denn Steuerleitungen an.
>
> Und das TFT Display habe ich auf eine Platine gemacht. Diese passt genau
> auf denn Arduino UNO. Ist also ein "Arduino Shield". Dort drauf ist ein
> 3,3 Regler. 2 CD4050 Converter 1 für TFT ILI9341

Und wie ist das genau verdrahtet? Wirklich?

> und einer für denn SD Karten Slot.

Ah sieh an, noch ein SPI-Teilnehmer.
Wenn der fest verdrahtet ist gehört der auch in den Schaltplan, auch 
wenn CS per Pullup auf VCC hängt und keine Karte im Slot ist.
OP #4801444
Lesenswert?

Rudolph R. schrieb:
> Und wie ist das genau verdrahtet? Wirklich?

Ich habe dafür auch noch mal ein Schaltplan angefertigt. Ich verwende 
anstatt des AMS1117 3.3V Regler ein kleinen DC-DC Step Down Regler(max 1 
A) wo die Spannung auf 3,35 Volt eingestellt ist.

Hinter/Vor denn Pin Header steht die Bezeichnung was der Pin bedeutet 
die Zahl in der Klammer dahinter steht für die Zahl am Pin Header bsp: 
SCK(2) mit 2 ist dann gemeint beim Pin Header wo die Zahl 2 steht.

Rudolph R. schrieb:
> Ah sieh an, noch ein SPI-Teilnehmer.

Naja. Also die MISO ist gar nicht am Controller angeschlossen. Und CS 
auch nicht.

Rudolph R. schrieb:
> Wenn der fest verdrahtet ist gehört der auch in den Schaltplan, auch
> wenn CS per Pullup auf VCC hängt und keine Karte im Slot ist.

Sorry. vergessen.

Also nochmal was andere ich habe auf mein TFT Display eine Lade 
Animation gebastelt. Dort sind acht Punkte die weiß sind. Jede 100 
ms(über overflow) macht er denn nächsten Punkt schwarz und denn 
vorherigen weiß. So habe ich eine kleine Lade Animation. Das heißt ja 
auch das alle 100 ms die CS Leitung low gelegt wird.
Wenn ich nun die Webseite aufrufe dann bleibt das TFT stehen. Komisch 
ist jedoch auch, das die Animation bereits läuft bevor überhaupt der 
ENC28J60 Initialisiert ist, und während der ENC28J60 über das SPI 
Initialisiert(Mac Adresse / Server) werden SPI Befehle ausgeführt. Und 
das TFT bleibt nicht stehen erst wenn die ethernet_arp_request() 
Funktion anschlägt bleibt es stehen.

Lg Jan.
Angehängte Dateien:
Gast #4801541
Lesenswert?

Ich tipp auf einen falsch angeschlossenen Pegelwandler, so dass CS high 
nichts bewirkt, aber habe nur flüchtig drüber gelesen... Das SD 
cardmodule von catalex hat diesen Fehler und hat mich erst mal ein paar 
Stunden gekostet.
OP #4802871
Lesenswert?

Hallo Leute,
Nach vielen Debuggen mit dem Display und denn ENC28J60, habe ich nun das 
Problem gefunden.
Und zwar was das ganze kein Problem der Hardware oder am SPI Bus.
Sondern das Problem lag im Code. Ich habe meine Lade Animation die ich 
vorher fürs Display programmiert habe auf dem Display gezeigt. Und habe 
nach und nach denn Code von der HTTP Webseite entfernt bis ich denn 
Fehler gefunden habe:

Folgender Code:
1
plen=fill_tcp_data_p(buf, plen, PSTR("Temperatur Sensor Außen: <font color='red'>Can't find Temp Sensor</font>!<br/>"));

Das Problem ist das <font color='red'>. Wenn ich dieses aus dem Code 
entferne dann läuft das Display normal weiter und auch der ENC läuft 
ohne Probleme weiter. Das Display läuft auch weiter wenn ich die Seite 
aufrufe.

Kann mir jemand vielleicht erklären warum das grade mit dem <font 
color='red>zu Problemen führen kann? Kann mir es selber nicht erklären.

Lg Jan.
#4802881
Lesenswert?

Hallo,


pauschal könnte man vermuten, daß irgendein Speicher verbotenerweise 
beschrieben wird. Dies fällt anscheinend nur an dieser Stelle auf. 
Vermutlich ist aber sonst ein Fehler dafür verantwortlich: falsche 
Variablendeklaration, Arrayzugriff außerhalb des definierten Bereichs, 
Überlauf... Dazu müßte man schon genauer das Programm untersuchen.

MfG
OP #4803721
Lesenswert?

Christian S. schrieb:
> daß irgendein Speicher

Hallo,

Es scheint doch nicht an den <font> zu legen sondern. An der Buffersize. 
Diese habe ich auf 900 festgelegt(Standard Wert von der Library). Ich 
habe die einfach mal Spaßeshalber auf 1500(bytes) gesetzt. Und auf 
einmal ging alles wieder ohne Probleme.

Vielleicht wahr der Speicher von 900 Bytes voll. Und das hat zu irgend 
einer Kettenreaktion geführt. Die dann dafür sorgte das der SPI Bus lahm 
gelegt wurde.

Lg Jan.

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