www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MCP23S17 Daten lesen


Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Kohl (stekohl)
Datum:

Bewertung
0 lesenswert
nicht 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:
//MCP23S17.h
#ifndef __MCP23S17_H
#define __MCP23S17_H

//Deklaration MCP Register
/*

' MCP23S17 Register  RO=ReadOnly
' Adresse 00 01  IODIR   Richtung Port a/b 0=Output 1=Input
' Adresse 02 03  IPOL    Polarität 1=umgekehrt
' Adresse 04 05  GPINTEN Interrupt aktivieren 1=an 0=aus
' Adresse 06 07  DEFVAL  Vergleichsregister für Interrupt
' Adresse 08 09  INTCON  1=PIN<->DEFVAL 0=PIN neu <->PIN alt
' Adresse 0A 0B  IOCON   Configuration
' Adresse 0C 0D  GPPU    PullUp 1=aktiv 0= aus
' Adresse 0E 0F  INRF    Interrupt Flag register RO
' Adresse 10 11  INTCAP  Interrupt Capture Register RO
' Adresse 12 13  GPIO    Port Werte RW
' Adresse 14 14  OLAT    Output Latch Register

*/
#define MCP_IODIR     0x00
#define MCP_IPOL     0x02
#define MCP_GPINTEN   0x04
#define MCP_DEFVAL    0x06
#define MCP_INTCON    0x08
#define MCP_IOCON    0x0A
#define MCP_GPPU    0x0C
#define MCP_INRF    0x0E
#define MCP_INTCAP    0x10
#define MCP_GPIO    0x12
#define MCP_OLAT    0x14

#define DUMMY_WRITE    (U8)(0xFF)
// Port definition
#define MCP_CS_BIT  3  
#define MCP_CS_PORT   PORTB   
#define MCP_CS_DDR   DDRB   

#define MCP_RESET_BIT  0  
#define MCP_RESET_PORT   PORTB   
#define MCP_RESET_DDR   DDRB   

#define MCP_INTERRUPT_BIT  2  
#define MCP_INTERRUPT_PORT   PORTB   
#define MCP_INTERRUPT_DDR   DDRB   

#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); }

#define MCP_CS_ON()   cbi(MCP_CS_PORT,MCP_CS_BIT);
#define MCP_CS_OFF()   sbi(MCP_CS_PORT,MCP_CS_BIT);

#define MCP_RESET_ON()    cbi(MCP_RESET_PORT,MCP_RESET_BIT);
#define MCP_RESET_OFF()   sbi(MCP_RESET_PORT,MCP_RESET_BIT);

 #define SPI_CTRL_REGISTER  SPCR
 #define SPI_STATUS_REGISTER  SPSR
 #define SPI_DATA_REGISTER  SPDR
 #define SPI_STATUS_IF_BIT  SPIF

 #define SPI_WRITE(a)     { SPI_DATA_REGISTER=(a); }
 #define SPI_WAIT()     { while(! ( SPI_STATUS_REGISTER & (1<<SPI_STATUS_IF_BIT) ) ); }
 #endif

und die passende MCP23S17.c Datei
//MCP23S17.C
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/delay.h>
#include <string.h>
#include "mcp23s17.h"

void conf_mcp_send(uint8_t addr,uint8_t art,uint8_t pa,uint8_t pb)
    {
  cli();
   //uint8_t send_addr;
   //send_addr=addr && 0b111;
   //addr= send_addr<<1;
   MCP_CS_ON();   
   SPI_WRITE(((addr )<<1) | 0x40);
   SPI_WAIT();
   SPI_WRITE(art);
   SPI_WAIT();
   SPI_WRITE(pa);
   SPI_WAIT();
   SPI_WRITE(pb);
SPI_WAIT();     
   MCP_CS_OFF();
_delay_us(2);

     }

void mcp_send(uint8_t addr,uint8_t pa,uint8_t pb)
    {
  cli();
   //uint8_t send_addr;
   //send_addr=addr && 0b111;
   //addr= send_addr<<1;
    MCP_CS_ON();
//_delay_us(20);      
   SPI_WRITE((addr <<1) | 0x40);
   SPI_WAIT();
   SPI_WRITE(0x12);
   SPI_WAIT();
   SPI_WRITE(pa);
   SPI_WAIT();
   SPI_WRITE(pb);
SPI_WAIT(); 
//_delay_us(20);
   MCP_CS_OFF();
_delay_us(2);   

     }
   
int mcp_rec(uint8_t addr)
    {
  cli();
  uint8_t timeout;
  uint8_t by;
  uint8_t bx;
  MCP_CS_ON();
//_delay_us(20);      
  SPI_WRITE((addr <<1) | 0x41);
  SPI_WAIT();
  SPI_WRITE(0x12);
  SPI_WAIT();
   
  timeout=255;
 
    //wait for response
    do
  {
    SPI_WRITE(DUMMY_WRITE);
    SPI_WAIT();
    by=SPI_DATA_REGISTER;
    timeout--;
    if(timeout==0) break; // no response
  } while(by==DUMMY_WRITE);
  
  do
  {
    SPI_WRITE(DUMMY_WRITE);
    SPI_WAIT();
    bx=SPI_DATA_REGISTER;
    timeout--;
    if(timeout==0) break; // no response
  } while(bx==DUMMY_WRITE);
  MCP_CS_OFF();
_delay_us(2);    
   
  return by | bx<<8; 
   
   

   
   
   
   
    }
   
void mcp_int_on()
     {cli();
   conf_mcp_send(3,MCP_GPINTEN,0XFF,0XFF);  
    conf_mcp_send(3,MCP_DEFVAL,0X00,0X00);
   }
   
void initmcp()
  {cli();
  // SPCR SPI Controlregister
// SPIE=0; //No SPI Interrupt
// SPE=1;  //SPI Enable
// DORD=0; //Send MSB first
// MSTR=1; //I am the master !
// CPOL=0; //SCK low if IDLE
// CPHA=0; //SPI Mode 0
// SPR1=1; //SPI Clock = f/128 = 125kHz @16MHz Clock
// SPR0=1; //or f/64 if SPI2X = 1 in SPSR register

 SPI_CTRL_REGISTER = (1<<SPE) | (1<<MSTR) |(0<<DORD) |(0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// SPSR SPI Statusregister
// SPI2X=0; // No double speed
    _delay_ms(1);
   conf_mcp_send(1,MCP_IOCON,0x48,0x48);
   conf_mcp_send(1,MCP_IODIR,0X00,0X00);
   
   conf_mcp_send(2,MCP_IOCON,0x48,0x48);
   conf_mcp_send(2,MCP_IODIR,0X00,0X00);   
   
   conf_mcp_send(3,MCP_IOCON,0b01001000,0b01001000);
   conf_mcp_send(3,MCP_IODIR,0XFF,0XFF);   
   conf_mcp_send(3,MCP_IPOL,0XFF,0XFF);  
    conf_mcp_send(3,MCP_GPPU,0XFF,0XFF);
   
   EIMSK = (1<<INT2);
   EIFR = (1<<INTF2);
   EICRA |=(0<<ISC20);
     EICRA |=(0<<ISC21);



/* Move interrupts to Boot Flash section */


   
   }

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.