C Problem mit TWI Verbindung zwischen 2 Atmega8 (MY AVR Board MK2)

Bobbybau91

Neues Mitglied
15. Nov. 2013
31
0
0
33
Ayl, Germany
Sprachen
  1. ANSI C
Hallo zusammen,

ich soll für die Technikerschule nur zu Anschauungszwecken eine TWI-Verbindung zwischen 2 MyAVR MK2 Boards herstellen (2x Atmega8). Da unsere Microcontroller- und C-Kentnisse ziemlich gering sind, habe ich versucht, diese Aufgabenstellung mit Hilfe der Website von Timo Gruss (http://timogruss.de/2014/07/i2c-master-und-slave-mit-zwei-atmegas/) zu realisieren.

Anschließend wurde der Hardwareaufbau durchgeführt. 2 Boards nebeneinander gelegt, die angegebenen LED´s und Taster mit den den im Programm angegebenen Pins verbunden (vorher die Pins im Programm geändert, da diese Teilweise auf dem Board nicht vorhanden waren) und die Pins PC4 und 5 (SCL und SDA) beider Microcontroller miteinander verbunden.
Kompilieren mit dem AVR-Studio hat auch ohne Probleme geklappt, aber leider tut sich nichts. Muss man eventuell Programmbestandteile abändern, da auf der Website 2 Atmega128 verwendet wurden?


Danke im Vorraus
Bob
 
Hallo Bob,

C ist so garnicht mein Ding :rolleyes: aber ...

Anschließend wurde der Hardwareaufbau durchgeführt. 2 Boards nebeneinander gelegt, die angegebenen LED´s und Taster mit den den im Programm angegebenen Pins verbunden (vorher die Pins im Programm geändert, da diese Teilweise auf dem Board nicht vorhanden waren) und die Pins PC4 und 5 (SCL und SDA) beider Microcontroller miteinander verbunden.

... aber leider tut sich nichts.

ne blöde Frage ... hast du auch PullUps an SCL und SDA gesetzt? Ohne das wird es nicht funktionieren.

Gruß
Dino
 
Habe jetzt mal ein anderes Programm geschrieben, welches meines Erachtens etwas simpler ist.
Allerdings funktioniert das auch nicht. Wir können zwar mit dem Oszi den Bus-Takt messen, aber ansonsten passiert nicht viel. Sieht da vielleicht jemand einen Fehler?

Nachfolgend der Quelltext, das Projekt ist aber auch angehangen (Anhang anzeigen TWI.zip).


Gruß Bob



Master:
Code:
#include <avr/io.h>
#include "i2cmaster.h"
#define SLAVE_ADRESSE 0x50

uint8_t Taster; 

int main(void)
{
	DDRB  = 0b00000000;		//Alles Eingänge
	PORTB = 0b00000001;		//Pull-Up an PINB.1 setzen
	
	while (1)
	{
		i2c_init();         // init I2C interface

		if (bit_is_clear (PINB, 0))
		{
			Taster = 0b00000001;
		}
		else
		{
			Taster = 0b00000000; 
		}
		
		if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?
		{
			i2c_write(0x00);	// Buffer Startadresse setzen
			i2c_write(Taster);	// Ein Bytes schreiben...
			i2c_stop();			// Zugriff beenden
		}
	}
}

ic2master.c
Code:
/*************************************************************************
* Title:    I2C master library using hardware TWI interface
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
* File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
* Target:   any AVR device with hardware TWI 
* Usage:    API compatible with I2C Software Library i2cmaster.h
**************************************************************************/
#include <inttypes.h>
#include <compat/twi.h>

#include "i2cmaster.h"


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 3686400
#endif

/* I2C clock in Hz */
#define SCL_CLOCK  100000


/*************************************************************************
 Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
  
  TWSR = 0;                         /* no prescaler */
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */

}/* i2c_init */


/*************************************************************************	
  Issues a start condition and sends address and transfer direction.
  return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

	// send device address
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

	return 0;

}/* i2c_start */


/*************************************************************************
 Issues a start condition and sends address and transfer direction.
 If device is busy, use ack polling to wait until device is ready
 
 Input:   address and transfer direction of I2C device
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
    uint8_t   twst;


    while ( 1 )
    {
	    // send START condition
	    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
    	// wait until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
    
    	// send device address
    	TWDR = address;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    
    	// wail until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
    	{    	    
    	    /* device busy, send stop condition to terminate write operation */
	        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	        
	        // wait until stop condition is executed and bus released
	        while(TWCR & (1<<TWSTO));
	        
    	    continue;
    	}
    	//if( twst != TW_MT_SLA_ACK) return 1;
    	break;
     }

}/* i2c_start_wait */


