Forum: Mikrocontroller und Digitale Elektronik LCD Problem nach I2C-Start


von Adrian (Gast)


Lesenswert?

Tach

Arbeite am Bau einer Wetterstation mit dem PIC16F877A. Ich will 3 
Sensoren (Temperatur,Feuchte,Druck) mit I2C auslesen und dann über die 
I/0 Pins auf dem LCD ausgeben. Ein einfaches Programm, welches etwas auf 
das Display schreibt funktioniert. Doch sobald der I2C-Startbefehl 
ausgeführt wird, geht nichts mehr. An was kann das liegen?

Display ist ein 20x4 mit HD44780 Controller

lg

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

>An was kann das liegen?

An dem Programm, an der Hardware oder an sonstwas. :-)

Vor allem beschreibe bitte Dein Problem detailliert.
Dann poste bitte, Schaltplan und Software.

Hilfreich ist auch der Artikel: 
http://www.mikrocontroller.net/articles/Netiquette

von Adrian (Gast)


Angehängte Dateien:

Lesenswert?

So und ein Ausschnitt vom Code wäre hier:
1
#include "..\Include\HTC_pbainc.h"
2
3
  
4
void main(void)
5
{
6
  init_pba();
7
  i2c_init();
8
lcd_init();
9
  i2c_start();
10
  i2c_write(0x90);
11
  i2c_write(0x00);
12
  i2c_stop();
13
  
14
  while(1)
15
  {
16
    float result;
17
    signed int temph;
18
    unsigned char templ;
19
    delay_ms(105);
20
    i2c_start();
21
    i2c_write(0x90);
22
    i2c_write(0x00);
23
    i2c_restart();
24
    i2c_write(0x91);
25
    temph=(signed int)i2c_read(1)*10;
26
    templ=i2c_read(0);
27
    i2c_stop();
28
    if(bit_test(templ,7))
29
    {
30
      if(temph < 0) temph=temph-5;
31
      else temph=temph+5;
32
    }  
33
    (float)result=temph/10.0;
34
    
35
    printf("%3.1f",result);
36
    lcd_gotoxy(0,0);
37
    
38
  }  
39
  
40
}

: Bearbeitet durch User
von Adrian (Gast)


Lesenswert?

Edit: Dieser Code soll nur den Temperatursensor auslesen und auf dem LCD 
ausgeben.

von Jörg E. (jackfritt)


Lesenswert?

Probier mal kleinere Abschlusswiderstände im 5V Teil. So 2k.

von RobWa (Gast)


Lesenswert?

Hallo,
weißt Du wo Dein Programm hängenbleibt?
Ich hatte mal ein ähnliches Problem, zufälligerweise ebenfalls bei einer 
I2C-Kommunikation. Bei mir war es ein verstellter 
Kommunikationsparameter (Busgeschwindigkeit). Dies hatte zur Folge, dass 
im Unterprogramm zum Versenden der Daten in einer Endlosschleife auf ein 
Flag gewartet wurde, dass aber nicht gekommen ist. Dieses Unterprogramm 
war in einer I2C-Bibliothek, die ich bekommen habe.

Grüße,
Robert.

von Adrian (Gast)


Lesenswert?

Jörg Esser schrieb:
> Probier mal kleinere Abschlusswiderstände im 5V Teil. So 2k.

Hat leider nicht funktioniert

RobWa schrieb:
> Hallo,
> weißt Du wo Dein Programm hängenbleibt?
> Ich hatte mal ein ähnliches Problem, zufälligerweise ebenfalls bei einer
> I2C-Kommunikation. Bei mir war es ein verstellter
> Kommunikationsparameter (Busgeschwindigkeit). Dies hatte zur Folge, dass
> im Unterprogramm zum Versenden der Daten in einer Endlosschleife auf ein
> Flag gewartet wurde, dass aber nicht gekommen ist. Dieses Unterprogramm
> war in einer I2C-Bibliothek, die ich bekommen habe.

Ja laut Debugg wartet es so wie ich es intepretiere auf ein Flag und 
bleibt hängen
Wie hast du das Problem gelöst?

von RobWa (Gast)


Lesenswert?

Hi,

das ist zwar schon etwas länger her, aber ich glaube bei mir war das 
globale Interruptflag gelöscht oder die Interrupt-Prioritätsstufe 
deaktiviert. Dadurch wurde der zugehörige Interrupt vom I2C-Datenempfang 
nicht ausgelöst in dem das Flag gesetzt wurde. In dem Fall entweder 
schauen warum der Interrupt deaktiviert wurde oder sicherheitshalber vor 
Eintritt in die kritische Funktion einfach wieder aktivieren.

