SPI startmoment ?

trix

Golden Member

hallo, ik heb een simpele start opstelling gemaakt om het SPI gebeuren te testen, 1 master en 1 slave.
het gaat om de data v/d slave naar de master, in de slave staat deze in een array.
het probleem is, dat wanneer de SPI de 1e byte naar buiten shift, er eerst een aantal bytes komen met 0x00 (maar ik verwacht als 1e byte 0x255 (1e byte in de array)). dat aantal bytes met 0x00 is random. zodra de 1e byte uit de array verschijnt komt de hele array er correct achter aan.

in de datasheet staat, zodra de SS laag word start de SPI de pulstrein en shift zijn SPDR naar buiten, dan zou dus meteen de SPDR in de slave ook over de MISO naar de master moeten gaan.

als test heb ik nog in de slave SPDR = 0x255 dus zonder de hele array, en dat gaat wel goed. het lijkt hem dus echt in het array gebeuren te zitten.

ik test het een en ander met een logic analyzer, de blauwe lijn onder aan is de SS. (SS_TSOP).

ik hoop dat iemand hier ziet wat er nou fout gaat, alvast bedankt.

MASTER

c code:

//*******************************17-8-2019 TEST PSI****************************
//**********************************MASTER**************************************

#define F_CPU 1000000UL // 1 MHz int osc
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>



int main(void)
{
	char data;

	DDRB |= (1<<PINB1)|(1<<PINB2)|(1<<PINB0);    // SCK, MOSI and SS as outputs
	DDRB &= ~(1<<PINB3);                 // MISO as input
	
	DDRC = 0b11111111;

	SPCR |= (1<<MSTR);               // Set as Master
	SPCR |= (1<<SPR0)|(1<<SPR1);     // divided clock by 128
	SPCR |= (1<<SPE);                // Enable SPI
	
	while(1)
	{

		_delay_ms(1);
		PORTC &= ~(1 << PINC5); // maakt SS laag
		
		SPDR = 0b01010101;                 // send the data
		while(!(SPSR & (1<<SPIF)));  // wait until transmission is complete
		
		PORTC |= (1 << PINC5); // maakt SS hoog

		
	}
					
}			
				

SLAVE

c code:



//****************17-8-2019 TEST PSI*****************************************************

#define F_CPU 1000000UL // 1 MHz int osc

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>

int testers [38] = {255, 0, 255, 0, 255, 0, 0, 0, 0, 0,
	            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0,} ;

int bytenr;
int data;

//*****************************SLAVE*********************************************

int main(void)
{
	//	   char data;

	DDRB &= ~((1<<PINB7)|(1<<PINB5)|(1<<PINB4));   // SCK, MOSI and SS as inputs
	DDRB |= (1<<PINB6);                    // MISO as output

	SPCR &= ~(1<<MSTR);                // Set as slave
	SPCR |= (1<<SPR0)|(1<<SPR1);       // divide clock by 128
	SPCR |= (1<<SPE);                  // Enable SPI

	while(1)
	{
		for (bytenr=0; bytenr<38; bytenr++)
		{
		
			
		
			while(!(SPSR & (1<<SPIF)));    // wait until all data is received
			SPDR =  testers[bytenr];       // hurray, we now have our data
		}
	}
	
}

eigenwijs = ook wijs
Arco

Special Member

De status van de SS lijn heeft niets met het versturen van de data te maken...
(je kunt rustig de SS lijn laagtrekken en pas na een uurtje de data ophalen...)
SS laag is alleen een teken dat de betreffende slave actief is op de SPI bus.

