Forum: Mikrocontroller und Digitale Elektronik MSP23S17 Adresspins Verhalten


von Maxim B. (max182)


Lesenswert?

Hallo,

ich wollte Adresspins von MSP23S17 benutzen und Verhalten von Chip ist 
komisch: nur A2 wirkt, A1 und A0 scheinen egal zu sein. Ich habe zwei IC 
ausprobiert, alles gleich.
Sind die beide defekt oder weiß ich etwas nicht?

Bei Init setze ich HAEN in IOCON auf 1. Seitdem sollte IC Adresse auf 
A0-A2 unterscheiden. Aber: wenn ich A2 auf 0 halte, antwortet IC auf 
Adressen 0 bis 3, wenn A2 = 1, dann von 4 bis 7. Dabei völlig egal, ob 
A1 und A0 auf 0 sind oder auf 1.

Wo liegt Fehler? Hier ist gekürztes Testprogramm.
1
; spi.asm
2
.macro  SPI_INIT    
3
  sbi SPI_PORT,SPI_SS
4
  in @0, SPI_DDR
5
  ori @0, (1<<SPI_SS)|(1<<SPI_MOSI)|(1<<SPI_SCK)
6
  andi @0, ~(1<<SPI_MISO)
7
  out SPI_DDR, @0
8
  ldi @0, (1<<SPE)|(1<<MSTR)  
9
  out SPCR, @0
10
  ldi @0, (1<<SPI2X)  ; F_CPU/2
11
  out SPSR, @0
12
  out SPDR, @0
13
  sbis SPSR,SPIF
14
  rjmp PC-1
15
.endm
16
17
.macro  SPI_SEND
18
  out SPDR, @0
19
  sbis SPSR,SPIF
20
  rjmp PC-1
21
.endm
22
23
; mcp23s17.asm
24
mcp23s17_wr:  ; temp=Daten, temph=slave address, temp3=IC-Reg
25
  cbi MCP23S17_SS_PORT, MCP23S17_SS
26
  lsl temph
27
  ori temph, (1<<6)  ;0b0100xxx0
28
  SPI_SEND temph
29
  SPI_SEND temp3
30
  SPI_SEND temp
31
  sbi MCP23S17_SS_PORT, MCP23S17_SS
32
  ret
33
34
mcp23s17_rd:  ; temp= geles.Daten, temph=slave address, temp3=IC-Reg
35
  cbi MCP23S17_SS_PORT, MCP23S17_SS
36
  lsl temph
37
  ori temph, (1<<MCP23S17_RW)|(1<<6)  ;0b0100xxx1
38
  SPI_SEND temph
39
  SPI_SEND temp3
40
  SPI_SEND temp
41
  sbi MCP23S17_SS_PORT, MCP23S17_SS
42
  in temp,SPDR
43
  ret
44
45
mcp23s17_init:
46
  ldi temp, (1<<MCP23S17_IOCON_HAEN)
47
  ldi temph, 0
48
  ldi temp3, MCP23S17_IOCON
49
  rjmp mcp23s17_wr
50
51
; ledreihe.asm
52
.equ  LEDREIHE_ADR  = 7
53
.equ  LED1  = 0
54
.equ  LED2  = 7
55
56
led1_ein:
57
    ldi temp, ~(1<<LED1)
58
    ldi temph, LEDREIHE_ADR
59
    ldi temp3, MCP23S17_GPIOB
60
    rjmp mcp23s17_wr
61
62
led1_aus:
63
    ldi temp, (1<<LED1)
64
    ldi temph, LEDREIHE_ADR
65
    ldi temp3, MCP23S17_GPIOB
66
    rjmp mcp23s17_wr
67
68
led2_ein:
69
    ldi temp, (1<<LED2)
70
    ldi temph, LEDREIHE_ADR
71
    ldi temp3, MCP23S17_GPIOA
72
    rjmp mcp23s17_wr
73
74
75
led2_aus:
76
    ldi temp, ~(1<<LED2)
77
    ldi temph, LEDREIHE_ADR
78
    ldi temp3, MCP23S17_GPIOA
79
    rjmp mcp23s17_wr
80
81
; main.asm
82
;...
83
    SPI_INIT temp
84
    rcall mcp23s17_init
85
    rcall led1_ein
86
    rcall led2_aus
