Forum: Mikrocontroller und Digitale Elektronik TWI mehrfach Initialisierung


von D a v i d K. (oekel) Benutzerseite


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:
1
/*************************************************************************
2
* Title:    I2C master library using hardware TWI interface
3
* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
4
* File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6
* Target:   any AVR device with hardware TWI 
7
* Usage:    API compatible with I2C Software Library i2cmaster.h
8
**************************************************************************/
9
10
#include <inttypes.h>
11
#include <compat/twi.h>
12
#include "i2cmaster.h"
13
14
/**
15
 * The standard clock (SCL) speed for I2C up to 100KHz. Philips do define faster speeds: Fast mode, which is up to 400KHz
16
 */
17
/* I2C clock in Hz */
18
#define SCL_CLOCK  100000L
19
20
21
/*************************************************************************
22
 Initialization of the I2C bus interface. Need to be called only once
23
*************************************************************************/
24
void i2c_init(void)
25
{
26
#if ((F_CPU/SCL_CLOCK)-16)/2 < 10
27
  #error TWBR to small
28
#endif
29
30
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
31
  
32
  TWSR = 0;                         /* no prescaler */
33
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
34
35
36
}/* i2c_init */
37
...

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


Dann selektiere ich noch:
1
uint8_t I2C_Detect(uint8_t addr)
2
// look for device at specified address; return 1=found, 0=not found
3
{
4
    return !i2c_start(addr); // return 0 if OK otherwise 1
5
}
6
uint8_t LCD_I2C_DEVICE = I2C_PCF8574;
7
void i2c_detectPCF8574() {
8
    bool i2cFound_PCF8574 = I2C_Detect(I2C_PCF8574);
9
    bool i2cFound_PCF8574A = I2C_Detect(I2C_PCF8574A);
10
    if (!i2cFound_PCF8574 && i2cFound_PCF8574A) {
11
        LCD_I2C_DEVICE = I2C_PCF8574A;
12
    }
13
}

und mache ein:
1
void lcd_init(void) {
2
3
    lcd_light(false);
4
5
    _delay_ms(15);                //-  Wait for more than 15ms after VDD rises to 4.5V
6
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
7
    _delay_ms(5);                //-  Wait for more than 4.1ms
8
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
9
    _delay_ms(1);                //-  Wait for more than 100us
10
    lcd_write(CMD_D1 | CMD_D0);    //-  Set interface to 8-bit
11
    lcd_write(CMD_D1);            //-  Set interface to 4-bit
12
13
    _delay_ms(50);
14
    //- From now on in 4-bit-Mode
15
    lcd_command(LCD_LINE_MODE | LCD_5X7);
16
    _delay_ms(50);
17
    lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
18
    _delay_ms(50);
19
    lcd_command(LCD_INCREASE | LCD_DISPLAYSHIFTOFF);
20
    _delay_ms(50);
21
    lcd_command(LCD_CLEAR);
22
    _delay_ms(50);
23
}


Reihenfolge:
1
int main(void) {
2
    ioinit();
3
    timer2_init();
4
    timer1_pwm_init();
5
6
    i2c_init();
7
    i2c_detectPCF8574();
8
    lcd_init();
9
    //ADC_init();
10
    /** Interrupts (IRQs) global erlauben */
11
    sei();
12
    wait_10ms(1);
13
14
    readOldVariables();
15
16
    while (1) {
17
        sceduled_menue();
18
        if(section == RunRun){
19
            runningCoutdown();
20
        }
21
        sceduled_motor();
22
    }
23
}

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

von Sascha W. (sascha-w)


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

von D a v i d K. (oekel) Benutzerseite


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?
1
/*************************************************************************
2
  Send one byte to I2C device
3
  
4
  Input:    byte to be transfered
5
  Return:   0 write successful 
6
            1 write failed
7
*************************************************************************/
8
unsigned char i2c_write( unsigned char data )
9
{  
10
    uint8_t   twst;
11
    
12
  // send data to the previously addressed device
13
  TWDR = data;
14
  TWCR = (1<<TWINT) | (1<<TWEN);
15
16
  // wait until transmission completed
17
  while(!(TWCR & (1<<TWINT)));
18
19
  // check value of TWI Status Register. Mask prescaler bits
20
  twst = TW_STATUS & 0xF8;
21
  if( twst != TW_MT_DATA_ACK) return 1;
22
  return 0;
23
24
}/* i2c_write */

Die ich nicht verarbeite:
1
void lcd_write(uint8_t value) {
2
    uint8_t data_out = 0;
3
4
...
5
6
    // direct I2C access, write all three bytes in one cycle for faster operation
7
    i2c_start_wait(LCD_I2C_DEVICE + I2C_WRITE);
8
    i2c_write(data_out);                // setup data BEFORE E!   
9
    i2c_write(data_out | LCD_E);        // set E to high
10
    i2c_write(data_out);                // set E to low
11
    i2c_stop();
12
}

: Bearbeitet durch User
von Regeln Erklehrbehr (Gast)


Angehängte Dateien:

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?

von D a v i d K. (oekel) Benutzerseite


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

von Regeln Erklehrbehr (Gast)


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
1
/*************************************************************
2
  Send one byte to I2C device
3
  Input:    byte to be transfered
4
  Return:   0 write successful 
5
            1 write failed
6
*************************************************************/
7
unsigned char i2c_write( unsigned char data )
8
{  
9
  uint8_t   twst;
10
  bla blubb foo bar
11
  return 0;
12
}/* i2c_write */

von Sascha W. (sascha-w)


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

von my2ct (Gast)


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"

von Timmo H. (masterfx)


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.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Timmo H. schrieb:
> 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.

Ich kann leider keine ResetLeitung erkennen.

[VSS, VDO, VO, RS, RW, E, D0...D7, A, K]

Es scheint so, dass ich diese "Sonderzeichen" reproduziert bekomme, wenn 
ich SCL mehrmals vom PCF8574X hintereinander ab und anstöpsel.

Jedoch habe ich noch nicht den Dreh (Sofware) raus, diesen in einer 
10sec-Schleife wieder zu "entfernen".

In wiefern kann ich hiervon profitieren?

Manfred L. schrieb:
> void TWIS_Stop (void)
> {
>    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(1<<TWEA)|(1<<TWIE);
> }
>
> ist Gold wert und hat nun jetzt auch bei mir auf Anhieb funktioniert.

Bzw. hiervon:
https://www.mikrocontroller.net/articles/AVR_TWI#Bekannte_Bugs


Grüße David

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.