Mikrocontroller und Digitale Elektronik
›
Thread
MCP23S17 Daten lesen
M
Michi
Gast
15.07.2008 09:30
#926674
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 , 0 b01001000 , 0 b01001000 );
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
↑ Nach oben
← Zurück zu Mikrocontroller und Digitale Elektronik
Antwort schreiben