HTH,
Robert.

von Jörg E. (jackfritt)


Lesenswert?

Das er so lange auf ein Flag wartet sollte aber nur passieren wenn der 
Bus ziemlich schlechte Signale führt. In einem meiner Projekte ist das 
so und dort habe ich einen Timer eingebaut der bei überschreiten der 
Wartezeit die Kommunikation von vorne startet. Allerdings sollte sowas 
nicht die Regel sein. In deinem Fall würde ich mir die Signale mit nem 
Oszi erstmal anschauen. Wenn du alles Freiluft und mit 100m Kabel und 
mit 1Mhz Bustakt verdrahtet hast kann das natürlich schon eher 
passieren. Aber das sieht meine Glaskugel leider nicht....

von RobWa (Gast)


Lesenswert?

Hallo,

ein zweites Mal hatte ich so ein Problem als ich die Taktfrequenz des 
Controllers zur Laufzeit geändert hatte. Dabei habe ich vergessen die 
Timingparameter der I2C-Schnittstelle umzustellen. Das hat ebenfalls 
dazu geführt, dass das erwartete Flag ausgeblieben ist.

BG,
Robert.

von Adrian (Gast)


Lesenswert?

Jörg Esser schrieb:
> Das er so lange auf ein Flag wartet sollte aber nur passieren wenn der
> Bus ziemlich schlechte Signale führt. In einem meiner Projekte ist das
> so und dort habe ich einen Timer eingebaut der bei überschreiten der
> Wartezeit die Kommunikation von vorne startet. Allerdings sollte sowas
> nicht die Regel sein. In deinem Fall würde ich mir die Signale mit nem
> Oszi erstmal anschauen. Wenn du alles Freiluft und mit 100m Kabel und
> mit 1Mhz Bustakt verdrahtet hast kann das natürlich schon eher
> passieren. Aber das sieht meine Glaskugel leider nicht....

Das ganze ist auf einem Print mit Hauptsächlich SMD bauteilen :)

Ich werde mir das ganze am Montag nochmals genauer anschauen. Vielleicht 
finde ich noch heraus wo der Hund begraben liegt.

Danke schonmal

von Frank K. (fchk)


Lesenswert?

Wer hat die Schaltung entworfen? Du?

Warum wird der 5V-Zweig des PCA9306 über einen 200k-Widerstand versorgt? 
Was hast sich der Erfinder dabei gedacht?

Wenn man gewollte hätte, hätte man das ganze auch nur mit 3.3V aufbauen 
können.  Entweder wollte man nicht oder war zu doof dazu.

fchk

PS: Wenn ich nochmal auf den Plan schaue, fallen mir noch ein paar 
weitere Fehler auf.

: Bearbeitet durch User
von Jörg E. (jackfritt)


Lesenswert?

LM75? :)
So genau habe ich gar nicht hingeguckt.

von Adrian (Gast)


Lesenswert?

Frank K. schrieb:
> Wer hat die Schaltung entworfen? Du?
Teilweise

Frank K. schrieb:
> Warum wird der 5V-Zweig des PCA9306 über einen 200k-Widerstand versorgt?
> Was hast sich der Erfinder dabei gedacht?
Habe ich so übernommen aus einem alten Projekt, welches nicht von mir 
stammt.

Frank K. schrieb:
> Wenn man gewollte hätte, hätte man das ganze auch nur mit 3.3V aufbauen
> können.  Entweder wollte man nicht oder war zu doof dazu.
Zu doof

Frank K. schrieb:
> PS: Wenn ich nochmal auf den Plan schaue, fallen mir noch ein paar
> weitere Fehler auf.
Raus damit, nehme Kritik gerne entgegen

von Adrian (Gast)


Lesenswert?

Hab herausgefunden wo das Programm hängenbleibt. Und zwar beim Befehl: 
while(!SSPIF);

da wartet er auf SSPIF, was nicht kommt..

Habe aber keine Ahnung woran das liegt

Gruss

von Frank M. (frank_m35)


Lesenswert?

Was ist i2c_init();?
Woher kommt es, was steht da drin?

Das selbe mit i2c_start();

Wo stellst du den Takt deines uC ein?

Welche I2C Geräte sind bisher am Bus angeschlossen? Alle? Kannst du Alle 
bis auf den EEPROM mal weg lassen?