/*************************************************************************
 Issues a repeated start condition and sends address and transfer direction 

 Input:   address and transfer direction of I2C device
 
 Return:  0 device accessible
          1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
    return i2c_start( address );

}/* i2c_rep_start */


/*************************************************************************
 Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
    /* send stop condition */
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	
	// wait until stop condition is executed and bus released
	while(TWCR & (1<<TWSTO));

}/* i2c_stop */


/*************************************************************************
  Send one byte to I2C device
  
  Input:    byte to be transfered
  Return:   0 write successful 
            1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{	
    uint8_t   twst;
    
	// send data to the previously addressed device
	TWDR = data;
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits
	twst = TW_STATUS & 0xF8;
	if( twst != TW_MT_DATA_ACK) return 1;
	return 0;

}/* i2c_write */


/*************************************************************************
 Read one byte from the I2C device, request more data from device 
 
 Return:  byte read from I2C device
*************************************************************************/
unsigned char i2c_readAck(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
	while(!(TWCR & (1<<TWINT)));    

    return TWDR;

}/* i2c_readAck */


/*************************************************************************
 Read one byte from the I2C device, read is followed by a stop condition 
 
 Return:  byte read from I2C device
*************************************************************************/
unsigned char i2c_readNak(void)
{
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));
	
    return TWDR;

}/* i2c_readNak */

Code:
#ifndef _I2CMASTER_H
#define _I2CMASTER_H   1
/************************************************************************* 
* Title:    C include file for the I2C master interface 
*           (i2cmaster.S or twimaster.c)
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
* File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
* Target:   any AVR device
* Usage:    see Doxygen manual
**************************************************************************/

#ifdef DOXYGEN
/**
 @defgroup pfleury_ic2master I2C Master library
 @code #include <i2cmaster.h> @endcode
  
 @brief I2C (TWI) Master Software Library

 Basic routines for communicating with I2C slave devices. This single master 
 implementation is limited to one bus master on the I2C bus. 

 This I2c library is implemented as a compact assembler software implementation of the I2C protocol 
 which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
 Since the API for these two implementations is exactly the same, an application can be linked either against the
 software I2C implementation or the hardware I2C implementation.

 Use 4.7k pull-up resistor on the SDA and SCL pin.
 
 Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module 
 i2cmaster.S to your target when using the software I2C implementation ! 
 
 Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.

 @note 
    The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted 
    to GNU assembler and AVR-GCC C call interface.
    Replaced the incorrect quarter period delays found in AVR300 with 
    half period delays. 
    
 @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury

 @par API Usage Example
  The following code shows typical usage of this library, see example test_i2cmaster.c

 @code

 #include <i2cmaster.h>


 #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet

 int main(void)
 {
     unsigned char ret;

     i2c_init();                             // initialize I2C library

     // write 0x75 to EEPROM address 5 (Byte Write) 
     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
     i2c_write(0x05);                        // write address = 5
     i2c_write(0x75);                        // write value 0x75 to EEPROM
     i2c_stop();                             // set stop conditon = release bus


     // read previously written value back from EEPROM address 5 
     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode

     i2c_write(0x05);                        // write address = 5
     i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode

     ret = i2c_readNak();                    // read one byte from EEPROM
     i2c_stop();

     for(;;);
 }
 @endcode

*/
#endif /* DOXYGEN */

/**@{*/

#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif

#include <avr/io.h>

/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ    1

/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_WRITE   0


/**
 @brief initialize the I2C master interace. Need to be called only once 
 @param  void
 @return none
 */
extern void i2c_init(void);


/** 
 @brief Terminates the data transfer and releases the I2C bus 
 @param void
 @return none
 */
extern void i2c_stop(void);


/** 
 @brief Issues a start condition and sends address and transfer direction 
  
 @param    addr address and transfer direction of I2C device
 @retval   0   device accessible 
 @retval   1   failed to access device 
 */
extern unsigned char i2c_start(unsigned char addr);


/**
 @brief Issues a repeated start condition and sends address and transfer direction 

 @param   addr address and transfer direction of I2C device
 @retval  0 device accessible
 @retval  1 failed to access device
 */
