- 3D-Druck Einstieg und Tipps         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 22

Thema: Software-SPI-Slave mit Tiny13V

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    21.07.2011
    Beiträge
    27

    Software-SPI-Slave mit Tiny13V

    Anzeige

    Powerstation Test
    Hy zusammen,
    ich versuche ein SW-SPI-Slave zu schreiben, aber es haut nicht hin.
    Ne Master Version habe ich gefunden und die wollte ich zum Slave umschreiben.
    Code:
    unsigned int SPI_Write_Word(unsigned int word)
    {
    unsigned char i;
    unsigned int mask;
    unsigned int temp;
    
    SPI_SS_PORT  &= ~(1<<SPI_SS_PIN);  //SS auf Low Schalten Start der Übertragung
    
    mask = 0x8000;
    temp = 0;
    
    for(i=0;i<15;i++)
    {
    if(mask | word) SPI_MOSI_PORT|=(1<<SPI_MOSI_PIN); 
    else SPI_MOSI_PORT&=~(1<<SPI_MOSI_PIN); 
    if(SPI_MISO_PIN == 1) temp |= mask;
    SPI_CLK_PORT |=(1<<SPI_CLK_PIN); 		//CLK-Takt HIGH
    SPI_CLK_PORT &=~(1<<SPI_CLK_PIN); 		//CLK LOW
    mask >>= 1;
    }
    
    SPI_SS_PORT |= (1<<SPI_SS_PIN);  //SS auf High Schalten Ende der Übertragung
    
    return(temp);
    }
    eigendlich dachte ich es wäre einfacher
    Ports ändern von Ausgang auf eingang schalten und Bit-maske schieben (clk-Abhängig)
    bei der Bitmaske habe ich jetzt das problem.

  2. #2
    Moderator Begeisterter Techniker Avatar von tucow
    Registriert seit
    15.01.2006
    Ort
    Düsseldorf
    Alter
    38
    Beiträge
    269
    Hey ExKluski,

    schau Dir mal diesen Slave Code an:

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    
    volatile unsigned char data;
    unsigned char status;
    
    
    SIGNAL (SIG_SPI) {
        data = SPDR;
        if (data == '1')    PORTD = 0x00;            //LEDs an
        if (data == '0')    PORTD = 0xff;            //LEDs aus
    }
    
    
    void slave_init (void) {
        DDRB |= _BV(PB4);                            //MISO als Ausgang, der Rest als Eingang
        SPCR = _BV(SPE) | _BV(SPIE);                 //Aktivierung des SPI + Interrupt
        status = SPSR;                               //Status löschen
    }
    
    
    int main (void) {
    
    
        DDRD = 0xff;
        slave_init ();
        sei ();
        
        for (;;);
        return 0;
    }
    Quelle: http://www.mikrocontroller.net/topic/12197


    E
    s ist schwer Deinem Code etwas zu entlocken, wie sieht der Rest aus, hast Du alle nötigen includes? Wie sieht Deine main() aus?
    Ist Deine Schaltung korrekt?


    Gruß
    Geändert von tucow (18.01.2012 um 12:19 Uhr)
    Gruß
    Andreas




    Mein: Humanoide // nanoCopter Projekt
    Das Raspberry Pi als: Wifi Access Point // Wifi Router

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    21.07.2011
    Beiträge
    27
    Danke für die schnelle antwort.

    Den code kenne ich, aber läuft nicht auf den AtTiny13 weil er HW-SPI ist.

    >>Es ist schwer Deinem Code etwas zu entlocken
    klar sehe ich gerade auch. der code ist aus einer SW-SPI-Master code um ein AVR mit 2 MAX3100 als SPI-UART-brigde.
    QUELLE: http://www.mikrocontroller.net/attac...dual_rs485.pdf

    >> Du alle nötigen includes?
    denke ich mal. habe zurzeit eine 1 IO.h werde später Interrupt.h noch ein binden als Taktgeber für CLK ex.INT0.

    die main ist noch nicht fertig. Ich beschreibe mal was gemacht werden soll dann versteht man den code besser (hoffe ich)
    der Tiny13 soll adc werte als slave an Attiny2313(Master) per spi schicken (AVR-CDC-SPI) und ma PC-terminal ausgeben.
    So dachte ich mir wie SPI-Slave funktioniert SS schaltet Low. Tiny13 weiss es wird gesendet und schiebt immer ein Bit raus wenn CLK high wird. Bis alle Bits gesendet sind.
    Die Schatung für den tiny2313 läuft und kann per command SS0 und SS1, High bzw Low geschalten werden.

    Der Code für Tiny13
    Code:
    #include <avr/io.h>     // Namen der IO Register
    #include "adc-init.h"
    #include "SPI-init.h"
    
    unsigned int SPI_Write_Word(unsigned int word)
    {
    uint16_t MSB = 0b100000000000000; // Letzte bit
    uint16_t temp = 0;
    //CLK gibt den takt/übertagungsgeschwindigkeit vor MISO und MOSI halten sich daran
    
    	
    	if(SPI_CLK_PB2 & (1<<SPI_CLK_PB2)) //wen sck auf High wird 1 bit gesende
    	{
    		if(MSB & word)SPI_MISO_PORT |= (1<<SPI_MISO_PB3); //Pin Miso high
    		else SPI_MISO_PORT &= ~(1<<SPI_MISO_PB3);
    		MSB <<=1;			//MSB First
    	
    	}
    	
    	else //wenn clk low ist nichts machen
    
    return (temp);	
    }
    
    int main(void)
    {    		
      uint16_t adcval;
      ADC_Init();
    
      while( 1 ) {
        adcval = ADC_Read(3);  // Kanal 0
        // mach was mit adcval
     
        adcval = ADC_Read_Avg(2, 4);  // Kanal 2, Mittelwert aus 4 Messungen
        // mach was mit adcval
      
    
          if(!(SPI_SS_PB1 & (1<<SPI_SS_PB1)))	// Wenn SS(PB1) auf low geht start der Übertragung  
    	  {   
              SPI_Write_Word(adcval); 	//
          }
          else
    	  {
            
          }
    	  }
       return 0;
    }
    Mit dem code ADC-Init lief eigendlich ohne probleme auf mega8 habe die register für tiny13 angepasst

    Code:
    /* ADC initialisieren */
    void ADC_Init(void) {
     
      uint16_t result;
     
    //  ADMUX = (0<<REFS1) | (1<<REFS0);      // AVcc als Referenz benutzen
      ADMUX =  (1<<REFS0)|(1<<MUX1)|(1<<MUX0);      // interne Referenzspannung nutzen
      // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
      // schon auf 0, also single conversion
      ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
      ADCSRA |= (1<<ADEN);                  // ADC aktivieren
     
      /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
         also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
     
      ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
      while (ADCSRA & (1<<ADSC) ) {}        // auf Abschluss der Konvertierung warten
      /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
         Wandlung nicht übernommen. */
      result = ADCW;
    }
     
    /* ADC Einzelmessung */
    uint16_t ADC_Read( uint8_t channel )
    {
      // Kanal waehlen, ohne andere Bits zu beeinflußen
      ADMUX = (ADMUX & ~(0x0F)) | (channel & 0x0F); //ADC3 ist PB3
      ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
      while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
      return ADCW;                    // ADC auslesen und zurückgeben
    }
     
    /* ADC Mehrfachmessung mit Mittelwertbbildung */
    uint16_t ADC_Read_Avg( uint8_t channel, uint8_t average )
    {
      uint32_t result = 0;
     
      for (uint8_t i = 0; i < average; ++i )
        result += ADC_Read( channel );
     
      return (uint16_t)( result / average );
    }
    Der Spi-init ist nur die PORT deklaration
    Code:
     //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_PB0  PB0
    #define SPI_SS_PB1    PB1
    #define SPI_CLK_PB2   PB2
    #define SPI_MISO_PB3  PB3
    
    
    
    //Slave-deklaration
    void SPI_INIT(void)
    {
    // MOSI, CLK und SS auf Eingang setzen
      SPI_MOSI_DDR = (1<<SPI_MOSI_PB0);
      SPI_CLK_DDR  = (1<<SPI_CLK_PB2);
      SPI_SS_DDR   = (1<<SPI_SS_PB1);
    // MOSI, CLK und SS Internen Pull-Up aktivieren 
      SPI_MOSI_PORT |=(1<<SPI_MOSI_PB0);
      SPI_CLK_PORT  |=(1<<SPI_CLK_PB2);
      SPI_SS_PORT   |=(1<<SPI_SS_PB1);
    // MISO auf Ausgang setzen 
      SPI_MISO_DDR |= (1<<SPI_MISO_PB3);
    //MISO auf High setzten
      SPI_MISO_PORT |= (1<<SPI_MISO_PB3);
    }
    hoffe Ihr erschlägt mich nicht für den langen Post bzw. schreckt nicht ab

  4. #4
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Was ich so auf den ersten Blick sehe (also kein Anspruch auf Vollständigkeit):

    1)
    Code:
    uint16_t MSB = 0b100000000000000; // Letzte bit
    Für solche Konstanten die binäre Schreibweise zu verwenden, ist meist keine so gute Idee. Bei den vielen Nullen verzählt man sich schon mal, und genau das hast du auch.

    2)
    Code:
    if(SPI_CLK_PB2 & (1<<SPI_CLK_PB2))
    
    
    if(!(SPI_SS_PB1 & (1<<SPI_SS_PB1)))
    Diese if-Bedingungen machen überhaupt keinen Sinn, und sind immer false.

    3)
    Code:
    MSB <<=1;
    Falsche Richtung.

    4)
    Wo ist der Rest von SPI_Write_Word?
    MfG
    Stefan

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    21.07.2011
    Beiträge
    27
    zu 1)
    uint16_t MSB = 0x8000;

    zu 2) Ich dachte als abfrage für die Pins.
    SS Solange SS high nichts machen und sobald low ist mit dem senden anfangen
    Und bei CLK fast genauso nur er soll schieben wenn CLK high ist.

    zu 3) Er soll mit dem Höchsten bit anfangen?

    zu 4) habe kein Rest nur die SW-SPI-Master Funktion von oben (1.post), da habe ich die sachen die ich nicht brauche (glaube ich zu mindestens) weg gelassen, Weil SS und CLK wird ja dem Tiny13 vom Tiny2313 geschickt.

    MfG exkluski

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    zu 2) Ich dachte als abfrage für die Pins.
    Und wo in diesen Bedingungen wird irgendetwas abgefragt? Da steht einfach nur
    Code:
    if (2 & (1<<2)))

    zu 3) Er soll mit dem Höchsten bit anfangen?
    Und? Wie sieht MSB nach dieser Operation aus?


    zu 4) habe kein Rest nur die SW-SPI-Master Funktion von oben (1.post)
    Da wird also genau ein Bit ausgegeben. Was ist mit den anderen 15?
    MfG
    Stefan

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    21.07.2011
    Beiträge
    27
    Mit der abfrage habe ich mich verlesen sollte so heißen
    Code:
     if(!(SPI_SS_PIN1 & (1<<SPI_SS_PB1)))
    Und? Wie sieht MSB nach dieser Operation aus?
    1 Bit weiter schieben und das dann ausgeben, mache ich das nicht mit
    Code:
     MSB<<=1;
    es ist doch in einer schleife die Solange durchlaufen wird bis 16 bit raus geschoben sind.

    MfG exkluski

  8. #8
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von ExKluski Beitrag anzeigen
    Mit der abfrage habe ich mich verlesen sollte so heißen
    Code:
     if(!(SPI_SS_PIN1 & (1<<SPI_SS_PB1)))
    Ob das jetzt korrekt ist, hängt davon ab, wie SPI_SS_PIN1 definiert ist. Die 1 darin lässt allerdings nichts Gutes vermuten.


    Zitat Zitat von ExKluski Beitrag anzeigen
    1 Bit weiter schieben und das dann ausgeben, mache ich das nicht mit
    Code:
     MSB<<=1;
    es ist doch in einer schleife die Solange durchlaufen wird bis 16 bit raus geschoben sind.

    MfG exkluski
    Nochmal: wenn MSB vorher 0x8000 ist, was ist es dann hinterher?
    Und wo bitte ist diese Schleife?
    MfG
    Stefan

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    21.07.2011
    Beiträge
    27
    hinterher ist er 0, wäre es dann nicht besser es als Globale Variable "volatile" und die Richtung zu ändern

    Die Schleife meine ich
    Code:
    for(i=0;i<15;i++)
    {
    if(mask | word) SPI_MOSI_PORT|=(1<<SPI_MOSI_PIN); 
    else SPI_MOSI_PORT&=~(1<<SPI_MOSI_PIN); 
    if(SPI_MISO_PIN == 1) temp |= mask;
    SPI_CLK_PORT |=(1<<SPI_CLK_PIN); 		//CLK-Takt HIGH
    SPI_CLK_PORT &=~(1<<SPI_CLK_PIN); 		//CLK LOW
    mask >>= 1;
    }

  10. #10
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von ExKluski Beitrag anzeigen
    Die Schleife meine ich
    Und was hat diese Schleife mit deinem Slave-Code zu tun? Wo ist da eine Schleife?
    MfG
    Stefan

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. Slave-Master-Slave übertragung geht nicht
    Von Dämmi im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 16
    Letzter Beitrag: 26.11.2008, 00:08
  2. Software-Slave für I2C-Bus
    Von ZellRobi im Forum Software, Algorithmen und KI
    Antworten: 11
    Letzter Beitrag: 25.06.2008, 15:59
  3. Problem beim Programmieren bei minimaler Taktung Tiny13V
    Von Windi im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 16
    Letzter Beitrag: 11.09.2007, 14:02
  4. Bezugsquelle für Tiny13V
    Von Windi im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 20.02.2006, 22:30
  5. AT90S2313 als I2C-Slave (Software-Implementierung)
    Von talentraspel_kai im Forum AVR Hardwarethemen
    Antworten: 8
    Letzter Beitrag: 08.02.2006, 15:03

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests