Forum: Mikrocontroller und Digitale Elektronik PIC18F4550 und I2C funktioniert nur teilweise. Spuki


von Jdelphi (Gast)


Lesenswert?

Hi, ich hab da mal ein kleines Problem bei der I2C und dem PIC18F4455 
oder auch 18F4550.

Nur vorweg, der I2C Bus geht von der Hardware her zu 100%.

Ich habe angefangen mit USB rumzuspielen, als erstes mit dem Treiber von 
Microchip nun will ich das ganze als HID laufen lassen. Die USB Seite 
klappt soweit auch gut. Nur gibt es seit dem ich auf den HID Stack 
umgestiegen bin, Probleme bei der I2C Schnittstelle.

Ich versuche momentan, einfach nur ein Paar Zeichen über die I2C zu 
senden, als Beispiel an ein EEPROM. Dazu nehme ich die von Microchip in 
der C Libare vorhandene EEPageWrite funktion. Dies klappt dan auch 
Problemlos. Sobald ich aber, die Funktion aus der Quelldatei in meinen 
Quellcode Kopiere und in EEPageWrite2 umbenenne, funktioniert diese 
nicht mehr.

Geht
1
unsigned char send_x(void)
2
{
3
  ReceivedDataBuffer[0] = 2;
4
  ReceivedDataBuffer[1] = 3;
5
  ReceivedDataBuffer[2] = 4;
6
  ReceivedDataBuffer[3] = 5;
7
  ReceivedDataBuffer[4] = 0x00;
8
9
  EEPageWrite(0x42,0x01,ReceivedDataBuffer);
10
  return 0;
11
}
Geht nicht mehr.
1
unsigned char EEPageWrite2( unsigned char control, unsigned char address, unsigned char *wrptr )
2
{
3
  IdleI2C();                      // ensure module is idle
4
  StartI2C();                     // initiate START condition
5
  while ( SSPCON2bits.SEN );      // wait until start condition is over 
6
  if ( PIR2bits.BCLIF )           // test for bus collision
7
  {
8
    return ( -1 );                // return with Bus Collision error 
9
  }
10
  else
11
  {
12
    if ( WriteI2C( control ) )    // write 1 byte - R/W bit should be 0
13
    {
14
    StopI2C(); 
15
      return ( -3 );              // return with write collision error
16
    }
17
18
    //IdleI2C();                    // ensure module is idle
19
    if ( !SSPCON2bits.ACKSTAT )   // test for ACK condition, if received 
20
    { 
21
      if ( WriteI2C( address ) )  // write address byte to EEPROM
22
      {
23
      StopI2C(); 
24
        return ( -3 );            // return with write collision error
25
      }
26
27
      //IdleI2C();                  // ensure module is idle
28
      if ( !SSPCON2bits.ACKSTAT ) // test for ACK condition, if received
29
      {
30
        if ( putsI2C ( wrptr ) )
31
        {
32
      StopI2C(); 
33
          return( -4 );           // bus device responded possible error
34
        }
35
      }
36
      else
37
      {
38
      StopI2C(); 
39
        return ( -2 );            // return with Not Ack error
40
      }
41
    }
42
    else
43
    {
44
    StopI2C(); 
45
      return ( -2 );              // return with Not Ack error
46
    }
47
  }
48
49
 //IdleI2C();                      // ensure module is idle
50
  StopI2C();                      // send STOP condition
51
  while ( SSPCON2bits.PEN );      // wait until stop condition is over 
52
  if ( PIR2bits.BCLIF )           // test for Bus collision
53
  {
54
    return ( -1 );                // return with Bus Collision error 
55
  }
56
  return ( 0 );                   // return with no error
57
}
58
59
unsigned char send_x(void)
60
{
61
  ReceivedDataBuffer[0] = 2;
62
  ReceivedDataBuffer[1] = 3;
63
  ReceivedDataBuffer[2] = 4;
64
  ReceivedDataBuffer[3] = 5;
65
  ReceivedDataBuffer[4] = 0x00;
66
67
  EEPageWrite2(0x42,0x01,ReceivedDataBuffer);
68
  return 0;
69
}

Er steigt mir jedesmal bei „if ( WriteI2C( control ) )    // write 1 
byte - R/W bit should be 0“ aus.

Nun hab ich mir mal Disassemblerlisting angesehn. Da die Funktion ja 1 
zu 1 Kopiert wurde, sollte der Compiler in beiden Fällen einen 
identischen code erstellen. Leider sind im Code, erhebliche 
Abweichungen.

Geht
1
16:                unsigned char EEPageWrite( unsigned char control, unsigned char address, unsigned char *wrptr )
2
  2F3C    CFD9     MOVFF 0xfd9, 0xfe6
