Jump to content
I2Cdevlib Forums

Strange start up behavior with PIC32


Recommended Posts

Hi all, thanks in advance for reading.

I am interfacing the PIC32MX320F128H with the MPU6050 over I2C. For some reason my program hangs when I try to initiate a start condition through I2C using plib. More specifically, when I call I2CGetStatus, the I2C_STATUS never returns I2C_START. Without changing the program on the microcontroller, I can get the program to work by doing a hack I've discovered. I unplug my microcontroller from power, I hold the reset button on the microcontroller, plug in the power, and release the reset button, and then my program runs fine. I get values from my accelerometer and gyroscope on the device. But then after reading from the device, I try to initiate a stop condition with I2CStop, but I get no I2C_STOP condition when I call I2CGetStatus afterwards. So I'm starting to think my original issue is related to my issue I get even when I use my workaround.

 

I'm using the MPU6050 from sparkfun.

https://www.sparkfun.com/products/11028

My schematic is very simple.

VDD - 3.3v from microcontroller

GND - GND from microcontroller

SCL - A5

SDA - A4

VIO - 3.3v from microcontroller

 

I have been looking at the power on procedure as listed on page 23 of 52 on the datasheet.

https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf

 

I have hooked up my VDD and VIO lines to the oscilloscope, and I have looked at both cases when I use my workaround and normal power up, I don't see anything different, so I am very lost.

 

I have successfully been able to interface and use the HMC5883L so I know how I2C works, and I know my I2C library works. But here is my code anyway.

 

main.c

#include "xc.h"
#include <stdio.h>
#include "serial.h"
#include "BOARD.h"
#include "IO_Ports.h"
#include "I2Cpic32.h"
#include <plib.h>

#define SYS_CLOCK 80000000
#define SLV_CLOCK 400000
#define SLV_ADDR 0x68

#define DELAY(x)    for (wait = 0; wait <= x; wait++) {asm("nop");}
#define A_BIT       183000
#define A_LOT       18300000

int wait;

