www.mikrocontroller.net

Forum: Compiler & IDEs i2c fleury lib Probleme


Autor: benjamin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich bin gerade dabei ein digitalen Funktionsgenerator zu bauen. Die 
einzelnen Funktionsgruppen wurden schon ausgiebig getestet und 
funktionieren. Da ich früher mit BASCOM programmiert habe, habe ich mir 
nun endlich vorgenommen auf C umzusteigen.
Ich will nun über den I2C Bus mit  zwei PCF8574 eine PLL steuern. 
Vorneweg: Mit BASCOM funktioniert es. Man kann also ein HW Fehler 
ausschließen.
Benutzen tu ich die Lib von Fleury für den I2C.
Jedoch bleibe ich immer bei i2c_start() eine "1" zurück, also dass es 
nicht geklappt hat, den SLAVE anzusprechen.
#include <avr/io.h>
#include <pll.h>
#include <i2c.h>
#include <uart.h>
#include <stdlib.h>

#define PCF8574_1  0x40
#define PCF8574_2  0x42

void init_pll(void)
{  
  // MUX Pins an PortD auf Ausgänge schalten
  DDRD |= (1 << DDD4) | (1 << DDD5) | (1 << DDD6) | (1 << DDD7);

  // i2c Bus initialisieren
  i2c_init();

  // Pll auf niedrigste Frequenz setzen
  set_pll_frequency(1);  
}

void i2c_send_byte(unsigned char addr, unsigned char byte)
{
  unsigned char ret;

  ret = i2c_start(addr+I2C_WRITE);       

  if (ret) 
  {
      // Baustein nicht erreichbar
      i2c_stop();
  }else 
  {
      i2c_write(byte);                       
      i2c_stop();
  }
}


void set_pll_frequency(unsigned short multiplier)
{
  unsigned short divider = 1024;
  unsigned char mux = 10;
  unsigned char byte1 = 0;
  unsigned char byte2 = 0;
  unsigned short n;
  unsigned char tmp;

  while (divider * multiplier > 2000)
  {
    divider >>= 1;
    mux--;
  } 

  // divider * multiplier -> Zerlegen in die zwei PCF8574 Bytes für PLL und über i2c wegschicken
  n = divider * multiplier;

  if (n % 2 != 0)
  {
    byte1 = n % 2;
  }

  n = n / 2;

  if (n / 1000 > 0)
  {
    tmp = n / 1000;
    byte1 += (tmp << 1);
    n -= tmp * 1000;
  }
  
  if (n / 100 > 0)
  {
    tmp = n / 100;
    byte2 += (tmp << 4);
    n -= tmp * 100;
  }
  
  if (n / 10 > 0)
  {
    tmp = n / 10;
    byte2 += tmp;
    n -= tmp * 10;
  }
  
  if (n / 1 > 0)
  {
    tmp = n / 1;
    byte1 += (tmp << 4);
    n -= tmp * 1;
  }

  /*char num[9];
  
  itoa(byte1, num, 10);
  uart_puts(num);

  itoa(byte2, num, 10);
  uart_puts(num);*/
  
  i2c_send_byte(PCF8574_1, byte1);
  i2c_send_byte(PCF8574_2, byte2);    

  // mux -> MUX Ports setzen
  if (mux & 0x01)
  {
    PORTD |= (1 << PD4);
  }
  if (mux & 0x02)
  {
    PORTD |= (1 << PD5);
  }
  if (mux & 0x04)
  {
    PORTD |= (1 << PD6);
  }
  if (mux & 0x08)
  {
    PORTD |= (1 << PD7);
  }
}
/*************************************************************************
* 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 <uart.h>

#include <i2c.h>


/* define CPU frequency in Mhz here if not defined in Makefile */
#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 */
  //TWSR = 1;
  //TWBR = 192;

}/* 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;

             !HIERHER KOMM ICH NICHT!

  // 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 */

Brauch ihr noch etwas zur hoffentlich erfolgreichen Fehleranalyse? Ich 
bin echt am verzweifeln mittlerweile.

Voller Hoffnung,
Benjamin

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Brauch ihr noch etwas zur hoffentlich erfolgreichen Fehleranalyse?

Wie wärs mit der Funktion main(). Ohne die geht eigentlich gar nichts.

Oliver

Autor: benjamin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
main.c sieht ganz unspektakulär aus:
#include <pll.h>
#include <uart.h>
#include <avr/interrupt.h>

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#define UART_BAUD_RATE      19200

void init(void)
{
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
  sei();

  init_pll();
}

int main(void)
{  

  init();
  
    while (1)
  {

  }

  return 0;
}

Habt ihr vielleicht eine Idee, an was es liegen könnte?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.