87
88
    ldi temp, ~(1<<LED2)
89
    ldi temph, LEDREIHE_ADR
90
    ldi temp3,MCP23S17_IODIRA
91
    rcall mcp23s17_wr       ; GPA7 = Ausgang
92
    ldi temp, ~(1<<LED1)
93
    ldi temph, LEDREIHE_ADR
94
    ldi temp3,MCP23S17_IODIRB
95
    rcall mcp23s17_wr       ; GPB0 = Ausgang
96
97
loop:  rcall led1_aus
98
  rcall led2_ein
99
  MEIN_DELAY_3BYTE 799996
100
  rcall led1_ein
101
  rcall led2_aus
102
  MEIN_DELAY_3BYTE 799996
103
  rjmp loop

Vielen Dank für hilfreiche Tipps

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Schade!
Ich wollte mehrere mcp23S17 mit einem ~SS betreiben, mit verschiedenen 
Adressen A0-A2. Aber solange nur A2 wirkt, kann ich höchstens zwei IC 
auf einem ~SS hängen lassen. Dabei ist Fehler recht komisch, so bleibt 
gewisse Risiko, daß irgendwann auch A2 nicht mehr wirkt... IC stammen 
von Reichelt.

Ich weiß nicht, was hier besser zu machen ist: ein paar mcp23S17 bei 
Conrad bestellen und genauso testen? Oder einfach für alle IC separate 
~SS verwenden? Dann allerdings scheint in manchen Fällen 74HC595 besser 
zu sein: nur 1 byte zu übertragen statt 3.

Ich habe mit verschiedenen Geschwindigkeiten ausprobiert. IOCON lässt 
sich lesen lassen. HAEN steht auf 1. Für Sicherheit habe ich auch andere 
Register abgelesen: alles stimmt.
1
;==== Test
2
mcp23s17_regzeigen:  ; temp3: IC-reg-adr, temph: IC-adr, temp: zeile(7-5)/platz(4-0)
3
  push temph
4
  push temp
5
  mov temph, temp
6
  andi temph, 0x1f
7
  pop temp
8
  swap temp
9
  lsr temp
10
  andi temp, 3
11
  rcall lcd_setcursor
12
  pop temph
13
  rcall mcp23s17_rd
14
15
  mov temph, temp
16
  ldi temp3, 8
17
18
mcp23s17_regzeigen_loop1:
19
  sbrs temph,7
20
  rjmp mcp23s17_regzeigen_L01
21
  ldi temp, '1'
22
  rjmp mcp23s17_regzeigen_H01
23
24
    mcp23s17_regzeigen_L01:  
25
  ldi temp, '0'
26
    mcp23s17_regzeigen_H01:  
27
  rcall lcd_data
28
  lsl temph
29
  dec temp3
30
  brne mcp23s17_regzeigen_loop1
31
  ret
32
33
.macro  MCP23S17_REGLCD    ; @0 = zeile  @1 platz
34
  ldi temp, (@0<<5)|@1  ; @2 = IC-adr @3 =temp3: IC-reg-adr
35
  ldi temph, @2
36
  ldi temp3, @3
37
  rcall mcp23s17_regzeigen
38
.endm
39
40
  MCP23S17_REGLCD 1,8, 0, MCP23S17_IOCON
41
  MCP23S17_REGLCD 1,0, 0, MCP23S17_OLATA
42
  MCP23S17_REGLCD 0,8, 0, MCP23S17_OLATB

 Auch A2 wirkt. Nur A0 und A1 ohne Wirkung... Hat A2 GND, dann antwortet 
IC auf Adressen 0 bis 3. Wenn A2=Vcc, dann sind das die Adressen 4 bis 
7.

von Christian S. (roehrenvorheizer)


Lesenswert?

Hallo,

hast Du die obligatorischen 100nF-Abblockkondensatoren am IC angebracht?
Sind A0...A2 direkt oder über Widerstände immer an GND oder + 
angeschlossen?
Was machst Du mit dem Reset-Anschluß?
Kannst Du mal Exemplare eines anderen Herstellers testen? Vielleicht 
sind die bisherigen Ausschuß?

Bei mir haben sie vor Jahren korrekt funktioniert, als ich die Adressen 
eingestellt habe...

