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
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
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!
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
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?
sorry, wohl nicht. Der Code sieht ok aus. Schreibt die "zu Fuss Version" auch auf den MOSI Pin? PORT B.2?
SS (PB0) als Output konfiguriert, oder Pullup an SS aktiviert, oder externer Pullup an SS? LG, Sebastian
:
Bearbeitet durch User
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
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
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
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
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.
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.