Forum: Mikrocontroller und Digitale Elektronik SPI mit Attiny 841 und MCP23S17


von Achim (Gast)


Lesenswert?

Hallo
Versuche den MCP23S17 am Attiny841 zu betreiben. Dazu verwende ich 
diesen Code.
main
1
#define F_CPU 16000000UL      // Angabe der Frequenz, wichtig für die Zeit
2
#include "util/delay.h"      // Einbindung Datei Pause
3
#include "avr/io.h"        // Einbindung Datei Ausgänge
4
#include "spi.h"
5
#include "mcp.h"
6
int main(void)
7
  {
8
  spi_master_init();        // setzt SPI Master und Transfer in spi.c
9
  mcp_init(MCP_OPC);  // setzt Betriebsmodus und Hardware Adresse in mcp.c
10
  while (1)
11
    {
12
    mcp_write(MCP_OPC, GPIOA, 0xff);// (1<<(7-ct)));
13
    _delay_ms(500);  
14
    mcp_write(MCP_OPC, GPIOA, 0x00);// (1<<(7-ct)));
15
    _delay_ms(500);  
16
    }
17
  }
/mcp.c/
1
void mcp_init(uint8_t addr)
2
  {
3
  MCP_PORT &= ~(1<<SS);      // setzt SS auf Low
4
  mcp_write(addr, IOCON, 0x28);  // setzt im IOCON SEQOP und HAEN auf 1 
5
  mcp_write(addr, IODIRA, 0x01);  // Port A auf Ausgang
6
  MCP_PORT |= (1<<SS);      // setze SS auf High 1.
7
  }
8
9
// MCP schreiben 
10
void mcp_write(uint8_t addr, uint8_t reg, uint8_t data)
11
  {
12
  MCP_PORT &= ~(1<<SS);  // setzt SS auf Low
13
  spi_transfer(addr);  // sende Adresse, 
14
  spi_transfer(reg);      // sende Registerbyte
15
  spi_transfer(data);      // sende Daten
16
  MCP_PORT |= (1<<SS);  // setze SS auf High
17
  }
/mcp.h/
1
// Bank = 0 dann Register gepaart, Bank = 1 dann Register getrennt 
2
// Alle Angaben für Bank = 1 - Register getrennt
3
#define IODIRA 0x00    // B1 Richtungsregister Port A - 0x00 als Ausgang
4
#define IODIRB 0x10    // B1 Richtungsregister Port B - 0x01 als Eingang
5
#define IPOLA 0x01    // B1 Register Eingangspolarität Port A
6
#define IPOLB 0x11    // B1 Register Eingangspolarität Port B
7
#define GPINTENA 0x02  // B1 Interrupt Register Port A
8
#define GPINTENB 0x12  // B1 Interrupt Register Port B
9
#define DEFVALA 0x03  // B1 Register Vorgabewert Port A
10
#define DEFVALB 0x13  // B1 Register Vorgabewert Port B
11
#define INTCONA 0x04  // B1 Steuerregister für Unterbrechung Port A
12
#define INTCONB 0x14  // B1 Steuerregister für Unterbrechung Port B
13
14
#define IOCON 0x05    // B1 Konfigurationsregister für Bank=1
15
16
#define GPPUA 0x06    // B1 Widerstandsregister Port A
17
#define GPPUB 0x16    // B1 Widerstandsregister Port B
18
#define INTFA 0x07    // B1 Register Unterbrechungs-Flag Port A
19
#define INTFB 0x17    // B1 Register Unterbrechungs-Flag Port B
20
#define INTCAPA 0x08  // B1 Register Erfasster Interrupt Wert Port A 
21
#define INTCAPB 0x18  // B1 Register Erfasster Interrupt Wert Port B
22
#define GPIOA 0x09    // B1 allgemeines Anschlussregister Port A
23
#define GPIOB 0x19    // B1 allgemeines Anschlussregister Port B
24
#define OLATA 0x0A    // B1 Ausgangs Latch Register Port A 
25
#define OLATB 0x1A    // B1 Ausgangs Latch Register Port B
26
27
#define MCP_OPC 0x40    // Adresse MCP23S17 A0, A1, A2 = 0 - 0x40
/spi.c/
1
// SPI Init
2
void spi_master_init(void)
3
  {
4
  // Setzen von MOSI und SCK auf output und alle anderen auf input
5
  SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);// Angabe der Pins
6
  // Einschalten SPI, Master, setzen Clock Teiler auf 16
7
  SPCR =(1<<SPR0);  // CLK Teiler auf 16 setzen
8
  SPCR =(1<<SPE);    // SPI aktivieren
9
  SPCR =(1<<MSTR);  // Ati841 als Master
10
  }
11
12
// Transfer init
13
void spi_transfer(uint8_t data)
14
  {
15
    // Starte transmission
16
  SPDR = data;            
17
  // Warte bis Transmission komplett
18
  while(!(SPSR & (1<<SPIF)));
19
  }
/spi.h/
1
#define SPI_DDR      DDRA  // Angabe DDR  DDRA
2
#define SPI_PORT    PORTA  // Angabe Port PORTA
3
#define SCK        PORTA4  // SCK PORT A4 am Ati841
4
#define MOSI      PORTA6  // Mosi PORT A6 am Ati841 Ausgang
5
#define MISO      PORTA5  // Miso PORT A5 am Ati841 Eingang
6
#define SS        PORTA7  // SS, CS PORT A7 am Ati841
7
8
void spi_master_init(void);
9
void spi_transfer(uint8_t data);
Leider zeigt der MCP23S17 keinerlei Reaktion. Hat jemand eine Idee was 
falsch ist?

von c-hater (Gast)


Lesenswert?

Achim schrieb:

> Leider zeigt der MCP23S17 keinerlei Reaktion. Hat jemand eine Idee was
> falsch ist?

Also, ich habe es nur überflogen, aber ich könnte beim Überflug keine 
Stelle erkennen, an der du ein Chip-Select setzt...

von Axel R. (axlr)


Lesenswert?

Bitte als Anhang posten.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Achim schrieb:
> Leider zeigt der MCP23S17 keinerlei Reaktion.
Wie stellst du das fest? Mit einem Logikanalyzer oder einem Oszilloskop?
> Hat jemand eine Idee was
> falsch ist?
Eine Messung mit einem Logikanalyzer oder einem Oszi und der Vergleich 
des Timings mit dem Datenblatt bringt Fehler ans Tageslicht.

von Achim (Gast)


Lesenswert?

Achim schrieb:
> mcp_write(addr, IOCON, 0x28);  // setzt im IOCON SEQOP und HAEN auf 1


Da ich hier HAEN auf 1 setze wird doch A0,A1 und A2 aktiv. Da alle 3 
Pins auf GND liegen ist doch die Aderesse 0x40

Achim schrieb:
> #define MCP_OPC 0x40    // Adresse MCP23S17 A0, A1, A2 = 0 - 0x40

Bist du dir sîcher es als Anhang haben willst. Das ist die bereinigte 
Version. Im ori sind noch viel mehr auskommentiere Sacgen drin die da 
eigentlich nichts mehr zu suchen haben.

von Achim (Gast)


Lesenswert?

Lothar M. schrieb:
> Wie stellst du das fest? Mit einem Logikanalyzer oder einem Oszilloskop?

Einen Logikanalyser habe ich nicht. Oszi muss ich schaun ob der noch 
funktioniert.
Habe einen MCP23S17 auf einer Platte angesteckt. Die LEDs sind per RN 
9/8 (Widerstand) verbunden, SPI per Steckverbinder an eine Pltine mit 
dem Attiny 841.
Was müsste ich den per Oszi messen? Taktsignal?

von Ergo70 (Gast)


Lesenswert?

Achim schrieb:
> Da alle 3 Pins auf GND liegen ist doch die Aderesse 0x40

SPI? Adresse? Oder ist das ein MCP23017?

von Achim (Gast)


Lesenswert?

Nein, es ist ein MCP23 S 17 (SPI) mit 3 Adressen die durch A0, A1 und A2 
eingestellt werden können wenn man HAEN auf 1 stellt.
Benutze dabei die Bank 1 mit getrennten Registern (A/B)

// MCP 23S17
// Port B Eingang auf Taster, legt Eingang auf GND
// Port A Ausgang auf LED über R nach GND

Die LEDs liegen über ein IW (RN 9/8) nach GND. Muss also +5V einschalten 
damit LEDs leuchten

von Achim (Gast)


Lesenswert?

Habe am SCK am MCP23S17 mit meinem Oszi eine Frequenz gemessen. Konnte 
aber noch nicht feststellen wie gross sie ist. Nach dem Programm müsste 
es 1 MHz sein.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Achim schrieb:
> Was müsste ich den per Oszi messen? Taktsignal?
Alle 4 Signale (MO)SI, (MI)SO, SCK und CS# sind für die Kommunikation 
relevant.
Die zeitlichen Abhängigkeiten müssen den Timingangaben im Datenblatt 
entsprechen.
Wenn da alles passt, dann funzt die Schnitte.

(einfach mal davon ausgegangen, dass die elektrische Verschaltung soweit 
passt...)

> Was müsste ich den per Oszi messen?
Zuerst muss der CS# vor der Übertragung low gesetzt und mach der 
Übertragung wieder high werden.

Welches Oszi hast du? Digital? Wieviele Kanäle?

Achim schrieb:
> Nein, es ist ein MCP23 S 17 (SPI) mit 3 Adressen die durch A0, A1 und A2
> eingestellt werden können
Dann kann ein einziger CS# Ausgang 8 solcher Bausteine ansteuern. Kann 
man machen. Die sind aber jetzt alle mal fest auf '0', oder nicht?

: Bearbeitet durch Moderator
von Achim (Gast)


Lesenswert?

Sind alle auf 0 (GND)

von Achim (Gast)


Lesenswert?

Die Belegung am Attiny 841 nach Datenblatt
// PA0 --> TP 1
// PA1 --> TP 2
// PA2 --> TP 3
// PA3 --> TP 4

// PA4 --> SCK
// PA5 --> MiS0
// PA6 --> MOSI
// PA7 --> CC,CS

// PB0 --> LP 3
// PB1 --> LP 2
// PB2 --> LP 1

von EAF (Gast)


Lesenswert?

Lothar M. schrieb:
> Zuerst muss der CS# vor der Übertragung low gesetzt und mach der
> Übertragung wieder high werden.
Das ist natürlich richtig!

Wobei aber sichergestellt sein sollte, dass der Pin vorher auf HIGH 
liegt.
Das kann ich leider in dem Code nicht erkennen!

Evtl. besser:
1
// SPI Init
2
void spi_master_init(void)
3
{
4
  MCP_PORT |= (1<<SS);      // setze SS (Pullup) auf High 1.
5
  // Setzen von MOSI und SCK auf output und alle anderen auf input
6
  SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);// Angabe der Pins
7
  // Einschalten SPI, Master, setzen Clock Teiler auf 16
8
  SPCR =(1<<SPR0);  // CLK Teiler auf 16 setzen
9
  SPCR =(1<<SPE);    // SPI aktivieren
10
  SPCR =(1<<MSTR);  // Ati841 als Master
11
}