extern unsigned char i2c_rep_start(unsigned char addr);


/**
 @brief Issues a start condition and sends address and transfer direction 
   
 If device is busy, use ack polling to wait until device ready 
 @param    addr address and transfer direction of I2C device
 @return   none
 */
extern void i2c_start_wait(unsigned char addr);

 
/**
 @brief Send one byte to I2C device
 @param    data  byte to be transfered
 @retval   0 write successful
 @retval   1 write failed
 */
extern unsigned char i2c_write(unsigned char data);


/**
 @brief    read one byte from the I2C device, request more data from device 
 @return   byte read from I2C device
 */
extern unsigned char i2c_readAck(void);

/**
 @brief    read one byte from the I2C device, read is followed by a stop condition 
 @return   byte read from I2C device
 */
extern unsigned char i2c_readNak(void);

/** 
 @brief    read one byte from the I2C device
 
 Implemented as a macro, which calls either i2c_readAck or i2c_readNak
 
 @param    ack 1 send ack, request more data from device<br>
               0 send nak, read is followed by a stop condition 
 @return   byte read from I2C device
 */
extern unsigned char i2c_read(unsigned char ack);
#define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); 

/**@}*/
#endif

Slave:
Code:
#include <util/twi.h> 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR
#include <stdint.h> 	    //definiert den Datentyp uint8_t
#include "twislave.h"

#define SLAVE_ADRESSE 0x50 //Die Slave-Adresse

int main (void)																						
{
	DDRB  = 0b00000001;		//Alles Eingänge
	PORTB = 0b00000000;		//Pull-Up an PINB.1 setzen
	PORTC = 0b00110000;		
	
	//TWI als Slave mit Adresse slaveadr starten
	init_twi_slave(SLAVE_ADRESSE);
	
	while(1)
	{
		//i2cdatamit Werten füllen
		for(uint8_t i=0;i<i2c_buffer_size;i++)
		{
			i2cdata[i]=10+i;
		}
	
		if (i2cdata[0] = 0b00000001)
		{
			PORTB |= (1<<0);			
		}
		else
		{
			PORTB &= ~(1<<0);
		}				
	} 
} //end.main


twislave.c
Code:
#include <util/twi.h> 	    //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR
#include <avr/interrupt.h>  //dient zur Behandlung der Interrupts
#include <stdint.h>         //definiert den Datentyp uint8_t
#include "twislave.h"

//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%
/*Der Buffer, in dem die Daten gespeichert werden.
Aus Sicht des Masters läuft der Zugrif auf den Buffer genau wie bei einem I2C-EEPROm ab.
Für den Slave ist es eine globale Variable
*/
volatile uint8_t buffer_adr; //"Adressregister" für den Buffer

/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse
Parameter adr: gewünschte Slave-Adresse
*/
void init_twi_slave(uint8_t adr)
{
	TWAR= adr; //Adresse setzen
	TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
	TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
	buffer_adr=0xFF;
	sei();
}


//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!).
//Makros für die verwendeten Bitmuster:

//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);

//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);

//switch to the non adressed slave mode...
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC);


/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann
ein Statuscode, anhand dessen die Situation festgestellt werden kann.
*/
ISR (TWI_vect)
{
	uint8_t data=0;

	switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen
	{

		// Slave Receiver

		case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
		TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden
		buffer_adr=0xFF; //Bufferposition ist undefiniert
		break;
		
		case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
		data=TWDR; //Empfangene Daten auslesen
		if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen
		{
			//Kontrolle ob gewünschte Adresse im erlaubten bereich
			if(data<i2c_buffer_size+1)
			{
				buffer_adr= data; //Bufferposition wie adressiert setzen
			}
			else
			{
				buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!
			}
			TWCR_ACK;	// nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
		}
		else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern
		{
			
			if(buffer_adr<i2c_buffer_size+1)
			{
				i2cdata[buffer_adr]=data; //Daten in Buffer schreibe
			}
			buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff
			TWCR_ACK;
		}
		break;


		//Slave transmitter

		case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
		//Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!
		
		case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert

		if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben!
		{
			buffer_adr=0;
		}
		
		if(buffer_adr<i2c_buffer_size+1)
		{
			TWDR = i2cdata[buffer_adr]; //Datenbyte senden
			buffer_adr++; //bufferadresse für nächstes Byte weiterzählen
		}
		else
		{
			TWDR=0; //Kein Daten mehr im Buffer
		}
		TWCR_ACK;
		break;
		case TW_SR_STOP:
		TWCR_ACK;
		break;
		case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
		case TW_SR_DATA_NACK: // 0x88
		case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
		default:
		TWCR_RESET;
		break;
		
	} //end.switch (TW_STATUS)
} //end.ISR(TWI_vect)

