Forum: Mikrocontroller und Digitale Elektronik ATmega2560, AD7714, SPI


von Mario EDUARDO (Gast)


Lesenswert?

Ich hab Probleme mit dem SPI Transfer:
Ich habe einen AD7714 mit SPI an einen AtMega2560 angeschlossen.
Mit zu Fuß programmierter SPI Übetragung, also ohne dem CPU Support, 
funktioniert die Kommunikation. Sobald ich meinen Treiber auf den CPU 
Support umstelle bekomme ich Zufallszahlen. Die Geschwindigkeit kann 
m.e. nicht das Problem sein, da ich zu Fuß schneller bin (Clock Puls 
Dauer etwa 15yS) als mit dem CPU Support im langsamsten Modus (Clock 
Puls etwa 32 yS bei 4 MHz).

Weiß jemand, welchen SPI Mode ich einstellen muß und wie der POL Pin des 
AD7714 zu beschalten ist. Hab jetzt fast alles probiert.

Ich hab auch eine Treiber für einen AD7793, der funktioniert problemlos 
mit dem CPU - SPI Interface.

Es muß scheinbar zwischen dem AD7793 und dem AD7714 Unterschiede geben. 
Welche ?

Es gab hier ja Dikussionen mit einem AtMega 32 und 8, hab da aber keine 
Initialisierung gefunden.
Hat wir eine Idee ?

Danke, Mario

von ich (Gast)


Lesenswert?

1. y für Mikro gibt Augenkrebs :-)
2. POL = 1
3. "warum" interessiert Dich wohl nicht, sonst hättest 
gegooglet/gedatenblättert und's selbst rausgefunden... ;-)
4. Datenblätter weiter studieren, Schema und Code veröffentlichen hilft 
machmal auch

von ich nochmal (Gast)


Lesenswert?

mit POL = 1 mein ich natürlich logisch '1' - also HIGH. Dann hast Du das 
gleich wie beim 7793.
Mit "CPU Support" meinst Du wohl einen hardwaremässigen SPI Controller. 
Die haben manchmal die dumme Angewohnheit Byteweise zu arbeiten obwohl 
Du lieber z.B. genau 28 Bits pro Befehl übertragen möchtest. Dann hast 
Du evtl. Probleme mit der Zeit, die dazwischen vertstreicht oder damit, 
dass vielfache von 8 Bits übertragen werden müssen und du nicht weisst 
ob die höchst- oder niederwertigsten Bits abgeschnitten (bzw. ignoriert) 
warden. Bei beiden Problemen hilft ein KO und oder Datenblatt-Studium.

Viel Erfolg!

von Mario EDUARDO (Gast)


Lesenswert?

Hi,

Ich google jetzt und lese seit 1 Woche.

Meine derzeitige Konfig ist:
POL=High,
SPCR = 0x5F
SPSR = 0

die Leseroutine:



/*
  empfängt ein Byte vom AD7714
  Select gibt an, wie das CS Signal aussehen soll
  SelectAtBegin == 0 -> CS = Low~aktiviert,    ansonst unverändert
  SelectAtEnd   != 0 -> CS = High~deaktiviert, ansonst unverändert
*/

unsigned char  AD7714_GetByte ( unsigned char SelectAtBegin, unsigned 
char SelectAtEnd )
{
  unsigned char x,y ;

   if (SelectAtBegin == 0)
    {
     ADI_PART_CS_LOW ;
    }

   SPDR = 0   ;
   while (!(SPSR & 0x80)) ;
   x = SPDR ;

   if (SelectAtEnd != 0)
    {
     ADI_PART_CS_HIGH ;
    }

   return (x) ;
}

die Schreibroutine:



/*
  sendet ein Byte an den AD7714
  Select gibt an, wie das CS Signal aussehen soll
  SelectAtBegin == 0 -> CS = Low~aktiviert,    ansonst unverändert
  SelectAtEnd   != 0 -> CS = High~deaktiviert, ansonst unverändert
*/

void  AD7714_SendByte ( unsigned char data, unsigned char SelectAtBegin, 
unsigned char SelectAtEnd )
{
  unsigned char x,y ;

   if (SelectAtBegin == 0)
    {
     ADI_PART_CS_LOW ;
    }

   SPDR = data   ;
   while (!(SPSR & 0x80)) ;
   ADI_PART_MOSI_HIGH ;

   if (SelectAtEnd != 0)
    {
     ADI_PART_CS_HIGH ;
    }

}