MfG

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Christian S. schrieb:
> hast Du die obligatorischen 100nF-Abblockkondensatoren am IC angebracht?

Ja.

> Sind A0...A2 direkt oder über Widerstände immer an GND oder +
> angeschlossen?

Entweder an GND oder an Vcc.

> Was machst Du mit dem Reset-Anschluß?

Vcc.
Da IC ansonsten alles macht, die Ports arbeiten für IN und OUT, glaube 
ich nicht, daß Reset an Power-on nicht funktioniert.

> Kannst Du mal Exemplare eines anderen Herstellers testen? Vielleicht
> sind die bisherigen Ausschuß?

Ich dachte, die sind alle von Microchip. Macht sie noch jemand?
Ich dachte, bei Reichelt trifft man keine defekten IC wie bei Chinesen 
per Amazon? Sollte ich ein paar von Conrad kaufen?

von S. Landolt (Gast)


Lesenswert?

> Bei Init setze ich HAEN in IOCON auf 1.

Vermutlich geschieht eben dies nicht - lässt sich aber nicht überprüfen, 
da die Definitionen fehlen.

von Maxim B. (max182)


Lesenswert?

S. Landolt schrieb:
> Vermutlich geschieht eben dies nicht - lässt sich aber nicht überprüfen,
> da die Definitionen fehlen.

Ich habe auch IOCON gelesen und auf LCD angezeigt. Dafür dienen Funktion 
mcp23s17_regzeigen und Macros MCP23S17_REGLCD. Ich habe auch alle andere 
Register abgelesen, um sicher zu bleiben, daß IOCON gelesen wird und 
nicht etwas anderes. Ergebnis bei IOCON ist nach Init immer "00001000"

Definitionen:
1
.equ   MCP23S17_IOCON      = 0x05  
2
.equ   MCP23S17_IOCON_1    = 0x0a  
3
.equ  MCP23S17_IOCON_BANK    = 7
4
.equ  MCP23S17_IOCON_MIRROR  = 6  
5
.equ  MCP23S17_IOCON_DISSLW  = 4  
6
.equ  MCP23S17_IOCON_HAEN    = 3  
7
.equ  MCP23S17_IOCON_ODR    = 2  
8
.equ  MCP23S17_IOCON_INTPOL  = 1  
9
10
11
12
.equ   MCP23S17_IODIRA    = 0x00; IOCON.BANK = 0  
13
.equ   MCP23S17_IODIRA_1  = 0x00; IOCON.BANK = 1  
14
15
.equ   MCP23S17_IODIRB    = 0x01; IOCON.BANK = 0
16
.equ   MCP23S17_IODIRB_1  = 0x10; IOCON.BANK = 1
17
18
.equ   MCP23S17_IPOLA    = 0x02; IOCON.BANK = 0  
19
.equ   MCP23S17_IPOLA_1  = 0x01; IOCON.BANK = 1  
20
21
.equ   MCP23S17_IPOLB    = 0x03; IOCON.BANK = 0  
22
.equ   MCP23S17_IPOLB_1  = 0x11; IOCON.BANK = 1  
23
24
.equ   MCP23S17_GPINTENA  = 0x04; IOCON.BANK = 0  
25
.equ   MCP23S17_GPINTENA_1  = 0x02; IOCON.BANK = 1  
26
27
.equ   MCP23S17_GPINTENB  = 0x05; IOCON.BANK = 0  
28
.equ   MCP23S17_GPINTENB_1  = 0x12; IOCON.BANK = 1  
29
30
.equ   MCP23S17_DEFVALA  = 0x06; IOCON.BANK = 0  
31
.equ   MCP23S17_DEFVALA_1  = 0x03; IOCON.BANK = 1  
32
33
.equ   MCP23S17_DEFVALB  = 0x07; IOCON.BANK = 0  
34
.equ   MCP23S17_DEFVALB_1  = 0x13; IOCON.BANK = 1  
35
36
.equ   MCP23S17_INTCONA  = 0x08; IOCON.BANK = 0  
37
.equ   MCP23S17_INTCONA_1  = 0x04; IOCON.BANK = 1  
38
39
.equ   MCP23S17_INTCONB  = 0x09; IOCON.BANK = 0  
40
.equ   MCP23S17_INTCONB_1  = 0x14; IOCON.BANK = 1  
41
42
.equ   MCP23S17_GPPUA    = 0x0c; IOCON.BANK = 0  
43
.equ   MCP23S17_GPPUA_1  = 0x06; IOCON.BANK = 1  
44
45
.equ   MCP23S17_GPPUB    = 0x0d; IOCON.BANK = 0  
46
.equ   MCP23S17_GPPUB_1  = 0x16; IOCON.BANK = 1  
47
48
.equ   MCP23S17_INTFA    = 0x0e; IOCON.BANK = 0  
49
.equ   MCP23S17_INTFA_1  = 0x07; IOCON.BANK = 1  
50
51
.equ   MCP23S17_INTFB    = 0x0f; IOCON.BANK = 0  
52
.equ   MCP23S17_INTFB_1  = 0x17; IOCON.BANK = 1  
53
54
.equ   MCP23S17_INTCAPA  = 0x10; IOCON.BANK = 0  
55
.equ   MCP23S17_INTCAPA_1  = 0x08; IOCON.BANK = 1  
56
57
.equ   MCP23S17_INTCAPB  = 0x11; IOCON.BANK = 0  
58
.equ   MCP23S17_INTCAPB_1  = 0x18; IOCON.BANK = 1  
59
60
.equ   MCP23S17_GPIOA    = 0x12; IOCON.BANK = 0  
61
.equ   MCP23S17_GPIOA_1  = 0x09; IOCON.BANK = 1  
62
63
.equ   MCP23S17_GPIOB    = 0x13; IOCON.BANK = 0  
64
.equ   MCP23S17_GPIOB_1  = 0x19; IOCON.BANK = 1  
65
66
.equ   MCP23S17_OLATA    = 0x14; IOCON.BANK = 0  
67
.equ   MCP23S17_OLATA_1  = 0x0a; IOCON.BANK = 1  
68
69
.equ   MCP23S17_OLATB    = 0x15; IOCON.BANK = 0  
70
.equ   MCP23S17_OLATB_1  = 0x1a; IOCON.BANK = 1  
71
72
73
.equ  MCP23S17_SS_PORT  = PORTB
74
.equ  MCP23S17_SS_DDR    = DDRB
75
.equ  MCP23S17_SS      = PB4
76
77
.equ  MCP23S17_RW      = 0

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Was passiert, wenn Sie in mcp23s17_init
1
  ldi temp3, MCP23S17_IOCON_1