////Ende von twislave.c////

twislave.h
Code:
#ifndef _TWISLAVE_H
#define _TWISLAVE_H

#include <util/twi.h> 		  //enthaelt z.B. die Bezeichnungen fuer die Statuscodes in TWSR
#include <avr/interrupt.h>  //dient zur behandlung der Interrupts
#include <stdint.h> 		    //definiert den Datentyp uint8_t
a

/** 
 *  @defgroup twislave TWI-Slave
 *  @code #include "twislave.h" @endcode
 * 
 *  @brief Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave.
 *  Zu Beginn muss init_twi_slave mit der gewuenschten Slave-Adresse als
 *  Parameter aufgerufen werden.
 *
 * Der Datenaustausch mit dem Master erfolgt ueber den Buffer i2cdata, 
 * auf den von Master und Slave zugegriffen werden kann. 
 * Dies ist fuer den Slave eine globale Variable (Array aus uint8_t). 

 * Der Zugriff durch den Master erfolgt aehnlich wie bei einem
 * normalen I2C-EEPROM.
 * Man sendet zunaechst die Bufferposition, an die man schreiben will,
 * und dann die Daten. 
 * Die Bufferposition wird automatisch hochgezaehlt, sodass man mehrere
 * Datenbytes hintereinander schreiben kann, ohne jedesmal die 
 * Bufferadresse zu schreiben.
 *
 * Um vom Master aus zu lesen, uebertraegt man zunaechst in einem 
 * Schreibzugriff die gewuenschte Bufferposition und liest dann nach
 * einem repeated start die Daten aus. Die Bufferposition wird 
 * automatisch hochgezaehlt, sodass man mehrere Datenbytes
 * hintereinander lesen kann, ohne jedesmal die Bufferposition zu
 * schreiben.
 *
 * Abgefangene Fehlbedienung durch den Master:
 * - Lesen ueber die Grenze des txbuffers hinaus
 * - Schreiben ueber die Grenzen des rxbuffers hinaus
 * - Angabe einer ungueltigen Schreib/Lese-Adresse
 * - Lesezugriff, ohne vorher Leseadresse geschrieben zu haben
 * 
 *  @author uwegw
 */

/*@{*/

//%%%%%%%% von Benutzer konfigurierbare Einstellungen %%%%%%%%
/**@brief Groesse des Buffers in Byte (2..254) */
#define i2c_buffer_size 10// I2C_REG_ANZAHL 254 Hier kann eingestellt werden wieviele Register ausgegeben werden


//%%%%%%%% Globale Variablen, die vom Hauptprogramm genutzt werden %%%%%%%%
/**@brief Der Buffer, in dem die Daten gespeichert werden.
 * Aus Sicht des Masters laeuft der Zugrif auf den Buffer genau wie
 *  bei einem I2C-EEPROm ab.
 * Fuer den Slave ist es eine globale Variable
*/
volatile uint8_t i2cdata[i2c_buffer_size];


/**@brief Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse
 * @param adr gewuenschte Slave-Adresse */
void init_twi_slave(uint8_t adr);

//%%%%%%%% ab hier sind normalerweise keine weiteren Aenderungen erforderlich! %%%%%%%%//
//____________________________________________________________________________________//


//Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher in diesem Fall mit Fehlermeldung abbrechen
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
	#error "This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler !"
#endif

//Schutz vor unsinnigen Buffergroessen
#if (i2c_buffer_size > 254)
	#error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt.
#endif

#if (i2c_buffer_size < 2)
	#error Buffer muss mindestens zwei Byte gross sein!
#endif



#endif //#ifdef _TWISLAVE_H
////Ende von twislave.h////
 
slave.c / in der main ist schon mal ein Fehler bei der IF-Abfrage - verwende "=="
Hast du deine Sourcecodes auch ohne Warnungen compiliert?
Code:
.
.
.
.
		if (i2cdata[0] = 0b00000001)
		{
			PORTB |= (1<<0);			
		}
		else
.
.
.



