IOWarrior und SPI

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

IOWarrior und SPI

Post by stippe »

Bin neuling und versuche seit kurzem ein Programm zu schreiben.
Ich muß ein Chip von Atmel AT89S52 über die SPI Schnittstelle programmieren.
Ich suche einen Beispielcode, womit ich die SPI aktivieren kann und folgende Daten in Hex 85 A0 80 02 senden kann.

Nächste Frage. Wenn ich die SPI aktivire, bekomme ich sofort das Clock-Signal?

danke in voraus

gruß
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Das Thermometerbeispiel verwendet SPI, wenn auch nur in Senderichtung (was bei SPI aber keinen Unterschied macht, da das immer in beide Richtungen gleichzeitig geht).

Das Clock Signal wird nur während der Übertragung erzeugt, also 8 Takte pro Byte.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Post by Christoph Jung »

Guido hat recht, steht im Sample der Temperaturmessung.

Aber das sollte ungefähr so aussehen:

Code: Select all

IOWKIT_SPECIAL_REPORT report;

// Aktivieren des SPI-Mode 
report.RportID = 0x8;
report.Bytes[0] = 0x01;
report.Bytes[1] = 0x07;

IowKitWrite(); //zu faul zum tippen ;)

//Schreiben deiner Bytes
report.ReportID = 0x9;
report.Bytes[0] = 0x02;
report.Bytes[1] = 0x85;
report.Bytes[2] = 0xA0;
report.Bytes[3] = 0x80;
report.Bytes[4] = 0x02;

IowKitWrite();
So sollte das ungefähr aussehen. Schau aber nochmal im Sample und im Datenblatt nach, weil ich mir mit dem Bytes[0] beim schreiben nicht so sicher bin.
stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

Post by stippe »

Hallo

Mit der Aktivierung der Scnittstelle bin ich klar gekommen.

report.RportID = 0x8;
report.Bytes[0] = 0x01;
report.Bytes[1] = 0x03;

Hier musste ich aber 03 eingeben. Laut Datenblatt von AT89S52.

Wo ich immer noch nicht durchblicke, ist die Flagsetzung bei report 9.
Wieso kommst du auf 0x02 bei report.Byte[0].
Ist das so, wenn ich z.B. report.Bytes[0] = 0x44; eingebe, dann habe ich folgendes eingestellt.
useDRDY=0; SSactive=1; ignoreDRDY=0;.... und der Rest???
Muß ich beim ersten mal alles einstellen?.
z.B. ob ich mit LSB anfange? dann wäre es 0x41 oder?
wenn ich mit MSB anfange dann 0x44?
Und wie stelle ich den "data count" ein?
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

stippe wrote: Wo ich immer noch nicht durchblicke, ist die Flagsetzung bei report 9.
Wieso kommst du auf 0x02 bei report.Byte[0].
0x02 ist umgangssprachlich :
useSRDY wird nicht verwendet,
SSactive wird nach diesem Report zurückgesetzt. Die meisten SPI-Slaves erwarten nur wenige Bytes in einem Kommando. Mein LCD-Display braucht z.B.. immer nur 2 Bytes. Dafür wäre diese Einstellung richtig.
ignoreDRDY ist nicht gesetzt. Das macht auch nur Sinn wenn man useDRDY gesetzt hatte.
Und es werden 2 Bytes übertragen. Da kommt jetzt die 2 im report.Byte[0] her.
Ist das so, wenn ich z.B. report.Bytes[0] = 0x44; eingebe, dann habe ich folgendes eingestellt.
useDRDY=0; SSactive=1; ignoreDRDY=0;.... und der Rest???
Das ergibt :
Ich verwende kein DRDY;
Nach der Übertragung bleibt das Signal SS aktiv, weil ich noch mehr Daten übertragen will.
Ich will 4 Bytes zum Slave schicken.
Die eigentlichen Daten müssen dann in report.Byte[1] bis report.Byte[4] stehen.

