Forum: Mikrocontroller und Digitale Elektronik PIC I2C Fehler mit CCS Compiler in MPLAB


von Michael W. (mwulz)


Lesenswert?

Hallo Leute,

Ich hab MPLAB mit CCS Compiler (MPLAB Version 5).
Ich kann MPLAB leider nicht updaten, da das aktuelle MPLAB Version 8 den 
alten ICD-Programmer/Debugger für die 16F8xx Serie nicht mehr kann.

Da hab ich das Problem, dass der Code bei "i2c_start();" hängen bleibt!
Egal ob ich den ICD-Debugger verwende oder nicht.

Hatte jemand von euch einen solchen Fehler schon mal?

gruss
Michael

von gast (Gast)


Lesenswert?

Hallo, ich habe daselbe Problem. das ist mein Code:
1
void IdleI2C( void )
2
{
3
  while ( ( SSPCON2 & 0x1F ) )continue;
4
}
5
6
void StartI2C( void )
7
{
8
  SSPCON2bits.SEN = 1;            // initiate bus start condition
9
  while(SSPCON2bits.SEN);
10
}
11
u08 WriteI2C( u08 data_out )
12
{
13
  SSPBUF = data_out;           // write single byte to SSPBUF
14
  if ( SSPCON1bits.WCOL )      // test if write collision occurred
15
   return ( -1 );              // if WCOL bit is set return negative #
16
  else
17
  {
18
    while( SSPSTATbits.BF );   // wait until write cycle is complete         
19
    return ( 0 );              // if WCOL bit is not set return non-negative #
20
  }
21
}
22
void StopI2C( void )
23
{
24
  SSPCON2bits.PEN = 1;            // initiate bus stop condition
25
}
26
 u08 I2C_senden(u08 addr, u08 data)
27
 {
28
   IdleI2C();
29
   StartI2C();
30
   IdleI2C();
31
   WriteI2C(addr&0xFE);
32
   IdleI2C();
33
   if(SSPCON2bits.ACKSTAT)
34
   {
35
     StopI2C();
36
     return 0;
37
   }
38
   WriteI2C(data);
39
   IdleI2C();
40
    if(SSPCON2bits.ACKSTAT)
41
   {
42
     StopI2C();
43
     return 0;
44
   }
45
   StopI2C();
46
   return 1;
47
 }
48
 
49
 u08 I2C_lesen(void)
50
{
51
  SSPCON2bits.RCEN = 1;           // enable master for 1 byte reception
52
  while (!SSPSTATbits.BF );      // wait until byte received  
53
  return ( SSPBUF );              // return with read byte 
54
}
55
56
 
57
58
u08 DataRdyI2C( void )
59
{
60
  if ( SSPSTATbits.BF )           // test if buffer full bit is set     
61
    return (1 );                // data in SSPBUF register
62
  else
63
    return ( 0 );                 // no data in SSPBUF register
64
}
65
u08 recevoir(void)
66
{ 
67
  u08 y=0;;
68
  if(DataRdyI2C())
69
  {
70
  y=I2C_lesen();
71
  if(y==0x45)
72
  {
73
    LATDbits.LATD1=1;
74
    LATDbits.LATD2=0;
75
  }else{
76
    LATDbits.LATD2=1;
77
  LATDbits.LATD1=0;
78
  }
79
  }
80
}
wenn du eine Antwort hat kannst du mir helfen

von Michael W. (mwulz)


Lesenswert?

Ich hab das Hardware-I2C Modul des PIC 16F877 verwendet.
Mein Code sieht so aus:
1
#include <16f877.h>
2
#device ICD=TRUE
3
#use delay(clock=20000000)
4
#include <lcd.c>
5
#use i2c(master, sda=PIN_C4, scl=PIN_C3, noforce_sw)
6
7
int i2cT1,i2cT2;
8
9
main()
10
{
11
  lcd_init();
12
13
  i2c_stop();
14
15
   while(TRUE)
16
   {
17
  i2c_start();
18
  i2c_write(0b10010001);
19
  i2cT1=i2c_read();
20
  i2cT2=i2c_read(0);
21
  i2c_stop();
22
23
24
   delay_ms(50);
25
26
   lcd_gotoxy(1,1);
27
   printf(lcd_putc,"1:%3u",i2cT1);
28
   lcd_gotoxy(1,2);
29
   printf(lcd_putc,"2:%3u",i2cT2);
30
31
   delay_ms(500);
32
   }
33
34
}