Zudem könnte es Sinn machen, /CS mit einem externen Pullup zu versehen, 
damit einem der Baustein beim ISCP nicht dazwischen quatscht.

von jo mei (Gast)


Angehängte Dateien:

Lesenswert?

Achim schrieb:
> // MCP schreiben
> void mcp_write(uint8_t addr, uint8_t reg, uint8_t data)
>   {
>   MCP_PORT &= ~(1<<SS);  // setzt SS auf Low
>   spi_transfer(addr);  // sende Adresse,
>   spi_transfer(reg);      // sende Registerbyte
>   spi_transfer(data);      // sende Daten
>   MCP_PORT |= (1<<SS);  // setze SS auf High
>   }

Wenn ich das Datenblatt lese kann ich nicht erkennen dass man
dem Chip ein separates Adressbyte schicken soll so wie es dein
Code zeigt. Also liegt für mich da der Hund begraben ....
Vielleicht habe ich aber auch das Protokol nicht richtig
verstanden.

von EAF (Gast)


Lesenswert?

Wobei,  MCP_PORT finde ich nicht, soll bestimmt  SPI_PORT heißen.....

von Achim (Gast)


Lesenswert?

EAF schrieb:
> // SPI Init
> void spi_master_init(void)
> {
>   MCP_PORT |= (1<<SS);      // setze SS (Pullup) auf High 1.
>   // Setzen von MOSI und SCK auf output und alle anderen auf input
>   SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);// Angabe der Pins
>   // Einschalten SPI, Master, setzen Clock Teiler auf 16
>   SPCR =(1<<SPR0);  // CLK Teiler auf 16 setzen
>   SPCR =(1<<SPE);    // SPI aktivieren
>   SPCR =(1<<MSTR);  // Ati841 als Master
> }

Bist du dir sicher das das die richtige Stelle ist? Hier mache ich doch 
im Attiny 841 das init und nicht am MCP23S17. Wenn ich das so eintrage 
bekomme ich eine Fehlermeldung.

von Ergo70 (Gast)


Lesenswert?

jo mei schrieb:
> dass man
> dem Chip ein separates Adressbyte schicken soll so wie es dein
> Code zeigt.

Hatte mich auch gewundert, aber auf S. 16 sieht man, dass es anscheinend 
möglich ist, bis zu 8 von den Dingern an ein CS zu hängen und dann 
individuell mit einer Adresse anzusprechen. Soll wohl CS Leitungen 
sparen...

von Achim (Gast)


Lesenswert?

Schau mal in das DB, auf Seite 8 Figur 1-3 steht die Zuordnung für die 
Adressen. Darüber steht auch gleich für I2C.

von jo mei (Gast)


Lesenswert?

Achim schrieb:
> Schau mal in das DB, auf Seite 8 Figur 1-3 steht die Zuordnung für die
> Adressen. Darüber steht auch gleich für I2C.

Kannst auch gleich mal erklären was du mit diesem Aussage-Mist
sagen willst. Plötzlich geht's um I2C? Nichts verstanden?

von jo mei (Gast)


Lesenswert?

Ergo70 schrieb:
> Hatte mich auch gewundert, aber auf S. 16 sieht man, dass es anscheinend
> möglich ist

Das soll einen aber nicht davon abhalten das Protokoll einzuhalten
wie es mein gepostetes Diagramm zeigt bzw. fordert. Es sei denn
es gibt noch irgendein geheimes Zusatzprotokoll das ich noch nicht
gefunden habe ....

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

jo mei schrieb:
> Plötzlich geht's um I2C? Nichts verstanden?
Der -S- ist der SPI-Typ.
Man kann mit 1 einzigen CS#-Pin jeweils 8 solcher Bausteine adressieren.

jo mei schrieb:
> Kannst auch gleich mal erklären was du mit diesem Aussage-Mist
> sagen willst.
Da steht:

1. Schau mal ins Datenblatt. Da steht das mit den A0-A2 drin für SPI.

2. Und gleich darüber steht das selbe mit den A0--A2 ebenfalls für 
I2C.

: Bearbeitet durch Moderator
von jo mei (Gast)


Lesenswert?

Ja und? Was hat das mit dem Protokoll zu tun das der TO
implementiert hat?

von S. Landolt (Gast)


Lesenswert?

Es fehlt im spi_master_init die VerODERung bei den letzten beiden 
'SPCR='.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

jo mei schrieb:
> Das soll einen aber nicht davon abhalten das Protokoll einzuhalten
> wie es mein gepostetes Diagramm zeigt bzw. fordert.
Man muss 1. kontrollieren, ob alle Signale an den IC-Pins gut aussehen: 
ohne Klingeln und der Takt mit stetigen Flanken.

Dann muss man 2. kontrollieren ob das Timing auf Bit-Ebene passt: wird 
überhaupt der richtige SPI-Mode verwendet?

Dann muss man 3. kontrollieren, ob die Bits, die man am MOSI sendet, in 
der richtigen Reihenfolge auf dem Bus auftauchen: LSB oder MSB first?

Und dann muss man 4. kontrollieren, ob das was man sendet für das Device 
überhaupt die richtigen Daten in der richtigen Reihenfolge sind.

jo mei schrieb:
> Was hat das mit dem Protokoll zu tun das der TO implementiert hat?
Irgendwas passt halt einfach nicht zu dem, was im Datenblatt gefordert 
wird. Das ist in >>99,9% der Fälle so. Denn wenn das dann alles passt, 
dann klappt es auch mit der Übertragung.

: Bearbeitet durch Moderator
von EAF (Gast)


Lesenswert?

Achim schrieb:
> Wenn ich das so eintrage
> bekomme ich eine Fehlermeldung.
Geheim?
Wie ich schon im Nachtrag sagte, ersetze MCP_PORT |= (1<<SS);  durch 
SPI_PORT |= (1<<SS);

Achim schrieb:
> Bist du dir sicher das das die richtige Stelle ist? Hier mache ich doch
> im Attiny 841 das init und nicht am MCP23S17
Richtig!
Und zum SPI Init gehört es, /CS auf High zu ziehen, bevor man irgendwas 
anderes tut.

von jo mei (Gast)


Lesenswert?

Wenn ich die Beiträge sehe dann bleibt mir der Eindruck
dass meine (vermutlich berechtigte) Kritik scheinbar von
niemandem gelesen wurde.

Beitrag "Re: SPI mit Attiny 841 und MCP23S17"

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

EAF schrieb:
> Wie ich schon im Nachtrag sagte, ersetze MCP_PORT |= (1<<SS);  durch
> SPI_PORT |= (1<<SS);
Kann ja sein, dass das der selbe Port ist. Die sind ja vorliegenden Code 
die Dinger nicht definiert. Das muss also woanders passieren.


@Achim:
besser keinen Kommentar als einen falschen...
1
  // Setzen von MOSI und SCK auf output und alle anderen auf input
2
  SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);// Angabe der Pins

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

jo mei schrieb:
> Kritik scheinbar von niemandem gelesen wurde.
Die im Datenblatt geforderte Bitanordnung passt auf jeden Fall nicht zu 
dieser Sequenz:
1
  spi_transfer(addr);  // sende Adresse, 
2
  spi_transfer(reg);   // sende Registerbyte
3
  spi_transfer(data);  // sende Daten
Denn im Datenblatt werden 16 Bit übertragen, im Code sind 24 Bits 
unterwegs...

Siehe Punkt 4 meiner obigen "Kurzanleitung zur Inbetriebnahme eines 
seriellen Busses".

von Achim (Gast)


Lesenswert?

jo mei schrieb:
> Kannst auch gleich mal erklären was du mit diesem Aussage-Mist
> sagen willst. Plötzlich geht's um I2C? Nichts verstanden?

Es geht nicht um I2C. Diesen IC gibt es zwei verschiedenen Versionen. 
Einmal I2C und SPI, unterscheiden sich im Namen durch MCP23S17 und 
MCP23017. Das Datenblatt gilt für beide. Wie weit beide in der Technik 
übereinstimmen ist mir nicht bekannt. Es geht mir um den MCP23S17 und 
SPI.

Lothar M. schrieb:
> // Setzen von MOSI und SCK auf output und alle anderen auf input
>   SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);// Angabe der Pins

Hatte das aud em Datenblatt zum Attiny 841 übernommen. Wenn der 
Kommentar falsch ist bitte nicht beachten.

jo mei schrieb:
> Wenn ich das Datenblatt lese kann ich nicht erkennen dass man
> dem Chip ein separates Adressbyte schicken soll so wie es dein
> Code zeigt. Also liegt für mich da der Hund begraben ....
> Vielleicht habe ich aber auch das Protokol nicht richtig
> verstanden.

Wenn ich im Register IOCON HAEN auf 1 setze sind die Adresseingänge 
gültig. Wird auch genau beschrieben.

Lothar M. schrieb:
> EAF schrieb:
>> Wie ich schon im Nachtrag sagte, ersetze MCP_PORT |= (1<<SS);  durch
>> SPI_PORT |= (1<<SS);
> Kann ja sein, dass das der selbe Port ist. Die sind ja vorliegenden Code
> die Dinger nicht definiert. Das muss also woanders passieren.

Das werde ich gleich kontrollieren.

von Ergo70 (Gast)


Lesenswert?

jo mei schrieb:
> Das soll einen aber nicht davon abhalten das Protokoll einzuhalten
> wie es mein gepostetes Diagramm zeigt bzw. fordert.

Das stimmt natürlich, Opcode und Register können direkt hintereinander 
während CS die ganze Zeit Low ist. Aber dass der Chip auch bei SPI 
Adressen ähnlich zu I2C unterstützt ist schon ungewöhnlich, da muss man 
ja nicht gleich rummaulen, wenn noch jemand darauf hinweist.

von Achim (Gast)


Lesenswert?

Hatte sich leider versteckt zwischen den Kommentaren:
/mcp.h/
1
#define MCP_DDR      DDRA
2
#define MCP_PORT    PORTA
3
#define SS      PORTA7
Sorry

von jo mei (Gast)


Lesenswert?

Achim schrieb:
> Wenn ich im Register IOCON HAEN auf 1 setze sind die Adresseingänge
> gültig. Wird auch genau beschrieben.

Du hast es immer noch nicht begriffen worum es geht. Du sendest
drei Bytes wo das Protokoll nur zwei verlangt. Die Adresse des
Chips wird laut Vorschrift in den Device-Opcode hineingemappt
und nicht separat gesendet.

Beratungsresistenz ist eine Zier, doch weiter kommt man ohne ihr.

von Achim (Gast)


Lesenswert?

jo mei schrieb:
> Beratungsresistenz ist eine Zier, doch weiter kommt man ohne ihr.

Das hat damit nichts zu tun, Es gibt Angaben zu diesem IC im Netz z.B. 
mit dem Raspi, die weisen darauf hin das die Übertragung mit Adress 
erfogen soll. Du hast allerdings vollkommen Recht, laut DB sind es nur 
16 Bit. Werde es gleich testen.

von jo mei (Gast)


Lesenswert?

Achim schrieb:
> Du hast allerdings vollkommen Recht, laut DB sind es nur
> 16 Bit.

Lautes Aufatmen.