von Adrian (Gast)


Lesenswert?

Frank M. schrieb:
> Was ist i2c_init();?

Eine Funktion zum initialisieren damit i2c verwendet werden kann
1
#include "..\Include\HTC_pbainc.h"
2
3
void i2c_wait_if(void)
4
{
5
  while(!SSPIF);               //Warten bis I2C-IF gesetzt (MSSP action done)
6
  SSPIF=0;                //Interrupt-Flag rücksetzen  
7
}
8
9
void i2c_init(void)
10
{
11
  TRISC|=0b00011000;            //RC3(SCL), RC4(SDA) als Inputs definieren
12
  SSPADD=BRGVAL;              //Takt 100kHz: BRGVAL = (FOSC / (4 * SCL)) -1
13
  SSPCON=0x08;              //master mode, clock=Fosc/(4*(SSPADD+1))
14
  SSPEN=1;                //MSSP-Modul eingeschalten (SSP-Enable)
15
}
16
17
void i2c_start(void)
18
{
19
  SEN=1;                  //Bus übernemen
20
  i2c_wait_if();              //Warten bis Bus übernommen  
21
}
22
23
void i2c_restart(void)
24
{
25
  RSEN=1;                  //Bus erneut übernehmen
26
  i2c_wait_if();              //Warten bis Bus übernommen  
27
}
28
  
29
void i2c_stop(void)
30
{
31
  PEN=1;                  //Bus freigeben
32
  i2c_wait_if();              //Warten bis Bus freigegeben
33
}  
34
35
void i2c_write(unsigned char value)
36
{
37
  SSPBUF=value;              //Ein Byte zum I2C-Slave übertragen 
38
  i2c_wait_if();              //Warten bis Daten geschrieben
39
}  
40
41
unsigned char i2c_read(unsigned char ack)
42
{
43
  RCEN=1;                  //Daten Empfang einschalten
44
  i2c_wait_if();              //Warten bis Bus übernommen
45
  ACKDT=!ack;                //ACK / NoACK von Master
46
  ACKEN=1;                //Acknowledge Sequenz starten
47
  i2c_wait_if();              //Warten bis Bus übernommen
48
  return SSPBUF;
49
}

: Bearbeitet durch User
von Adrian (Gast)


Lesenswert?

Habe es Momentan so aufgebaut, dass nur der LM75 angeschlossen ist.

Der Takt wird folgendermassen eingestellt:

#ifndef HTC_PBAi2c
#define HTC_PBAi2c true

#define FSCL_KHZ   100              //100kHz I2C-Mode
#define BRGVAL     20000/(4*FSCL_KHZ)-1    //BRG = (PIC / (4 * SCL)) -1

void i2c_wait_if(void);
void i2c_init(void);
void i2c_start(void);
void i2c_restart(void);
void i2c_stop(void);
void i2c_write(unsigned char value);
unsigned char i2c_read(unsigned char ack);

#endif

von RobWa (Gast)


Lesenswert?

Hallo,

Adrian schrieb:
> Hab herausgefunden wo das Programm hängenbleibt. Und zwar beim Befehl:
> while(!SSPIF);
>
> da wartet er auf SSPIF, was nicht kommt..

hast Du schon überprüft ob Dein Interrupt an dieser Stelle aktiv ist?
Das sieht ziemlich gleich aus wie mein Problem, dass ich in meiner 
Antwort vom 06.12.2013 16:26 beschrieben habe.

Grüße,
Robert.

von Adrian (Gast)


Lesenswert?

RobWa schrieb:
> hast Du schon überprüft ob Dein Interrupt an dieser Stelle aktiv ist?
> Das sieht ziemlich gleich aus wie mein Problem, dass ich in meiner
> Antwort vom 06.12.2013 16:26 beschrieben habe.
>
> Grüße,
> Robert.

Seh ich das in den Special Function Registers? Wenn ja ist es da nicht 
aufgeführt->nicht aktiv?

von RobWa (Gast)


Lesenswert?

Ich kenn mich mit den PIC-µCs nicht so aus, aber kannst Du nicht einfach 
den globalen Interrupt vor der Aktivierung des I2C-Transfers enablen? 
z.B. durch die Funktion sei();
Da können Dir aber sicher PIC-Experten besser weiterhelfen.

Grüße,
Robert.

von Dietrich L. (dietrichl)


Lesenswert?

@Adrian:

