PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit SPI Schnittstelle



franzl
23.01.2008, 14:23
Hallo zusammen,
ich bin gerade dabei einen Positionsgeber der Firma austriamicrosystems auszuwerten und bin dabei auf ein Problem gestoßen.
http://www.austriamicrosystems.com/03products/products_detail/AS5045/download/AS5045_datasheet.pdf


#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "uart.h"


#ifndef F_CPU
#define F_CPU 16000000UL
#endif

/* 9600 baud */
#define UART_BAUD_RATE 9600


#define MODE PB0
#define SS PB2
#define MOSI PB3
#define MISO PB4
#define SCK PB5

long int position;
unsigned char Geber[3];
char a,b;
unsigned int pos;

char Buffer[4];


int main(void)
{

DDRB |= (1<<MODE)|(1<<SS)|(1<<MOSI)|(1<<SCK);
/* PB2(SS),PB3(MOSI),PB5(SCK)=Ausgang*/
PORTB |= (1<<MODE)|(1<<SS);
/* PB1(MODE),PB2(SS),PB4(MISO),PB5(SCK)=high*/
/*SPI_init*/
SPCR |= (1<<SPR0)|(1<<SPR1)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPE);
/* SPR0/SPR1 = F_CPU/128; SPI Master; Ruhezustand SCK=High;
Übernahme bei zweiter Taktflanke SPE= SPI Enable */

/*
* Initialize UART library, pass baudrate and AVR cpu clock
* with the macro
* UART_BAUD_SELECT() (normal speed mode )
* or
* UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
*/
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

sei();

_delay_ms(100);


for(;;)
{
PORTB |= (1<<SS);

//Positionsauswertung um die Position in einem Integer zu speichern
pos = Geber[0];
pos <<=8;
pos |= Geber[1];
pos >>=4;
pos &= 0x0FFF;

//Senden der Position an den PC
itoa( pos, Buffer, 10);
uart_puts(Buffer);
//neue Zeile
uart_puts("\n\r");
if(SPSR & (1<<WCOL))
{uart_puts("Uebertragungsfehler\n\r");}

for(b=0;b<10;b++) //Wartezeit 1s
{_delay_ms(100);}

PORTB &=~ (1<<SS); // Geber auswählen

_delay_us(1);

/*Auslesen des Gebers. Dazu wird 3x ein Dummybyte gesendet
und anschließend die empfangenen Bytes in ein Array Geber gespeichert*/
for(a=0;a<=2;a++)
{SPDR=0;
while(!(SPSR & (1<<SPIF)))
{Geber[a]=SPDR;}
}

}
}
und zwar bekomme ich mit diesem Programm die falschen Werte heraus und weiß nicht warum. Hab dann versucht das CPOL und CPH bit zu ändern und wenn beide 0 sind empfange ich 7richtige bits und muss mir diese dann eben zusammenbasteln. Nur leuchtet es mir nicht ein warum dies mit den meinermeinung nach völlig falschen Takteinstellungen zum Ergebnis führt, aber manchmal auch fehlerhaft ist. Währ super wenn ihr mir sagen könntet wo da in meinem Programm der Fehler liegt, da ich sonst ohne Logikanalyzer wohl nicht mehr weiter komme. Ich programmiere übrigens mit einem Atmega8 und 16MHz Quarz.

mfg franz

McJenso
23.01.2008, 18:08
Hallo,

mit diesen Einstellungen würde ich es als erstes versuchen.


SPCR |= (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<SPR1)|;
SPSR |= (1<< SPI2X);

Ich denke SPI Mode 2 ist der richtige. Im Datenblatt des Sensors wird clk vor dem CS high dargestellt. Der Zustand ist auf die fallende Flanke abzufragen. Das erste Byte ist dann hoffentlich der richte Wert mit einer 8Bit auflösung. Wenn du 12 Bits haben möchtest musst du natürlich Bitbasteln.
Der Baustein hat max. clk Frequenz von 1MHz. Daher hab ich jetzt mal f /32 gewählt.
Hoffe dashilft. Wirklich sicher bin ich mir da jetzt auch nicht.

Gruß

Jens

franzl
23.01.2008, 21:19
Hallo,
erst mal danke für die Hilfe, ich hab jetz festgestellt, dass wenn ich den takt erhöhe die Einstellung Mode 3 wie ich eigentlich auch erwartet habe sehr gut läuft. Nur was mich noch stört ist, dass das erste bit erst als zweites eingelesen wird. Weiß vielleicht jemand wie man das noch ändern könnte.
mfg franz

McJenso
23.01.2008, 21:39
Das erste eingelesene Bit ist immer 0? Ich will mich mit Mode 2 nicht aufdrängen, aber hast du es mal versucht?
Gruß

Jens

franzl
23.01.2008, 21:49
Hi,
ja hast recht mit mode 2 funktionierts ebenso. Hat allerdings den Vorteil das ich das Bit erst übernehme wenn es sicher seinen Pegel hat, da hast du schon recht. Werd jetzt wahrscheinlich auch mode 2 nehmen. Also nochmals danke für die Hilfe.
mfg franz