Kannst du auch an der Datenleitung was sehen?

am besten du misst beide Leitungen mal gleichzeitig / Datenleitung und Clockleitung und schaust, ob überhaupt Daten ausgetauscht werden.
 
Hast du deine Sourcecodes auch ohne Warnungen compiliert?...
Ich hab ja keine Ahnung von C, aber warum soll das 'ne Warnung schmeissen? War C nicht die Sprache, die unglaublich verschachtelte Konstrukte erlaubte und interpretieren würde?
Dann wäre doch
Code:
i2cdata[0] = 0b00000001
'ne Zuweisung (also i2cdata[0]<--'1').
Anschließend würde if dann i2cdata[0],prüfen, effektiv also
Code:
if(1) {...}
was immer wahr sein sollte.

Wenn nicht zwischendurch irgendein IRQ zuschlägt, und die Variable wieder löscht?

Ob das Compilat dann den beabsichtigten Algorithmus darstellt, ist 'ne andere Sache, aber bei solchen Fehlern gibt's ja normalerweise keine Warnung...
 
Hast du deine Sourcecodes auch ohne Warnungen compiliert?...
Ich hab ja keine Ahnung von C, aber warum soll das 'ne Warnung schmeissen? War C nicht die Sprache, die unglaublich verschachtelte Konstrukte erlaubte und interpretieren würde?
Dann wäre doch
Code:
i2cdata[0] = 0b00000001
'ne Zuweisung (also i2cdata[0]<--'1').
Anschließend würde if dann i2cdata[0],prüfen, effektiv also
Code:
if(1) {...}
was immer wahr sein sollte.

Wenn nicht zwischendurch irgendein IRQ zuschlägt, und die Variable wieder löscht?

Ob das Compilat dann den beabsichtigten Algorithmus darstellt, ist 'ne andere Sache, aber bei solchen Fehlern gibt's ja normalerweise keine Warnung...


Wenn sagst, dass du "keine Ahnung hast", dann......

AVR-Studio wirft auf jeden Fall ne Warnung aus.... (jeden Falls bei mir), und ich denke bei ihm auch....
Folgende Warnung wird vermutlich angezeigt: "suggest parentheses around assignment used as truth value [-Wparentheses]"

Meine Erfahrung zeigt, auch Warnungen sollten einfach beachten werden, dann kann man auch sicher sein, dass alles so ist, wie es sich gehört.


Eine if-Abfrage darf/sollte keine Zuweisung enthalten - das ergäbe ja auch keinen Sinn......
Seine Zuweisung in der if-Anweisung ist auch mit Sicherheit nicht gewollt, er hat sich einfach nur vertippt, wie es sicher jedem schon mal passier ist, also wieso diese sinnloses Geplänkel .....
 
Wenn sagst, dass du "keine Ahnung hast", dann...
...darf ich sicher Fragen Stellen, oder?
Meine Frage war, warum es dann eine Warnung geben soll - ich war allerdings von einem Fehler ausgegangen, also daß der Code nicht compilierbar wäre. Diese Warnung würde dann zB immer zuschlagen wenn sich 'ne Zuweisung innerhalb der Bedingung befindet? Aber trotzdem ausführbaren Code erzeugt (sinnig habe ich nicht gesagt)?
...Eine if-Abfrage darf/sollte keine Zuweisung enthalten - das ergäbe ja auch keinen Sinn......
Seine Zuweisung in der if-Anweisung ist auch mit Sicherheit nicht gewollt, er hat sich einfach nur vertippt, wie es sicher jedem schon mal passier ist, also wieso diese sinnloses Geplänkel .....
So, ich habs jetzt selbst wiedergefunden: "Programmieren mit C", Clauß und Fischer, 1988
Da taucht sowas zB auf:
Code:
while((c=getchar()) != EOF) {...}
Warum soll das hier keinen Sinn machen? Spart halt eine Zeile Quellcode.
Als ich das Buch damals überflog ist unter anderem hängengeblieben, daß man C-Code sehr kompakt zusammenziehen kann - eben mit solchen Konstrukten. Das geht meiner(!) Meinung nach zu Lasten der Lesbarkeit/Verständlichkeit des Codes ohne daß es sich auf den resultierenden Maschienencode auswirkt...
 
Hast du deine Sourcecodes auch ohne Warnungen compiliert?...


Wenn sagst, dass du "keine Ahnung hast", dann......

