Hallo Zusammen,
ich habe einen atmega32 als I2C Slave im Interrupt Mode geschrieben. Der Code (siehe unten) arbeitet ohne Probleme bei einer Datenlänge als Antwort kleiner 3 Bytes. Werden längere Antwort erwartet, scheint nur Blödsinn (oder 0xff) am Master anzukommen.
Der Master, ruft ohne Probleme an einem Hardware Client (RTC Uhr) die Daten in einem Rutsch ab (5 Byte). Das ganze bei einem Atmega 32 (20Mhz) geht jedoch derzeit schief.
Bei der Abfrage mit dem Bereich "K" erwarte ich eigentlich eine Antwort mit "1,2,3,4,5,6", gesendet wird aber "1,2,1,255,255,255" und das sehr stabil !
Hat jemand eine Idee, welchen Fehler ich hier gemacht habe. Laut Tabelle sollte der atMega mit dieser taktfreq. doch einen 100k oder sogar 400kBus handhaben können oder ?Code:SIGNAL (SIG_2WIRE_SERIAL) { unsigned char data=0; switch (TW_STATUS) //Check the TWI-Status register { case TW_SR_SLA_ACK: // 0x30 Slave Receiver, Slave was addressed m_buffer_adr=NULL; // Buffer position is not defined TWCR_ACK; // Send Ack and request the next data byte break; // get variables from the system case TW_SR_DATA_ACK: // 0x80 Slave Receiver, a data byte received data=TWDR; // get the data byte from the register if (m_buffer_adr == NULL) // Is it the first byte to receive (setup buffer) { switch( data ) // get the command byte, which data area { case 'A': // Actual position m_buffer_adr = (char*) &m_ActualPosition[0]; m_NumberOfBytesToSend=sizeof(m_ActualPosition); break; case 'B': // Bumper state m_buffer_adr = (char*) &m_BumperState; m_NumberOfBytesToSend=sizeof(m_BumperState); break; case 'C': // Command byte send m_buffer_adr = (char*) &m_command; m_NumberOfBytesToSend=sizeof(m_command); break; case 'E': // End position m_buffer_adr = (char*) &m_EndPosition[0]; m_NumberOfBytesToSend=sizeof(m_EndPosition); break; case 'G': // Actual position in grid unit m_buffer_adr = (char*) &m_ActualPositionLow[0]; m_NumberOfBytesToSend=sizeof(m_ActualPositionLow); break; case 'L': // velocity Left m_buffer_adr = (char*) &m_TargetSpeedLeft; m_NumberOfBytesToSend=sizeof(m_TargetSpeedLeft); break; case 'S': // Start position m_buffer_adr = (char*) &m_StartPosition[0]; m_NumberOfBytesToSend=sizeof(m_StartPosition); break; case 'O': // Base Angle m_buffer_adr = (char*) &m_BaseOrientation; m_NumberOfBytesToSend=sizeof(m_BaseOrientation); break; case 'P': // Actual Angle (Cal. by all different values) m_buffer_adr = (char*) &m_ActualOrientation; m_NumberOfBytesToSend=sizeof(m_ActualOrientation); break; case 'D': // Actual Angle by the Decoder (Impulse module) m_buffer_adr = (char*) &m_ActualOrientationEnCoder; m_NumberOfBytesToSend=sizeof(m_ActualOrientationEnCoder); break; case 'Y': // Actual Angle by the Gyro module (Angle change per second) m_buffer_adr = (char*) &m_ActualOrientationGyro; m_NumberOfBytesToSend=sizeof(m_ActualOrientationGyro); break; case 'R': // velocity Right m_buffer_adr = (char*) &m_TargetSpeedRight; m_NumberOfBytesToSend=sizeof(m_TargetSpeedRight); break; case '!': // Status of the Program m_buffer_adr = (char*) &m_Status; m_NumberOfBytesToSend=sizeof(m_Status); break; case '@': // Steps of the sensors (Array) m_buffer_adr = (char*) &sensSteps; m_NumberOfBytesToSend=sizeof(sensSteps); break; case '?': // Version of the m_buffer_adr = (char*) &m_version; m_NumberOfBytesToSend=sizeof(m_version); break; case 'K': // Data buffer of PID Controller of other Diagnosis values DataBuffer[0] = (char) control[0].setActPoint; DataBuffer[1] = (char) control[1].setActPoint; DataBuffer[2] = (char) control[0].setOutPut; DataBuffer[3] = (char) control[1].setOutPut; DataBuffer[4] = (char) control[0].difValue; DataBuffer[5] = (char) control[1].difValue; m_buffer_adr = (char*) &DataBuffer; m_NumberOfBytesToSend=sizeof(DataBuffer); break; case '1': // m_buffer_adr = (char*) &m_MotorTemperatur_Left; m_NumberOfBytesToSend=sizeof(m_MotorTemperatur_Left); break; case '2': // m_buffer_adr = (char*) &m_MotorTemperatur_Right; m_NumberOfBytesToSend=sizeof(m_MotorTemperatur_Right); break; case '5': // m_buffer_adr = (char*) &m_MotorCurrent_Left; m_NumberOfBytesToSend=sizeof(m_MotorCurrent_Left); break; case '6': // m_buffer_adr = (char*) &m_MotorCurrent_Right; m_NumberOfBytesToSend=sizeof(m_MotorCurrent_Right); break; case '7': // m_buffer_adr = (char*) &m_AkkuVoltage; m_NumberOfBytesToSend=sizeof(m_AkkuVoltage); break; default: DataBuffer[0] = (char) 0; // Give dummy data back m_buffer_adr = (char*) &DataBuffer; m_NumberOfBytesToSend=1; } TWCR_ACK; // Set ack and get the next byte to receive } else // get now 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 < 1) { m_buffer_adr=NULL; } TWCR_ACK; // we still have to receive bytes } else { TWCR_NACK; // We have a Problem. All was send before } } break; //Slave transmitter ============================================================================ case TW_ST_SLA_ACK: //0xA8 Slave addressed in read mode //no break, the rest of the code will also execute case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Request of data // Transmitting variables to the Master system (reading) if(m_buffer_adr != NULL) // Buffer set up ? { if(m_NumberOfBytesToSend > 0) // do we have to send bytes still { TWDR = *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 if(m_NumberOfBytesToSend > 0) // are we finished to send { TWCR_ACK; // we still have to receive bytes } else { m_buffer_adr=NULL; TWCR_NACK; // we have all bytes send } } else { TWCR_NACK; // we have all bytes send } } else { TWCR_NACK; } break; // case TW_ST_DATA_NACK: // 0xC0 No more data requested // case TW_SR_DATA_NACK: // 0x88 // case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has ben transmitted (TWEA = “0”); ACK has been received default: TWCR_RESET; break; break; } }
Grundsätzlich entspricht dieser Code der RN.Wissen DB (http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc)
Edit:
So arbeitet der Code jetzt. Was lernen wir daraus. Niemal einen laufenden Code versuchen zu optimieren, wenn man kurz danach für 3 Wochen in Urlaub und danach auf Dienstreise fährt.
Edit 2:
Nun ja, weiss ich ich auch noch einen weiteren Grund für meine Probleme. Der neue Kernel benutzt ein Speed von 250kBaud. Da komme ich schon an die Grenzen von meinem Amtel atmega32. Evtl. werde ich dann doch den Port auf dem atmega644 vorziehen, da dieser nochmal was schneller ist (20Mhz). Nur das ganze Programm wieder anpassen...
Gruss R.







Zitieren

Lesezeichen