int main(void) {

    int               p_size, id;
    UINT32            actualClock;
    UINT8             packet[10], read_data[14];
    uint8_t           powerManagementReg;
    INT16             AcX, AcY, AcZ, GyX, GyY, GyZ, temp; // temp is temperature
    I2C_7_BIT_ADDRESS slave7BitAddress;

    DELAY(A_BIT);
    BOARD_Init();
    printf("Board initialized\n");
    DELAY(A_LOT);

    actualClock = I2CSetFrequency(I2C1, SYS_CLOCK, SLV_CLOCK);
    if ( abs(actualClock-SLV_CLOCK) > SLV_CLOCK/10 )
        printf("Error: I2C1 clock frequency (%u) error exceeds 10%%.\n", (unsigned)actualClock);
    printf("Clock set: %u\n", actualClock);

    I2CEnable(I2C1, TRUE);
    printf("I2C Enabled\n");
    DELAY(A_LOT);

    I2C_FORMAT_7_BIT_ADDRESS(slave7BitAddress, SLV_ADDR, I2C_WRITE);

    DELAY(A_BIT);
    // wakes up the MPU
    packet[0] = slave7BitAddress.byte;
    packet[1] = 0x6b;
    packet[2] = 0x00;
    p_size = 3;
    send_packet(packet, p_size);

    // gyro config
    packet[1] = 0x1b;
    packet[2] = 0x08;
    send_packet(packet, p_size);

    // sample rate config
    packet[1] = 0x19;
    packet[2] = 0x07;
    send_packet(packet, p_size);

    DELAY(A_LOT);

    for (; {

        I2C_FORMAT_7_BIT_ADDRESS(slave7BitAddress, SLV_ADDR, I2C_WRITE);
        packet[0] = slave7BitAddress.byte;
        packet[1] = 0x3b;
        p_size = 2;
        send_packet(packet, p_size);

        StartTransfer(FALSE);
        I2C_FORMAT_7_BIT_ADDRESS(slave7BitAddress, SLV_ADDR, I2C_READ);
        TransmitOneByte(slave7BitAddress.byte);

        read_data[0]  = read_byte(I2C1); // ACCEL_XOUT[15:8]
        read_data[1]  = read_byte(I2C1); // ACCEL_XOUT[7:0]
        read_data[2]  = read_byte(I2C1); // ACCEL_YOUT[15:8]
        read_data[3]  = read_byte(I2C1); // ACCEL_YOUT[7:0]
        read_data[4]  = read_byte(I2C1); // ACCEL_ZOUT[15:8]
        read_data[5]  = read_byte(I2C1); // ACCEL_ZOUT[7:0]
        read_data[6]  = read_byte(I2C1); // TEMP_OUT[15:8]
        read_data[7]  = read_byte(I2C1); // TEMP_OUT[7:0]
        read_data[8]  = read_byte(I2C1); // GYRO_XOUT[15:8]
        read_data[9]  = read_byte(I2C1); // GYRO_XOUT[7:0]
        read_data[10] = read_byte(I2C1); // GYRO_YOUT[15:8]
        read_data[11] = read_byte(I2C1); // GYRO_YOUT[7:0]
        read_data[12] = read_byte(I2C1); // GYRO_ZOUT[15:8]
        read_data[13] = read_byte(I2C1); // GYRO_ZOUT[7:0]

        AcX  = (read_data[0] << 8)  | read_data[1];
        AcY  = (read_data[2] << 8)  | read_data[3];
        AcZ  = (read_data[4] << 8)  | read_data[5];
        temp = (read_data[6] << 8)  | read_data[7];
        GyX  = (read_data[8] << 8)  | read_data[9];
        GyY  = (read_data[10] << 8) | read_data[11];
        GyZ  = (read_data[12] << 8) | read_data[13];

        printf("AcX: %d\n", AcX);
        printf("AcY: %d\n", AcY);
        printf("AcZ: %d\n", AcZ);
        printf("temp: %d\n", temp);
        printf("GyX: %d\n", GyX);
        printf("GyY: %d\n", GyY);
        printf("GyZ: %d\n", GyZ);

        check_status(I2C1);
        StopTransfer();

        DELAY(A_LOT);
    }
    return 0;
}

I2Cpic32.c

// Standard headers
#include <stdbool.h>
#include <stdint.h>

// Microchip headers
#include <xc.h>
#include <plib.h>

// User headers
#include "I2Cpic32.h"

BOOL ret;
I2C_RESULT res;

BOOL StartTransfer( BOOL restart )
{
    I2C_STATUS  status;

    // Send the Start (or Restart) signal
    if(restart)
    {
        I2CRepeatStart(I2C1);
    }
    else
    {
        // Wait for the bus to be idle, then start the transfer
        while( !I2CBusIsIdle(I2C1) );

        if(I2CStart(I2C1) != I2C_SUCCESS)
        {
            printf("Error: Bus collision during transfer Start\n");
            return FALSE;
        }
    }

    // Wait for the signal to complete
    do
    {
        status = I2CGetStatus(I2C1);

    } while ( !(status & I2C_START) );

    return TRUE;
}

BOOL TransmitOneByte( UINT8 data )
{
    // Wait for the transmitter to be ready
    while(!I2CTransmitterIsReady(I2C1));

    // Transmit the byte
    if(I2CSendByte(I2C1, data) == I2C_MASTER_BUS_COLLISION)
    {
        printf("Error: I2C Master Bus Collision\n");
        return FALSE;
    }

    // Wait for the transmission to finish
    while(!I2CTransmissionHasCompleted(I2C1));

    return TRUE;
}

void StopTransfer( void )
{
    I2C_STATUS  status;

    // Send the Stop signal
    I2CStop(I2C1);

    // Wait for the signal to complete
    do
    {
        status = I2CGetStatus(I2C1);
        printf("asuh\n");

    } while ( !(status & I2C_STOP) );
}

void check_status(I2C_MODULE id) {

    I2C_STATUS stat = I2CGetStatus(id);
    if (stat&I2C_TRANSMITTER_FULL)
        printf("check_status: I2C_TRANSMITTER_FULL\n");
    if (stat&I2C_DATA_AVAILABLE)
        printf("check_status: I2C_DATA_AVAILABLE\n");
    if (stat&I2C_SLAVE_READ)
        printf("check_status: I2C_SLAVE_READ\n");
    if (stat&I2C_START)
        printf("check_status: I2C_START\n");
    if (stat&I2C_STOP)
        printf("check_status: I2C_STOP\n");
    if (stat&I2C_SLAVE_DATA)
        printf("check_status: I2C_SLAVE_DATA\n");
    if (stat&I2C_RECEIVER_OVERFLOW)
        printf("check_status: I2C_RECEIVER_OVERFLOW\n");
    if (stat&I2C_TRANSMITTER_OVERFLOW)
        printf("check_status: I2C_TRANSMITTER_OVERFLOW\n");
    if (stat&I2C_10BIT_ADDRESS)
        printf("check_status: I2C_10BIT_ADDRESS\n");
    if (stat&I2C_GENERAL_CALL)
        printf("check_status: I2C_GENERAL_CALL\n");
    if (stat&I2C_ARBITRATION_LOSS)
        printf("check_status: I2C_ARBITRATION_LOSS\n");
    if (stat&I2C_TRANSMITTER_BUSY)
        printf("check_status: I2C_TRANSMITTER_BUSY\n");
    if (stat&I2C_BYTE_ACKNOWLEDGED)
        printf("check_status: I2C_BYTE_ACKNOWLEDGED\n");
}

BYTE read_byte(I2C_MODULE id) {

    BYTE val;

    ret = I2CReceiverEnable(I2C1, TRUE);
    //printf("I2CReceiverEnable(I2C1, TRUE): %d\n", ret);
    while(!(ret = I2CReceivedDataIsAvailable(I2C1)));
    ret = I2CReceivedDataIsAvailable(I2C1);
    //printf("I2CReceivedDataIsAvailable(I2C1): %d\n", ret);
    I2CAcknowledgeByte(I2C1, TRUE);
    val = I2CGetByte(id);
    //printf("val: %x\n", val);
    while(!(ret = I2CAcknowledgeHasCompleted(I2C1)));
    //printf("I2CAcknowledgeHasCompleted(I2C1): %d\n", ret);

    return val;
}

void send_packet(UINT8 data[], int size) {

    int i;

    // Start transfer
    ret = StartTransfer(FALSE);
    //printf("StartTransfer(FALSE): %d\n", ret);

    for (i = 0; i < size; i++) {

        ret = TransmitOneByte(data[i]);
        //printf("TransmitOneByte(%x): %d\n", data[i], ret);
        ret = I2CByteWasAcknowledged(I2C1);
        //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);
    }

    // Stop transfer
    StopTransfer();
}

uint8_t I2C_ReadReg(uint8_t address, uint8_t reg) {

    uint8_t val;

    printf("asuh\n");
    StartTransfer(FALSE);
    ret = TransmitOneByte(address << 1);
    printf("TransmitOneByte(%x): %d\n", (address << 1), ret);
    ret = I2CByteWasAcknowledged(I2C1);
    printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);
    ret = TransmitOneByte(reg);
    printf("TransmitOneByte(%x): %d\n", reg, ret);
    ret = I2CByteWasAcknowledged(I2C1);
    printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);

    StartTransfer(TRUE);
    ret = TransmitOneByte((address << 1) + 1);
    printf("TransmitOneByte(%x): %d\n", ((address << 1) + 1), ret);

    ret = I2CReceiverEnable(I2C1, TRUE);
    printf("I2CReceiverEnable(I2C1, TRUE): %d\n", ret);
    while(!(ret = I2CReceivedDataIsAvailable(I2C1)));
    ret = I2CReceivedDataIsAvailable(I2C1);
    val = I2CGetByte(I2C1);
    printf("val: %x\n", val);
    StopTransfer();

    return val;
}