AVR-Studio wirft auf jeden Fall ne Warnung aus.... (jeden Falls bei mir), und ich denke bei ihm auch....
Folgende Warnung wird vermutlich angezeigt: "suggest parentheses around assignment used as truth value [-Wparentheses]"

Meine Erfahrung zeigt, auch Warnungen sollten einfach beachten werden, dann kann man auch sicher sein, dass alles so ist, wie es sich gehört.


Eine if-Abfrage darf/sollte keine Zuweisung enthalten - das ergäbe ja auch keinen Sinn......
Seine Zuweisung in der if-Anweisung ist auch mit Sicherheit nicht gewollt, er hat sich einfach nur vertippt, wie es sicher jedem schon mal passier ist, also wieso diese sinnloses Geplänkel .....

Wie redest du denn hier?! Ich habe mir nicht den ganzen Thread durchgelesen, aber finde deinen Beitrag absolut überflüssig.
Aber Ja, du hast es richtig erkannt. Eine Warnung warnt vor möglichen Fehlern und sollte ausgemerzt werden. Deshalb lässt man sich mit den CompilerFlags -Wall -Wextra alle Warnungen anzeigen, und im Normalfall sind alle Vermeidbar.

Hier ist es eine Warnung, bezüglich der Klammerung.
[CCODE]if ((i2cdata[0] = 0b00000001))[/CCODE]
Das dürfte den Compiler zum schweigen bringen. Man muss halt wissen, was gewollt ist. Aber falsch ist es nicht.


Wie Lothar bereits richtig schreibt: Zuweisungen in If Abfragen? Warum nicht, nutze ich gerne mal. Macht den Code Kompakt und ich sehe auf den ersten Blick was er tut.

[CCODE]while((c=getchar()) != EOF) {...}[/CCODE]

Hier wird der Rückgabewert von getchar() mit EOF verglichen. Wenn ungleich bekommt c den int Wert 1 zugewiesen, sonst 0. In diesem Fall ist es sogar sehr Sinnvoll verwendet, da man es ansonsten unter umständen vor und in der Schleife erneut zuweisen müsste.

Fazit: avr_newbies Beitrag war falsch und nicht hilfreich. LotadaC hat recht, ein solches Konstrukt erzeugt keine Warnung
 
Fazit: avr_newbies Beitrag war falsch und nicht hilfreich. LotadaC hat recht, ein solches Konstrukt erzeugt keine Warnung


Also da bin ich ganz anderer Meinung.

Wenn man zusätzlich Klammern um den Ausdruck setzt, wird keine Warnung mehr erzeugt. Nur was hat da die if-Abfrage für einen Sinn, wenn das Ergebnis immer wahr ist?

avr_newbie hat darauf hingewiesen, dass dieser Teil falsch ist und dass hier doch eigentlich eine Warnung ausgegeben werden müsste und dass man immer auf Warnungen achten sollte.

[CCODE]if (i2cdata[0] = 0b00000001)
[/CCODE]

Das sehe ich genauso.

PB0 wird immer auf 1 gesetzt, egal was über i2c empfangen wird.
[CCODE]
if (i2cdata[0] = 0b00000001)
{
PORTB |= (1<<0);
} else {
PORTB &= ~(1<<0);
} [/CCODE]


Bevor die Diskussion sich zu sehr vom Thema wegbewegt, sollte der Themenersteller Bob einfach mal in die if-Abfrage einen boolschen Ausdruck (i2cdata[0] == 0b00000001) angeben und schauen, ob sein Programm nun funktioniert.
Sicher können noch weitere Fehler vorhanden sein, aber der von avr_newbie gefundene Fehler verhindert nun mal die richtige Auswertung der beim Slave empfangenen Daten.

Dirk :ciao:
 
Wie redest du denn hier?! Ich habe mir nicht den ganzen Thread durchgelesen, aber finde deinen Beitrag absolut überflüssig.
Aber Ja, du hast es richtig erkannt. Eine Warnung warnt vor möglichen Fehlern und sollte ausgemerzt werden. Deshalb lässt man sich mit den CompilerFlags -Wall -Wextra alle Warnungen anzeigen, und im Normalfall sind alle Vermeidbar.

Hier ist es eine Warnung, bezüglich der Klammerung.
[CCODE]if ((i2cdata[0] = 0b00000001))[/CCODE]
Das dürfte den Compiler zum schweigen bringen. Man muss halt wissen, was gewollt ist. Aber falsch ist es nicht.


