- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 2 von 2

Thema: Referenzen, Parameter für TWI-Funktion

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    45
    Beiträge
    269

    Referenzen, Parameter für TWI-Funktion

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Moin moin!

    Ich habe hier den Code von einem ATm16, der als Master ein Datenpaket (struct parameters_ctrl) über TWI von einem Slave abruft. Das Datenpaket ist in Master und Slave exakt gleich deklariert und im Slave auch initialisiert. Der Slave ist ein ATm8.

    Das Problem ist, daß die Werte, die im Slave in die Struktur geschrieben wurden, nicht in der Struktur im Master ankommen. Die TWI-Kommunikation ist dabei wahrscheinlich nicht das Problem. Per printf-debugging habe ich festgestellt, daß die Funktion twi_request() mit return-Wert 0 beendet, also durchläuft wie geplant.

    Ich vermute das Problem eher bei meinen Parameter-Übergaben, also die Referenzen auf die Struktur und das De-Referenzieren in der twi_request()-Funktion. Könnte sich das mal jemand anschauen?

    Um den Compiler zu befriedigen, muß ich die Referenz auf die Struktur beim Aufruf aus main() auf "(unsigned char *)" casten. Da ich einfach nur die Struktur byteweise übertragen will, sollte das ok sein, weil die Datenbytes der Struktur im Speicher einfach hintereinander folgen. Richtig?
    Wo ich mir nicht so sicher bin, ist diese Anweisung: *(buffer+i)=TWDR in twi_request(). Ist das die richtige Methode, um die Struktur byteweise vollzuschreiben?

    Vielen Dank,

    Nils

    Code:
    volatile struct {
    	unsigned char kp_pitch;
    	unsigned char tn_pitch;
    	unsigned char tv_pitch;
    	unsigned char kp_roll;
    	unsigned char tn_roll;
    	unsigned char tv_roll;
    } parameters_ctrl;
    
    volatile int twi_request(unsigned char adr, unsigned char *buffer, int buffersize) {
    int i;
    	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);				//generate start condition
    	while (!(TWCR & 0x80)) { };							//wait for TWINT set
        if(TWSR!=0x08) {									//0x08 == start condition sent
    		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);			//release Bus
    		return 1; }
    	
    	TWDR=(adr<<1)|0x01;									//slave address and read-bit into TWDR
    	TWCR=(1<<TWINT)|(1<<TWEN);							//address slave
    	while (!(TWCR & 0x80)) { };							//wait for TWINT set
        if(TWSR!=0x40) {									//0x40 == slave has acknowledged
    		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);			//generate stop condition
    		return 2; }
    	
    	for(i=0;i<buffersize;i++) {
    		if(i<buffersize-1) {
    			TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);		//request byte transfer from slave
    			while (!(TWCR & 0x80)) { };					//wait for TWINT set
    			if(TWSR!=0x50) {							//0x50 == byte received,ack returned
    				TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);	//generate stop condition
    				return 3; }
    		}
    		else {
    			TWCR=(1<<TWINT)|(1<<TWEN);					//request last lowbyte transfer from slave
    			while (!(TWCR & 0x80)) { };					//wait for TWINT set
    			if(TWSR!=0x58) {							//0x58 == byte received,nack returned
    				TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);	//generate stop condition
    				return 4; }
    		}
    		*(buffer+i)=TWDR;
    	}
    
    	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);				//generate stop condition
    	return 0;
    }
    In main() wird zyklisch der twi_request aufgerufen:
    Code:
    receive=twi_request(CTRL_B, (unsigned char *) &parameters_ctrl, sizeof(parameters_ctrl));

  2. #2
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    03.01.2004
    Ort
    Pottenstein
    Alter
    45
    Beiträge
    269
    Und Kommando zurück....

    Die TWI-Kommunikation ist in der Tat in Ordnung, aber der Zahlenmüll, der beim Master rauskommt, wird beim Slave schon genauso reingeschrieben. Hatte vorher im Slave zu optimistisch getestet und deswegen angenommen, es gingen die richtigen Zahlen raus.
    Also jetzt das neue Problem, immerhin schärfer eingegrenzt:

    Diese Struktur:

    Code:
    volatile struct {
    	unsigned char kp_pitch;
    	unsigned char tn_pitch;
    	unsigned char tv_pitch;
    	unsigned char kp_roll;
    	unsigned char tn_roll;
    	unsigned char tv_roll;
    } parameters_ctrl;
    soll mit dieser Funktion:

    Code:
    ISR(SIG_2WIRE_SERIAL) {
    int i;
    	...
    
    	if((TWSR&0xF8) == 0xA8) {								// Slave transmitter mode: transmit parameters
    		for(i=0;i<sizeof(parameters_ctrl);i++) {
    			TWDR=*( (unsigned char *) ((&parameters_ctrl)+i) );				//!!!!!!!!!!!!!!!!!!
    			if(i==3) yellow_lights(TWDR);
    			if(i<sizeof(parameters_ctrl)-1)	TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);	//send TWDR
    			else 				TWCR=(1<<TWINT)|(1<<TWEN);				//after last byte, don't expect ack
    			while (!(TWCR & 0x80)) { };
    		}
    	    TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE);		//switch to receive mode
    	}
    }
    über den TWI-Bus gesendet werden. Das Problem ist jetzt, die Struktur byteweise auf den Bus zu schaufeln. Da mir keine andere Methode eingefallen ist, die Struktur durchzu"iterieren", versuche ich das über Zeiger zu erreichen. Also nehme ich die Basisadresse "&name" und addiere in der Schleife die Zahlvariable. Dummerweise muß man dabei den Zeiger casten. Aber warum das ganze nicht funktioniert, sehe ich noch nicht. Sieht jemand mehr als ich?

    Danke,
    Nils

    PS: Die Zeile mit "yellow_lights(...)" ist mein "printf"-Debugging. Es sind acht LEDs angeschlossen, die das TWDR anzeigen. Daran sehe ich, daß das TWDR bei den jeweiligen Schleifendurchläufen nicht auf 10, 20, 30, 40, 50, 60 steht (so ist die Struktur initialisiert, das habe ich geprüft), sondern auf 10, 62, 18, 13, 128, 129.

Berechtigungen

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

12V Akku bauen