Forum: Mikrocontroller und Digitale Elektronik software -SPI-Slave


von kluski (Gast)


Lesenswert?

hi zusammen,

ich habe mir Vorgenommen ein SPI-Slave auf den Tiny13V.
Es hapert an der Realisierung bzw. sind fragen offen.
1) Ist eine schleife nötig?
2) Kann ich den SCK-takt als Taster ansehen?

der code sieht zur zeit so aus
[c]
#include <avr/io.h>
#include <avr/interrupt.h>
#include "SPI-INIT.h"

unsigned int SPI_Write_Word(unsigned int word)
{
uint8_t MSB = 0b1000000; // Letzte bit
uint8_t temp = 0;
//CLK gibt den takt/übertagungsgeschwindigkeit vor MISO und MOSI halten 
sich daran
if(SPI_CLK_PIN & (1<<SPI_CLK_PIN)) //wen sck auf High wird 1 bit gesende
{
  if(MSB & word)SPI_MISO_PORT |= (1<<SPI_MISO_PIN); //Pin Miso high
  else SPI_MISO_PORT &= ~(1<<SPI_MISO_PIN);
  MSB <<=1;      //MSB First
}

return (temp);
}

int main()
{
SPI_INIT();
int8_t wechsel = 0b10101010;
while(1)
{
if( !(SPI_SS_PIN & (1<<SPI_SS_PIN))) //Wenn SS auf low geht schicke MISO
{
  SPI_Write_Word(wechsel);  //MISO-funktion
}
}
   return 0;
}
[c/]

ich bekomme die warnung ../Tiny-SW-SPI-SLAVE.c:36: warning: control 
reaches end of non-void function


MfG Kluski

von Sebastian M. (compressed)


Lesenswert?

