Moin

Also ich hab ein ganz komisches Problem: Ich hab hier das Pollin Board mit dem ich eine Meßstation aufbaue. (Mega16) Nun möchte ich dafür auch gerne eine Uhr ansprechen. Dafür habe ich den DS1307. (Datasheet zu finden, bei z.b. Reichelt)

Das lässt sich laut Datasheet über I²C ansprechen. Da ich keine Lust hatte mir das alles selbst zu schreiben, habe ich die twimaster.c verwendet die ich hier im Download Bereich gefunden habe. Aber irgendwie funktioniert das nicht. Das Problem ist, dass schon die i2c_start() in ner Endlosschleife wohl hängen bleibt, da das BIT nicht gesetzt wird, welches eine erfolgreiche Start kombination anzeigt. Das selbe passiert viel seltsamer sogar, wenn cih den DS1307 herausnehme und somit also eigentlich ncihts an den Bus angeschloßen ist.

Daraus spekuliere ich, dass es irgendwas mit den Zeiten zu tun hat, oder so. Kann da mal bitte einer drüber schauen? Danke. Hier die main.c und die twimaster.c ganz unten die Ausgabe die ich im Terminal bekomme.

Code:
/* -- main.c --
Dieses Programm steuert den ATmega16 des SUBMS.
Selbstfahrendes Umwelt Beobachtungs System - Johannes Kreuzer - 2006
johanneskreuzer@gmx.de
Arbeit für: Jugend Forscht 2006
*/
#ifndef F_CPU
#define F_CPU 8000000           /* Oszillator-Frequenz in Hz */
#endif

#define DS1307 208

#include "avr/io.h"
#include "sht71.h"
#include "uart.h"
#include "i2cmaster.h"
#include <stdint.h>
#include <util/delay.h>

void init_pwm(void);
void PrintInt(int);
void Msleep(int dauer);
uint16_t ReadChannel(uint8_t mux);
uint16_t gibDruck(uint8_t channel);
uint8_t min, sek, hour, wday, date, mon, year;

int main(void)
{
	Msleep(50);
	uart_init();
	i2c_init();                             // initialize I2C library
	//init_pwm();
	FEUCHTE_CONNECTIONRESET();
	
	/*i2c_start_wait(DS1307+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
	*/
	
	
	
	
	while(1) {
	uart_puts("\r\nBitte Befehl eingeben: ");
	int befehl;
	befehl = uart_getc_wait();
	uart_puts("\r\nDer eingegebene Befehl lautet: "); PrintInt(atoi(&befehl)); uart_puts("\r\n");
	switch (atoi(&befehl)) {
		case 0: 
			uart_puts("Alles messen und ausgeben . . .\r\n");
			uart_puts("Luftdruck: "); PrintInt(gibDruck(3)); uart_puts("\r\n");
			FEUCHTE_CONNECTIONRESET();
			FEUCHTE_MESSUNG(TEMPERATUR);
			FEUCHTE_MESSUNG(FEUCHTE);
			FEUCHTE_LINEARISIERUNG();
			uart_puts("Komp. Feuchte: "); PrintInt(Sensordaten.feuchte_komp); uart_puts("\r\n");
			uart_puts("Lin. Temp.: "); PrintInt(Sensordaten.temperatur_lin); uart_puts("\r\n");
			uart_puts("Ende!\r\n");
		break;
		case 8:
			uart_puts("Uhrzeit anzeigen: ");
			uint8_t min, sek, hour, wday, date, mon, year;
			i2c_start_wait(DS1307+I2C_WRITE);
			i2c_write(0x00);
			i2c_rep_start(DS1307+I2C_READ);
			sek = i2c_readAck();
			min = i2c_readAck();
			hour = i2c_readAck();
			wday = i2c_readAck();
			date = i2c_readAck();
			mon = i2c_readAck();
			year= i2c_readNak();
			i2c_stop();
			PrintInt(hour>>4);	PrintInt((hour&15));
			uart_puts(":");
			PrintInt(min>>4); PrintInt((min&15));
			uart_puts(":");
			PrintInt(sek>>4); PrintInt((sek&15));
			uart_puts(" ");
			PrintInt(date>>4); PrintInt((date&15));
			uart_puts(".");
			PrintInt(mon>>4); PrintInt((mon&15));
			uart_puts(".");
			PrintInt(year>>4); PrintInt((year&15));
		break;		
		case 9:
			/*
			Dieses Case sollte auskommentiert werden, wenn es nicht benötigt wird, da es sehr viel Speicher belegt.*/
			uart_puts("Uhrzeit einstellen . . . \r\n");
			uint8_t min2, hour2, date2, mon2, year2;
			uart_puts(" vars ");
			i2c_init();
			uart_puts(" init ");
			PrintInt(i2c_start(DS1307+I2C_WRITE));
			uart_puts(" start ");
			PrintInt(i2c_write(0x00));
			PrintInt(i2c_write(128)); //Uhr anhalten 
			uart_puts("Sekunden: 0 \r\n");
			uart_puts("Bitte geben sie die Minuten ein: ");
			min = atoi(uart_getc_wait());
			min2 = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x01);
			i2c_write(((min<<4)+min2));
			uart_puts("Bitte geben sie die Stunden ein (mit 0): ");
			hour = atoi(uart_getc_wait());
			hour2 = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x02);
			i2c_write(((hour<<4)+(hour2)));
			uart_puts("Bitte geben sie den Tag ein (0-7): ");
			wday = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x03);
			i2c_write(wday);
			uart_puts("Bitte geben sie den Monatstag ein (0-31): ");
			date = atoi(uart_getc_wait());
			date2 = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x04);
			i2c_write(((date<<4)+(date2)));
			uart_puts("Bitte geben sie den Monat ein (1-12): ");
			mon = atoi(uart_getc_wait());
			mon2 = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x05);
			i2c_write(((mon<<4)+(mon2)));
			uart_puts("Bitte geben sie das Jahr ein (z.B: 06): ");
			year = atoi(uart_getc_wait());
			year2 = atoi(uart_getc_wait());
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x06);
			i2c_write(((year<<4)+(year2)));
			//Starten der Uhr:
			i2c_rep_start(DS1307+I2C_WRITE);
			i2c_write(0x00);
			i2c_write(0);
			i2c_stop();
		break;
	}
	
	}
	while(1);
	return 0;
}



