Forum: Mikrocontroller und Digitale Elektronik I2C Probleme mit PIC32 MX250F128B - Master Bus Collision


von WernerPrbk (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

zuerst mal mein Setup:
- ChipKit DP32 mit PIC32MX250F128B @ 40MHz
- AudioProto Board von MikroE mit WM8731 Chip
- PicKit3
- MPLAB X v2.26 in Linux
- XC32 Compiler v1.33, keine Optimierung

Ich habe Probleme mit dem I2C Interface beim PIC32MX 250F128B.
Der PIC ist Master und der WM8731 Audio Codec ist der Slave (Addresse 
0x1A). Pull-Ups(1k) an SDA und SCL sind vorhanden. Keine weiteren 
Devices am Bus.

Wenn ich Daten zum Slave übertrage, wird das erste Byte (Adresse + 
Write-Bit) mit einem ACK bestätigt, aber dann hört das I2C Peripheral 
auf zu senden und ich erhalte eine Master-Bus-Collision Error.
Ich habe es mit verschiedenen Baudraten (1kHz - 400kHz) versucht, immer 
das selbe Ergebnis.

Ich habe auch eine Bit-Bang Implementierung getestet, diese funktioniert 
einwandfrei. Also grundsätzlich sollte es funktionieren.

Ich habe beide Varianten mit einem Logic-Analyzer aufgezeichnet und als 
Anhang eingefügt.
Die gesendeten Daten sind 0x34, 0x1E und 0x00.
Außerdem habe ich die Signale mit einem Oszi überprüft ob sie 
verschliffen werden oder ähnliches. Die Signalverläufe sind aber OK.

Hier ist der Relevante Code meines Projektes:
1
// I2C Interface
2
#define WM8731_I2C_MODULE I2C1
3
#define WM8731_I2C_BAUDRATE 100000 // 100 kHz
4
#define WM8731_I2C_ADDRESS 0x1A      // -> 0x34 for Write
5
6
void initWM8731()
7
{
8
     // I2C pins as input
9
    TRISBbits.TRISB8 = 1;
10
    TRISBbits.TRISB9 = 1;
11
12
    // Setup I2C interface
13
    I2CConfigure(WM8731_I2C_MODULE, 0);
14
    I2CSetFrequency(WM8731_I2C_MODULE, GetPeripheralClock(), WM8731_I2C_BAUDRATE);
15
}
16
 
17
// This code is adapted from Microchip Audio Accessory Board
18
static bool WM8731SendReg(WM8731_REGISTER reg, uint16_t cmd)
19
{
20
    // register address is 7 bit, command is 9 bit
21
    reg <<= 1;
22
    reg |= ((cmd & 0x0100) >> 8);
23
    cmd &= 0xFF;
24
25
    I2CEnable(WM8731_I2C_MODULE, true);
26
    while(I2CBusIsIdle(WM8731_I2C_MODULE) == false);
27
28
    if(I2CStart(WM8731_I2C_MODULE) != I2C_SUCCESS)
29
    {
30
             I2CStop(WM8731_I2C_MODULE);
31
             while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
32
             I2CEnable(WM8731_I2C_MODULE, false);
33
             return false;
34
    }
35
    while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_START));
36
37
    if(I2CSendByte(WM8731_I2C_MODULE, (WM8731_I2C_ADDRESS << 1)) != I2C_SUCCESS)
38
    {
39
            I2CStop(WM8731_I2C_MODULE);
40
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
41
            I2CEnable(WM8731_I2C_MODULE, false);
42
            return false;
43
    }
44
    while(!I2CTransmissionHasCompleted(WM8731_I2C_MODULE));
45
46
    if(I2CByteWasAcknowledged(WM8731_I2C_MODULE) == false)
47
    {
48
            I2CStop(WM8731_I2C_MODULE);
49
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
50
            I2CEnable(WM8731_I2C_MODULE, false);
51
            return false;
52
    }
53
    while (!I2CBusIsIdle(WM8731_I2C_MODULE));
54
55
 //-----------------------------------------------------------------------
56
 // MAYBE HERE IS THE PROBLEM
57
 // because this byte isn't transmitted (see logic analyzer screenshot)
58
 //-----------------------------------------------------------------------
59
    if(I2CSendByte(WM8731_I2C_MODULE, reg) != I2C_SUCCESS)
