Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Problem with I2C at PIC32
12-03-2012, 05:23 PM,
#1
Problem with I2C at PIC32

Hi! I post the same problem at Syntax & Programs, but I think that this section is more for it.

I am working with Pinguino-PIC32 board (rev.B) using the pinguino IDE X2 revision 293 for windows 7.
I would use the I2C bus for comunicate the pinguino board with some drivers YGE 30i for brushless motors. The problem is that when I would send the speed (I2C.send), the program doesn't run and waits infinitely.
I am using the 3.3v for Vdd and a 2K2 resistors for pull up.
The code I am using, more simply than the code of the other post, is this:

#define I2C_MAX 120 // Maximum value of the speed reference
#define I2C_LFT 0x54 // Address of left driver

void setup()
{
pinMode(D2,INPUT);
I2C.init(I2C1,I2C_MASTER_MODE,I2C_SLEW_ON); //I2C_SLEW_ON alta velocidad 40kHz
}

void loop()
{
while(digitalRead(D2));
CDC.println("Sending");
//I2C.send(0x54,80);
I2C.sendID(0x54,0); //0 write, 1 read
I2C.writechar(80);
CDC.println("Sent");
}

Thanks so much.
Reply
19-03-2012, 11:28 PM,
#2
RE: Problem with I2C at PIC32
I'm finding the same problem. Have you found the solution?
Reply
20-03-2012, 09:27 PM,
#3
RE: Problem with I2C at PIC32
Hello, I also have problems with the I2C library. I have used the PICkit 2 as Logic analyzer, and see the clock instead of going at 100 kHz, goes at about 8 kHz (attached picture).


.bmp   250khz.bmp (Size: 5.95 KB / Downloads: 28)

Try to change all the values of I2C1BRG in the /PINGUINO/pinguinoX.2rev305/p32/include/pinguino/core/i2c.c file, but still the same problem.

Thank you for some help!

I am using:
PIC32_Pinguino_OTG board
Ubuntu 10.10
Pinguino x.2 rev 305
Reply
22-03-2012, 12:31 AM,
#4
RE: Problem with I2C at PIC32
I have got I2C working on a Pinguino-OTG PIC32MX440 with a BMP085 barometric sensor.

I used a Saleae Logic analyzer to check the timings, gradually getting one byte at a time to work. This is a fantastic device - everyone should have one!
   

There is some redundant checking in the sequence and no timeout. I'm still testing to get the cleanest routine. The BMP085 seems to get stuck sometimes if the sequence is wrong, requiring a power on reset to regain communication. So I suggest that the BMP085 XCLR pin is used to ensure that the device is in a known state.

The BRG value is hard coded at the moment for 100kHz. I haven't worked out yet, how to calculate the correct value.

I2C1 setup:
Code:
    u32 pbclk = GetPeripheralClock();
    I2C1CON |= (1 << 15);
    // 1 = Slew rate control disabled for Standard Speed mode (100 kHz); also disabled for 1 MHz mode
    I2C1CONbits.DISSLW = 1;    
    //I2C1BRG = (pbclk / (2 * 10)) - 2;    WRONG!
    I2C1BRG = 196;    
    //IntSetVectorPriority(INT_I2C1_VECTOR,2,2);
    IFS0bits.I2C1MIF = 0;
    IFS0bits.I2C1SIF = 0;
    IFS0bits.I2C1BIF = 0;

    IEC0bits.I2C1MIE = 0;
    IEC0bits.I2C1SIE = 0;
    IEC0bits.I2C1BIE = 0;

