mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik TWI mehrfach Initialisierung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: D a v i d K. (oekel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe zwei Probleme, die unmittelbar zusammenhängen. Dabei bezieht 
sich meine Frage hier auf einen Workarround (2).

1. Ich habe eine Platine, die irgendwie beim bespeisen eines DC-Motors 
sehr sporalische Probelem mit dem Display hat (TWI-Seriell wandler.)

1.1
Ich hätte behauptet, dass durch die Rückinduktion der µC mittels 
BrownOut (1,8V) selbst abschaltet.
Ich war beim Kunden und er könnte mir dieses "Problem" leider bei keinen 
der 70 Platinen zeigen (Vorführeffekt) und in meiner Werkstatt habe ich 
es auch nie selbst gesehen :(

Er beschreibt es so:
"Display bekommt Sonderzeichen aber Programm im Hintergrund läuft 
weiter". (Läuft weiter heißt doch 1.1 ist ausgeschlossen!?!)
1.2
Diese Sonderzeichen, kenne ich nur, wenn der Bus schlecht verlötet ist 
und die Initialisierung nicht richtig klappt. Daher habe ich NACHLÖTEN 
empfohlen.

2.
Ich würde gerne probieren, ob ich einen Workarround hin bekomme, so das 
das Display selbst nach diesem Fehler wieder "sauber" wird.

Daher die eigentliche Frage: "Kann/darf ich den i2c_init() regelmäßig 
wiederholen und/oder kann dies andere Seiteneffekte haben?"

Folgendes verwende ich:
/*************************************************************************
* 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"

/**
 * The standard clock (SCL) speed for I2C up to 100KHz. Philips do define faster speeds: Fast mode, which is up to 400KHz
 */
/* I2C clock in Hz */
#define SCL_CLOCK  100000L


/*************************************************************************
 Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
#if ((F_CPU/SCL_CLOCK)-16)/2 < 10
  #error TWBR to small
#endif

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

Verändert habe ich nur (da ich mit 8Mhz arbeite und sonst die Formel 
nicht auf geht):
//#define SCL_CLOCK  400000L
#define SCL_CLOCK  100000L


Dann selektiere ich noch:
uint8_t I2C_Detect(uint8_t addr)
// look for device at specified address; return 1=found, 0=not found
{
    return !i2c_start(addr); // return 0 if OK otherwise 1
}
uint8_t LCD_I2C_DEVICE = I2C_PCF8574;
void i2c_detectPCF8574() {
    bool i2cFound_PCF8574 = I2C_Detect(I2C_PCF8574);
    bool i2cFound_PCF8574A = I2C_Detect(I2C_PCF8574A);
    if (!i2cFound_PCF8574 && i2cFound_PCF8574A) {
        LCD_I2C_DEVICE = I2C_PCF8574A;
    }
}

und mache ein:
void lcd_init(void) {

    lcd_light(false);

    _delay_ms(15);                //-  Wait for more than 15ms after VDD rises to 4.5V
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
    _delay_ms(5);                //-  Wait for more than 4.1ms
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
    _delay_ms(1);                //-  Wait for more than 100us
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
    lcd_write(CMD_D1);            //-  Set interface to 4-bit

    _delay_ms(50);
    //- From now on in 4-bit-Mode
    lcd_command(LCD_LINE_MODE | LCD_5X7);
    _delay_ms(50);
    lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
    _delay_ms(50);
    lcd_command(LCD_INCREASE | LCD_DISPLAYSHIFTOFF);
    _delay_ms(50);
    lcd_command(LCD_CLEAR);
    _delay_ms(50);
}


Reihenfolge:
int main(void) {
    ioinit();
    timer2_init();
    timer1_pwm_init();

    i2c_init();
    i2c_detectPCF8574();
    lcd_init();
    //ADC_init();
    /** Interrupts (IRQs) global erlauben */
    sei();
    wait_10ms(1);

    readOldVariables();

    while (1) {
        sceduled_menue();
        if(section == RunRun){
            runningCoutdown();
        }
        sceduled_motor();
    }
}

Könnte es einen positiven Effekt haben
- i2c_init();
oder
lcd_init();

mehrfach. (z.B. in einer Schleife von 5Sek aufzurufen?
Wie gesagt, konnte ich den Fehler selbst nie sehen geschweigedenn 
reproduzieren, daher wäre ein "probier es doch aus" nicht so hilfreich 
;)

Alles anderen bezüglich Grundlagenwissen höre ich gerne und bin 
neugierig drauf.

Grüße David

Autor: Sascha W. (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

die Init kannst du so oft durchführen wie du willst.
Die Frage ist:
Wenn der Fehler auftritt wird das Display dann nach den falschen Zeichen 
überhaupt nicht mehr aktualisiert?
Wenn ja,
dann hängt wohl der Bus und das i2c_init sollte das beheben - es sei 
denn das Display oder der Wandler hat sich auch verhaspelt. Das sollte 
sich mit einer gewissen Anzahl an Clockpulsen beheben lassen. Den 
Zustand sollte der Controller feststellen können, da vom Display kein 
ACK mehr kommt.
Wenn nein,
dann hat sich evl. etwas an der Konfig des Displays verstellt, dann muss 
du auch das Display neu initialisieren und dann alles wieder ausgeben.

Sascha

Autor: D a v i d K. (oekel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha W. schrieb:
> denn das Display oder der Wandler hat sich auch verhaspelt. Das sollte
> sich mit einer gewissen Anzahl an Clockpulsen beheben lassen. Den
> Zustand sollte der Controller feststellen können, da vom Display kein
> ACK mehr kommt.

Meinst du die hiesige 1?
/*************************************************************************
  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 */


Die ich nicht verarbeite:
void lcd_write(uint8_t value) {
    uint8_t data_out = 0;

...

    // direct I2C access, write all three bytes in one cycle for faster operation
    i2c_start_wait(LCD_I2C_DEVICE + I2C_WRITE);
    i2c_write(data_out);                // setup data BEFORE E!   
    i2c_write(data_out | LCD_E);        // set E to high
    i2c_write(data_out);                // set E to low
    i2c_stop();
}

: Bearbeitet durch User
Autor: Regeln Erklehrbehr (Gast)
Datum:
Angehängte Dateien:

Bewertung
2 lesenswert
nicht lesenswert
D a v i d K. schrieb:
> Alles anderen bezüglich Grundlagenwissen höre ich gerne und bin
> neugierig drauf.

Bist hier schon 10 (in Worten: zehn) Jahren angemeldet.

Warum hältst du es nicht für nötig dich an diese kleinen
minimalen Regeln zu halten?

Autor: D a v i d K. (oekel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Regeln Erklehrbehr schrieb:
> Warum hältst du es nicht für nötig dich an diese kleinen
> minimalen Regeln zu halten?
Das "[c]" statt "[code]" fällt mir jetzt gerade erst auf. Entschuldigt 
aber in keiner Form den zu lang geratenen ersten Post.

Danke

Autor: Regeln Erklehrbehr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D a v i d K. schrieb:
> Das "[ c]" statt "[code]" fällt mir jetzt gerade erst auf.

Man kann im Preview überprüfen ob man alles richtig gemacht hat
/*************************************************************
  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;
  bla blubb foo bar
  return 0;
}/* i2c_write */

Autor: Sascha W. (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D a v i d K. schrieb:
> Sascha W. schrieb:
>> denn das Display oder der Wandler hat sich auch verhaspelt. Das sollte
>> sich mit einer gewissen Anzahl an Clockpulsen beheben lassen. Den
>> Zustand sollte der Controller feststellen können, da vom Display kein
>> ACK mehr kommt.
>
> Meinst du die hiesige 1?
ja, kannst aber auch die detect-funktion für den PCF verwenden. Wenn der 
Bus hängt dann sollte dort false zurückkommen.

Sascha

Autor: my2ct (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Regeln Erklehrbehr schrieb:
> Warum hältst du es nicht für nötig dich an diese kleinen
> minimalen Regeln zu halten?

Für manche Leuten ist alles was einen "Dreizeiler" überschreitet, schon 
"längerer Source Code"

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn sich die State-Machine im Display durch komische Spikes völlig 
ver­rannt hat, hilft ofmals nur ein richtiger Reset falls das Display 
eine Reset-Leitung hat. Ansonsten Vcc vom Display schaltbar machen.

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.

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