Ob diese Einstellungen nun für den AT89S52 richtig sind weiß ich nicht. Wieviele Bytes sollen denn zu Gerät geschickt werden? (Wenn es <=6 Bytes sind reicht ein einzelner Report bei dem SSactive auf 0 gesetzt ist. Um nur 4 Bytes an den Slave zu schicken würde man folgenden Report erstellen:
report.Id=0x09;
report.Byte[0]=0x04; Kein Handshake, SS wird nach Ende der Übertragung wieder auf High gesetzt, Es werden 4 Bytes übertragen.
report.Byte[1]=Data1
report.Byte[2]=Data2
report.Byte[3]=Data3
report.Byte[4]=Data4
report.Byte[5]=Dieser Wert ist egal, er wird nicht übertragen
report.Byte[6]=Dieser Wert ist egal, er wird nicht übertragen
Muß ich beim ersten mal alles einstellen?.
z.B. ob ich mit LSB anfange? dann wäre es 0x41 oder?
wenn ich mit MSB anfange dann 0x44?
Die MSB/LSB Einstellungen werden nur bei der Initialisierung des SPI-Mode einmal gesetzt (ReportId=0x08) und dann solange verwendet bis der SPI-Mode wieder abgeschaltet wird.

Ich hoffe das hilft weiter?
Eberhard
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Post by Christoph Jung »

@ Stippe:

Hab da oben nen Tippfehler drin...ist natürlich

Code: Select all

report.Bytes[0] = 0x04;
Wäre ja sonst quatsch. Aber vom Prinzip ist es das selbe in pink ^^

@ wayoda:

Nett erklärt. Hab sogar ich verstanden ^^
Wäre nen gutes FAQ, wenn wir die Datenblätter nicht hätten
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

Post by stippe »

Hallo und Dankeschön für die prompte Antwort

Ich benutze SS für den RESET und der sollte für ca. 500ms auf low gehen und erst dann kann ich Daten schicken. Und SS solte möglichst ohne Unterbrechngen auf low bleiben. (µC braucht HIGH für RESET, habe aber einen Inverter davor gesetzt.)

Laut Datenblatt muß ich 6 Bytes schicken um weitere Daten, ohne Unterbrechung der SS, zu schreiben.

Code: Select all

printf("SPI enable\n");
	report.ReportID = 0x08;
	report.Bytes[0] = 0x01;
	report.Bytes[1] = 0x03;
	IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, sizeof(report));
	IowKitSetWriteTimeout(iows[i], 1000);	
	}
	printf("programming enable\n");
	memset(&report, 0, sizeof(report));
	report.ReportID = 0x09;
	report.Bytes[0] = 0x46;
	report.Bytes[1] = 0x00;
	report.Bytes[2] = 0x00;
	report.Bytes[3] = 0x00;
	report.Bytes[4] = 0x00;
	report.Bytes[5] = 0x00;
	report.Bytes[6] = 0x00;
	IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);
	IowKitRead(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);
	Sleep(500);
d. h. ich warte 500ms und erst dann kann ich Daten schicken.
Progrmming enable AC 53 xx xx
Chip Erase AC 8x xx xx
Dann wäre da folgendes

Code: Select all

report.ReportID = 0x09;
	report.Bytes[0] = 0x46;
	report.Bytes[1] = 0xAC;
	report.Bytes[2] = 0x53;
	report.Bytes[3] = 0x00;
	report.Bytes[4] = 0x00;
	report.Bytes[5] = 0xAC;
	report.Bytes[6] = 0x80;
	IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);
	IowKitRead(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);

Code: Select all

report.ReportID = 0x09;
	report.Bytes[0] = 0x42;
	report.Bytes[1] = 0x00;
	report.Bytes[2] = 0x00;
IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);
	IowKitRead(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, IOWKIT_SPECIAL_REPORT_SIZE);
Wärend des Vorgangs darf SS nicht den Zustand ändern.
Also immer auf LOW. Und ich schätze der Datenfluß darf nicht unterbrechen. (SCK immer konstant weiterlaufen)

Übrigens gute Erklärung

Danke nochmals

Artur
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Hallo Artur,
Wärend des Vorgangs darf SS nicht den Zustand ändern.
Also immer auf LOW. Und ich schätze der Datenfluß darf nicht unterbrechen. (SCK immer konstant weiterlaufen)
Steckt da jetzt noch eine Frage drin, oder ist das Problem gelöst?