Leider fehlt die Hälfte :(
bitte das gesamte Projekt zeigen.

von kluski (Gast)


Lesenswert?

sorry jetzt sehe ich es auch

[c]//DDRB
#define SPI_MOSI_DDR  DDRB
#define SPI_CLK_DDR   DDRB
#define SPI_MISO_DDR  DDRB
#define SPI_SS_DDR    DDRB

//PORTB
#define SPI_MOSI_PORT  PORTB
#define SPI_CLK_PORT   PORTB
#define SPI_MISO_PORT  PORTB
#define SPI_SS_PORT    PORTB

// PIN
#define SPI_MOSI_PIN  PB0
#define SPI_SS_PIN    PB1
#define SPI_CLK_PIN   PB2
#define SPI_MISO_PIN  PB3

//Slave-deklaration
void SPI_INIT(void)
{// MOSI, CLK und SS auf Eingang setzen
  SPI_MOSI_DDR &= ~(1<<SPI_MOSI_PIN);
  SPI_CLK_DDR  &= ~(1<<SPI_CLK_PIN);
  SPI_SS_DDR   &= ~(1<<SPI_SS_PIN);
// MOSI, CLK und SS Internen Pull-Up aktivieren
  SPI_MOSI_PORT |=(1<<SPI_MOSI_PIN);
  SPI_CLK_PORT  |=(1<<SPI_CLK_PIN);
  SPI_SS_PORT   |=(1<<SPI_SS_PIN);
// MISO auf Ausgang setzen
  SPI_MISO_DDR |= (1<<SPI_MISO_PIN);
//MISO auf High setzten
  SPI_MISO_PORT |= (1<<SPI_MISO_PIN);
}[c/]

Ich kann mir das nicht so richtig vorstellen wie ich das mit dem SCK/CLK 
machen soll.

von Anschein (Gast)


Lesenswert?

kluski schrieb:
> Ich kann mir das nicht so richtig vorstellen wie ich das mit dem SCK/CLK
> machen soll.


Als Interrupteingang mit der richtigen Flanke definieren und
im Interrupt MOSI einlesen und MISO setzen?

(Ich hoffe, dass der AVR edge-sensitive Interrupts hat...)

HDH,

Anschein

von kluski (Gast)


Lesenswert?

ja habe mir auch gedacht SCK als INT zu machen.

> (Ich hoffe, dass der AVR edge-sensitive Interrupts hat...)
das datenblatt habe ich mal durch gesucht steht aber nichts drin von 
einem egde-sensitive Interrupt

1
unsigned int SPI_Write_Word(unsigned int word)
2
{
3
uint8_t MSB = 0b1000000; // Letzte bit
4
uint8_t temp = 0;
5
//CLK gibt den takt/übertagungsgeschwindigkeit vor MISO und MOSI halten
6
sich daran
7
if(SPI_CLK_PIN & (1<<SPI_CLK_PIN)) //wen sck auf High wird 1 bit gesende
8
{
9
  if(MSB & word)SPI_MISO_PORT |= (1<<SPI_MISO_PIN); //Pin Miso high
10
  else SPI_MISO_PORT &= ~(1<<SPI_MISO_PIN);
11
  MSB <<=1;      //MSB First
12
}
13
14
return (temp);
15
}

ist der teil Überhaupt richtig mit dem bitweise rausschieben wenn sck 
auf high geht?

von Anschein (Gast)


Lesenswert?

>ist der teil Überhaupt richtig mit dem bitweise rausschieben wenn sck
>auf high geht?

Kommt drauf an, ob Du MSB- oder LSB-first willst.

Wenn Du den Interrupt mit der steigenden Flanke oder
H-Pegel auslöst, ist die Abfrage des SPI_CLK_PINs redundant.

Wird beim AVR das Interruptflag automatisch gelöscht?

Wir wird die Uebertragung gestartet/gestoppt?

Ausserdem:
Dein MSB ist eine lokale Variable, die
beim Verlassen Deiner SPI_Write_Word() vergessen wird.
Wird wohl nicht das sein, was Du willst...
Schieberichtung ok? Bei Dir ist MSB nach dem ersten Schieben
0 (da uint 8).


Anschein.

von kluski (Gast)


Lesenswert?

Ich habe mir das ganze so gedacht:

SPI_SS_PIN geht LOW somit weiss der tiny, das er mit SPI_Write_Word()
senden soll.
Es soll die bit aber nach einem bestimmten periode schicken.
es soll jedes mal ein bit raus gehen wenn der SCK HIGH geht und nach 8 
Bit bzw. 16 bit soll die die Übertragung beendet werden.

> Kommt drauf an, ob Du MSB- oder LSB-first willst.
MSB-first


> Wenn Du den Interrupt mit der steigenden Flanke oder
> H-Pegel auslöst, ist die Abfrage des SPI_CLK_PINs redundant.
Mit H-Pegel
> ist die Abfrage des SPI_CLK_PINs redundant.
?? Mehrmals vorhanden oder Überflüssig

> Wir wird die Uebertragung gestartet/gestoppt?
so bald SS LOW ist wird die Übertragung gestartet

> Bei Dir ist MSB nach dem ersten Schieben 0 (da uint 8).
"0" Ich dachte "128" weil 0b10000000 ich es ja in binär geschrieben habe 
0b

danke dir für die Tipps und Änderungens vorschlage

von Anschein (Gast)


Lesenswert?

kluski schrieb:
> Ich habe mir das ganze so gedacht:
>
> SPI_SS_PIN geht LOW somit weiss der tiny, das er mit SPI_Write_Word()
> senden soll.

SPI_Write_Word() sieht eher nach der Bit-Senderoutine aus,
nicht nach der "Bereite das Senden eines Zeichens vor"-Routine.

> Es soll die bit aber nach einem bestimmten periode schicken.
> es soll jedes mal ein bit raus gehen wenn der SCK HIGH geht und nach 8
> Bit bzw. 16 bit soll die die Übertragung beendet werden.
>

Soweit ok.

>> Kommt drauf an, ob Du MSB- oder LSB-first willst.
> MSB-first
>
>
>> Wenn Du den Interrupt mit der steigenden Flanke oder
>> H-Pegel auslöst, ist die Abfrage des SPI_CLK_PINs redundant.
> Mit H-Pegel
>> ist die Abfrage des SPI_CLK_PINs redundant.
> ?? Mehrmals vorhanden oder Überflüssig
>
>> Wir wird die Uebertragung gestartet/gestoppt?
> so bald SS LOW ist wird die Übertragung gestartet
>


>> Bei Dir ist MSB nach dem ersten Schieben 0 (da uint 8).
> "0" Ich dachte "128" weil 0b10000000 ich es ja in binär geschrieben habe
> 0b
>
Ja bei der Zuweisung, nein nach dem Schieben.
bei 8 bit: 128 << 1 == 0

> danke dir für die Tipps und Änderungens vorschlage

Anschein

von kluski (Gast)


Lesenswert?

> SPI_Write_Word() sieht eher nach der Bit-Senderoutine aus,
> nicht nach der "Bereite das Senden eines Zeichens vor"-Routine.
achso, dumme frage wie sieht es bzw. der unterschied in beiden Formen 
geht doch ein bit raus

> Ja bei der Zuweisung, nein nach dem Schieben. bei 8 bit: 128 << 1 == 0
das heisst wenn wenn er den ersten bit schiebt wird dannach nicht mehr 
weiter geschoben
löse ich das problem nicht mit einer hilfvariable

=> dataout = MSB | wechsel (in meinem code zb.)
1
char databit;
2
/* Interrupt Code */
3
if(databit == 1)SPI_MISO_PORT |= (1<<SPI_MISO_PIN); //Pin Miso high
4
else SPI_MISO_PORT &= ~(1<<SPI_MISO_PIN);
5
databit<<=1;  //MSB First

von Anschein (Gast)


Lesenswert?

kluski schrieb:
>> SPI_Write_Word() sieht eher nach der Bit-Senderoutine aus,
>> nicht nach der "Bereite das Senden eines Zeichens vor"-Routine.
> achso, dumme frage wie sieht es bzw. der unterschied in beiden Formen
> geht doch ein bit raus
>
Vorbereiten (beispielsweise in einem Slave-Select Interrupt):
- Bitmaske initialisieren
- Bitzaehler initialisieren (optional)
- Interrupt enable

CLK-Interrupt:
- GPIO entsprechend dem Wert des zu senden Bits setzen
- bitmaske (das, was Du "MSB" genannt hast) schieben.
- (Optional) Bitzaehler dekrementieren. Wenn 0, dann
  Interrupt disable. Oder dann, wenn bitmaske == 0 geworden ist.

>> Ja bei der Zuweisung, nein nach dem Schieben. bei 8 bit: 128 << 1 == 0
> das heisst wenn wenn er den ersten bit schiebt wird dannach nicht mehr
> weiter geschoben

Doch, es wir weiter geschoben, aber 0 << 1 bleibt immer 0.

> löse ich das problem nicht mit einer hilfvariable
>

Nein. Du musst einfach nach RECHTS schieben statt
nach links (oder das zu sendende Wort nach links und
die Bitmaske konstant halten).

MSB und zu sendendes Wort müssen global sein (und "volatile") und ihren 
Wert von einem Interrupt zum anderen behalten.

> => dataout = MSB | wechsel (in meinem code zb.)char databit;
> /* Interrupt Code */
> if(databit == 1)SPI_MISO_PORT |= (1<<SPI_MISO_PIN); //Pin Miso high
> else SPI_MISO_PORT &= ~(1<<SPI_MISO_PIN);
> databit<<=1;  //MSB First

Anschein

von kluski (Gast)


Lesenswert?

Ich bekomme die Vorbereitung nicht hin Alles sieht aus wie eine 
senderoutine

von kluski (Gast)


Lesenswert?

Nach längerem grübeln ist der Code entstanden.
Ich bekomme eine Warnung

../spi-tiny13.c:38: warning: suggest parentheses around assignment used 
as truth value

weiss aber nichts damit anzufangen.
Also das Programm soll ein SPI slave simulieren und ADC-werte schicken.
Am MISO(PB3) werden dann die Pegel Geschaltet,
Ich bin mir aber nicht Sicher ob der befehl das macht was ich will
1
while(GIMSK  & (1<<INT0));
2
//warte bis am Externen Interrupt etwas passiert

Und das ist mein ganzer Code
1
#include <avr/io.h>        // Namen der IO Register
2
#include <avr/Interrupt.h> // Interrupt register
3
#include "adc-init.h"
4
#include "SPI-init.h"
5
6
volatile char MISO_Byte;
7
volatile int MSB = 0x8000;
8
9
ISR(INT0_vect)
10
{
11
if(MISO_Byte == 1)SPI_MISO_PORT |= (1<<SPI_MISO_PB3); //Pin Miso high
12
else SPI_MISO_PORT &= ~(1<<SPI_MISO_PB3);
13
}
14
15
int main(void)
16
{ 
17
       
18
  uint16_t adcval;
19
  ADC_Init();
20
/*Externen Interrupt-Init*/
21
  MCUCR = (1<<ISC01)|(1<<ISC00);
22
 //Interrupt auslösen wenn Steigende flanke ist
23
  GIMSK = (1<<INT0);  // Interrupt erlauben
24
  GIFR  = (1<<INTF0); 
25
 
26
while( 1 ) {
27
adcval = ADC_Read(0);  // Kanal 0
28
// mach was mit adcval
29
 
30
adcval = ADC_Read_Avg(2, 4);  // Kanal 2, Mittelwert aus 4 Messungen
31
// mach was mit adcval
32
33
MISO_Byte = MSB | adcval;
34
  
35
if(!(SPI_SS_PIN1 & (1<<SPI_SS_PB1)))// Wenn SS(PB1) auf low geht start der Übertragung
36
{
37
  for(uint16_t a =15 ; a = 0 ; a--)//Warning: suggest parentheses around          assignment used as truth value
38
{
39
 if(MISO_Byte & MSB)SPI_MISO_PORT |= (1<<SPI_MISO_PB3);
40
 else SPI_MISO_PORT &= ~(1<<SPI_MISO_PB3);
41
 while(GIMSK  & (1<<INT0)); 
42
//warte bis am Externen Interrupt etwas passiert
43
 MISO_Byte<<=1;// Bit nach Links schieben
44
}
45
}
46
 else;
47
}
48
   return 0;
49
}

Ich bedanke mich schonmal für die Kritik :P

MfG Kluski

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.