schreiben statt
1
  ldi temp3, MCP23S17_IOCON
?

von Michael U. (amiga)


Lesenswert?

Hallo,

es gab mal ein Errata dazu:
ww1.microchip.com/downloads/en/DeviceDoc/80311a.pdf
Keine Ahnung, ob das auf Deine Chip-Revision zutrifft.
Ich habe nur 2 Stück am SPI-Bus auf Adresse 0 und 1, da ist A2 auf Low 
und es läuft.
ICON hat 2 Adressen für das gleiche Register, 0x0A und 0x0B, es ist 
egal, womit man es adressiert.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Christian S. (roehrenvorheizer)


Lesenswert?

"Ich dachte, die sind alle von Microchip. Macht sie noch jemand?"

Hast Recht.

MfG

von S. Landolt (Gast)


Lesenswert?

Derzeit wird mit
.equ   MCP23S17_IOCON      = 0x05
adressiert, mir scheint, es wurde bei IOCON Bank 0 und 1 verwechselt.

von Maxim B. (max182)


Lesenswert?

S. Landolt schrieb:
> Was passiert, wenn Sie in mcp23s17_init  ldi temp3, MCP23S17_IOCON_1
> schreiben statt  ldi temp3, MCP23S17_IOCON
> ?

Genial!!!!
Nun arbeiten alle Adressenpins!!!!

Ich habe falsche Definition gemacht, Bank verwechselt...

Nun aber spinnt etwas mit anderen Register. Obwohl ich IOCON_BANK auf 0 
lasse, antworten die Register nur auf OLATA_1 und OLATB_1 und nicht auf 
OLATA und OLATB. Ich muß noch irgendwo Fehler haben...

Aber vielen Dank! Wenigstens A0-A2 Pins arbeiten.

von Michael U. (amiga)


Lesenswert?

Hallo,