Eberhard
stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

Post by stippe »

Wenn ich diesen Code benutzte bleibt SS immer auf LOW?
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Ja.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Wenn ich diesen Code benutzte bleibt SS immer auf LOW?
Ja
Und im letzten Report der Programmierungssequenz wird dann das /SS-Bit wieder auf Low gesetzt, um damit dem Reset am AT über das Ende der Programmierung zu Informieren.

Eberhard
stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

Post by stippe »

Habe folgendes Problem

memset(&report, 0, sizeof(report));
report.ReportID = 0x09;
report.Bytes[0] = 0x44;
report.Bytes[1] = 0xAC;
report.Bytes[2] = 0x53;
IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, sizeof(report));
IowKitRead(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, sizeof(report));

memset(&report, 0, sizeof(report));
report.ReportID = 0x09;
report.Bytes[0] = 0x44;
report.Bytes[1] = 0xAC;
report.Bytes[2] = 0x53;
report.Bytes[3] = 0x80;
IowKitWrite(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, sizeof(report));
IowKitRead(devHandle, IOW_PIPE_SPECIAL_MODE, (char *) &report, sizeof(report));

Ich habe diesen Code geschrieben.
Die Datenübertragung konnte ich am Osszilloskop überprüfen.
Problem ist aber, daß ich nach dem ersten IowKitWrite(..) für ca 10ms eine Pause sehe. Das ist zu viel für den Microcontroller und somit wird die Datenübertragung wieder abgeschaltet.

Wie stelle ich das an, damit ich zwischen den Reports keine Verzögerung habe.
Oder ist das Hardware bedingt?

Vielen Dank in voraus
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

Das ist USB-bedingt, die Zahl der Reports pro Sekunde ist begrenzt.

Aber warum packen Sie die Bytes nicht in einen Report? Es sind ja nur 6 Byte, die würden doch passen.
stippe
Posts: 14
Joined: Sat Aug 26, 2006 11:26 pm

Post by stippe »

Ich muß AC 53 00 00 und AC 53 80 00 schicken
und daß passt nicht in ein Report

und später muß ich noch den angeschlossenen controller programmieren können. Da könnes es schon bis zu 300 bytes und mehr sein, die ich schicken muß
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

stippe wrote: Die Datenübertragung konnte ich am Osszilloskop überprüfen.
Problem ist aber, daß ich nach dem ersten IowKitWrite(..) für ca 10ms eine Pause sehe. Das ist zu viel für den Microcontroller und somit wird die Datenübertragung wieder abgeschaltet.
Verstehe ich eigentlich nicht, das Prinzip der SPI-Interface ist doch, dass der Master (IOWarrior) die Übertragungsgeschwindigkeit steuert und der Slave (AT) nur auf die Änderungen am SCL-Eingang reagiert. Ich habe so etwas noch nicht gemacht, aber mal eben ins Datenblatt des AT geschaut. 2 Fragen sind mir eingefallen:

1. Welcher Quarz ist am AT. Ich würde die Datenrate am IOWarrior beim Aktivieren des SPI-Mode ganz nach unten setzen (0.0625 MBit/sec)

2. Aktivieren der Programmierung am AT durch setzen des RESET-Eingangs. Was ich da gelesen habe fand ich missverständlich:
1. Power-up sequence:
Apply power between VCC and GND pins.
Set RST pin to “H”.
If a crystal is not connected across pins XTAL1 and XTAL2, apply a 3 MHz to
33 MHz clock to XTAL1 pin and wait for at least 10 milliseconds.
Muss man jetzt erst mal 10 ms warten nachdem RST auf HIGH gesetzt ist? Bei der Verwendung des /SS-Pins vom IOWarrior am RST des AT wird das wohl nicht funktionieren. (Ich würde vielleicht mal einen freien IO-PIN am IOWarrior für den RST verwenden, den ich per write-Befehl auf low(Inverter vor RST) setze. Dann die Bytes zur Programmierung schicken, zum Schluß den Pin wieder auf High.)

Eberhard
Post Reply