Der Unterschied zwischen der CPU Version und der Zu-Fuß Version besteht 
- abgesehen von der Initialisierung - einzig darin, daß dort wo 
SPDR=data usw
steht, ein Call auf die Prozedur erfolgt, die das eben zu Fuß macht.

Das    ADI_PART_MOSI_HIGH ;

ist wirkungslos, da es vorher draußen war und auch nicht ging.

lg Mario

von ich noch immer (Gast)


Lesenswert?

Könnte es sein, dass Du den abgebildeten Code irgendwoher kopiert hast 
und alle Deine ADI_PART_xx_LOW und HIGH noch gar nicht definiert sind?

von ich noch immer (Gast)


Lesenswert?

sorry, wohl nicht. Der Code sieht ok aus.
Schreibt die "zu Fuss Version" auch auf den MOSI Pin? PORT B.2?

von Sebastian W. (wangnick)


Lesenswert?

SS (PB0) als Output konfiguriert, oder Pullup an SS aktiviert, oder 
externer Pullup an SS?

LG, Sebastian

: Bearbeitet durch User
von Mario EDUARDO (Gast)


Lesenswert?

Hier zuerst der Code der "zu Fuß" Ansteuerung:



/*

   Makros zum Anpassen an die Hardware
   ===================================

*/

// SPI Interface Ports

#define configure_pin_ss()      DDRB |=  0x01 ; PORTB |= 0x01
#define configure_pin_mosi()    DDRB |=  0x04 ; PORTB |= 0x04
#define configure_pin_sck()     DDRB |=  0x02 ; PORTB |= 0x02
#define configure_pin_miso()    DDRB &= ~0x08 ; PORTB |= 0x08


// Chip Select des AD7714 ist Ausgang

#define ADI_PART_CS_CFG            DDRB  |=  0x10
#define ADI_PART_CS_LOW            PORTB &= ~0x10
#define ADI_PART_CS_HIGH           PORTB |=  0x10


// Data Ready des AD7714 ist Eingang

#define ADI_PART_DRDY_CFG            DDRB  &= ~0x20
#define ADI_PART_DRDY_MASK           (PINB  & 0x20)
#define ADI_PART_DRDY_PuOn           PORTB |=  0x20

// Reset des AD7714 ist Ausgang

#define ADI_PART_RESET_CFG            DDRB  |=  0x40
#define ADI_PART_RESET_LOW            PORTB &= ~0x40
#define ADI_PART_RESET_HIGH           PORTB |=  0x40


//========================  LOW LEVEL Prozeduren 
========================




void SPI_HwInit ()
{

  unsigned char  x, y ;

    /* enable input or output for chip select  */
    ADI_PART_CS_CFG  ;
    ADI_PART_CS_HIGH ;

    ADI_PART_DRDY_CFG ;
    ADI_PART_DRDY_PuOn ;  // PullUp on


    /* enable outputs for MOSI, SCK, SS, input for MISO */
    configure_pin_mosi();
    configure_pin_sck();
    configure_pin_miso();
    configure_pin_ss() ;

    ADI_PART_RESET_CFG ;
    ADI_PART_RESET_LOW ;
    for (x=200;x!=0; x--) ;
    ADI_PART_RESET_HIGH ;

    return  ;
}




void AD7714_PutSlow (u08   val)
{

   PORTB |= 0x02 ;        // Clk  is High on idle
   PORTB |= 0x04 ;        // MoSi is High on idle

   if (val&0x80)          // Bit 7 first
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 6
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 5
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 4
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


    val = val << 1 ;       // Bit 3
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 2
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 1
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }
   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle


   val = val << 1 ;       // Bit 0
   if (val&0x80)
    {
      PORTB |= 0x04  ;    // MoSi is High
    }
    else
    {
      PORTB &= ~0x04 ;    // MoSi is Low
    }

   PORTB &= ~0x02 ;       // Clk to Low
   PORTB |= 0x02 ;        // Clk  is High on idle

   PORTB |= 0x04 ;        // MoSi

}