S. Landolt schrieb:
> Derzeit wird mit
> .equ   MCP23S17_IOCON      = 0x05
> adressiert, mir scheint, es wurde bei IOCON Bank 0 und 1 verwechselt.

IOCON ist nach PowerOn/Reset auf 0x0a/0x0b weil Bank 0 aktiv ist, 
richtig.

Gruß aus Berlin
Michael

von S. Landolt (Gast)


Lesenswert?

Gruß aus dem Schwarzwald:

Hoorig isch die Katz!
Oh jerum, oh jerum, d' Fasnet het e Loch.

von Maxim B. (max182)


Lesenswert?

Guten Abend!

Ich bin immer noch an Basteln mit MCP23S17.

Verhalten von IC ist trotzdem komisch...

Testprogramm:
1. HAEN = 1. MCP23S17 wird für diese Operation mit 0b01000000 
angesprochen.
danach alle Operationen mit Rücksicht auf Einstellung von Pins A0-A2.
2. IODIR wo notwendig auf 0 (Ausgang).
3. unendliche Schleife: IODIR, IOCON, GPIO und OLATA werden gelesen und 
auf dem LCD gezeigt. Dazwischen blinken zwei LEDs.

Wenn A2=0, alles einwandfrei.

Wenn A2=1:
Trotz Einsetzen wird HAEN als 0 gelesen. Auch IC antwortet auf alle 
Adressen mit A2=1 (aber mit A2=0 antwortet IC nicht! ).
Wenn ich beim Starten A2=0 eine Weile halte und schalte A2=1 erst 
während der Schleife, dann wird HAEN=1 gezeigt und Verhalten von IC wird 
wie erwartet, d.h. nur eine Adresse wird erkannt. Dann natürlich blinken 
LEDs nicht, da IODIR nicht eingestellt wird. Aber auf LCD wird alles 
korrekt angezeigt...

Hantieren mit SPI-Geschwindigkeit hat nichts gebracht.

Korrektes Verhalten wurde erreicht, indem ich einfaches Schreiben in 
Register durch Lesen - Modifizieren - Schreiben ersetzt hatte. D.h. 
statt
1
led2_ausgang:
2
    ldi temp, ~(1<<LED2)
3
    ldi temph, LEDREIHE_ADR
4
    ldi temp3,MCP23S17_IODIRB
5
    rjmp mcp23s17_wr       ; GPB0 = Ausgang
1
led2_ausgang:
2
    ldi temph, LEDREIHE_ADR
3
    ldi temp3, MCP23S17_IODIRA
4
    rcall mcp23s17_rd
5
    andi temp,~(1<<LED2)
6
    ldi temph, LEDREIHE_ADR
7
    rjmp mcp23s17_wr      ; GPA7 = Ausgang

gemacht.
1
mcp23s17_wr:  ; temp=Daten, temph=slave address, temp3=reg
2
  cbi MCP23S17_SS_PORT, MCP23S17_SS
3
  lsl temph
4
  ori temph, (1<<6)  ;0b0100xxx0
5
  SPI_SEND temph
6
  SPI_SEND temp3
7
  SPI_SEND temp
8
  sbi MCP23S17_SS_PORT, MCP23S17_SS
9
  ret
10
11
mcp23s17_rd:  ; temp= geles.Daten, temph=slave address, temp3=reg
12
  cbi MCP23S17_SS_PORT, MCP23S17_SS
13
  lsl temph
14
  ori temph, (1<<MCP23S17_RW)|(1<<6)  ;0b0100xxx1
15
  SPI_SEND temph
16
  SPI_SEND temp3
17
  ldi temp, 0xff
18
  SPI_SEND temp
19
  sbi MCP23S17_SS_PORT, MCP23S17_SS
20
  in temp,SPDR
21
  ret

Nun überlege ich, was war das eigentlich? :)
Warum so?

Kann das daran liegen, daß IC auf einem Kontaktfeld ohne Löten aufgebaut 
wurde (aber mit Kondensator 100 n )?
Ich glaube, das innere Leben von MCP23S17 sollte kompliziert sein, da 
Zustand von Pin A2, zum Unterschied von A1 und A0, irgendwo getriggert 
sein sollte.

von S. Landolt (Gast)


Lesenswert?

Also das sieht aber doch nach dem von Michael U. (aus Berlin) verlinkten 
Erratum aus; haben Sie das gelesen?

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.