This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TM4C123GH6PM: TM4C123GH6PMI / I2C and HMC5883L

Part Number: TM4C123GH6PM

Tool/software: TI C/C++ Compiler

hello everyone i'm trying to get the HMC5883L to work , but my code gets stuck checking if bus is busy at the first occurrence of while(ROM_I2CMasterBusy(I2C1_BASE)); , am i messing something ,please help


#define TARGET_IS_BLIZZARD_RB1
#define PART_TM4C123GH6PM


#include <stdint.h> // ift
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/pin_map.h"
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_i2c.h"

void send_start(int a,int b,int c){
    
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE,0x1E, false);
    
    ROM_I2CMasterDataPut(I2C1_BASE, a);

ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);

while(ROM_I2CMasterBusy(I2C1_BASE));
    
    
    ROM_I2CMasterDataPut(I2C1_BASE, b);

ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

while(ROM_I2CMasterBusy(I2C1_BASE));
    
    
    
    ROM_I2CMasterDataPut(I2C1_BASE, c);
    
ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

while(ROM_I2CMasterBusy(I2C1_BASE));
    
}
void send_start2(int a,int b){
    
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE,0x1E, false);
    
    ROM_I2CMasterDataPut(I2C1_BASE, a);

ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);

while(ROM_I2CMasterBusy(I2C1_BASE));
    
    
    ROM_I2CMasterDataPut(I2C1_BASE, b);
    
ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

while(ROM_I2CMasterBusy(I2C1_BASE));
    
}


void ReadByteArray(int *arr,int cnt);
int data[6]={1,2,3,4,5,6};
int main(void)
{
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
    
    ROM_GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
    
    ROM_I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
    
    //initialization process for “continuous-measurement mode (HMC5883L) Page 18
    
    //(8-average, 15 Hz default, normal measurement)
    send_start(0x3C,0x00,0x70);
    //(Gain=5, or any other desired gain)
    send_start(0x3C,0x01,0xA0);
  //(Continuous-measurement mode)
    send_start(0x3C,0x02,0x00);
    
    ROM_SysCtlDelay(5500000); // writing time
    
    
    
    while(1){
        send_start2(0x3D,0x03);// 1
        ReadByteArray(data,1);
        
    }
    
}