Read register AA:
Code:
    //start
    I2C1CONbits.SEN = 1;
    while (I2C1CONbits.SEN == 1)
      ;    // wait until start clear
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);                    
    
    //write address
    I2C1TRN = 0xEE; //0x77<<1
    while (I2C1STATbits.TBF == 1)
      ;    // wait until buffer clear
    while (I2C1STATbits.ACKSTAT == 1)
      ;    // wait until buffer clear
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);

    //write register to read
    I2C1TRN = 0xAA;
    while (I2C1STATbits.TBF == 1)
      ;    // wait until buffer clear
    while (I2C1STATbits.ACKSTAT == 1)
      ;    // wait until buffer clear
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);
                        
    I2C1CONbits.RSEN=1;
    while (I2C1CONbits.RSEN == 1)
      ;    // wait for restart
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);
    
    //read BMP085
    I2C1TRN = 0xEF; //0x77<<1
    while (I2C1STATbits.TBF == 1)
      ;    // wait until buffer clear
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);

    //read byte 1
    I2C1CONbits.RCEN = 1;
    while (I2C1CONbits.RCEN == 1)
      ;    // wait until char in buffer
    b = I2C1RCV;
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);                
    
    //Master ACK
    I2C1CONbits.ACKDT = 0;
    I2C1CONbits.ACKEN = 1;
    while (I2C1CONbits.ACKEN == 1)
       ;                        

    //read byte 2
    I2C1CONbits.RCEN = 1;
    while (I2C1CONbits.RCEN == 1)
      ;    // wait until char in buffer
    b = I2C1RCV;
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);                
    //Master ACK
    I2C1CONbits.ACKDT = 0;
    I2C1CONbits.ACKEN = 1;
    while (I2C1CONbits.ACKEN == 1)
       ;    
      
    //read byte 3
    I2C1CONbits.RCEN = 1;
    while (I2C1CONbits.RCEN == 1)
      ;    // wait until char in buffer
    b = I2C1RCV;
    while (IFS0bits.I2C1MIF==0)
       ;
    IFS0bits.I2C1MIF = 0;
    //Delayus(20);                

    //Master NACK
    I2C1CONbits.ACKDT = 1;
    I2C1CONbits.ACKEN = 1;
    while (I2C1CONbits.ACKEN == 1)
       ;        
    //stop                   
    I2C1CONbits.PEN=1;
    while (I2C1CONbits.PEN == 1)
      ;    // wait until stop clear

Reply
22-03-2012, 12:05 PM,
#5
RE: Problem with I2C at PIC32
I'm getting consistent results now with a BMP085 and a LIS331.
I'm still trying to find the best place for a timeout, so that the read and write functions don't get stuck.

Some PIC32MX flag reads seem to break my functions. I don't know why.
For example ...
To recognize a data receive complete, there are the RBF, I2C1MIF, and RCEN bits. Some seem to work, others don't. Or perhaps it's a combination of reads that don't work. More testing ...
Reply
22-03-2012, 11:43 PM,
#6
RE: Problem with I2C at PIC32
Thank you!

The I2C1BRG = 196; fixes the clock to 100kHz. Now it looks like transmitting OK to the WM8731, but need to check in depth.
Reply
23-03-2012, 10:21 AM,
#7
RE: Problem with I2C at PIC32
Hi RLmonitor & gfrforte,
Now that you guys are our I2C specialists, could you have a look at pinguino i2c library and eventually fix and/or complete it Wink (slave mode for ex.) ?
It would be also great to have some simple examples how to use Pinguino with WM8731, BMP085 and LIS331. Do you think a dedicated library would be necessary ?
I don't have such modules but if you need some help how to make a pinguino library or keywords file, I'd gladly help you.
It is easier to complain than it is to do, but it is better to do than it is to complain.
Reply
23-03-2012, 04:36 PM,
#8
RE: Problem with I2C at PIC32
This is my code for the WM8731, but still not work (the same I have in mikroC 32 and there works) A WM8731 library would be very useful, will learn how to do it (but first need to get I2C and SPI fully functional Wink )

#include <i2c.c>
#include <spi.c>

#define DACLRC 7
#define ADCLRC 9
#define BCLK 13
#define MISO_ADCDAT 12
#define CSB 10

u8 datos[8];
u8 i;

// const u8 WM8731_address = 0x34;

//--------------- Writes data to WM8731 - single location
void WmMasterWrite(u8 wAddr, u16 wData) { // p46
u8 wDataS;
wAddr = wAddr << 1;

// wAddr.B0 = wData.B9;
if (wData > 0x00FF)
{
wAddr = wAddr + 1;
}
wDataS = (u8)(wData & 0xff);


// (0x1A<<1)|0) = 0x34
I2C_sendID(I2C1, 0x34, I2C_WRITE); // send byte via I2C (command )
I2C_writechar(I2C1, wAddr); // send byte (address location)
I2C_writechar(I2C1, wDataS); // send data (data to be written)
I2C_stop(I2C1);
}