Wie Lothar bereits richtig schreibt: Zuweisungen in If Abfragen? Warum nicht, nutze ich gerne mal. Macht den Code Kompakt und ich sehe auf den ersten Blick was er tut.

[CCODE]while((c=getchar()) != EOF) {...}[/CCODE]

Hier wird der Rückgabewert von getchar() mit EOF verglichen. Wenn ungleich bekommt c den int Wert 1 zugewiesen, sonst 0. In diesem Fall ist es sogar sehr Sinnvoll verwendet, da man es ansonsten unter umständen vor und in der Schleife erneut zuweisen müsste.

Fazit: avr_newbies Beitrag war falsch und nicht hilfreich. LotadaC hat recht, ein solches Konstrukt erzeugt keine Warnung

[CCODE]if ((i2cdata[0] = 0b00000001))[/CCODE]
FALSCH - durch die doppelte Klammerung wird sogar verhindert, dass eine Warnung ausgeworfen wird

Mit einfacher Klammerung wird die obige von mir gepostete Warnung ausgegeben....

Ich habe nicht behauptet, dass eine Zuweisung in einer if-Abfrage nicht möglich ist, sie muss aber einen Vergleich enthalten, sonst macht es keinen Sinn.



Ach ja, und wie ich hier spreche ? ... nunja, ich schreibe hier nur ^^
 
Also da bin ich ganz anderer Meinung.

Wenn man zusätzlich Klammern um den Ausdruck setzt, wird keine Warnung mehr erzeugt. Nur was hat da die if-Abfrage für einen Sinn, wenn das Ergebnis immer wahr ist?

avr_newbie hat darauf hingewiesen, dass dieser Teil falsch ist und dass hier doch eigentlich eine Warnung ausgegeben werden müsste und dass man immer auf Warnungen achten sollte.

[CCODE]if (i2cdata[0] = 0b00000001)
[/CCODE]

Das sehe ich genauso.

PB0 wird immer auf 1 gesetzt, egal was über i2c empfangen wird.
[CCODE]
if (i2cdata[0] = 0b00000001)
{
PORTB |= (1<<0);
} else {
PORTB &= ~(1<<0);
} [/CCODE]

Korrekt, durch die Klammerung verschwindet die Warnung, und das ist richtig so. Weil es völlig normales C ist. Es ist eine Warnung bezüglich der Klammerung, nicht ob der Inhalt sinnvoll ist oder nicht. Selbst mit sinnvollem Inhalt würde diese Warnung ohne doppelte Klammerung kommen.

Abgesehen davon ergibt es so (mit ==) nun immer eine unwahre Aussage weil er icdata[0] mit 10 beschreibt. Also ist es so auch nicht sinnvoll.

for(uint8_t i=0;i<i2c_buffer_size;i++)
{
i2cdata=10+i;
}

if (i2cdata[0] = 0b00000001)

Es geht mir hier weniger darum zu behaupten, die IF Schleife mache Sinn (das tut sie derzeit in keiner Form, auch nicht mit ==) als richtig zu stellen, dass es auch mit einem == nicht besser wird, der TE also was anderes im Sinn hatte.


Trotzdem sollte ein freundlicher Umgangston an den Tag gelegt werden. Da helfen auch deine .... Auslassungen nichts.
Wenn sagst, dass du "keine Ahnung hast", dann......
Solche Anspielungen haben mit Freundlichkeit nichts zutun. Lothar hat viele hilfreiche Beiträge geschrieben, warum darf man da nicht bedenken äußern.
 
Um wieder zum Thema zurück zu kommen, ich hatte bei der IF-Abfrage nur ein = statt ==, deswegen hat es natürlich nicht funktioniert.

Hier noch das Projekt, vielleicht, kann es ja noch jemand gebrauchen.

Anhang anzeigen TWI.zip

Danke für die Hilfe :)
 
Da hast jetzt aber das alte Projekt wieder hochgeladen? - Lade doch bitte das aktuell Projekt hoch, das auch funzt, sonst sucht der nächste wieder.....

Um wieder zum Thema zurück zu kommen, ich hatte bei der IF-Abfrage nur ein = statt ==, deswegen hat es natürlich nicht funktioniert.

Hier noch das Projekt, vielleicht, kann es ja noch jemand gebrauchen.

Anhang anzeigen 6711

Danke für die Hilfe :)
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)