Tiny ASURO Library: Thread und sf.net Seite
Hallo Markus,
heisst das, ich muss die CS Leitung für jedes Byte tooglen oder kann ich die gesamte Übertragung mit einem Low CS fahren, wenn ich mehre Bytes zu übertragen habe.
Bin derzeitig am Debuggen mit Logikanalyser..
Gruss R.
- - - Aktualisiert - - -
Hallo Markus,
hier die Startroutine, welche im Hauptprogramm liegt und die Interruptverarbeitung startet:
Hier die eigentliche Startroutine, welche auch noch andere Steuerfunktionen übernimmtCode:CLEAR_BIT(PORTB,OUTPUT_SELECT_SPI_GYRO); // Select the slave // ReadGyroADIS16265(); // load Data for command ReadAngleADIS16265(); Master_Start_Send_SPI( SPI_SLAVE_GYRO, GYRO_SPEED_CALCULATION );
Code:// ================================================================== // Start the communication with the Slave // ================================================================== void Master_Start_Send_SPI (int iChannel, int iBit ) { m_Active_SPI_Channel=iChannel; // Select the channel m_SPIByteToSend--; // Send the first byte out SPDR=SPISendBuffer[0]; // Send it m_ArrayReadPointer=0; // Set Pointer to first byte to receive m_ArrayWritePointer=1; // Set Pointer to the next byte m_DummyByteReceived=false; // Dummy byte not received CLEAR_BIT( m_SPI_Status, iBit); // Clear the request }
Hier die Interruptroutine
Code:/ ================================================================== // SPI Interrupt for the received chars from Slaves // ================================================================== SIGNAL (SPI_STC_vect) { unsigned char data=0; // Clear data bytes data=SPDR; // get the data byte from the register if(m_SPIByteToSend > 0) { SPDR=SPISendBuffer[m_ArrayWritePointer]; // Send the next byte out to slave m_ArrayWritePointer++; m_SPIByteToSend--; // to get the complete answer } if( m_SPIBytetoReceive > 0) // Do we wait still for answers { SPIReceiveBuffer[m_ArrayReadPointer]=data; // Store the byte received if( m_DummyByteReceived == true ) // We have to send one more byte { m_SPIBytetoReceive--; // Still a byte received m_ArrayReadPointer++; // Set pointer to the next position } if(m_SPIBytetoReceive > 0 && m_SPIByteToSend == 0 ) // Send of data finished SPDR=0x0; // Send a dummy Byte to get the next bytes } if(m_SPIBytetoReceive == 0) // transmission block finished { SET_BIT(PORTB,OUTPUT_SELECT_SPI_GYRO); // De select the all slave SET_BIT(PORTB,OUTPUT_SELECT_SPI_COMPASS); SET_BIT(PORTB,OUTPUT_SELECT_SPI_ATMEGA8); // Select of which to select costs more CPU power, than all once } m_DummyByteReceived=true; // Dummy byte received }
Im Anhang das Impulsdiagram der Schnittstelle.
Sieht meiner Meinung nach o.k. aus.
Wenn, nicht bitte komentar, sonst benutzt jemand anderes das hier und hat Probleme.
Ich teste noch weiter mit meinem Atmega8 Slave, den Code kann ich ja dann auch posten, wenn erst fertig ist.
Gruss R.
Kaum macht man es richtig, schon funktioniert's ...
Du musst CS während der ganzen Übertragung auf Low halten! Mit CS Low->High beendest du die Übertragung und setzt (üblicherweise) den Zustandsautomaten des Slaves zurück, danach beginnt die Kommunikation wieder ganz von vorne!
Der angehängte Plot sieht gut aus, der Code bei grobem Überfliegen auch.
mfG
Markus
Tiny ASURO Library: Thread und sf.net Seite
Hallo Markus,
die erste Auswertung der übertragenen Werte sieht auch von meiner Seite gut aus.
Ich muss die Platine jetzt wieder mit dem Hauptrechner (linux cpu) verdrahten, da dieser eine bessere
Darstellung der Messwerte hat (Interface zum PC)
Hier wie versprochen der Quellcode des Slaves (ATMEGA8 auf Interrupt-Basis:
Init Master
Init SlaveCode:// ================================================================== // Setup of the SPI Interface // ================================================================== void InitSPIInterface(void) { SPCR = (1<<CPOL)| (1<<CPHA); // Signal Mode 3 SPCR |= (1<<SPE) | (1<<SPIE); //Activate the SPI Interrupt SPSR =0; // Clear the Control Register }
Code:// ================================================================== // Setup of the SPI Interface // ================================================================== void InitSPIInterface(void) { SPCR = (1<<CPOL)| (1<<CPHA); // Signal Mode 3 SPCR |= (1<<SPE) | (1<<SPIE); //Activate the SPI Interrupt SPSR =0; // Clear the Control Register }Code:// ================================================================== // SPI Interrupt handling // ================================================================== SIGNAL (SIG_SPI) { char *pointer; unsigned char data=0; data=SPDR; // get the data byte from the register if ( data != 0) { if (m_buffer_adr == NULL) // Is it the first byte to receive (setup buffer) { switch( data ) // get the command byte, which data area { case 'G': // Actual Angle by the Gyro module (Angle change per second) m_buffer_adr = (char*) &DataBuffer; m_NumberOfBytesToSend=10; pointer=(char*) &m_FilteredGyro; DataBuffer[0]= (char)*pointer++; DataBuffer[1]= (char)*pointer++; DataBuffer[2]= (char)*pointer++; DataBuffer[3]= (char)*pointer; pointer=(char*) &m_accelerometer_x; DataBuffer[4]= (char) *pointer++; DataBuffer[5]= (char) *pointer; pointer=(char*) &m_accelerometer_y; DataBuffer[6]= (char) *pointer++; DataBuffer[7]= (char) *pointer; pointer=(char*) &m_accelerometer_z; DataBuffer[8]= (char) *pointer++; DataBuffer[9]= (char) *pointer; break; case 'C': m_buffer_adr = (char*) &m_OrientationFromCompass; // Actual Compass value of the extern compass m_NumberOfBytesToSend=sizeof(m_OrientationFromCompass); break; case '!': // Status of the Program m_buffer_adr = (char*) &m_Status; m_NumberOfBytesToSend=sizeof(m_Status); break; case 'I': // Version of the m_buffer_adr = (char*) &m_version; m_NumberOfBytesToSend=sizeof(m_version); break; case 'T': // m_buffer_adr = (char*) &DataBuffer; m_NumberOfBytesToSend=4; DataBuffer[0]=m_MotorTemperatur_Left; DataBuffer[1]=m_MotorTemperatur_Right; DataBuffer[2]=m_ControllerTemperatur_Left; DataBuffer[3]=m_ControllerTemperatur_Right; break; case 'S': // m_buffer_adr = (char*) &DataBuffer; pointer=(char*) &m_MotorCurrent_Left; DataBuffer[0]= (char) *pointer++; DataBuffer[1]= (char) *pointer; pointer=(char*) &m_MotorCurrent_Right; DataBuffer[2]= (char) *pointer++; DataBuffer[3]= (char) *pointer; m_NumberOfBytesToSend=4; break; case 'V': // m_buffer_adr = (char*) &m_AkkuVoltage; m_NumberOfBytesToSend=sizeof(m_AkkuVoltage); break; default: m_buffer_adr = (char*) &m_version; m_NumberOfBytesToSend=sizeof(m_version); } SPDR = *m_buffer_adr; // Send the received command as a feedback return to master m_NumberOfBytesToSend--; } else // get no the data into the buffer { if(m_NumberOfBytesToSend > 0) { if( m_buffer_adr != NULL ) // Do we have a valid pointer { *m_buffer_adr=data; // Store the data into the buffer m_buffer_adr++; // Incr. Buffer address for the next byte } m_NumberOfBytesToSend--; // dec. counter of byte to send/receive if(m_NumberOfBytesToSend <= 0) { m_buffer_adr=NULL; // Clear Buffer Pointer } } else { m_buffer_adr=NULL; // Clear Buffer Pointer } SPDR = 0x0; // Dummy Answer } } else { //Slave transmitter ============================================================================ if(m_buffer_adr != NULL) // Buffer set up ? { if(m_NumberOfBytesToSend > 0) // do we have to send bytes still { SPDR = *m_buffer_adr; // send the data byte m_buffer_adr++; // get the next byte of the buffer m_NumberOfBytesToSend--; // dec. counter of byte to send } else { m_buffer_adr=NULL; // Clear Buffer Pointer SPDR=0x0; // No more values in the buffer } } else { m_buffer_adr=NULL; // Clear Buffer Pointer SPDR=0x0; // No more values in the buffer } } }
Vielen Dank für die Hilfe. Manchmal sieht man den Wald vor lauter Bäumen nicht und ist so eine Hilfe doch nicht schlecht.
Gruss R.
Kaum macht man es richtig, schon funktioniert's ...
Lesezeichen