[SOLVED] I2C not working with my ATMega168

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello

 

I use the I2C lib of P. Fleury on my ATMega8 - all is working fine, no problems.

Now I want to use it with my ATMega168 - it doesn't work and I have no clue why that's happening.

 

the I2C - lib:

 

/*************************************************************************
* Title:    I2C master library using hardware TWI interface
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
* File:     $Id: twimaster.c,v 1.4 2015/01/17 12:16:05 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"
#include "twi.h"*/
#include "libatm8.h"

#ifndef F_CPU
#define F_CPU 3686411UL		/* Frequenz AVR & Quartz */
#endif

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

/*************************************************************************
 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 */
 /*TWBR = 12; */
}/* 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;
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);	/* send START condition */
	while(!(TWCR & (1<<TWINT)));	/* wait until transmission completed */
	/* check value of TWI Status Register. Mask prescaler bits. */
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
	TWDR = address;		/* send device 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 )  {
	    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);	/* send START condition */
     	while(!(TWCR & (1<<TWINT)));	/* wait until transmission completed */

    	/* check value of TWI Status Register. Mask prescaler bits. */
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
    	TWDR = address;		/* send device address */
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while(!(TWCR & (1<<TWINT)));	/* wail until transmission completed */

    	/* 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){
	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); 	/* send stop condition */
	/* 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;
	TWDR = data;	/* send data to the previously addressed device */
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));	/* wait until transmission completed */
	/* 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 */

my code (only parts of it):

 


/* ----  check, ob I2C Teilnehmer PCA9555D ok ist --- */
static void check_PCA9555D(void) {
	if(i2c_start(PCA9555D+I2C_WRITE)) { 	/* Dev Adresse + Write Mode*/
		i2c_stop();
		PORT_ON(PORTD, PD5);	/* Fehler I2C => Port D PIN 5 HIGH => rote LED */
		while(1);			/* unendliche Warteschleife */
	} else {
		i2c_write(0x06); 	/* Adresse Configregister 6 = Config Port0 */
		i2c_write(0xF0); 	/* ConfigDaten A = Port0 = "B"
							   Bit0 .. Bit3 = 0 => Ausgang
							   Bit4 .. Bit7 = 1 => Eingang*/
		i2c_write(0x00); 	/* ConfigDaten B = Port1 = "A"
								Bit0 .. Bit7 = 0 => Ausgang => 7 Segment*/
		i2c_stop();      	/* set stop condition = release bus */
	}
}

int main(void) {
/*	PRR &=~0xFF; */
	/* 	init_PWM();					TIMER1, LEDs dimmen - PB1!! */
	init_LED();					/* initialisiere die LEDs */
	init_TIMER0();				/* initialisiere den TIMER0 => toggelt PD4 */
	/*	init_TIMER2();				 initialisiere den TIMER2 => toggelt PB0 */
 	init_SLAVE_INT();			/*initialisiere den SPI - Interrupt */
	/*	init_USART(MYUBBR); 			 initialisiere den USART */
	i2c_init();          		/* initalisieren I2C Interface */

check_PCA9555D();				/* nicht ok => Alarm Endlosschleife */
/*	check_MCP23017();			 nicht ok => Alarm Endlosschleife */
sei();
						/* Freigabe der Interrupts */

	uint8_t temp1;				/* temp Zaehler fuer Toggeln */

the main isn't complete, it's only the start and there's the problem - when calling that "check PCA9555D()" the system just hangs.

 

As I'm sort of lost your kind help would be much appreciated

 

thanks in advance

 

best regards Hero_123

 

edit - found the error in my self-made library MAKEFILE - used the wrong "DEVICE = atmega8" instead of "DEVICE = atmega168" smiley

Last Edited: Sun. Sep 8, 2019 - 07:51 PM