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