Bei diesem Code bleibt der Microcontroller immer beim Befehl 
"i2c_start();" hängen. Sieht man im ICD Debugger schön!

Was kann hier der Grund sein?
Ich hab schon nachgesehen, scl und sda Pin's sind mit Pullup auf +5V 
gelegt. Der LM75 Temperatursensor, welcher am I2C Bus hängt hat addresse 
"000" und ich möchte aus diesem Lesen.

Hatte jemand sochon mal sowas?

Michael

von Harald A. (embedded)


Lesenswert?

Bei einem Fujitsu Controller hatte ich mal ein ähnliches Problem, der 
Controller blieb blieb hängen, weil die SDA Leitung nicht 
erwartungsgemäß auf High ging. Und das war so:

Es wurde ein I2C EEPROM ausgelesen, bei dem viele Datenzellen auf "0" 
waren. Erwartungsgemäß ist somit beim Auslesen die SDA Leitung relativ 
häufig Low. Sporadisch hing sich das Protokoll auf, auch nach kompletten 
Neustart ging nichts. Es klemmte ebenfalls bei der Erzeugung der 
Start-Condition. Nach längeren Arbeitspausen (ab ca. 20 Minuten) ging es 
dann auf einmal wieder. Auffällig war bei Messungen auf jeden Fall, dass 
das EEPROM seinerseits die Datenleitung auf Low zog. Einfach so, auch 
nach Reset und Trennung der Spannung.
Warum?
Es handelte sich um ein EEPROM, dass auch noch für Spannungen ab 1.8V 
spezifiziert war. Ein EEPROM hat keinen Reset-Eingang, die interne 
State-Machine wird nur bei einem Power-On Reset zurückgesetzt. 
Irgendwann hat es eine Verhakung im Protokoll gegeben und das EEPROM ist 
auf SDA=0 stehengeblieben. Das Ausschalten der Spannung hat nichts 
gebracht, da VCC relativ lange bei ca. 1V stehenbleibt. Das EEPROM war 
selbst bei dieser Spannung noch funktionell. Erst nach langer Zeit fällt 
die Spannung weit unter 1V und das EEPROM machte einen vernünftigen 
Power-On Reset. Daher das Phänomen nach Mittagspause, wo kurzzeitig 
wieder alles funktionierte.

Die Lösung lag darin, nach Power-On des Mikrocontrollers einfach einige 
zig Takte auf SCL manuell zu erzeugen, während SDA=1 bleibt. Dadurch kam 
die State-Machine im EEPROM wieder in den Tritt und der I2C Controller 
im Mikrocontroller fand bei Erzeugung der Start-Bedingung den korrekten 
Zustand SDA=1 vor!

Dieses Phänomen könntet ihr auch mal abchecken, die I2C Start 
Implementierungen bei verschiedenen Controllern sind häufig so 
gestrickt, dass einfach per Endlos-Loop auf SDA=1 (Busfreigabe) gewartet 
wird. Ist bei dieser Abfrage definitiv SDA=1 ???

von Michael W. (mwulz)


Lesenswert?

Hallo Danke für die Hilfe!

Ich hab's jetzt mit der Software-Variante des CCS Compilers geschafft!

Es gibt hier zwei Möglichkeiten:

einmal um das integrierte i2c Modul zu verwenden
1
#use i2c(master, sda=PIN_C4, scl=PIN_C3, noforce_sw)

oder
1
#use i2c(master, sda=PIN_C4, scl=PIN_C3)

Mit der 2ten Variante ohne Hardware Modul läuft es ohne Probleme!
Um auf die software Implementierung zurückzugreifen.

Offensichtlich hat mein LM75 hier ein Problem damit.
Ich werde mal den Tipp mit den SCL Takten versuchen!

danke
Michael

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.