void SetupRecPlay() { // p46
// pag 50 WM8731
WmMasterWrite(0x0F, 0x00);
WmMasterWrite(0x00, 0x017); // Left Line In
WmMasterWrite(0x01, 0x017); // Right Line In
WmMasterWrite(0x02, 0x079); // Left Line Out
WmMasterWrite(0x03, 0x079); // Right Line Out
WmMasterWrite(0x04, 0x015); // Analogue Path Control
WmMasterWrite(0x05, 0x001); // Digital Path Control high pass filter enabled
WmMasterWrite(0x06, 0x000); // Power Down Control
WmMasterWrite(0x07, 0x00D); // Digital Audio Interface Format SLAVE MODE
WmMasterWrite(0x08, 0x00C); // 8 KHz
WmMasterWrite(0x09, 0x001); // Active Control, Activate Interface
}

void Setup2() { // p46 bypass input signal to output
// pag 50 WM8731
WmMasterWrite(0x0F, 0x00);
WmMasterWrite(0x04, 0x00A); // Analogue Path Control
WmMasterWrite(0x06, 0x00E); // Power Down Control
WmMasterWrite(0x09, 0x001); // Active Control, Activate Interface
}

void adc_MASTER_READ() {
for (i = 0; i < 8; i++) {
if (i == 0) {
digitalWrite(ADCLRC,HIGH);
}
if (i == 4) {
digitalWrite(ADCLRC, LOW);
}
datos[i] = SPI_read();
}
}

void adc_MASTER_PLAY() {
for (i = 0; i < 8; i++) {
if (i == 0) {
digitalWrite(DACLRC, HIGH);
}
if (i == 4) {
digitalWrite(DACLRC, LOW);
}
SPI_write(datos[i]);
}
}

void setup() {
// CHECON = 30;
// AD1PCFG = 0xFFFF;

// ************* Initialize SPI pins ************************
// pinMode(BCLK, OUTPUT);
// digitalWrite(BCLK, LOW);
pinMode(ADCLRC, OUTPUT);
digitalWrite(ADCLRC, LOW);
pinMode(DACLRC, OUTPUT);
digitalWrite(DACLRC, LOW);
// CSB low for ADDRESS = 0x1A
pinMode(CSB, OUTPUT);
digitalWrite(CSB, LOW);
// ************* End Initialize SPI pins *******************

// Initialize the I2C1 module with clock_rate of 100000
I2C_init(I2C1, I2C_MASTER_MODE, I2C_SLEW_OFF);

// WM8731 setup
SetupRecPlay();

//Setup2();
// SPI2_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, 4, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);
SPI_init();
}

void loop() { // Endless loop
adc_MASTER_READ();
adc_MASTER_PLAY();
}
Reply
24-03-2012, 12:09 AM,
#9
RE: Problem with I2C at PIC32
I really recommend that you get one of these http://www.saleae.com/logic
You'll be able to capture the MikroC bit stream and compare with the Pinguino.
The software decodes the bytes, ACK, NACK etc.

I'll tidy up my code. I'm just about to test with t he BMP085 and the LIS331 connected at the same time.
Reply
27-03-2012, 12:38 AM,
#10
RE: Problem with I2C at PIC32
Regis - if you send me some information on the library development, I'll have a look at it. But firstly, I need to get it working properly for a particular job. The BMP085 needs filtering to remove noise and the LIS331 implementation would depend a lot on the application. It has 2 x interrupt pins that can be setup in many ways.

I have both the BMP085 and LIS331 operating on the one bus at 400kHz, slew ON. I have some example files for each device, outputting the data over CDC. I should probably add more comments ...

The BRG calculation should be ...
#define I2C_BUS_KHZ 400
u32 pbclk = GetPeripheralClock();
I2C1BRG = (pbclk / (2*I2C_BUS_KHZ*1000))-2;
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)