Hallo, ich habe ein Problem mit dem MCP23S17...ich bekomme keine Daten heraus. Hat jemand einen Beispielcode, mit dem es definitiv funktioniert? Das Datenblatt ist da eher arm. Danke
Sag mal für was?! Wenn du mit einem AVR auf den Exoander zugreifen willst kann ich Dir helfen. Ich habe in C eine Header und eine Include Datei. Ich kann Dir aber schonmal folgenden Tipp geben. Der MCP erwartet während des kompletten Befehls (Senden oder Empfangen) immer das CS low bleibt. In Bascom habe ich mal Stunden gebraucht um zu merken, dass nach jedem gesendeten SPI Befehl ChipSelect wieder deaktiviert wird. Beim folgenden Lesen war dann nix zum lesen da. Also CS auf low, dann den Auslesebefehl Senden Werte abfragen CS auf High. Hier meine Headerdatei:
1 | //MCP23S17.h
|
2 | #ifndef __MCP23S17_H
|
3 | #define __MCP23S17_H
|
4 | |
5 | //Deklaration MCP Register
|
6 | /*
|
7 | |
8 | ' MCP23S17 Register RO=ReadOnly
|
9 | ' Adresse 00 01 IODIR Richtung Port a/b 0=Output 1=Input
|
10 | ' Adresse 02 03 IPOL Polarität 1=umgekehrt
|
11 | ' Adresse 04 05 GPINTEN Interrupt aktivieren 1=an 0=aus
|
12 | ' Adresse 06 07 DEFVAL Vergleichsregister für Interrupt
|
13 | ' Adresse 08 09 INTCON 1=PIN<->DEFVAL 0=PIN neu <->PIN alt
|
14 | ' Adresse 0A 0B IOCON Configuration
|
15 | ' Adresse 0C 0D GPPU PullUp 1=aktiv 0= aus
|
16 | ' Adresse 0E 0F INRF Interrupt Flag register RO
|
17 | ' Adresse 10 11 INTCAP Interrupt Capture Register RO
|
18 | ' Adresse 12 13 GPIO Port Werte RW
|
19 | ' Adresse 14 14 OLAT Output Latch Register
|
20 | |
21 | */
|
22 | #define MCP_IODIR 0x00
|
23 | #define MCP_IPOL 0x02
|
24 | #define MCP_GPINTEN 0x04
|
25 | #define MCP_DEFVAL 0x06
|
26 | #define MCP_INTCON 0x08
|
27 | #define MCP_IOCON 0x0A
|
28 | #define MCP_GPPU 0x0C
|
29 | #define MCP_INRF 0x0E
|
30 | #define MCP_INTCAP 0x10
|
31 | #define MCP_GPIO 0x12
|
32 | #define MCP_OLAT 0x14
|
33 | |
34 | #define DUMMY_WRITE (U8)(0xFF)
|
35 | // Port definition
|
36 | #define MCP_CS_BIT 3
|
37 | #define MCP_CS_PORT PORTB
|
38 | #define MCP_CS_DDR DDRB
|
39 | |
40 | #define MCP_RESET_BIT 0
|
41 | #define MCP_RESET_PORT PORTB
|
42 | #define MCP_RESET_DDR DDRB
|
43 | |
44 | #define MCP_INTERRUPT_BIT 2
|
45 | #define MCP_INTERRUPT_PORT PORTB
|
46 | #define MCP_INTERRUPT_DDR DDRB
|
47 | |
48 | #define MCP_CS_INIT() { cbi(MCP_INTERRUPT_DDR,MCP_INTERRUPT_BIT); sbi(MCP_CS_PORT,MCP_CS_BIT); sbi(MCP_CS_DDR,MCP_CS_BIT);sbi(MCP_RESET_PORT,MCP_RESET_BIT); sbi(MCP_RESET_DDR,MCP_RESET_BIT); }
|
49 | |
50 | #define MCP_CS_ON() cbi(MCP_CS_PORT,MCP_CS_BIT);
|
51 | #define MCP_CS_OFF() sbi(MCP_CS_PORT,MCP_CS_BIT);
|
52 | |
53 | #define MCP_RESET_ON() cbi(MCP_RESET_PORT,MCP_RESET_BIT);
|
54 | #define MCP_RESET_OFF() sbi(MCP_RESET_PORT,MCP_RESET_BIT);
|
55 | |
56 | #define SPI_CTRL_REGISTER SPCR
|
57 | #define SPI_STATUS_REGISTER SPSR
|
58 | #define SPI_DATA_REGISTER SPDR
|
59 | #define SPI_STATUS_IF_BIT SPIF
|
60 | |
61 | #define SPI_WRITE(a) { SPI_DATA_REGISTER=(a); }
|
62 | #define SPI_WAIT() { while(! ( SPI_STATUS_REGISTER & (1<<SPI_STATUS_IF_BIT) ) ); }
|
63 | #endif
|
und die passende MCP23S17.c Datei
1 | //MCP23S17.C
|
2 | #include <avr/io.h> |
3 | #include <stdio.h> |
4 | #include <avr/interrupt.h> |
5 | #include <avr/eeprom.h> |
6 | #include <avr/delay.h> |
7 | #include <string.h> |
8 | #include "mcp23s17.h" |
9 | |
10 | void conf_mcp_send(uint8_t addr,uint8_t art,uint8_t pa,uint8_t pb) |
11 | {
|
12 | cli(); |
13 | //uint8_t send_addr;
|
14 | //send_addr=addr && 0b111;
|
15 | //addr= send_addr<<1;
|
16 | MCP_CS_ON(); |
17 | SPI_WRITE(((addr )<<1) | 0x40); |
18 | SPI_WAIT(); |
19 | SPI_WRITE(art); |
20 | SPI_WAIT(); |
21 | SPI_WRITE(pa); |
22 | SPI_WAIT(); |
23 | SPI_WRITE(pb); |
24 | SPI_WAIT(); |
25 | MCP_CS_OFF(); |
26 | _delay_us(2); |
27 | |
28 | }
|
29 | |
30 | void mcp_send(uint8_t addr,uint8_t pa,uint8_t pb) |
31 | {
|
32 | cli(); |
33 | //uint8_t send_addr;
|
34 | //send_addr=addr && 0b111;
|
35 | //addr= send_addr<<1;
|
36 | MCP_CS_ON(); |
37 | //_delay_us(20);
|
38 | SPI_WRITE((addr <<1) | 0x40); |
39 | SPI_WAIT(); |
40 | SPI_WRITE(0x12); |
41 | SPI_WAIT(); |
42 | SPI_WRITE(pa); |
43 | SPI_WAIT(); |
44 | SPI_WRITE(pb); |
45 | SPI_WAIT(); |
46 | //_delay_us(20);
|
47 | MCP_CS_OFF(); |
48 | _delay_us(2); |
49 | |
50 | }
|
51 | |
52 | int mcp_rec(uint8_t addr) |
53 | {
|
54 | cli(); |
55 | uint8_t timeout; |
56 | uint8_t by; |
57 | uint8_t bx; |
58 | MCP_CS_ON(); |
59 | //_delay_us(20);
|
60 | SPI_WRITE((addr <<1) | 0x41); |
61 | SPI_WAIT(); |
62 | SPI_WRITE(0x12); |
63 | SPI_WAIT(); |
64 | |
65 | timeout=255; |
66 | |
67 | //wait for response
|
68 | do
|
69 | {
|
70 | SPI_WRITE(DUMMY_WRITE); |
71 | SPI_WAIT(); |
72 | by=SPI_DATA_REGISTER; |
73 | timeout--; |
74 | if(timeout==0) break; // no response |
75 | } while(by==DUMMY_WRITE); |
76 | |
77 | do
|
78 | {
|
79 | SPI_WRITE(DUMMY_WRITE); |
80 | SPI_WAIT(); |
81 | bx=SPI_DATA_REGISTER; |
82 | timeout--; |
83 | if(timeout==0) break; // no response |
84 | } while(bx==DUMMY_WRITE); |
85 | MCP_CS_OFF(); |
86 | _delay_us(2); |
87 | |
88 | return by | bx<<8; |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | }
|
97 | |
98 | void mcp_int_on() |
99 | {cli(); |
100 | conf_mcp_send(3,MCP_GPINTEN,0XFF,0XFF); |
101 | conf_mcp_send(3,MCP_DEFVAL,0X00,0X00); |
102 | }
|
103 | |
104 | void initmcp() |
105 | {cli(); |
106 | // SPCR SPI Controlregister
|
107 | // SPIE=0; //No SPI Interrupt
|
108 | // SPE=1; //SPI Enable
|
109 | // DORD=0; //Send MSB first
|
110 | // MSTR=1; //I am the master !
|
111 | // CPOL=0; //SCK low if IDLE
|
112 | // CPHA=0; //SPI Mode 0
|
113 | // SPR1=1; //SPI Clock = f/128 = 125kHz @16MHz Clock
|
114 | // SPR0=1; //or f/64 if SPI2X = 1 in SPSR register
|
115 | |
116 | SPI_CTRL_REGISTER = (1<<SPE) | (1<<MSTR) |(0<<DORD) |(0<<CPHA) | (0<<SPR1) | (0<<SPR0); |
117 | |
118 | // SPSR SPI Statusregister
|
119 | // SPI2X=0; // No double speed
|
120 | _delay_ms(1); |
121 | conf_mcp_send(1,MCP_IOCON,0x48,0x48); |
122 | conf_mcp_send(1,MCP_IODIR,0X00,0X00); |
123 | |
124 | conf_mcp_send(2,MCP_IOCON,0x48,0x48); |
125 | conf_mcp_send(2,MCP_IODIR,0X00,0X00); |
126 | |
127 | conf_mcp_send(3,MCP_IOCON,0b01001000,0b01001000); |
128 | conf_mcp_send(3,MCP_IODIR,0XFF,0XFF); |
129 | conf_mcp_send(3,MCP_IPOL,0XFF,0XFF); |
130 | conf_mcp_send(3,MCP_GPPU,0XFF,0XFF); |
131 | |
132 | EIMSK = (1<<INT2); |
133 | EIFR = (1<<INTF2); |
134 | EICRA |=(0<<ISC20); |
135 | EICRA |=(0<<ISC21); |
136 | |
137 | |
138 | |
139 | /* Move interrupts to Boot Flash section */
|
140 | |
141 | |
142 | |
143 | }
|
In initmcp werden meine 3 Expander konfiguriert (1&2 schreiben, 3 Lesen). Muß Du nach eigenmem Gusto umschreiben. Tut mir leid, nicht besonders Toll Dokumentiert. Beim lesen einfach DUMMY_Write(0XFF) senden je empfangenem Byte ACHTUNG der Code bezieht sich auf einen ATMEGA644. Muß Du evtl. für andere Atmega'S umschreiben. Ein paar Deklarationen sind von Holger Klabundes SD LIB übernommen. Gruß, Stephan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.