Forum: Mikrocontroller und Digitale Elektronik MCP23S17 Daten lesen


von Michi (Gast)


Lesenswert?

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

von Stephan K. (stekohl)


Lesenswert?

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
Noch kein Account? Hier anmelden.