2

I am trying to communicate to BQ24259 through I2C using PIC16LF1554. The 7th register of the device has a bit which can be used to turn off the battery. I used Mplab's MCC to configure the I2C settings. Using the example code in header files i wrote a similar function.

here is the relevant snippet of the code

    #define RETRY_MAX       100
    #define ON              0x4B   //register 7 toggle 5th bit to turn ON/OFF
    #define OFF             0x6B
    I2C_MESSAGE_STATUS status;

    uint16_t        timeOut;
    uint8_t         writeBuffer[1];                // writeBuffer[0] = 07, writeBuffer[1] = data 01001011b(on) 01101011b(off)
    uint8_t         stat;
    uint16_t        address = (0x6B/2) ;           //Bit shifting to the write, and having '0' for write opertaoin, at MSB

uint8_t bat_fet(uint8_t val){
    writeBuffer[0] = 7;                      //slave's seventh register
    writeBuffer[1] = val;
    timeOut=0;
    while(status != I2C_MESSAGE_FAIL){
        I2C_MasterWrite( writeBuffer,        // address of data to be sent
                         2,                  // number of data bytes
                         address,            // address of the peripheral
                         &status);           // address of status register

        while(status == I2C_MESSAGE_PENDING);

        if(status == I2C_MESSAGE_COMPLETE){
            return 1;
            break;
        }
        if(timeOut == RETRY_MAX){
            return 0;

            break; 
        }
        else
            timeOut++;
    }
    if(status == I2C_MESSAGE_FAIL)
        return 0;

}

but its not working, nothing happens, sometimes the controller just freezes, mostly it continues to work. I have connected an LED to an unused IO pin, and programmed it to turn on whenever the function returns 1, and it turns on. But the battery remains on too.

Similarly, i am trying to use ADC 1 of the pic to check the battery voltage,

here is the code,

uint16_t check_bat_voltage(){

    uint16_t bat_v;

    ADC1_StartConversion(01011); //i am using Channel AN11, but no matter what variation of channel and AN11 i passed, it just wouldn't recognize. so i just pass the 5 bit values of the ADCON1 register.

    while(ADC1_IsConversionDone());

    bat_v = ADC1_GetConversionResult();  

//digital value = [analog voltage / (vref+ - vref-)] * 1024 
 //analog value minimum = 2.5/2, voltage divider network
 //vref+ 5
 //vref- 0
 // 1.25/5 * 1024 = 256
    return bat_v;
}

but again nothing happens. Can anyone please review it? I am just stuck. Thanks.

I can attach screen shots of MCC too, maybe i didnot configure the peripherals right.

P.S. i do initialize both modules in main().

aamir
  • 21
  • 4
  • adc works, i was calculating the values incorrectly. My bad. – aamir Oct 24 '17 at 18:57
  • Are you sure that you need adress with last bit read/write?, Or mcc automatically change it if you will use read or write? – DmO Mar 28 '18 at 08:17

2 Answers2

0

I believe that your problem is that you are forgetting to initialize status to something other than I2C_MESSAGE_FAIL before your loop (I'm assuming that your global stat is a typo - it should be status).

Unless variables are declared persistent using __attribute__((persistent)) (XC16 compiler - not sure about XC8), the startup code will initialize all global variables to zero. Since I'm guessing the constant I2C_MESSAGE_FAIL is non-zero, it means that your loop never executes.

The compiler likely gave you a warning about using a variable before it was initialized.

Try using a do {} while loop instead.

EBlake
  • 735
  • 7
  • 14
  • I am not creative when it comes to naming variables; status and stat are different variables. i initialized status to I2C_MESSAGE_PENDING, but again nothing happens. – aamir Oct 24 '17 at 18:55
  • Ah, I see the declaration for `status`now. Now that initialization is taken care of, perhaps the the issue is configuration of the I2C port. I am not familiar with this particular MPU. Does it have more than one I2C peripheral? Does it use PPC (programmable port configuration)? IMHO, it is useful to not use canned routines because the effort of writing the raw port read/writes leads to a better understanding of the hardware. – EBlake Oct 24 '17 at 23:32
0

maybe its a typo in your declarations? try changing:

uint8_t    writeBuffer[1];

to

uint8_t    writeBuffer[2];

Would recommend scoping the scl and sda lines and checking what is actually sent when the led turns on.

Ron
  • 3
  • 3