3
  2F3E    FFE6     NOP
4
  2F40    CFDA     MOVFF 0xfda, 0xfe6
5
  2F42    FFE6     NOP
6
  2F44    CFE1     MOVFF 0xfe1, 0xfd9
7
  2F46    FFD9     NOP
8
  2F48    CFE2     MOVFF 0xfe2, 0xfda
9
  2F4A    FFDA     NOP
10
17:                {
11
18:                  IdleI2C();                      // ensure module is idle
12
  2F4C    50C7     MOVF 0xfc7, W, ACCESS
13
  2F4E    0B04     ANDLW 0x4
14
  2F50    E001     BZ 0x2f54
15
  2F52    0E01     MOVLW 0x1
16
  2F54    D842     RCALL 0x2fda
17
  2F56    E1FA     BNZ 0x2f4c
18
19:                  StartI2C();                     // initiate START condition
19
  2F58    80C5     BSF 0xfc5, 0, ACCESS
20
20:                  while ( SSPCON2bits.SEN );      // wait until start condition is over 
21
  2F5A    B0C5     BTFSC 0xfc5, 0, ACCESS
22
  2F5C    D7FE     BRA 0x2f5a
23
21:                  if ( PIR2bits.BCLIF )           // test for bus collision
24
  2F5E    B6A1     BTFSC 0xfa1, 0x3, ACCESS
25
  2F60    D033     BRA 0x2fc8
26
22:                  {
27
23:                    return ( -1 );                // return with Bus Collision error 
28
24:                  }
29
25:                  else
30
26:                  {
31
27:                    if ( WriteI2C( control ) )    // write 1 byte - R/W bit should be 0
32
  2F62    0EFD     MOVLW 0xfd
33
  2F64    D83F     RCALL 0x2fe4
34
  2F66    E10B     BNZ 0x2f7e
35
  2FE4    CFDB     MOVFF 0xfdb, 0xfe6
36
  2FE6    FFE6     NOP
37
  2FE8    EC44     CALL 0x3288, 0
38
  2FEA    F019     NOP
39
  2FEC    52E5     MOVF 0xfe5, F, ACCESS
40
  2FEE    0900     IORLW 0
41
  2FF0    0012     RETURN 0
42
28:                    {
43
29:                      return ( -3 );              // return with write collision error
44
30:                    }
45
31:                
46
32:                    IdleI2C();                    // ensure module is idle
Geht nicht
1
1466:              unsigned char EEPageWrite2( unsigned char control, unsigned char address, unsigned char *wrptr )
2
  1D8E    D86B     RCALL 0x1e66
3
  1E66    CFD9     MOVFF 0xfd9, 0xfe6
4
  1E68    FFE6     NOP
5
  1E6A    CFE1     MOVFF 0xfe1, 0xfd9
6
  1E6C    FFD9     NOP
7
  1E6E    0012     RETURN 0
8
1467:              {
9
1468:                IdleI2C();                      // ensure module is idle
10
  1D90    50C7     MOVF 0xfc7, W, ACCESS
11
  1D92    0B04     ANDLW 0x4
12
  1D94    E001     BZ 0x1d98
13
  1D96    0E01     MOVLW 0x1
14
  1D98    D86F     RCALL 0x1e78
15
  1D9A    E1FA     BNZ 0x1d90
16
  1E78    6E0B     MOVWF 0xb, ACCESS
17
  1E7A    0E1F     MOVLW 0x1f
18
  1E7C    14C5     ANDWF 0xfc5, W, ACCESS
19
  1E7E    100B     IORWF 0xb, W, ACCESS
20
  1E80    0012     RETURN 0
21
1469:                StartI2C();                     // initiate START condition
22
  1D9C    80C5     BSF 0xfc5, 0, ACCESS
23
1470:                while ( SSPCON2bits.SEN );      // wait until start condition is over 
24
  1D9E    B0C5     BTFSC 0xfc5, 0, ACCESS
25
  1DA0    D7FE     BRA 0x1d9e
26
1471:                if ( PIR2bits.BCLIF )           // test for bus collision
27
  1DA2    B6A1     BTFSC 0xfa1, 0x3, ACCESS
28
  1DA4    D024     BRA 0x1dee
29
1472:                {
30
1473:                  return ( -1 );                // return with Bus Collision error 
31
1474:                }
32
1475:                else
33
1476:                {
34
1477:                  if ( WriteI2C( control ) )    // write 1 byte - R/W bit should be 0
35
  1DA6    0EFE     MOVLW 0xfe
36
  1DA8    D8FB     RCALL 0x1fa0
37
  1DAA    E105     BNZ 0x1db6
38
1478:                  {
39
1479:                  StopI2C(); 
40
1480:                    return ( -3 );              // return with write collision error
41
1481:                  }
42
1482:              
43
1483:                  //IdleI2C();                    // ensure module is idle
44
1484:                  if ( !SSPCON2bits.ACKSTAT )   // test for ACK condition, if received

Hat vielleicht jemand von euch eine Erklärung. Zum einen Woran es liegen 
könnte und zum anderen, warum bei einem copy und past sich der 
assemblercode so verkürtzt.

von Andreas G. (beastyk)


Lesenswert?

Wie sieht denn die Hardwareseite bei dir aus?

Gruß
Andi

von Jdelphi (Gast)


Lesenswert?

Was willst du dort genauer wissen?
Die HArdware Funktioniert ja zu 100%.

Der Compiler ist übrigens der C18 von Microchip

von Andreas G. (beastyk)


Lesenswert?

Moin,

wenn es eine selbstgebaute Hardware ist und nicht top secret könnteste 
das doch auch mal posten.

Wenn du allerdings vollkommen sicher bist das es 100% von der 
Softwareseite kommt...

Gruß
Andi

von JDelphi (Gast)


Lesenswert?

Bin mir zu 200% sicher das es nicht von der Hardware kommt.

Habe 3 Aufbauten, prototy, PICDEM Boardund nun eine LP von nem LP 
HErsteller.
Alle 3 mit verschiedenen PIC's.

Wie schon erwähnt,existieren ja 2 Versionen von der Software, 1x mit 
Microchip DLL und 1x mit HID Treiber.

Wenn ich die Firmware, von der Microchip DLL verwende, geht die I2C auf 
allen 3 Boards zu 100%.

Wenn ichnun die andere HID Version aufspiele, gehen nur noch die 
Original I2C Routinen von Microchip, selbst ein Copy und Past vom 
Original und umbenennen des Funktionsaufrufes geht nicht mehr.

Wenn ich mir dann noch das Disassemblerlisting ansehe, finde ich den 
unterschied schon erheblich.

Also es muss irgendwo in der Firmware liegen. Ich tippe eher auf 
irgendeine Compileranweisung, wodurch der unterschied zustrande kommt.

Achso. Ein angeschlossener PICit Serial analyser, kann auch ohne 
Probleme alles ansprechen.

Wennihr wollt, kannich den Quellcodegerne gerne hochladen.

von Jdelphi (Gast)


Angehängte Dateien:

Lesenswert?

Sobald oben bugy definiert wird, Fängt der Compiler an, seine „feature“ 
zu zeigen.

Im ersten Durchlauf, die Zeile kommentiert lassen.
Im Disassembly Listing nach „The next line is translated“ suchen.

Es sollte hier das dabei Herauskommen:

1334:              //  The next line is translated properly.
1335:                  if ( WriteI2C( control ) )    // write 1 byte - 
R/W bit should be 0
  25BE    0EFE     MOVLW 0xfe
  25C0    D88F     RCALL 0x26e0
  25C2    E105     BNZ 0x25ce
  26E0    CFDB     MOVFF 0xfdb, 0xfe6
  26E2    FFE6     NOP
  26E4    EC57     CALL 0x2cae, 0
  26E6    F016     NOP
  26E8    52E5     MOVF 0xfe5, F, ACCESS
  26EA    0900     IORLW 0
  26EC    0012     RETURN 0
1336:                  {
1337:                  StopI2C();

Im zweiten Durchlauf, den Kommentar '//' vor bugy entfernen.
Im Disassembly Listing nach „The next line is translated“ suchen.

Es sollte hier das dabei Herauskommen:

1334:              //  The next line is translated properly.
1335:                  if ( WriteI2C( control ) )    // write 1 byte - 
R/W bit should be 0
  25BE    0EFE     MOVLW 0xfe
  25C0    D8AC     RCALL 0x271a
  25C2    0900     IORLW 0
  25C4    E106     BNZ 0x25d2
1336:                  {
1337:                  StopI2C();


Durch das definieren von Bugy wird am ende, der Inhalt der Funktion 
write_ext_eeprom eingefügt.
Dies sollte aber bei der oben gelisteten Funktion keinen unterschied 
ausmachen. Er dürfte höchstens, den Code an eine andere stelle packen, 
was er aber selbst in dem Fall nicht macht. Der Compiler baut aus meiner 
Sicht einfach nen riesen Mist.

Wieso bewirkt das simple hinzufügen von ein paar I2C Routinen, so einem 
fatalen Fehler an einer anderen stelle.


„It's not a bug, it's a feature „

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.