von jo mei (Gast)


Lesenswert?

Achim schrieb:
> Das hat damit nichts zu tun, Es gibt Angaben zu diesem IC im Netz z.B.
> mit dem Raspi, die weisen darauf hin das die Übertragung mit Adress
> erfogen soll.

Ja, und alles was im Netz geschrieben ist, ist wahr bzw. richtig, gell?

von EAF (Gast)


Lesenswert?

jo mei schrieb:
> dass meine (vermutlich berechtigte) Kritik scheinbar von
> niemandem gelesen wurde.
Weiß nicht.....
Ich habe sie schon gelesen.
Bin aber zu dem Schluss gekommen, dass dieses:
jo mei schrieb:
> Vielleicht habe ich aber auch das Protokol nicht richtig
> verstanden.
Durchaus zutreffend ist.
Denn:
Wenn da ein halbes Dutzend gleicher Bausteine auf dem Bus hängt, an 
einem einzigen /CS, dann ist das Adressbyte nötig, um diese einzeln 
ansprechen zu können.

von jo mei (Gast)


Lesenswert?

EAF schrieb:
> dann ist das Adressbyte nötig, um diese einzeln
> ansprechen zu können.

Nein ist es nicht da jeder Chip das erste Byte liest und
dann entscheidet ob er (durch die Adresse) angesprochen
sein soll oder nicht. Das schafft so ein Chip, auch wenn
er bereits durch /CS "aktiviert" bzw aufgeweckt wurde.

von jo mei (Gast)


Lesenswert?

jo mei schrieb:
> Das schafft so ein Chip, auch wenn
> er bereits durch /CS "aktiviert" bzw aufgeweckt wurde.

Das gleiche passiert übrigens auch beim I2C-Protokoll. Alle
Teilnehmer hören (bestimmt durch die Start-Condition) immer
zu und entscheiden erst dann ob sie angesprochen sind oder
nicht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Achim schrieb:
> Wenn der Kommentar falsch ist bitte nicht beachten.
Sag das mal 2 Jahre später, wenn du selber nicht mehr weißt, ob der Code 
oder der Kommentar jetzt korrekt ist...

Achim schrieb:
> Es gibt Angaben zu diesem IC im Netz
> die weisen darauf hin das die Übertragung mit Adress erfogen soll.
Soll sie ja laut Datenblatt auch. Nur eben entsprechend der Bitanordung 
im Datenblatt: 4 Bit Opcode, 3 Bit Adresse, 1 Bit R/W und dann die 
Daten.

von EAF (Gast)


Lesenswert?

jo mei schrieb:
> Du hast es immer noch nicht begriffen worum es geht. Du sendest
> drei Bytes wo das Protokoll nur zwei verlangt. Die Adresse des
> Chips wird laut Vorschrift in den Device-Opcode hineingemappt
> und nicht separat gesendet.
>
> Beratungsresistenz ist eine Zier, doch weiter kommt man ohne ihr.

Leider irrst du....
Mindestens 3 Byte, wenn man Daten im Chip lesen/ändern will.
1. Adresse des Chips
2. Register Adresse
3. Die zu schreibenden Daten oder eben Dummydaten beim lesen.

Oder möchtest du sequenziell lesen/schreiben?
Dann sind das durchaus noch viel mehr Byte bei einem Zugriff.
Nicht nur 2Byte!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

EAF schrieb:
> Nicht nur 2Byte!
Aber eben jeweils mit der Bitanzahl und -reihenfolge, wie sie im 
Datenblatt steht.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Lothar M. schrieb:
> ...wie sie im Datenblatt steht.

Scheint für einige schwierig zu vestehen zu sein dass man bei diesem 
Chip auch bei SPI eine Adressierung Byte voranstellen muss (und zwar 
immer, auch wenn nur ein Chip an CS hängt), genauso wie bei I2C. Damit 
wird auch R/W gesteuert. Bei SPI kommt da halt noch das CS zusätzlich 
hinzu.

- 
https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP23017-Data-Sheet-DS20001952.pdf
- I2C => FIGURE 3-4 & FIGURE 3-6 (Seite 15f)
- SPI => FIGURE 3-5 & FIGURE 3-7

von jo mei (Gast)


Lesenswert?

Irgend W. schrieb:
> Scheint für einige schwierig zu vestehen zu sein

Irgend W. schrieb:
> - SPI => FIGURE 3-5 & FIGURE 3-7

Ach! Echt jetzt? Gut nachgeplappert.

Beitrag "Re: SPI mit Attiny 841 und MCP23S17"

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Irgend W. schrieb:
> genauso wie bei I2C.
Der Witz an dem Ding ist, dass für I2C und SPI genau das selbe Protokoll 
verwendet wird. Lediglich die Art des "Einschiebens" der jeweiligen Bits 
ist anders.

Das hat der Chipdesigner wohl so gemacht, dass er im Chip selber 
möglichst wenig Arbeit hat und die Bits an der jeweiligen Position die 
gleiche Funktion haben.

Die Adressierung kennt man vom SPI anders. Normalerweise wird sie da 
komplett und explizit über den CS# erledigt.

von S. Landolt (Gast)


Lesenswert?

Also a) ist, wie bereits erwähnt, spi_master_init falsch, und b) würde 
ich mich für erste Gehversuche auf Bank 0 beschränken; dann sollte es 
laufen mit:
1
#define IODIRA 0x00
2
#define GPIOA 0x12
3
#define MCP_OPC 0x40 
4
...
5
void spi_master_init(void)
6
  {
7
  SPI_PORT = 0xFF;
8
  SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);
9
  SPCR =  (1<<SPE)+(1<<MSTR);
10
  }
11
...
12
void mcp_init(uint8_t addr)
13
  {
14
  mcp_write(addr, IODIRA, 0x00);  // Port A auf Ausgang
15
  }
16
...
17
int main(void)
18
  {
19
  spi_master_init();
20
  mcp_init(MCP_OPC);
21
  while (1)
22
    {
23
    mcp_write(MCP_OPC, GPIOA, 0xFF);
24
    _delay_ms(500);  
25
    mcp_write(MCP_OPC, GPIOA, 0x00);
26
    _delay_ms(500);  
27
    }
28
  }

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

Das vollständige Programm (für einen ATmega48PA).

von Heiner (Gast)


Lesenswert?

S. Landolt schrieb:
> Das vollständige Programm (für einen ATmega48PA).

Gut!
Würde aber die Definition von MCP_PORT und MCP_DDR nicht machen, da 
verwirrend (anstatt "MCP_xy" nur "SPI_xy" nehmen) und nicht noetig.

von S. Landolt (Gast)


Lesenswert?

Ich wollte mich an das ursprüngliche Programm von Achim anlehnen.

von Heiner (Gast)


Lesenswert?

S. Landolt schrieb:
> Ich wollte mich an das ursprüngliche Programm von Achim anlehnen.


+1

von Heiner (Gast)


Lesenswert?

Jetzt fehlt Achim nur noch das Einlesen vom MCP23S17 (z.B. Schalter)

von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:
> Das vollständige Programm (für einen ATmega48PA).

Fehlt bei Deinem Programm nicht die Verwendung von MISO - ist zwar 
definiert, aber nicht verwendet ... wenn Achim dann Daten einlesen will?

von S. Landolt (Gast)


Lesenswert?

Wie angedeutet, soll es eine Hilfe für den ersten Gehversuch Achims 
sein, ein allererstes LED-Blinken - folglich fehlt alles Weitere; das 
überlasse ich dann ihm.

von S. Landolt (Gast)


Lesenswert?

"Vollständig" bezog sich auf die Bruchstücke von 07:59.

von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:
> Wie angedeutet, soll es eine Hilfe für den ersten Gehversuch Achims
> sein, ein allererstes LED-Blinken - folglich fehlt alles Weitere; das
> überlasse ich dann ihm.

+ 1

Das ist "Hilfe zur Selbsthilfe" ;-)