60
    {
61
            I2CStop(WM8731_I2C_MODULE);
62
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
63
            I2CEnable(WM8731_I2C_MODULE, false);
64
            return false;
65
    }
66
    while(!I2CTransmissionHasCompleted(WM8731_I2C_MODULE));
67
68
    if(I2CByteWasAcknowledged(WM8731_I2C_MODULE) == false)
69
    {
70
            I2CStop(WM8731_I2C_MODULE);
71
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
72
            I2CEnable(WM8731_I2C_MODULE, false);
73
            return false;
74
    }
75
    while (!I2CBusIsIdle(WM8731_I2C_MODULE));
76
77
    if(I2CSendByte(WM8731_I2C_MODULE, cmd) != I2C_SUCCESS)
78
    {
79
//-----------------------------------------------------------------------
80
// HERE I GET THE "I2C_MASTER_BUS_COLLISION" ERROR         
81
//-----------------------------------------------------------------------
82
            I2CStop(WM8731_I2C_MODULE);
83
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
84
            I2CEnable(WM8731_I2C_MODULE, false);
85
            return false;
86
    }
87
88
    while(!I2CTransmissionHasCompleted(WM8731_I2C_MODULE));
89
90
    if(I2CByteWasAcknowledged(WM8731_I2C_MODULE) == false)
91
    {
92
            I2CStop(WM8731_I2C_MODULE);
93
            while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
94
            I2CEnable(WM8731_I2C_MODULE, false);
95
            return false;
96
    }
97
98
    while (!I2CBusIsIdle(WM8731_I2C_MODULE));
99
    I2CStop(WM8731_I2C_MODULE);
100
    while(!(I2CGetStatus(WM8731_I2C_MODULE) & I2C_STOP));
101
    I2CEnable(WM8731_I2C_MODULE, false);
102
    return true;
103
}


Die Configuration-Bits:
1
//* Oscillator Settings
2
#pragma config FNOSC = PRIPLL // Oscillator selection
3
#pragma config POSCMOD = XT // Primary oscillator mode
4
#pragma config FPLLIDIV = DIV_2 // PLL input divider
5
#pragma config FPLLMUL = MUL_20 // PLL multiplier
6
#pragma config FPLLODIV = DIV_2 // PLL output divider
7
#pragma config FPBDIV = DIV_1 // Peripheral bus clock divider
8
#pragma config FSOSCEN = OFF // Secondary oscillator enable
9
10
//* Clock control settings
11
#pragma config IESO = OFF // Internal/external clock switchover
12
#pragma config FCKSM = CSECME // Clock switching (CSx)/Clock monitor (CMx)
13
#pragma config OSCIOFNC = OFF // Clock output on OSCO pin enable
14
15
//* USB Settings
16
#pragma config UPLLEN = ON // USB PLL enable
17
#pragma config UPLLIDIV = DIV_2 // USB PLL input divider
18
#pragma config FVBUSONIO = OFF // Make VBUSON a GPIO pin
19
#pragma config FUSBIDIO = OFF // Controlled by port function
20
21
//* Other Peripheral Device settings
22
#pragma config FWDTEN = OFF // Watchdog timer enable
23
#pragma config WDTPS = PS1024 // Watchdog timer postscaler
24
#pragma config WINDIS = OFF
25
#pragma config JTAGEN = OFF // JTAG port disabled
26
27
//* Code Protection settings
28
#pragma config CP = OFF // Code protection
29
#pragma config BWP = OFF // Boot flash write protect
30
#pragma config PWP = OFF // Program flash write protect
31
32
//* Debug settings
33
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select
34
35
//* Reconfiguration
36
#pragma config PMDL1WAY = ON // Disallow multiple reconfigurations
37
#pragma config IOL1WAY = ON // Disallow multiple reconfigurations



Links zu den Devices:

ChipKit DP32:
https://digilentinc.com/Data/Products/CHIPKIT-DP32/chipKIT%20DP32_sch.pdf
https://digilentinc.com/Data/Products/CHIPKIT-DP32/chipKIT%20DP32_rm.pdf

WM8731 Datasheet:
http://www.rockbox.org/wiki/pub/Main/DataSheets/WM8731_8731L.pdf

MikroE Audio Proto:
http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/


Ich weiß, dass sich hier eher die AVR Leute rumtreiben, aber vielleicht 
hat ja trotzdem wer eine Idee woran es liegen könnte ;)

lg

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.