void ReadByteArray(int *arr,int cnt){
int i=1;
    
    
    
ROM_I2CMasterSlaveAddrSet(I2C1_BASE, 0x1E, false);


ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

while(ROM_I2CMasterBusy(I2C1_BASE));

arr[0] = ROM_I2CMasterDataGet(I2C1_BASE); //test
    

for (i=1;i<cnt;i++)
{
ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
//
while(ROM_I2CMasterBusy(I2C1_BASE));

arr[i] = ROM_I2CMasterDataGet(I2C1_BASE); //Receive
}

ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//
while(ROM_I2CMasterBusy(I2C1_BASE));


    
}


  • Before analyzing your code, have you checked the I2C bus with a scope. Please verify that you have proper SCL and SDA signals and see if the slave is sending an acknowledge. If not, verify you have pullups on SCL and SDA. If you are unsure of what the I2C bus should look like, this reference may help:
    www.ti.com/.../slva704.pdf
  • Along w/Vendor Bob's sound advice - it proves (always) wise to follow "KISS" - which directs you to (start) w/a far simpler I2C Slave.    (such as a small capacity, I2C based, EEProm Device ... which may also be employed in your project(s).)      Another key advantage - afforded by "KISS" - you, "Build your Understanding" - while  "Adding a new capability"  to your "bag of tricks."

    Device you've chosen - demands "multi-byte transfers" - which  "places significantly higher demands"  upon your I2C mastery & coding...    

    It proves "fine" to "END" w/so complex a device (after you've built your experience & confidence) - yet  rarely "wise" - to "START" with a device of such (complexity)...

  • thanks for your reply ,
    i did start with 24c04 eeprom , and based on what i learnt i tried to get the compus to work which failed somehow although i was using almost the same code (just changed the addresses or so)

    after some search i got it to work by replacing my function send_start2 with i2Csend but by comparing both functions i still can't figure out why would it fail in send_start2

    can you help me ?



    #define TARGET_IS_BLIZZARD_RB1
    #define PART_TM4C123GH6PM

    #include <stdarg.h>
    #include <stdint.h> // ift
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "inc/hw_i2c.h"
    #include "driverlib/i2c.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/pin_map.h"
    #include "inc/tm4c123gh6pm.h"
    #include "inc/hw_i2c.h"

    void send_start(int a,int b,int c){

    ROM_I2CMasterSlaveAddrSet(I2C1_BASE,0x1E, false);

    ROM_I2CMasterDataPut(I2C1_BASE, a);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    while(ROM_I2CMasterBusy(I2C1_BASE));


    ROM_I2CMasterDataPut(I2C1_BASE, b);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    while(ROM_I2CMasterBusy(I2C1_BASE));



    ROM_I2CMasterDataPut(I2C1_BASE, c);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    while(ROM_I2CMasterBusy(I2C1_BASE));

    }
    void send_start2(int a,int b){

    ROM_I2CMasterSlaveAddrSet(I2C1_BASE,0x1E, false);

    ROM_I2CMasterDataPut(I2C1_BASE, a);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    while(ROM_I2CMasterBusy(I2C1_BASE));


    ROM_I2CMasterDataPut(I2C1_BASE, b);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);

    while(ROM_I2CMasterBusy(I2C1_BASE));

    }


    void ReadByteArray(uint32_t *arr,uint8_t cnt);
    void I2CSend(uint8_t slave_addr, uint8_t num_of_args, ...);
    uint32_t data[6]={1,2,3,4,5,6};
    int8_t x,y,z;
    int main(void)
    {
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);
    ROM_GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);

    ROM_I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);

    //HWREG(I2C1_BASE + I2C_1_FIFOCTL) = 80008000;

    //initialization process for “continuous-measurement mode (HMC5883L) Page 18


    I2CSend(0x1E,2,0x02,0x00);






    while(1){
    //I2CSend(0x1E,4,0x3D,0x06,0x3C,0x03);
    I2CSend(0x1E,1,0x03);//TODO: remove this line
    ReadByteArray(data,6);
    x=(data[0]<<8)|data[1];
    y=(data[2]<<8)|data[3];
    z=(data[4]<<8)|data[5];

    ROM_SysCtlDelay(5500000); // writing time
    }

    }


    void ReadByteArray(uint32_t *arr,uint8_t cnt){
    int i=1;


    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, 0x1E, false);

    ROM_I2CMasterDataPut(I2C1_BASE, 0x03); // Addr 0x11

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_SEND);

    while(ROM_I2CMasterBusy(I2C1_BASE));

    //
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, 0x1E, true);

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    while(ROM_I2CMasterBusy(I2C1_BASE));

    arr[0] = ROM_I2CMasterDataGet(I2C1_BASE); //test


    for (i=1;i<cnt;i++)
    {
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    //
    while(ROM_I2CMasterBusy(I2C1_BASE));

    arr[i] = ROM_I2CMasterDataGet(I2C1_BASE); //Receive
    }

    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    //
    while(ROM_I2CMasterBusy(I2C1_BASE));



    }

    void I2CSend(uint8_t slave_addr, uint8_t num_of_args, ...)
    {
    // Tell the master module what address it will place on the bus when
    // communicating with the slave.
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, slave_addr, false);

    //stores list of variable number of arguments
    va_list vargs;

    //specifies the va_list to "open" and the last fixed argument
    //so vargs knows where to start looking
    va_start(vargs, num_of_args);

    //put data to be sent into FIFO
    ROM_I2CMasterDataPut(I2C1_BASE, va_arg(vargs, uint32_t));

    //if there is only one argument, we only need to use the
    //single send I2C function
    if(num_of_args == 1)
    {
    //Initiate send of data from the MCU
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_SEND);

    // Wait until MCU is done transferring.
    while(I2CMasterBusy(I2C1_BASE));

    //"close" variable argument list
    va_end(vargs);
    }

    //otherwise, we start transmission of multiple bytes on the
    //I2C bus
    else
    {
    //Initiate send of data from the MCU
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);

    // Wait until MCU is done transferring.
    while(I2CMasterBusy(I2C1_BASE));

    //send num_of_args-2 pieces of data, using the
    //BURST_SEND_CONT command of the I2C module
    for(uint8_t i = 1; i < (num_of_args - 1); i++)
    {
    //put next piece of data into I2C FIFO
    ROM_I2CMasterDataPut(I2C1_BASE, va_arg(vargs, uint32_t));
    //send next data that was just placed into FIFO
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);

    // Wait until MCU is done transferring.
    while(I2CMasterBusy(I2C1_BASE));
    }

    //put last piece of data into I2C FIFO
    ROM_I2CMasterDataPut(I2C1_BASE, va_arg(vargs, uint32_t));
    //send next data that was just placed into FIFO
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
    // Wait until MCU is done transferring.
    while(I2CMasterBusy(I2C1_BASE));

    //"close" variable args list
    va_end(vargs);
    }
    }
  • You Sir - are among the (very) few - who have "followed "KISS" - and built capability & understanding - via,  "Proceeding by Refinement."     I applaud you for that effort.

    You earlier noted:

    Mohammad El Sherbini said:
    my code gets stuck checking if bus is busy at the first occurrence of while(ROM_I2CMasterBusy(I2C1_BASE));

    You now note that "I2Csend" succeeds - while Send Start2 "fails."        Your code includes  "Send Start" as well as  "Send Start2" -  should "Send Start" remain?

    It proves (very) difficult to clearly recognize where  "I2Csend"  (either) starts or ends - multiple "occurrences" of  "I2Csend" are scattered throughout the code listing...