/*Initialisiert die PWM Komponente des Controllers*/
void init_pwm() {
	DDRD |= (1 << PD4) | (1 << PD5);      // OCR1A und B an PD4 und 5 (mega16)
	PORTD = 0;
	TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<COM1A0) | (1<<COM1B0) | (1<<WGM11) | (1<<WGM10); // 10 Bit Pwm, invertierend
	TCCR1B = (1<<CS11) | (1<<CS10);      // Prescaler 64
	DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3);		// Datenleitungen für L298 - Richtung
	PORTB = (0 << PB0) | (0 << PB1) | (0 << PB2) | (0 << PB3);	// Datenleitungen für L298 - Bremsen
	OCR1A = OCR1B = 1024; 
} 


/*Liest an dem angegeben Chanel die Spannung aus*/
uint16_t ReadChannel(uint8_t mux) {
  uint8_t i;
  uint16_t result = 0;         //Initialisieren wichtig, da lokale Variablen
                               //nicht automatisch initialisiert werden und
                               //zufällige Werte haben. Sonst kann Quatsch rauskommen
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)

  ADMUX = mux;                      // Kanal waehlen
  ADMUX |= (0<<REFS1) | (0<<REFS0); // externe Referenzspannung nutzen 

  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 

  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  for(i=0;i<4;i++)
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) );   // auf Abschluss der Konvertierung warten
    result += ADCW;		    // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)

  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert

  return result;
}

/*Schläft die angegeben Zeit in Millisekunden. (Achtung: Genauigkeit nicht bekannt!) */
void Msleep(int dauer) {
	int z;
	for(z=0;z<dauer;z+=10) _delay_ms(10);
}


/*Liefert den Luftdruck der durch den MPX4115 gemessen wurde.
Als Parameter muss der Channel des AD Converters angegeben werden. */
uint16_t gibDruck(uint8_t channel) {
	uint32_t temp;
	uint16_t rohWert;
	uint8_t ergebnis;
	rohWert = ReadChannel(channel);
	/*Um den Controller nicht mit Float operationen zu belasten, werden die Zahlen so groß gewählt, */
	temp = ((rohWert*10000)/93636)+105000;
	ergebnis = temp/10000;
return ergebnis;
}
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.2 2005/02/27 21:56:13 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 <stdint.h>
#include <compat/twi.h>

#include <i2cmaster.h>
#include "uart.h"


/* define CPU frequency in Mhz here if not defined in Makefile */
//Wurde in main.c schon richitg als 8000000 definiert
#ifndef F_CPU
#define F_CPU 16000000UL
#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;
	uart_puts("\r\n - - i2c_start - ");	PrintInt(address);	uart_puts(" - \r\n");
	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
	uart_puts("\r\n - - twi controll - "); PrintInt(TWCR); uart_puts(" - \r\n");
	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));
	uart_puts("\r\n - - Start komplett - - \r\n");
	// 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)));
	uart_puts("\r\n - - address komplett - - \r\n");
	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if( twst != TW_MT_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 */
Hier die Ausgabe am Terminal:
Bitte Befehl eingeben: 9
Der eingegebene Befehl lautet: 9
Uhrzeit einstellen . . .
vars init
- - i2c_start - 208 -

- - twi controll - 36 -
Herzlichen Dank

Andun