von EAF (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Fehlt bei Deinem Programm nicht die Verwendung von MISO - ist zwar
> definiert, aber nicht verwendet ... wenn Achim dann Daten einlesen will?

Ähhmmm.....
Soweit mir bekannt, wird Miso von der SPI Hardware bedient, bzw. 
gelesen. Mir fällt gerade nicht ein, was und wozu man daran "händisch" 
rumfummeln sollte.
Bzw. was du da gerade so vermisst.... was dich zu dieser Nachfrage 
animiert?

von NichtWichtig (Gast)


Lesenswert?

Je nach Spannungsversorgung kann der MSP einen foppen (nix machen).

Ich hab den mit 5V laufen um an den GPIOs ein olles 128x64 LCD zu 
Betreiben.
Der µC jedoch ist ein Bluepill mit 3V3.

SPI in der FT Version und irgendwann gings dann nicht.

Der MSP ist da pingelig was den Spannungslevel am SPI angeht.

5V * 0.8 oder so ist mehr als 3v3.

Vcc etwas niedriger setzten (Diode) half damit das LCD wieder bedient 
wurde.

von Egonwalter M. (heiner1234)


Lesenswert?

EAF schrieb:
> Egonwalter M. schrieb:
>> Fehlt bei Deinem Programm nicht die Verwendung von MISO - ist zwar
>> definiert, aber nicht verwendet ... wenn Achim dann Daten einlesen will?
>
> Ähhmmm.....
> Soweit mir bekannt, wird Miso von der SPI Hardware bedient, bzw.
> gelesen. Mir fällt gerade nicht ein, was und wozu man daran "händisch"
> rumfummeln sollte.
> Bzw. was du da gerade so vermisst.... was dich zu dieser Nachfrage
> animiert?

Wenn Du so fragst ...
Naja, ich verwende SPI zur Kommunikation zwischen 2 ATMega328, übertrage 
22 Bytes / Zyklus (und da ist MISO nötig), und gemäß Bild "Figure 17-2 
SPI Master-Slave Interconnection" von ATtiny441/841 [DATASHEET]
8495H–AVR–05/2014 steht es so... kann mich aber natürlich irren ...

wahrscheinlich weißt Du es besser

von Egonwalter M. (heiner1234)


Lesenswert?

@EAF

MISO - MasterInSlaveOut => Master liest vom Slave, daher sollte man den 
MISO Eingang villeicht schon per SW bedienen (vielleicht als Eingang 
setzen??), wenn der Master Daten vom Slave lesen will.

Kann mich natürlich irren...

von EAF (Gast)


Lesenswert?

Egonwalter M. schrieb:
> (und da ist MISO nötig),

Ich spreche mich ja überhaupt nicht gegen die Verwendung von Miso aus!
Ich frage dich nur, was du bei einem Master, an dem Miso, rumfummeln 
willst?
Selbst bei einem Slave wechselt Miso automatisch von "open", in den 
Output Mode, wenn /CS anliegt
Das tut die SPI Hardware Einheit ganz eigenständig.

Egonwalter M. schrieb:
> wahrscheinlich weißt Du es besser
Vielleicht!
Mag sein..... muss aber nicht.
Dennoch verstehe ich nicht, was du meinst.

von EAF (Gast)


Lesenswert?

Egonwalter M. schrieb:
> daher sollte man den
> MISO Eingang villeicht schon per SW bedienen (vielleicht als Eingang
> setzen??),
1. Eingang ist der Default für alle IOs, also nicht nötig
2. S. Landolt setzt Miso ganz explizit auf Input, auch wenn unnötig
3. Die SPI Hardware macht die Umschaltung von Input zu Output je nach 
Bedarf automatisch.

Ich sehe wirklich nicht, was dir da fehlt.

von EAF (Gast)


Lesenswert?

Sorry, es stimmt nicht ganz, was ich gesagt habe!
> Table 17-1. SPI Pin Overrides

Im Slave Mode muss man Miso händisch auf Output setzen.
Im Master Mode ist es immer ein Input,

Da wir hier über einen Master sprechen, muss man Miso nicht anfassen.
(wenigstens das stimmt)

von Egonwalter M. (heiner1234)


Lesenswert?

@EAF

Wenn Du meinst

von EAF (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Wenn Du meinst

Nein, nicht meinen....
Jetzt, spätestens, nach dem ich die SPI Abteilung dieses konkreten µC 
gelesen habe, bin ich mir ganz Sicher.
So dass es keine Meinung ist, sondern Wissen.
Gewissheit.

Du hast das Datenblatt doch auch vor dir liegen!
Oder?
In deinem steht es auch so drin.

von Egonwalter M. (heiner1234)


Lesenswert?

EAF schrieb:
>
> Im Slave Mode muss man Miso händisch auf Output setzen.
> Im Master Mode ist es immer ein Input,
>
> Da wir hier über einen Master sprechen, muss man Miso nicht anfassen.
> (wenigstens das stimmt)

Stimmt.

Hatte bei meinem Master MISO explizit als Eingang gesetzt, ist aber 
nicht nötig

: Bearbeitet durch User
von Achim (Gast)


Lesenswert?

Hallo an alle
Sorry das mich erst jetzt melde, war heute morgen beim Augenarzt. War 
unbedingt nötig damit ich alles lesen kann. Langsam kommt das lesen 
wieder. Mit dem Programm mache ich erst heute abend weiter.

Heiner schrieb:
> Jetzt fehlt Achim nur noch das Einlesen vom MCP23S17 (z.B. Schalter)

Das stimmt genau. Da ich bisher mit I2C gearbeitet habe ist SPI total 
neu für mich. Werde die Sachen später eintippen und sehen wie es 
funktioniert. Bitte alle Probleme nacheinander, nicht alles auf einmal. 
Habe damit schon genug Probleme.

von EAF (Gast)


Lesenswert?

Achim schrieb:
> nicht alles auf einmal.
Richtig!
Bitte immer nur im Schritttempo denken!

von S. Landolt (Gast)


Lesenswert?

Na, da hätt' ich auch noch was (nämlich Reinhard Mey):

Ich übe den Fortschritt,
und das nicht faul,
nehme zwei Schritt auf einmal
und fall aufs Maul.

von Achim (Gast)


Lesenswert?

Schritttempo - kann man das so sagen?
Lieber von Erfolg zu Erfolg

von Egonwalter M. (heiner1234)


Lesenswert?

Achim schrieb:
> Hallo an alle
> Sorry das mich erst jetzt melde, war heute morgen beim Augenarzt. War
> unbedingt nötig damit ich alles lesen kann. Langsam kommt das lesen
> wieder. Mit dem Programm mache ich erst heute abend weiter.

Off Topic
Augenarzt - gute Idee, sollte ich auch mal wieder hin (=> MISO!!) ;-)

von EAF (Gast)


Lesenswert?

Achim schrieb:
> Schritttempo - kann man das so sagen?
> Lieber von Erfolg zu Erfolg

Zwei vor, einen zurück.
Was einem "lieber" ist, ist nicht unbedingt mit der Realität vereinbar.

von Achim (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Off Topic
> Augenarzt - gute Idee, sollte ich auch mal wieder hin (=> MISO!!) ;-)

Gute Idee - fand ich auch, leider der Termin erst nach ca. 5 Monaten

Weiter mit dem Programm. Bin dabei alles zu vergleichen um den oder die 
Fehler zu finden. Ein paar Sachen sind mir schon aufgefallen, z.B.
1
void spi_master_init(void)
2
    {
3
    SPI_PORT = 0xFF;
4
    SPI_DDR  = (1<<SS) | (1<<MOSI) | (1<<SCK);
5
    SPCR =(1<<SPR0);  // CLK Teiler auf 16 setzen 
6
    SPCR     = (1<<SPE) | (1<<MSTR); 
7
    }
Muss dort nich noch der Teiler rein?
Muss nicht SEQOP und HAEN in IOCONA gesetzt werden?

Und noch ein Problem, das Programm geht nicht und es kommt keine 
Fehlermeldung.

von Heiner (Gast)


Lesenswert?

Achim

Hast Du das Programm von S. Landolt komplett übernommen und nur die 
Ports angepasst wie in seinem Programm angegeben oder wieder 
“rumgefummelt” (was Du ja immer machst)?

So wie ich ihn verstanden habe, müsste sein Programm problemlos laufen

von S. Landolt (Gast)


Lesenswert?

an Achim:

Das Programm läuft, so wie es ist, mit einem ATmega48PA auf einem 
Steckbrett; sollte, nach Anpassung der Pin-Definitionen, auch auf dem 
ATtiny841 funktionieren. Die aus dem Teiler /4 folgende SPI-Frequenz von 
4 MHz liegt unter dem vom MCP23S17 geforderten Wert.
  Wobei die von Ihnen eingefügte Zeile rein gar nichts bewirkt, da der 
anschließende Befehl den Wert überschreibt, Stichwort VerODERung.

Sie haben /RESET des MCP23S17 gegen Vdd angeschlossen? Mein (altes) 
Datenblatt ist da etwas irreführend.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> /RESET des MCP23S17 gegen Vdd angeschlossen?
Natürlich wäre auch ein Schaltplan und ein Foto vom realen Aufbau zur 
Fehlersuche hilfreich. Genauso wie Bilder vom den Oszi-Messungen...

Achim schrieb:
> Und noch ein Problem, das Programm geht nicht
Wie stellst du das fest?
Kann ja sein, dass das Programm tadellos funktioniert, aber die Hardware 
schlecht ist.

> Bin dabei alles zu vergleichen um den oder die Fehler zu finden.
Ich hatte da schon mal geschrieben, wie man so einen Bus in Betrieb 
nimmt:
Beitrag "Re: SPI mit Attiny 841 und MCP23S17"

Ein digitales 4-Kanal-Oszi ist da natürlich der Hit. Aber man kann auch 
ein analoges Einkanal-Oszi nehmen, damit kurz mal die Signalintegrität 
der beteiligten Signale kontrollieren und den Rest der Inbetriebnahme 
mit dem 10€ Logikanalyzer machen.

Der Witz an dieser schrittweisen Vorgehensweise: sie hat bisher immer 
funktioniert und nach einem halben Tag läuft der Bus. Denn du musst dich 
nicht am Punkt 4 (die richtigen Bits an der richtigen Stelle) abmühen, 
wenn die Signalqualität auf dem Bus nicht passt und z.B. der SCK 
klingelt wie die bayerische Bimmelbahn.

Oder andersrum: es ist mir ein Rätsel, wie man so einen seriellen Bus 
ohne Oszi (und LA) in Betrieb nehmen will. Denn ohne solche Messgeräte 
kann man nicht mal bewerten, ob die Signalqualität und das Timing zu den 
Vorgaben aus dem Datenblatt passen...

: Bearbeitet durch Moderator
von Egonwalter M. (heiner1234)


Lesenswert?

Primär würde ich
- erst mal die Verdrahtung prüfen (korrekte Verdrahtung, keine kalte 
Lötstellen, Kabellänge Master-Slave checken etc)
- dann mein Programm minimieren
- dann extensiv(!!) das Datenblatt mit meiner Programmierung vergleichen
- dann - falls das Programm "aus dem Netz ist" dieses mit dem aus dem 
Netz gesaugten vergleichen (unter der - vielleicht falschen Annahme - 
dass das gesaugte Programm tatsächlich funktionsfähig ist)

UND dann erst würde ich einen LA (habe aber keinen) oder einen Oszi 
(dito) anschließen.

Ich habe meine I2C und SPI Kommunikation auch OHNE LA und Oszi in 
Betrieb genommen (MCP23017, 2 ATMega328, PCA9555 etc) und es läuft.

Zur Fehlersuche sind obige Geräte sicherlich sehr hilfreich, aber wenn 
man keine hat ... für meine kleinen Basteleien sind obige Geräte m.E. 
nicht zwingend nötig

: Bearbeitet durch User
von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:
> an Achim:
>
> Sie haben /RESET des MCP23S17 gegen Vdd angeschlossen? Mein (altes)
> Datenblatt ist da etwas irreführend.

Ich habe /RESET mit 10kOhm an Vdd angeschlossen (man kann dann mittels 
Taster den man. Reset ohne Kurzschluss machen)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Egonwalter M. schrieb:
> Zur Fehlersuche sind obige Geräte sicherlich sehr hilfreich
Sie sind nicht primär zur Fehlersuche, sondern zum sicherstellen, dass 
die realen Timings zum Datenblatt passen. So wie ein Schraubendreher 
sicherstellt, dass eine Schraube entsprechend ihres vorgesehenen 
Einsatzbereichs angewendet wird. Man kann die Schraube aber auch mit dem 
Hammer reindreschen. Kann sein, dass das funktioniert.

> aber wenn man keine hat...
So ein LA kostet nun heute nicht mehr arg viel.

von Egonwalter M. (heiner1234)


Lesenswert?

Lothar M. schrieb:
> Egonwalter M. schrieb:
>> Zur Fehlersuche sind obige Geräte sicherlich sehr hilfreich
> Sie sind nicht primär zur Fehlersuche, sondern zum sicherstellen, dass
> die realen Timings zum Datenblatt passen.
>
>> aber wenn man keine hat...
> So ein LA kostet nun heute nicht mehr arg viel.

Aha! Also checkst Du das reale Timing immer, auch wenn kein Fehler 
ansteht. Kann man machen, muss man nicht.

Jedem das Seine

von Egonwalter M. (heiner1234)


Lesenswert?

Lothar M. schrieb:
> Egonwalter M. schrieb:
>> Zur Fehlersuche sind obige Geräte sicherlich sehr hilfreich
> So wie ein Schraubendreher
> sicherstellt, dass eine Schraube entsprechend ihres vorgesehenen
> Einsatzbereichs angewendet wird. Man kann die Schraube aber auch mit dem
> Hammer reindreschen. Kann sein, dass das funktioniert.
>

Es gibt Dübel (mit Schraube!!) von Fischer, die werden mit dem Hammer 
eingeschlagen!! Kannste dann mit dem Schraubendreher wieder 
rausdrehen,aber eingeschlagen ins Bohrloch werden sie mit dem Hammer!!!

von EAF (Gast)


Lesenswert?

Egonwalter M. schrieb:
> ....
Möchtest du mir erklären, dass Oszi und LA überflüssig sind?
Oder willst du gar nicht sehen, wie Spitz auf Knopf, deine Dinger genäht 
sind?
Aus den Augen, aus dem Sinn!

Sorgfalt!
I2C erfordert ein Mindestmaß! SPI auch!
Selbst die Bohrlöcher, für deine Nageldübel.
Hier mal ein Fremdwort für dich: Spezifikation!
(und natürlich das einhalten der selben)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Egonwalter M. schrieb:
> Aha! Also checkst Du das reale Timing immer, auch wenn kein Fehler
> ansteht.
Ja, genau das tue ich. Schon allein um sicher zu sein, dass es so ist, 
wie ich es vermute und geplant habe.

Denn wenn man das nicht macht, dann kann man schon mal den falschen 
SPI-Mode erwischen und das Design läuft "prinzipiell" trotzdem. Bis man 
das Ding mal in den Klimaschrank packt und auf -20..100°C durchknechtet. 
Dann schalten irgendwelche Ausganstreiber mehr oder weniger schnell und 
die Bits verschieben sich selbständig im Protokoll...

Egonwalter M. schrieb:
> Es gibt Dübel (mit Schraube!!) von Fischer, die werden mit dem Hammer
> eingeschlagen!! Kannste dann mit dem Schraubendreher wieder
> rausdrehen,aber eingeschlagen ins Bohrloch werden sie mit dem Hammer!!!
Fehlt da nicht noch ein Ausrufezeichen?

Aber du hast Recht: es gibt auch Busse, wo ich mit dem Oszi und dem LA 
nichts anfangen kann und andere qualifiziertere Messmittel brauche, um 
die Signalintegrität sicherzustellen.

von S. Landolt (Gast)


Lesenswert?

> Muss nicht SEQOP und HAEN in IOCONA gesetzt werden?

Um was genau zu bewirken?
  Müssten diese beiden Bits generell gesetzt werden, so wären sie ja 
völlig sinnlos, nicht wahr? Das gezeigte Einfachstprogramm kommt ohne 
aus.

von Achim (Gast)


Lesenswert?

Heiner schrieb:
> ast Du das Programm von S. Landolt komplett übernommen und nur die
> Ports angepasst wie in seinem Programm angegeben oder wieder
> “rumgefummelt” (was Du ja immer machst)?
>
> So wie ich ihn verstanden habe, müsste sein Programm problemlos laufen

An dem Programm habe ich nicht "rumgefummelt". Habe es fast ohne 
änderung übernommen. Als einziges sind dind die Pins/Ports angepasst 
worden.
Das mit dem Programm habe ich genau so verstanden.

S. Landolt schrieb:
> Die aus dem Teiler /4 folgende SPI-Frequenz von
> 4 MHz liegt unter dem vom MCP23S17 geforderten Wert.

Das DB habe ich so verstanden, das max. 10MHz möglich sind. Nach unten 
sind auch andere Frequenzen möglich.

S. Landolt schrieb:
> Sie haben /RESET des MCP23S17 gegen Vdd angeschlossen? Mein (altes)
> Datenblatt ist da etwas irreführend.

Reset liegt auf +5V.

S. Landolt schrieb:
> Wobei die von Ihnen eingefügte Zeile rein gar nichts bewirkt, da der
> anschließende Befehl den Wert überschreibt, Stichwort VerODERung.

Dieser Zusammenhang versteh ich nicht ganz. Hatte es mir im DB 
angeschaut und versteh es leider nicht.

S. Landolt schrieb:
> Um was genau zu bewirken?
>   Müssten diese beiden Bits generell gesetzt werden, so wären sie ja
> völlig sinnlos, nicht wahr?

Mit HAEN werden doch die Adreesn für A0,A1 und A2 freigegeben, 0x40 wird 
doch hier als Adresse verwendet. Nach deinen Worten muss die Adresse 
nicht angegeben werden, es funktioniert auch so.

Streite euch nicht um Dübel und Löcher oder anderes. Habe den I2C Bus 
auch ohne Oszi hinbekommen. Hatte bereits in einem anderen Beitrag Teile 
zu einem Projekt mit einm TFT Farbdisplay gezeigt, was nicht so ganz 
einfach war.

von S. Landolt (Gast)


Lesenswert?

> Nach unten sind auch andere Frequenzen möglich.

Eben. Dann passen folglich die 4 MHz, ohne explizites Setzen des 
Teilers, Default ist ja /4. Es sei denn, dass der Aufbau sehr ungünstig 
ist.

> ... Dieser Zusammenhang versteh ich nicht ganz ...

Ganz einfach: wenn auf ein 'SPCR =' wieder ein 'SPCR =' folgt, so wird 
das erste schlicht überschrieben; soll es gültig bleiben, muss es beim 
zweiten Mal 'SPCR |=' heißen.

von Achim (Gast)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
> Ganz einfach: wenn auf ein 'SPCR =' wieder ein 'SPCR =' folgt, so wird
> das erste schlicht überschrieben; soll es gültig bleiben, muss es beim
> zweiten Mal 'SPCR |=' heißen.

Das kannte ich nicht, Danke für deine Info.

Achim schrieb:
> SPI_DDR = (1<<SS) | (1<<MOSI) | (1<<SCK);

Gilt deine Info auch für diese Aufzählung? Muss es SPI_DDR|= sein?

Habe mal die Schaltung gezeichnet, wie sie mal aussehen soll und nach 
dem vorhandenen Aubau.

von S. Landolt (Gast)


Lesenswert?

Fazit: am Program liegt es nicht. Es könnte noch irgendein misslicher 
Unterschied zwischen ATmega48 und ATtiny841 sein, glaube ich aber 
weniger. Bleibt nur noch der Aufbau.
  Die Schaltung selbst sieht auf den ersten Blick okay aus.

SPI_DDR wird in meinem Programm nur einmal gesetzt, da spielt es keine 
Rolle, ob '=' oder '|='.

von Achim (Gast)


Lesenswert?

Habe die Schaltung auch noch mal angeschaut. Die LEDs auf Register A 
liegen ja auf GND über den RN. Welche Spannung nehmen die GPIO an? Damit 
die LEDs leuchten brauche ich ja +5V.

von S. Landolt (Gast)


Lesenswert?

> Welche Spannung nehmen die GPIO an?

Das ist unkritisch: laut Datenblatt Parameter 'D080 Output Low-Voltage' 
0.6 V sowie 'D090 Output High-Voltage' Vdd-0.7V.

von S. Landolt (Gast)


Lesenswert?

Wenn ein Multimeter vorhanden ist, so wäre der nächste Schritt, an 
beiden ICs (direkt) die Betriebsspannung zu messen sowie das /Reset am 
MCP23S17. An den SPI-Leitungen sollte sich, mit etwas Glück, Bewegung 
erkennen lassen (Oszilloskop oder LogicAnalyzer wäre natürlich besser), 
notfalls die Übertragung verlangsamen mit 'SPCR |= (1<<SPR1) | 
(1<<SPR0)', d.h. Teiler /128.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Die Schaltung selbst sieht auf den ersten Blick okay aus.
Mir fehlt dringend ein Blockkondensator am MCP. Da steht zwar nichts im 
Datenblatt, aber wenn das Ding mindestens mal die MISO-Leitung mit ein 
paar MHz treiben muss erscheint der sinnvoll. Und nicht umsonst hat der 
Chipdesigner für Vcc und GND zwei nebeneinanderliegende Pins genommen. 
Der C4 ist da tatsächlich ideal dafür geeignet. Denn dort wo er derzeit 
gezeichnet ist, ist er nutzlos.

Und natürlich kann man auch ein kleines Layout ganz locker vollständig 
vergeigen...

S. Landolt schrieb:
> Wenn ein Multimeter vorhanden ist
Es ist sogar ein Oszilloskop vorhanden. Da könnte man sogar messen, ob 
die Versorgung ordentlich stabil ist oder herumzappelt.

> An den SPI-Leitungen sollte sich, mit etwas Glück, Bewegung erkennen
> lassen (Oszilloskop oder LogicAnalyzer wäre natürlich besser)
Kaum zu glauben ... was schreibe ich seit genau einem kompletten Tag? 
Liest das eigentlich irgendwer?

Wünsche viel Erfolg beim weiteren Herumfrickeln!

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

Was noch sinnvoll wäre: im Programm ein Blinken an z.B. LP3 / PB0 
einbauen, damit sichergestellt ist, dass das Programm überhaupt läuft.

von Achim (Gast)


Lesenswert?

Lothar M. schrieb:
> Kaum zu glauben ... was schreibe ich seit genau einem kompletten Tag?
> Liest das eigentlich irgendwer?

Ja, ich lese es sehr genau. Versuche alle Infos zu verstehen.

S. Landolt schrieb:
> Was noch sinnvoll wäre: im Programm ein Blinken an z.B. LP3 / PB0
> einbauen, damit sichergestellt ist, dass das Programm überhaupt läuft.

Das ist eine sehr gute Idee. werde es noch einbauen.

von Achim (Gast)


Lesenswert?

Habe mir die Ansteuerung Master SPI im Atmega48 angeschaut. Scheint 
beides gleich zu sein. Komisch

Beitrag #7190868 wurde von einem Moderator gelöscht.
von jo mei (Gast)


Lesenswert?

Lothar M. schrieb:
> Wünsche viel Erfolg beim weiteren Herumfrickeln!

Ja das wünsche ich auch. Frickel as Frickel can. Ohne Sinn
und Verstand.

Allerdings kann ich nicht erkennen wie jemals ein Bit an den
Ports richtig herauskomen soll. Die diversen modifizierten
Programme mögen zwar "laufen" aber nichts sichtbares ergeben.
Solange die Write-Funktion drei Bytes statt zwei pro Chip-
Select Zyklus ausgibt wird sich der MCP23S17 nicht ange-
sprochen fühlen, allerhöchstens durch reinen Zufall ein
Register berührt werden.

Wie ich bereits vor einiger Zeit
Beitrag "Re: SPI mit Attiny 841 und MCP23S17"
angemerkt habe. Die Funktion entspricht nicht den Anforderungen
des Datenblatts.
Aber vielleicht hab ich auch irgendwas verpasst.

Beitrag #7190985 wurde von einem Moderator gelöscht.
von Hugo H. (hugo_hu)


Lesenswert?

Ist es seit neuestem erlaubt, mit 2 Identitäten in einem Thread zu 
schreiben?

Achim(Gast) aka Heiner(Gast)

siehe z.B.

Beitrag "Attiny 441 Register des Komparator 0"

Beitrag #7191016 wurde von einem Moderator gelöscht.
Beitrag #7191018 wurde von einem Moderator gelöscht.
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Hugo H. schrieb:
> Achim(Gast) aka Heiner(Gast)
Nicht ganz, aber der Heiner(Gast) fährt in diesem Thread trotzdem unter 
2 Flaggen. Ich habe die Posts mit dem 2. Usernamen gelöscht.

@ Heiner(Gast): Mehrere Namen pro Thread sind nicht erlaubt, siehe die 
Nutzungsbedingungen. Melde dich wieder mit deinem ursprünglichen 
Namen an.

von Axel R. (axlr)


Lesenswert?

Ich lese jetzt hier schon drei Tage mit:
1
void MCP23S17_byteWrite(uint8_t pex, uint8_t reg, uint8_t value)
2
{
3
  digitalWrite(CS, LOW);
4
5
  SPI.transfer(OPCODEW | ((pex << 1) & 0x0E)); // Send the MCP23S17 opcode, chip address, and write bit
6
  SPI.transfer(reg); // Send the register we want to write
7
  SPI.transfer(value); // Send the byte
8
9
  digitalWrite(CS, HIGH);
10
}
"pex" ist der Port_Expander_x null bis sieben, reg ist das Register und 
Value eben das, was Du da reinschreiben willst.
OPCODEW ist der Opcode für den Expander uns so definiert:
1
#define OPCODEW     (0b01000000) // Opcode for MCP23S17 with LSB (bit0) set to write (0), address OR'd in later, bits 1-3

Nach meinen Unterlagen sind es wohl tatsächlich drei Bytes, die hier 
gesendet werden.

Die Initialisierung sieht so aus, bei mir:
Da ich im aktuellen Design nur einen Portexpander drinnen habe, hatte 
ich den Rest (Zeilenweise) auskommentiert.
1
void MCP23S17_INIT()
2
{
3
//  int i;
4
//  for ( i=0; i<2; i++)
5
//  {
6
//    //MCP23S17_byteWrite(i,IOCON, SEQOP | HAEN );
7
//    MCP23S17_byteWrite(i,IOCON, HAEN );
8
//    MCP23S17_byteWrite(i,IODIRA, mpxdira[i]);
9
//    MCP23S17_byteWrite(i,IODIRB, mpxdirb[i]);
10
//    MCP23S17_byteWrite(i,OLATA, statusa[i]);
11
//    MCP23S17_byteWrite(i,OLATB, statusb[i]);
12
//  }
13
  MCP23S17_byteWrite(0,IODIRA, 0 );     // PORT_a auf Ausgang...HAEN noch auf "0", somit hören alle.
14
  MCP23S17_byteWrite(0,IODIRB, 0 );     // PORT_b auf Ausgang...HAEN noch auf "0", somit hören alle.
15
  MCP23S17_byteWrite(0,OLATA, 0);     // |
16
                                      //  > Alles aus
17
  MCP23S17_byteWrite(0,OLATB, 0);     // |
18
  MCP23S17_byteWrite(0,IOCON, SEQOP | HAEN );  
19
//  MCP23S17_byteWrite(1,IOCON, HAEN );
20
//  MCP23S17_byteWrite(2,IOCON, HAEN );
21
22
//  MCP23S17_byteWrite(2,IODIRA, mpxdira[2]); // Direction"A"
23
//  MCP23S17_byteWrite(2,IODIRB, mpxdirb[2]); // Direction"B"
24
//  MCP23S17_byteWrite(2,OLATA, statusa[2]);
25
//  MCP23S17_byteWrite(2,OLATB, statusb[2]);
26
27
}
IODIRA usw. sind die registerdefinitionen aus dem Datenblatt, kann man 
auch direkt 0x00, 0x01 usw eintragen. Sooft braucht mans ja nicht.
1
#define OLATA   (0x14) // MCP23x17 Output Latch Register
2
#define OLATB   (0x15) // 1 = Latch High, 0 = Latch Low (default) Reading Returns Latch State, Not Port Value!
3
#define IODIRA    (0x00) // MCP23x17 I/O Direction Register
4
#define IODIRB    (0x01) // 1 = Input (default), 0 = Output
5
#define SEQOP      0x20    // address pointer does not increment.
6
#define HAEN      0x08    // Enables the MCP23S17 address pins.
SPI hab ich MODE0, 1MHz und MSBFirst eingestellt.

von Achim (Gast)


Lesenswert?

Achim ist Achim und kein Heiner

von Achim (Gast)


Lesenswert?

Habe es eingefügt:
1
while (1)
2
    {
3
      mcp_write(MCP_OPC, GPIOA, 0xFF);
4
      PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
5
      _delay_ms(500);
6
      mcp_write(MCP_OPC, GPIOA, 0x00);
7
      PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein 
8
      _delay_ms(500);
9
    }
Damit blinkt die LED korrekt.

von S. Landolt (Gast)


Lesenswert?

... und 200 auf 500 geändert - außerdem noch etwas? Oder anders 
formuliert: ich würde gerne das aktuelle Programm sehen (als Anhang), 
nur zur Sicherheit.

von Egonwalter M. (heiner1234)


Lesenswert?

Achim schrieb:
> Habe es eingefügt:
>
1
> while (1)
2
>     {
3
>       mcp_write(MCP_OPC, GPIOA, 0xFF);
4
>       PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
5
>       _delay_ms(500);
6
>       mcp_write(MCP_OPC, GPIOA, 0x00);
7
>       PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein
8
>       _delay_ms(500);
9
>     }
10
>
> Damit blinkt die LED korrekt.

Damit blinkt aber doch nur die LED PB0 vom Attiny841 und nichts vom 
MCP23S17 - also fkt der SPI noch nicht, oder irre ich mich?

von S. Landolt (Gast)


Lesenswert?

> Damit ...

So ist es. Es sollte damit nur sichergestellt werden, dass wirklich das 
angefasste Programm auf den Controller übertragen wird und dort läuft.

von Achim (Gast)


Lesenswert?

1
int main(void)
2
    {
3
      DDRB=0b00000001;      // Port B auf Ausgang schalten
4
    PORTB=0b00000001;      // Port B auf aus  
5
    spi_master_init();
6
    mcp_init(MCP_OPC);
7
    while (1)
8
      {
9
      mcp_write(MCP_OPC, GPIOA, 0xFF);
10
      PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
11
      _delay_ms(500);
12
      mcp_write(MCP_OPC, GPIOA, 0x00);
13
      PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein 
14
      _delay_ms(500);
15
      }
16
    }
Nur diese Sachen habe ich geändert, alles andere ist noch genauso. Die 
LED blinkt, SPI geht nicht.

von Achim (Gast)


Lesenswert?

Axel R. schrieb:
> //  int i;
> //  for ( i=0; i<2; i++)
> //  {
> //    //MCP23S17_byteWrite(i,IOCON, SEQOP | HAEN );
> //    MCP23S17_byteWrite(i,IOCON, HAEN );
> //    MCP23S17_byteWrite(i,IODIRA, mpxdira[i]);
> //    MCP23S17_byteWrite(i,IODIRB, mpxdirb[i]);
> //    MCP23S17_byteWrite(i,OLATA, statusa[i]);
> //    MCP23S17_byteWrite(i,OLATB, statusb[i]);
> //  }
>   MCP23S17_byteWrite(0,IODIRA, 0 );     // PORT_a auf Ausgang...HAEN
> noch auf "0", somit hören alle.
>   MCP23S17_byteWrite(0,IODIRB, 0 );     // PORT_b auf Ausgang...HAEN
> noch auf "0", somit hören alle.
>   MCP23S17_byteWrite(0,OLATA, 0);     // |

i ist ein Zähler von 0 bis 2, ist klar. Damit werden 3 x MCP23S17 
angesteuert. Was ich nicht verstehe, wieso kann man einfach 0 schreiben? 
Hatte im DB geschaut, komme aber nicht auf die Erklärung.

von S. Landolt (Gast)


Lesenswert?

Warum, bitte, nehmen Sie nicht einfach die aktuelle Programmdatei und 
hängen sie hier an? Dauert doch keine halbe Minute. Damit wäre die 
Softwareseite endgültig ausgeschlossen.
  Dann bliebe nur noch der Aufbau und das Ausmessen dieses - was auch 
schon vorgeschlagen wurde, worauf aber keinerlei Reaktion erfolgte.

von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:
> Warum, bitte, nehmen Sie nicht einfach die aktuelle Programmdatei und
> hängen sie hier an? Dauert doch keine halbe Minute. Damit wäre die
> Softwareseite endgültig ausgeschlossen.
>   Dann bliebe nur noch der Aufbau und das Ausmessen dieses - was auch
> schon vorgeschlagen wurde, worauf aber keinerlei Reaktion erfolgte.

Achim ist nicht nur beratungsresistent, sondern er macht eigentlich nie 
das, was man ihm vorgeschlagen hat.
Wenn er dann von jemandem Codeschnipsel bekommt, versucht er diese 
(leider meist vergebens) zu verstehen und in sein nicht funktionierendes 
Programm zu integrieren.
Manche seiner Fragen bzw Antworten sind nicht unbedingt verständlich.

Er wurde bei diesem Thread schon mehrmals auf den Einsatz eines Oszi und 
LA hingewiesen - keine Reaktion.
Frage nach seinem jetzt verwendeten Programm - Fehlanzeige.

Manche seiner Fragen sind derart trivial und wurden schon in anderen 
seiner Threads beantwortet (Bitshiften, verODERn etc), aber anscheinend 
kann er sich die grundlegenden Sachen nicht merken und muss deshalb 
immer wieder nachfragen.
Alleine die Frage "Was ich nicht verstehe, wieso kann man 0 schreiben" 
zeigt sein Wissen.

Bewundernswert ist seine Hartnäckigkeit.

von Achim (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Alleine die Frage "Was ich nicht verstehe, wieso kann man 0 schreiben"
> zeigt sein Wissen.

Das ist komisch. Der Vorschlag mit dem MCP23S17 kam wohl von dir. Hatte 
bereits den Hinweis gegeben, das ich mit SPI vorher nie etwas gemacht 
habe. Der gesamte verwendete Code steht bereits drin inc. der 
Anschlüssse. Auch der Vorschlag mit den LEDs stand bereits hier. Wieso 
Beratungsresistent, habe es sofort gemacht. Einen LA besitze ich nicht. 
Ein Oszi ist zwar vorhanden, habe aber schon gesagt was ich gemessen 
habe. Leider bin ich kein Profi Signale beim SPI zu messen. Leider ist 
es dein Stil so etwas zu sagen.

von S. Landolt (Gast)


Lesenswert?

> Der gesamte verwendete Code steht bereits drin
> inc. der Anschlüssse.

Nein, das stimmt einfach nicht - wir können uns allenfalls 
zusammenreimen, was Sie gemacht haben könnten.

> schon gesagt was ich gemessen habe

Könnten Sie das bitte nochmals kurz angeben - ich habe bei den 110 
Antworten den Überblick verloren.

von Egonwalter M. (heiner1234)


Lesenswert?

Achim schrieb:
>
> Das ist komisch. Der Vorschlag mit dem MCP23S17 kam wohl von dir. Hatte
> bereits den Hinweis gegeben, das ich mit SPI vorher nie etwas gemacht
> habe.

Korrekt, der Vorschlag kam von mir, nachdem Du in einem Beitrag 
angegeben hast, mit dem ATtiny841 ein Display mittels SPI ansteuern zu 
wollen ohne den SPI zu kennen.
Daraufhin schlug ich vor, Du solltest erst mal mit dem MCP23S17 üben, 
bevor Du mit dem SPI ein Display ansteuerst - was m.E. schwieriger ist 
als mit dem MCP23S17 nur LEDs ansteuern und Taster einlesen - und selbst 
da hast Du große Schwierigkeiten (siehe diesen Thread).

Und was meinst Du mit "leider ist das Dein Stil so etwas zu sagen" - ich 
war weder unhöflich noch beleidigend, ich habe lediglich Dein Verhalten 
beschrieben - und Deine Hartnäckigkeit gelobt

S. Landolt hat ja auf das andere in Deinem obigen Beitrag geantwortet.

: Bearbeitet durch User
von Achim (Gast)


Lesenswert?

Das Display funktioniert, obwohl die Belegung etwas anders ist. Habe 
auch Sonderzeichen dazu gemacht.
Würde aber heute sagen das der MCP23S17 schwieriger ist als das Display. 
Gerade durch die Angaben wie Adresse, Register und Daten und zusätzlich 
auch noch die Bank kommt man sehr schnell durcheinader. Zu den anderen 
Schwierigkeiten bei diesem IC kann ich noch nichts sagen da ich noch 
nicht so weit bin.
Habe im Netz auch nach anderen Erklärungen, Tuts oder anderes gesucht 
was einen die Ansteuerung näher bringt, leider nur mit geringem Erfolg. 
Auch wenn ich andere Prozessor angebe, ist der Erfolg nicht sehr gross. 
Zum Attiny841 und SPI bzw. I2C Bus sieht es nicht besser aus.

Egonwalter M. schrieb:
> und Deine Hartnäckigkeit gelobt

Das freut mich, aber ärgert mich auch gleichzeitig. Es stimmt, als 
Anfänger fehlt mit viel Wissen. Leider kann ich damit (noch) nichts 
anfangen.

Egonwalter M. schrieb:
> verODERn

Habe gerade angefangen im Netz danach zu suchen.
Ist bei dieser Sache nicht Hartnäckigkeit ein Ausdruck um Wissen zu 
erlangen?
Habe mir einfach vorgenommen den Attiny841 zu nutzen. Er zeichnet sich 
für mich durch seine Kleinheit (SMD) und die relativ wenigen I/O als 
Ausreichend für kleine Projekt. Seine inneren Werte findet man sonst 
erst grösseren Prozessor. Leider ist er bei einigen Sachen anders als 
die anderen Attiny oder Atmega.

von Achim (Gast)


Lesenswert?

Das komplette Programm. Die LEDs habe ich eingefügt und bei MCP und SPI 
geändert. Das Programm schalte die LEDs korrekt in der angegebenen Zeit 
um, es erfolgt keine Fehlermeldung, SPI am MCP23S17 erfolgt keine 
Anzeige.
1
#define F_CPU 16000000UL
2
  #include "util/delay.h"
3
  #include "avr/io.h"
4
  //                  Attiny 841   ATtiny841 old   Atmega48
5
  #define SPI_DDR     DDRA         //  DDRA      DDRB
6
  #define SPI_PORT    PORTA        //  PORTA    PortB
7
  #define SCK         PINA4        //  PA4      PB5
8
  #define MISO        PINA5        //  PA5      PB4
9
  #define MOSI        PINA6        //  PA6      PB3
10
  #define SS          PINA7        //  PA7      PB2
11
12
  #define MCP_OPC     0x40    // 0x40
13
  #define IODIRA      0x00    // 0x00
14
  #define GPIOA       0x12
15
  #define MCP_DDR     SPI_DDR
16
  #define MCP_PORT    SPI_PORT
17
18
  void spi_transfer(uint8_t data)
19
    {
20
    SPDR = data;
21
    while(!(SPSR & (1<<SPIF)));  
22
    }
23
  
24
  void mcp_write(uint8_t addr, uint8_t reg, uint8_t data)
25
    {
26
    SPI_PORT &= ~(1<<SS);  // geändert von MCP auf SPI 
27
    //MCP_PORT &= ~(1<<SS);  // ori
28
    spi_transfer(addr);
29
    spi_transfer(reg);
30
    spi_transfer(data);
31
    SPI_PORT |= (1<<SS);  // geändert von MCP auf SPI
32
    // MCP_PORT |= (1<<SS);  // ori  
33
    }
34
35
  void mcp_init(uint8_t addr)
36
    {
37
    mcp_write(addr, IODIRA, 0x00);  // Port A auf Ausgang
38
    }
39
40
  void spi_master_init(void)
41
    {
42
    SPI_PORT = 0xFF;
43
    SPI_DDR  = (1<<SS) | (1<<MOSI) | (1<<SCK);
44
    SPCR     = (1<<SPE) | (1<<MSTR); 
45
    }
46
47
  int main(void)
48
    {
49
      DDRB=0b00000001;      // Port B auf Ausgang schalten
50
    PORTB=0b00000001;      // Port B auf aus  
51
    spi_master_init();
52
    mcp_init(MCP_OPC);
53
    while (1)
54
      {
55
      mcp_write(MCP_OPC, GPIOA, 0xFF);
56
      PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
57
      _delay_ms(500);
58
      mcp_write(MCP_OPC, GPIOA, 0x00);
59
      PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein 
60
      _delay_ms(500);
61
      }
62
    }

von Egonwalter M. (heiner1234)


Lesenswert?

Achim

Wenn Dein Display mit SPI funktioniert, dann zeige doch mal Dein 
Programm, denn soweit ich mich an den post erinnere, wolltest Du da 
gerade mit dem SPI anfangen.
Dann weißt Du ja, wie der SPI funktioniert und wie er zu parametrieren 
ist.

Ich verwende bei meinen Projekten auch SPI
- Kommunikation zwischen 2 Atmega328 (Master und Slave, tauschen 22 
Bytes zyklisch aus) - programmiert mit dem AVRStudio 4.18 (nix Arduino 
IDE)
- Ansteuerung eines 128*64 Display mittels SPI und MCP23S17, verwende da 
aber die lib von N.Gammon (Arduino), der Master ist ein Atmega168, 
Programm erstellt mit Arduino IDE, geflasht mit ISP.

Ich habe in die 4 SPI Leitungen je 1kOhm und /SS mit 10kOhm auf 5Volt 
gemacht (hatte den Tipp von einem anderen Forum bekommen).

: Bearbeitet durch User
von Achim (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Ich habe in die 4 SPI Leitungen je 1kOhm und /SS mit 10kOhm auf 5Volt
> gemacht (hatte den Tipp von einem anderen Forum bekommen).

Das ist mir total neu.

Egonwalter M. schrieb:
> SS mit 10kOhm auf 5Volt

Das erinnert mich stark an den I2C Bus. Wenn ich mal laut denke, SS ist 
bei Betrieb auf High, zum programmieren bzw, übertragung der daten muss 
SS auf Low gehen und nach Abschluss auf High ..... ?????
Mal sehen ob ich das messen kann.

von Egonwalter M. (heiner1234)


Lesenswert?

Nicht dass ein falscher Eindruck entsteht- die 1kOhm Widerstände sind in 
der MOSI, MISO etc Leitungen, und der/SS ist zusätzlich mit 10kOhm auf 5 
Volt gelegt

von Achim (Gast)


Lesenswert?

Habe den Code mal geändert um mehr Zeit zum messen zu haben.
1
mcp_write(MCP_OPC, GPIOA, 0xFF);
2
PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
3
_delay_ms(2000);
4
mcp_write(MCP_OPC, GPIOA, 0x00);
5
PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein 
6
_delay_ms(2000);
Wenn ich es richtig sehe, wird doch bei mcp_write ... Daten zum MCP 
übertragen, Ausgänge sollen doch geändert werden. Dazu müsste doch SS 
bzw. CS  (Pin 11 zu A7) kurz auf Low gelegt werden, danach wieder auf 
High. Nach der Messung liegen konstante 5V auf dem Pin. Ein kurzzeitiger 
Abfall auf 0V sind nicht erkennbar. ????

von S. Landolt (Gast)


Lesenswert?

> Ein kurzzeitiger Abfall auf 0V sind nicht erkennbar.

Ca. 6 us, um genau zu sein; das Oszilloskop sollte aber anzeigen, dass 
es triggert.
  Es wäre jedoch generell für die Messungen praktisch, den SPI-Takt auf 
ein Minimum zu setzen mit 'SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) | 
(1<<SPR0)'.

von Achim (Gast)


Lesenswert?

Habe eben mal was ausprobiert:
1
void mcp_write(uint8_t addr, uint8_t reg, uint8_t data)
2
    {
3
    //SPI_PORT &= ~(1<<SS);  // geändert von MCP auf SPI 1. 
4
    //MCP_PORT &= ~(1<<SS);  // ori
5
     SPI_PORT |= (1<<SS);  // geändert von MCP auf SPI 2.
6
    spi_transfer(addr);
7
    spi_transfer(reg);
8
    spi_transfer(data);
9
    //SPI_PORT |= (1<<SS);  // geändert von MCP auf SPI 1.
10
    // MCP_PORT |= (1<<SS);  // ori  
11
    SPI_PORT &= ~(1<<SS);  // geändert von MCP auf SPI 2. 
12
    }
Mit diesem Code bleibt (scheinbar) SS konstant auf 0V. Das erinnert mich 
stark an PUB (?) beim Attiny. Es lassen sich R zuschalten. So wie bei 
dir mit dem extra R ? Die zeit probiere ich auch gleich.

von NichtWichtig (Gast)


Lesenswert?

Achim schrieb:
> Habe den Code mal geändert um mehr Zeit zum messen zu haben.
>
1
> mcp_write(MCP_OPC, GPIOA, 0xFF);
2
> PORTB |= (1<<PINB0);    // Schaltet Pin PB0 aus
3
> _delay_ms(2000);
4
> mcp_write(MCP_OPC, GPIOA, 0x00);
5
> PORTB &= ~(1<<PINB0);    // Schaltet Pin PB0 ein
6
> _delay_ms(2000);
7
>
> Wenn ich es richtig sehe, wird doch bei mcp_write ... Daten zum MCP
> übertragen, Ausgänge sollen doch geändert werden. Dazu müsste doch SS
> bzw. CS  (Pin 11 zu A7) kurz auf Low gelegt werden, danach wieder auf
> High. Nach der Messung liegen konstante 5V auf dem Pin. Ein kurzzeitiger
> Abfall auf 0V sind nicht erkennbar. ????

CS muß für die Dauer des Zugriff auf low liegen!

von S. Landolt (Gast)


Lesenswert?

an Achim:

Nein, da sind Sie auf dem völlig falschen Dampfer: das /CS-Signal ist 
active-low!

von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:
>> Ein kurzzeitiger Abfall auf 0V sind nicht erkennbar.

>   Es wäre jedoch generell für die Messungen praktisch, den SPI-Takt auf
> ein Minimum zu setzen mit 'SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1) |
> (1<<SPR0)'.

und SPI2X => f/64

von S. Landolt (Gast)


Lesenswert?

PS:
Und, um es nochmal zu wiederholen: das Programm läuft, mutatis mutandis, 
hier bei mir auf einem ATmega48PA.

an Egonwalter M.:
Damit beschleunigen Sie um den Faktor 2.

Beitrag #7192427 wurde vom Autor gelöscht.
von Egonwalter M. (heiner1234)


Lesenswert?

S. Landolt schrieb:

> an Egonwalter M.:
> Damit beschleunigen Sie um den Faktor 2.

Sie haben recht! Mein Fehler!

von Achim (Gast)


Lesenswert?

S. Landolt schrieb:
> Nein, da sind Sie auf dem völlig falschen Dampfer: das /CS-Signal ist
> active-low!

Im Datenblatt zum MCP23S17 wird doch in der Figur 1-5 angegeben das CS 
auf High liegt und zur übertragung von Device und Register auf Low 
liegen soll und danach wieder auf High. Nach meinem Code ober müsste 
doch bei der übertragung von

NichtWichtig schrieb:
> mcp_write(MCP_OPC, GPIOA, 0xFF);

CS kurz auf Low liegen und danach wieder auf High bis zur nächsten 
übertragung. Nach meiner Messung liegt CS aber dauerhaft auf Low. Habe 
ich da einen Denkfehler?

von S. Landolt (Gast)


Lesenswert?

an Achim:

Halten Sie sich an Ihr um 09:44 gezeigtes Programm und bauen Sie noch 
den Vorschlag von 10:32 ein.

Ganz anderer Punkt: die LPn sind gegen +5V geschaltet, die LSn hingegen 
gegen GND - sind die auch richtig herum eingebaut?

von Klaus S. (kseege)


Lesenswert?

Ich lese diesen Thread mit wachsender Verwunderung. Er läuft seit 4 
Tagen.
Der TO besitzt ein Oszilloskop und damit sollte ein solcher Fehler in 
maximal 2 (in Worten:zwei) Stunden auffindbar sein. Dazu muß man 
aufhören, im Nebel herumzustochern und Schritt für Schritt die Sache von 
unten nach oben aufbauen. Das ist die langsamste, aber sicherste 
Methode.

Zerreißt mich in der Luft, wenn ich Schwachsinn rede, aber nach meiner 
Meinung hätte man spätestens nach 2 Tagen Stocherei umschalten müssen:

1. Miniversion Programm, nur /CS ausgeben, wieder hochsetzen und mit 
Oszi kontrollieren. (30 Minuten maximal)
2. Ein Byte zwischen /CS und CS ausgeben und MOSI und SCK auf die vom 
Slave gebrauchte Polarität prüfen. (30 Minuten maximal)
3. Einen der einfachsten zu beobachtenden Befehle für den Slave einbauen 
und die Reaktion auf dem Slave und auf MISO beobachten (30 Minuten max.)
4. 30 Minuten Zeit, das Datenblatt des Slave aufmerksam zu lesen und die 
eigenen Denkfehler zu lokalisieren.

Im Miniprogramm zum Testen dürfen nur die wirklich benötigten 
Definitionen stehen und keine externen Dateien eingebunden werden um die 
Übersicht zu behalten. Dazu extrahiert man manuell aus den Definitionen 
alles Benötigte.

Just my 2 cents

von S. Landolt (Gast)


Lesenswert?

an Klaus S.:

Korrekt!
Punkte 1 & 2 sind mit meinem Einfachstprogramm bzw. der daraus 
entstandenen Version von 09:44 erfüllt. Für Punkt 3 muss der MCP23S17 
erstmal reagieren, schwierig, in der jetzigen Situation. Punkt 4: das 
Datenblatt ist von eher schlechter Qualität (davon kann offenbar 'jo 
mei' ein Lied singen) - immerhin ist in der neueren Version die 
Inhaltsleiste brauchbar.

von NichtWichtig (Gast)


Lesenswert?

Einspruch, das Datenblatt liefert alle nötigen Informationen.

Der MSP23S17 ist jedoch nicht der kleinste GPIO chip und hat daher mehr 
drin was verstanden werden muß.
Daher #4 in 30 Minuten wäre mehr als sportlich.


Wie Klaus.S schrieb ist eine systematische Inbetriebnahme kein 
wirkliches Problem, Oscar oder LA vorausgesetzt.

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Einspruch, das Datenblatt liefert alle nötigen Informationen.

Was ist mit /CS in Figure 1.5? Daran hat sich auch schon 'jo mei' 
aufgehängt.

von Klaus S. (kseege)


Lesenswert?

S. Landolt schrieb:
> Punkte 1 & 2 sind mit meinem Einfachstprogramm bzw. der daraus
> entstandenen Version von 09:44 erfüllt.

Ja prima! Dann sollte der TO einfach mal 3 Oszillogramme posten:

Einmal CS mit SCK
Einmal CS mit MOSI
Einmal SCK mit MOSI getriggert von /CS

Dann wüßte man, ob der uC korrekt arbeitet. Erst dann lohnt es sich, 
über den Slave überhaupt nachzudenken.

Gruß Klaus (der soundsovielte)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Was ist mit /CS in Figure 1.5?
Das was da gemalt ist, kommt erst viel später...

Vorher ist die Seite 8 und der oberen Hälfte der Seite 9 relevant. Dort 
ist das SPI-Timing bis auf die Nanosekunde genau spezifiziert. Wenn 
dieses Timing nicht passt, kann man herumhampeln wie man will, der Bus 
wird halt trotzdem nicht brauchbar und zuverlässig laufen.

Klaus S. schrieb:
> Schritt für Schritt die Sache von unten nach oben aufbauen
Wie ich schon 4 Stunden nach dem Threadstart schrieb.

Aber ich habe es aufgegeben. Wenn wir nach 4 Tagen noch nicht mal 
wissen, welche Hardware und welches Oszi der Achim hat, obwohl das schon 
öfter zur Diskussion stand, dann wars das. Er will nicht, dass ihm 
geholfen wird. Und so bleibt er der einzige, der weiß was er hat und was 
er macht.

von Axel R. (axlr)


Lesenswert?

Achim schrieb:
> Axel R. schrieb:
>> //  int i;
>> //  for ( i=0; i<2; i++)
>> //  {
>> //    //MCP23S17_byteWrite(i,IOCON, SEQOP | HAEN );
>> //    MCP23S17_byteWrite(i,IOCON, HAEN );
>> //    MCP23S17_byteWrite(i,IODIRA, mpxdira[i]);
>> //    MCP23S17_byteWrite(i,IODIRB, mpxdirb[i]);
>> //    MCP23S17_byteWrite(i,OLATA, statusa[i]);
>> //    MCP23S17_byteWrite(i,OLATB, statusb[i]);
>> //  }
>>   MCP23S17_byteWrite(0,IODIRA, 0 );     // PORT_a auf Ausgang...HAEN
>> noch auf "0", somit hören alle.
>>   MCP23S17_byteWrite(0,IODIRB, 0 );     // PORT_b auf Ausgang...HAEN
>> noch auf "0", somit hören alle.
>>   MCP23S17_byteWrite(0,OLATA, 0);     // |
>
> i ist ein Zähler von 0 bis 2, ist klar. Damit werden 3 x MCP23S17
> angesteuert. Was ich nicht verstehe, wieso kann man einfach 0 schreiben?
> Hatte im DB geschaut, komme aber nicht auf die Erklärung.

die Funktion MCP23S17_byteWrite erledigt das richtige einfügen und 
hinrücken der angegebenen "0", "1" oder "2", was übrigens hier die ganze 
Zeit mit verODERn gemeint ist.

Beitrag "Re: SPI mit Attiny 841 und MCP23S17"

Ich trau mich zwar kaum zu fragen, aber wie machst Du das sonst im 
Programm?
Die Grundlagen der Bitmanipulation? Hast Du da noch nie etwas von 
gehört?
Was machst Du denn, wenn du den ADC-Kanal wechseln wollen wölltest, ohne 
die Referenzspannung an dieser Stelle zu ändern? mal so als Beispiel 
gefragt ...

: Bearbeitet durch User
von Klaus S. (kseege)


Lesenswert?

Lothar M. schrieb:
> Wie ich schon 4 Stunden nach dem Threadstart schrieb.

Habe dummerweise nicht die Geduld gehabt, alles genau zu lesen, sonst 
hätte ich das gern zitiert.

Aber ich bin wohl vom Naturell her geduldiger (4 Tage gegen 4 Stunden), 
insofern gebe ich Achim noch ein paar Tage. Es gibt Menschen, die müssen 
erstmal alle vermeidbaren Fehler selbst gemacht haben, einfach zu 
Lernzwecken :-)
Kenne persönlich mindestens einen solchen Menschen, der ansonsten ein 
herzensguter Kerl ist.

Gruß Klaus (der soundsovielte)

von S. Landolt (Gast)


Lesenswert?

Tja - "Geduld, mein Freund! Geduld sei die stärkste deiner Tugenden", 
sprach der Fuchs.
  Wenn selbst eine so einfache Frage wie die nach der Orientierung 
eingebauter LEDs nicht binnen vier Stunden beantwortet wird ...

von Achim (Gast)


Lesenswert?

So bin wieder da. Habe in den letzten Stunden die gesamte Hardware, 
Platine usw. durchgemessen bzw. angeschaut und überprüft. Hatte wirklich 
Angst das ich was falsch gemacht habe. Leider war es so.
Bitte, Bitte einen grossen Kübel Asche auf mein Haupt. Habe die LEDs am 
MCP verdreht eingebaut. Alle anderen korrekt. Der Fehler lag eindeutig 
bei mir.
Möchte mich in aller Form dafür eintschuldigen euch soviel dumme Fragen 
gestellt zuhaben. Mit der letzten Sftware blinken jetzt alle LEDs am MCP 
und eine LED vom Ati841 zur kontrolle.
Danke für eure Geduld und möchte dafür nochmal entschuldigen.
Werde alles jezt nochmal gründlich lesen und beachten.

von NichtWichtig (Gast)


Lesenswert?

Auch das gehört dazu, man lernt nie aus ;)

von S. Landolt (Gast)


Lesenswert?

Und dazu über vier Stunden?!
  Aber danke für die Rückmeldung - manch anderer scheut sich davor und 
verschwindet einfach.

von Klaus S. (kseege)


Lesenswert?

Achim schrieb:
> Der Fehler lag eindeutig bei mir.

Alte Reparateurs-Weisheit:
Nie jemandem trauen, am Wenigsten sich selbst :-)

Gruß Klaus (der soundsovielte)

von Achim (Gast)


Lesenswert?

NichtWichtig schrieb:
> Auch das gehört dazu, man lernt nie aus ;)

Dem kann ich nur zustimmen. Es ärgert mich ungemein und bin froh das ich 
den Fehler gefunden habe.

S. Landolt schrieb:
> Aber danke für die Rückmeldung - manch anderer scheut sich davor und
> verschwindet einfach.

Ich empfinde es als euer Recht diese Info zu bekommen. Habe über Stunden 
an meinem Problem mitgearbeitet. Mein Dank gilt an euch.
Bis zum nächsten Problem.

von S. Landolt (Gast)


Lesenswert?

> Bis zum nächsten Problem.

Yô - in einer Schleife auf GPIO-B einlesen und gleich wieder auf GPIO-A 
ausgeben.

von Achim (Gast)


Lesenswert?

Du bist aber schnell mit einem neuen Problem. Bin noch bei dem alten 
Problem und muss erst mal meine "alte" Software zum laufen bekommen. 
Danach soll aber das einlesen von Ports kommen um den MCP23S17 besser zu 
verstehen.

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.