Ich vermisse in Deiner Schaltung einen Kondensator an Pin 7 und 8 des 
PCA9306. Das Datenblatt sagt bei den "Application Information": "A 
filter capacitor on VREF2 is recommended."

Auch wenn das nur empfohlen ist, aber man kann es ja mal probieren ...

Gruß Dietrich

von Frank M. (frank_m35)


Lesenswert?

SSPIF wird unabhängig von Interrupts geschalten:
Datenblatt:
The following events will cause SSP Interrupt Flag bit,
SSPIF, to be set (SSP interrupt if enabled):
• Start condition
• Stop condition
• Data transfer byte transmitted/received
• Acknowledge transmit
• Repeated Start



Wo du einen Fehler hast, scheint in der Baudrate berechnung, die falsche 
Werte liefert, siehe Datenblatt Seite 99. Nimm dort einen fertig 
berechneten passenden Wert und teste es nochmal.

von Frank M. (frank_m35)


Lesenswert?

Seh grad, habe HEX und Decimal nicht beachtet. Scheint doch zu passen 
die Baudrate :-)

Schau mal hier:
http://www.8051projects.net/i2c-twi-tutorial/pic-i2c-code-example.php

Vielleicht hilft's weiter.

von Adrian (Gast)


Lesenswert?

Wenn ich SDA und SCL vom PCA9306 trenne funktioniert es ^^. Folglich 
müsste etwas mit der Verdrahtung des PCA9306 nicht stimmen oder am 
3.3V-Pfad ist was faul. Sieht jemand den Fehler gerade auf Anhieb? 
Schaue sicher Morgen weiter. Gibt nicht mehr soooo viele möglichkeiten.

Gruss
Adrian

von Frank K. (fchk)


Lesenswert?

Adrian schrieb:
> Wenn ich SDA und SCL vom PCA9306 trenne funktioniert es ^^. Folglich
> müsste etwas mit der Verdrahtung des PCA9306 nicht stimmen oder am
> 3.3V-Pfad ist was faul. Sieht jemand den Fehler gerade auf Anhieb?
> Schaue sicher Morgen weiter. Gibt nicht mehr soooo viele möglichkeiten.

Ja.
1. Überbrücke den 200k Widerstand
2. 100n zwischen 3.3V Pin und GND direkt am PCA9306
3. 100n zwischen 5V Pin und GND direkt am PCA9306

So, jetzt weiter:
4. Dein PIC hat zwei VCC-GND-Paare (11-12, 31-32) 100n zwischen jedes 
Paar, und zwar direkt an die Pins.
5. Betrifft LCD: Die im 4-Bit Modus unbenutzten Datenleitungen D0..D3 
offen lassen oder allenfalls über 10k an Ground oder VCC. Wenn Du vom 
Display liest, leiden sonst die Ausgangstreiber.
6. Hänge die Datenleitungen zum Display nicht an RB4-RB7, sondern an RD0 
bis RD3. Dadurch sparst Du Dir Schalter S1 und S2 und kannst problemlos 
debuggen.

Zur Umrüstung auf reinen 3.3V Betrieb:
7. Ersetze den PIC16F877A durch einen PIC16LF877A und den Quarz durch 
einen 10 MHz Quarz. Alternativ kannst Du auch einen ganz anderen PIC 
einsetzen - ich würde da den PIC18F46K20 empfehlen. Der läuft auch bei 
voller Taktrate mit 64 MHz bei 3.3V und braucht dafür einen 16MHz Quarz. 
Die Pinbelegung ist weitgehend gleich.
8. PCA9306 entfernen, SCL1 und SCL2 brücken, SDA1 und SDA2 brücken, 
Extra Pullups R4 und R5 entfernen.
9. Sicherstellen, dass das EEPROM eines für 3.3V ist (24C...: 5V 
24LC...:3-5V  24AA...: 1.8-5V)
10. Alle Bausteine von der 5V-Versorgung auf die 3.3V Versorgung 
umklemmen.
11. Die Textmodus-LCDs laufen fast alle auch mit 3.3V, brauchen dann 
aber eine negative Kontrastspannung. Heißt also: Den GND-Pin des 
Kontrastpotis musst Du auf etwa -3V legen, die Du Dir einfach mit einem 
ICL7660 und zwei 10u X7R keramisch erzeugen kannst. Alternativ reicht 
auch ein PWM-Ausgang und einige Dioden und Kondensatoren. Siehe
http://www.sprut.de/electronic/switch/minus.html

So, das wären meine Anmerkungen.

fchk

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.