int16_t I2C_ReadReg16(uint8_t address, uint8_t reg) {

    int16_t val;

    StartTransfer(FALSE);
    ret = TransmitOneByte(address << 1);
    printf("TransmitOneByte(%x): %d\n", (address << 1), ret);
    ret = I2CByteWasAcknowledged(I2C1);
    //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);
    ret = TransmitOneByte(reg);
    printf("TransmitOneByte(%x): %d\n", reg, ret);
    ret = I2CByteWasAcknowledged(I2C1);
    //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);

    StartTransfer(TRUE);
    ret = TransmitOneByte((address << 1) + 1);
    printf("TransmitOneByte(%x): %d\n", ((address << 1) + 1), ret);

    ret = I2CReceiverEnable(I2C1, TRUE);
    //printf("I2CReceiverEnable(I2C1, TRUE): %d\n", ret);
    while(!(ret = I2CReceivedDataIsAvailable(I2C1)));
    ret = I2CReceivedDataIsAvailable(I2C1);
    val = I2CGetByte(I2C1) << 8;
    ret = I2CReceiverEnable(I2C1, TRUE);
    //printf("I2CReceiverEnable(I2C1, TRUE): %d\n", ret);
    while(!(ret = I2CReceivedDataIsAvailable(I2C1)));
    ret = I2CReceivedDataIsAvailable(I2C1);
    val |= I2CGetByte(I2C1);
    
    printf("val: %x\n", val);
    StopTransfer();

    return val;
}

void I2C_WriteReg(UINT8 address, UINT8 reg, UINT8 val) {

    // Start transfer
    ret = StartTransfer(FALSE);
    //printf("StartTransfer(FALSE): %d\n", ret);

    ret = TransmitOneByte(address);
    //printf("TransmitOneByte(%x): %d\n", address, ret);
    ret = I2CByteWasAcknowledged(I2C1);
    //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);

    ret = TransmitOneByte(reg);
    //printf("TransmitOneByte(%x): %d\n", reg, ret);
    ret = I2CByteWasAcknowledged(I2C1);
    //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);

    ret = TransmitOneByte(val);
    //printf("TransmitOneByte(%x): %d\n", val, ret);
    ret = I2CByteWasAcknowledged(I2C1);
    //printf("I2CByteWasAcknowledged(I2C1): %d\n", ret);

    // Stop transfer
    StopTransfer();
}
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...