u08 AD7714_GetSlow ()
{

   u08  val, x ;

   PORTB |= 0x02 ;        // Clk  is High on idle
   PORTB |= 0x04 ;        // MoSi is High ob idle
   val = 0 ;


   PORTB &= ~0x02 ;       // Clk Low Read Bit 7 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x80 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 6 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x40 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 5 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x20 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 4 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x10 ;
     }


   PORTB &= ~0x02 ;       // Clk Low Read Bit 3 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x08 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 2 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x04 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 1 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x02 ;
     }



   PORTB &= ~0x02 ;       // Clk Low Read Bit 0 first
   PORTB |=  0x02 ;       // Clk  High, Slave asserts DataBit
   x   =  PINB & 0x08 ;  // MiSo Bit einlesen
   if (x)
     {
      val |= 0x01 ;
     }



   PORTB |= 0x02 ; // Clk
   PORTB |= 0x04 ; // MoSi
   return (val) ;
}


Nach einer Diskussion auf ez.analog.com dürfte der MoSi das Problem 
sein. Der sollte scheinbar High on Idle sein, ist er aber beim AtMega 
nicht.
Un der der läßt sich sobald die CPU Herr über den PortB ist nicht mehr 
beeinflussen.

lg, Mario

von Sebastian W. (wangnick)


Lesenswert?

Hallo Mario,

MOSI wird durch Aktivierung der SPI-Schnittstelle (mit SPE in SPCR) vom 
Atmega auf High getrieben. Das sollte also nicht das Problem sein.

Noch einmal: Wie initialisiert Du DDRB PB0 (SPI SS pin) in der 
"CPU-Version"? Die Datenrichtung von genau PB0 hat nämlich in der 
"CPU-Version" eine besondere Bewandnis:

"Master Mode

When the SPI is configured as a Master (MSTR in SPCR is set), the user 
can determine the direction of the SS pin. If SS is configured as an 
output, the pin is a general output pin which does not affect the SPI 
system. Typically, the pin will be driving the SS pin of the SPI Slave.

If SS is configured as an input, it must be held high to ensure Master 
SPI operation. If the SS pin is driven low by peripheral circuitry when 
the SPI is configured as a Master with the SS pin defined as an input, 
the SPI system interprets this as another master selecting the SPI as a 
slave and starting to send data to it. To avoid bus contention, the SPI 
system takes the following actions:

1. The MSTR bit in SPCR is cleared and the SPI system becomes a Slave. 
As a result of the SPI becoming a Slave, the MOSI and SCK pins become 
inputs.

..."

LG, Sebastian

: Bearbeitet durch User
von Mario EDUARDO (Gast)


Lesenswert?

Servus Sebastian,

Ich hab im Code, in allen Dateien nach PORTB, DDRB gesucht.
Es sollte passen.
Mit Meßgerät den PORTB0 geprüft, sollte ebenfalls passen.

Es gibt die Definitionen:

// SPI Interface Ports

#define configure_pin_ss()      DDRB |=  0x01 ; PORTB |= 0x01
#define configure_pin_mosi()    DDRB |=  0x04 ; PORTB |= 0x04
#define configure_pin_sck()     DDRB |=  0x02 ; PORTB |= 0x02
#define configure_pin_miso()    DDRB &= ~0x08 ; PORTB |= 0x08

und dann in der Init-Routine:


    /* enable outputs for MOSI, SCK, SS, input for MISO */
    configure_pin_mosi();
    configure_pin_sck();
    configure_pin_miso();
    configure_pin_ss() ;

    SPCR = 0x5f ;
    x = SPSR ;
    y = SPDR ;

sollte stimmen ...

Mario

von Sebastian W. (wangnick)


Lesenswert?

Ja, dann sollte es eigentlich auch gehen.

Jetzt wäre, glaube ich, der Quellcode (reduziert auf die einfachste 
nicht funktionierende Version), ein Schaltplan, ein Foto vom Aufbau, und 
ein Logikanalyzer-Trace angebracht ...

LG, Sebastian

: Bearbeitet durch User
von ich noch immer (Gast)


Lesenswert?

Nope,
Ist wirklich falsch! Unter "SPI Interface Ports" definierst Du die 
Portbits B 0 bis 3. Danach bedudelst Du unverständlicherweise Bits 4 bis 
6... Da liegt kein Segen drauf.

von ich noch immer (Gast)


Lesenswert?

also die AD7714 Makros meinte ich. Das unleserliche Bitgeschreibsel 
darunter könnte evtl. stimmen.

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.