Gast
#1121196
Hallo Mikrocontroller-Gemeinde =)
Ich verzweifel an einem Problem und hoffe auf ein bisschen Hilfe! =)
Zu meinem Problem:
Ich habe einen Atmega8 (Master) über TWI an einen TAS5518 (Slave)
angeschlossen. Dass es jetzt ein TAS5518 ist, ist wohl irrelevant... TWI
Clock ist 100kHz. Bei Schreibbefehlen tritt keinerlei Fehler auf, nach
jedem Byte bekomme ich ein ACK. Nun möchte ich die Speicherstelle 0x02
des TAS5518 auslesen. (ist ein Fehler-Status-byte)
Grundlage ist die lib von Peter Fleury...
Dazu muss ich die Addresse des TAS5518 senden(00110110=0x36) mit einem
Write, dann 0x02 senden, danach ein rep_start machen, danach wieder die
Adresse des TAS5518 aber mit einem Read-bit... Hier der mit Oszi
abgelesene Datenstrom:
00110110 0 00000010 0 restart 00110111 0
Adr.Write ACK 0x02 ACK cond. Adr.Read ACK
Hier sieht man dass der Slave brav nach jedem byte ACK sendet. Die
ersten beiden ACKs erkennt der Atmega auch noch. Z.B. steht nach dem
senden von 0x02 im TWSR 0x28 (Databyte gesendet und Ack empfangen)....
Leider steht nach dem Senden vom Adresse-Read-Byte 0x48 im TWSR, was ja
bedeutet dass KEIN ACK empfangen wurde... Das ACK kommt aber (laut
Oszi)... Woran kann das liegen??
Ich bin wirklich dankbar für jeden Hinweis!
Hier noch die Aufrufe die ich verwende:
Hauptprogramm:
i2c_start_wait(TAS5518+I2C_WRITE);
i2c_write(0x02);
i2c_rep_start(TAS5518+I2C_READ);
ret = i2c_readNak(); //Hier bleibt der Controller hängen
Hier die i2c_readNack():
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}/* i2c_readNak */
Da im TWSR steht dass kein ACK empfangen wurde fängt die TWI-Einheit
nicht an zu laufen beim Versuch TWEN zu setzen, so dass TWINT nie 0
gesetzt wird.
Danke, Lukas
Hier noch alle anderen Routinen:
/***********************************************************************
**
* 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 <util/delay.h>
#include "i2cmaster.h"
/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
/* I2C clock in Hz */
#define SCL_CLOCK 100000L
/***********************************************************************
**
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 */