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
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.
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
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?
>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.
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
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
> 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 |
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
Ich bekomme die Vorbereitung nicht hin Alles sieht aus wie eine senderoutine
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.