Verder stuurt de slave niets spontaan, maar in antwoord op een vraag van de master.
(voor commando's en hun opbouw zie datasheet van de slave)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
trix

Golden Member

dat laatste klopt, de slave gaat pas data naar de master sturen wanneer de master data naar de slave stuurt. dat is mijn "dummy" byte op de MOSI (0b01010101)

dat eerste kijk ik even nog na.

edit:
The SPI Master initiates the
communication cycle when pulling low the Slave Select SS pin of the desired Slave. Master and
Slave prepare the data to be sent in their respective Shift Registers, and the Master generates
the required clock pulses on the SCK line to interchange data.

kan ik hier niet uit aflijden dat de clockpulsen meteen komen nadat de SS laag word ?

edit 2: even verderop lees ik:
writing a byte to the SPI Data Register starts the SPI clock generator

eigenwijs = ook wijs
Arco

Special Member

Normaal gesproken moet je wel iets zinvols sturen. (een commando wat de slave begrijpt en zo weet wat 'ie moet doen...)
Klokpulsen komen alleen als je een commando of byte via MOSI verstuurt. Dat kan direct, maar ook een uur later. (als extreem voorbeeld... ;) )

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
trix

Golden Member

ja klopt, dat had ik hierboven al toegevoegd.

die dummy byte mag toch van alles zijn, maakt niet uit wat. de slave doet er toch niets mee.

maar in mijn geval stuur ik de dummy meteen na dat de SS laag word.

[Bericht gewijzigd door trix op woensdag 21 augustus 2019 18:57:07 (20%)

eigenwijs = ook wijs
Arco

Special Member

Hoe weet die slave dan wat 'ie moet doen?

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
trix

Golden Member

die stuurt toch autom. zijn SPDR over de MISO naar de master, zodra er over de MOSI een byte binnen komt ?

eigenwijs = ook wijs
Arco

Special Member

Geen idee wat voor chip het over gaat, is bij iedere chip verschillend.
Meestal moet je eerst vertellen wat de bedoeling is aan de chip, zodat 'ie weet wat terug te sturen...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
trix

Golden Member

verdorie, dat had ik nog niet gemeld.
master = atmaga 128
slave = atmega 16

eigenwijs = ook wijs

@Arco: volgens mij zowel de master als slave devices AVR microcontrollers bij de TS, met dus elk eigen code, en hij heeft de code van de slave gepost.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
trix

Golden Member

eigenwijs = ook wijs

SPI is eigenlijk best geinig. Als je de master goed als master instelt, dan genereert die precies 8 klokpulsjes iedere keer als je een byte in het dataregister zet.

Die 8 klokpulsjes hebben een geinig effect: De data in het registertje van de master en de slave verwisselen van plek.

Jou code doet pas de eerste byte in het dataregister op de slave NADAT er 8 bits verstuurd zijn. Dat kan niet goed gaan.

Mijn voorstel: regel een pin change interrupt op de SS pin. (in de slave). Zodra dat gebeurt, kijk je wat het SS signaal is. Als ie hoog is, dan ben je niet geselecteerd en zou je eigenlijk de MISO lijn tristate (input) moeten maken. Kan je ook zo laten. Als ie LAAG is dan ben je zojuist geselecteerd, zet je de teller op nul en stop je de eerste byte in het transmit data register. (teller nu op 1).
En dan kan je, des noods in het hoofdprogramma, de rest doen.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

Op 21 augustus 2019 21:03:19 schreef rew:
Jou code doet pas de eerste byte in het dataregister op de slave NADAT er 8 bits verstuurd zijn. Dat kan niet goed gaan.

dit begrijp ik wel, dat is inderdaad niet goed. ik begrijp alleen niet het verband met het geen ik fout zie gaan.

ik ga je oplossing wel proberen.

eigenwijs = ook wijs
Arco

Special Member

Je moet de byte gewoon 'klaarzetten in het SPI TX register op de slave. Dan wordt die verzonden als er wat binnenkomt.
Ik weet niet hoe de SPI bij die Atmega werkt, maar meeste Pics hebben een 8 byte fifo buffer, zodat je al 8 bytes klaar kunt zetten...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Als je een "startopstelling voor het SPI gebeuren" wilt maken, waarom dan niet een echt SPI device nemen en alleen de master zelf programmeren? Dan heb je maar 1 onzekere kant waar je aan kunt sleutelen. De andere kant, de slave, is dan een vast gegeven met documentatie in de datasheet.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Arco

Special Member

Zelf een slave maken is best te doen, alleen is het een hoop uitzoeken en proberen. (omdat maar weinigen het gebruiken is er weinig over te vinden)
Ik gebruik pics vaak als i2c slave. (die dan een bestaand i2c ic emuleren)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

code:


   for (bytenr=0; bytenr<38; bytenr++)
   {  while(!(SPSR & (1<<SPIF)));
      SPDR =  testers[bytenr];
   }

Verkeerde volgorde. SPIF wordt hoog nadat het eerste byte al verstuurd is. En dan is er nog geen data in SPDR.

Zo zal het wel beter gaan:

code:


   for (bytenr=0; bytenr<38; bytenr++)
   {  SPDR = testers[bytenr];
      while(!(SPSR & (1<<SPIF)));
   }

Maar een goede master moet er rekening mee houden dat zijn slave nog niet wakker is. Dus die moet blijven proberen totdat de juiste data terugkomt.

Die timing verklaart overigens maar een enkele 0x00 byte terwijl de trace meerdere 0x00 bytes laat zien. Blijkbaar gaat de master al transmitten terwijl de slave nog niet is opgestart?

Het is meestal geen goed idee om in main al meteen in de eerste microseconde aktief te worden. Misschien heeft de slave een andere voeding, die trager opstart, of een grotere reset condensator, of een groter opstart delay, of ... enz.

Het kan dus helpen om in de master een delay van bijv 500 milliseconden af te wachten voor de loop te starten.

[Bericht gewijzigd door deKees op donderdag 22 augustus 2019 00:06:03 (50%)

trix

Golden Member

nee ze zitten beide op dezelfde labvoeding.

Op 21 augustus 2019 22:13:31 schreef Arco:
Zelf een slave maken is best te doen, alleen is het een hoop uitzoeken en proberen. (omdat maar weinigen het gebruiken is er weinig over te vinden)
Ik gebruik pics vaak als i2c slave. (die dan een bestaand i2c ic emuleren)

ik dacht dat dat veel meer werd gedaan.

het gekke is dat wanneer ik in de SPDR v/d slave direkt een waarde zet b.v. 0x255, dat het dan wel goed gaat. je ziet meteen bij de eerste klokpulsen de byte op de MISO lijn.
ik zal daar morgen eens een plaatje van posten.

eigenwijs = ook wijs
Arco

Special Member

Voor communicatie tussen CPU's is de UART veel simpeler in gebruik...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Jouw master stuurt SS laag voor elke byte die verstuurd wordt, en weer hoog als de byte verzonden is. Dus feitelijk heb je 1-byte sessies.

In de slave gaat het nu mis. De SPI wordt aktief als SS laag wordt, maar dan is er nog geen data in SPDR. Vervolgens stuurt de master zijn data byte, en krijgt een leeg byte terug, want SPDR in de slave was immers nog niet geschreven. De slave schrijft pas in SPDR nadat de transmissie al gedaan is, die staat dus klaar voor de volgende transmissie, maar de master maakt SS dan weer hoog zodat de SPI in de slave wordt gereset.

Normaal wordt de data verstuurd in berichten van meerdere bytes. Dus dan gaat dat zo:

- Master maakt SS laag.
- Master verstuurt het eerste byte en krijgt 0x00 terug van de slave.
- Slave ontvangt eerste byte en schrijft antwoord in SPDR.
- Master moet de slave voldoende tijd geven en vervolgens de tweede byte versturen.
- Enz. SS blijft laag totdat de hele sequence is afgehandled. Pas dan wordt SS weer hoog.

Als de response op het eerste byte al meteen goed moet zijn, dan moet de slave al in SPDR schrijven voordat het eerste bit van het eerste byte al verzonden is. Dus zekere niet wachten op SPIF want die wordt pas hoog nadat er een heel byte binnen is gekomen.

trix

Golden Member

even voor de duidelijkheid, deze slave die ik wil maken is enkel en alleen bedoeld om het programma in de master te kunnen testen. straks komen de bytes die nu uit de slave komen van een ander device.

nog wat testjes gedaan, maar ik krijg de synchronisatie niet goed, dus ik dacht dan maar wat symptoom bestreiding, als ik maar kan testen. dus ik gooi die eerste "0 bytes" weg (hoeveel het er ook mogen zijn) en ga dan verder. alleen nu krijg ik zo nu en dan wat losse bits op de MISO lijn waardoor het ook niet gaat werken.

ik krijg het idee dat ik verder en verder weg dwaal van het geen ik wil, en dat SPI toch niet de juiste bus/protocol is voor het geen wat ik straks moet gaan doen.
dat word nog versterkt door de reacties hier dat het niet erg gebruikelijk is om zelf een slave te maken (waarom zou ik dat dan wel doen ?).

dus terug naar de basis: wat ik moet doen:

- ik heb straks een device waarin 19x een atmega 8 zit
- in elke atmega 8 zitten 600 bytes
- die moeten op een bepaalde volgorde naar de hoofdprint (atmega 128)
- kabellengte device -> hoofdprint = 10mtr.

dat is het eigenlijk, in de hoofdprint worden die bytes opgeslagen in externe RAM (23LC1024) dat werkt al.

wat is de best aangewezen oplossing ? waarvoor mijn dank uiteraard, jullie bijdragen worden enorm gewaardeerd.

eigenwijs = ook wijs
Arco

Special Member

- ik heb straks een device waarin 19x een atmega 8 zit

Dat lokt natuurlijk de vraag uit: waarom... :) (kan dat niet met 1 processor?)
Als je 19 SPI devices hebt, moet je ook 19 slave select pinnen aansturen. Hoe doe je dat?

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
benleentje

Golden Member

Als je 19 + master is 20 units hebt is het verstandig om alles geadresseerd te gaan aansturen. Je zou dat via i2C kunnen doen dat werkt met adressering en hoef je niet voor elke slave een aparte SS lijn te hebben.

IK denk wel dat SPI kan werken maar dan wel zoals de kees het beschrijft en anders ook even algemene SPI protocol in PDF eens doorlezen. Je schrijft dan wel zelfs de software voor slave en dat deel is dus wel vrij maar de onderliggende hardware werkt dan toch zoals het normale SPI protocol en dan moet je ook in de goede volgorde werken en je slave de tijd geven om te kunnen antwoorden.

Mensen zijn soms net als een gelijkrichter, ze willen graag hun gelijk hebben.
Arco

Special Member

Bij I2C heb je buffers als de P82B715 nodig. Gaat goed, heb ik met meerdere toestellen aan 1 bus over tientallen meters gebruikt.
En de UART kan ook zoals gezegd...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com