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.

TM4C123GH6PM: I2C communication with HMC5883L (3-Axis Digital Compass IC)

Part Number: TM4C123GH6PM

Hello Everyone,

I am trying to read data from HMC5883L. I have tried to establish a communication network according to HMC5883L datasheet but I can not read the data. I would appreciate it if you could go through my code and advise me how I could fix the problem. Thanks in advance for your time.

#include "tm4c123gh6pm.h"

//Global Variables
int i=0;
unsigned long DATA;

//


#define I2C_MCS_ACK             0x00000008  // Data Acknowledge Enable
#define I2C_MCS_DATACK          0x00000008  // Acknowledge Data
#define I2C_MCS_ADRACK          0x00000004  // Acknowledge Address
#define I2C_MCS_STOP            0x00000004  // Generate STOP
#define I2C_MCS_START           0x00000002  // Generate START
#define I2C_MCS_ERROR           0x00000002  // Error
#define I2C_MCS_RUN             0x00000001  // I2C Master Enable
#define I2C_MCS_BUSY            0x00000001  // I2C Busy
#define I2C_MCR_MFE             0x00000010  // I2C Master Function Enable

#define MAXRETRIES              5           // number of receive attempts before giving up

void I2C0_Init(void){
  SYSCTL_RCGCI2C_R |= 0x0001;            // activate I2C0
  SYSCTL_RCGCGPIO_R |= 0x0002;           // activate port B
  while((SYSCTL_PRGPIO_R&0x0002) == 0){};// ready?

  GPIO_PORTB_AFSEL_R |= 0x0C;           // 3) enable alt funct on PB2,3
  GPIO_PORTB_ODR_R |= 0x08;             // 4) enable open drain on PB3 only
  GPIO_PORTB_DEN_R |= 0x0C;             // 5) enable digital I/O on PB2,3
                                        // 6) configure PB2,3 as I2C
  GPIO_PORTB_PCTL_R = (GPIO_PORTB_PCTL_R&0xFFFF00FF)+0x00003300;
  GPIO_PORTB_AMSEL_R &= ~0x0C;          // 7) disable analog functionality on PB2,3
  I2C0_MCR_R = I2C_MCR_MFE;      // 9) master function enable
  I2C0_MTPR_R = 0x07;              // 8) configure for 100 kbps clock
  // 16MHZ*(TPR+1)*20ns => TPR=7
}

void Slave_Address (unsigned long slaveAddress){
	
	I2C1_MSA_R= ((slaveAddress) << 1);
	
}

void EndTransmission (void){
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
  //I2C0_MSA_R &= ~0x01;             // MSA[0] is 0 for send
 // I2C0_MDR_R = data1&0xFF;         // prepare first byte
  I2C0_MCS_R = (0
                        //  & ~I2C_MCS_ACK     // no data ack (no data on send)
														| I2C_MCS_STOP     // generate stop
                        //  | I2C_MCS_START    // no start/restart
                            | I2C_MCS_RUN);    // master enable
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
                                        
}

unsigned long I2C_Send_NO_START ( unsigned long data1){
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
  I2C0_MSA_R &= ~0x01;             // MSA[0] is 0 for send
  I2C0_MDR_R = data1&0xFF;         // prepare first byte
  I2C0_MCS_R = (0
                      // & ~I2C_MCS_ACK     // no data ack (no data on send)
                      // | I2C_MCS_STOP     // no stop
                      // | I2C_MCS_START    // no start/restart
                         | I2C_MCS_RUN);    // master enable
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
                                          // return error bits
  return (I2C0_MCS_R&(I2C_MCS_DATACK|I2C_MCS_ADRACK|I2C_MCS_ERROR));
}


unsigned long I2C_Send_NO_STOP ( unsigned long data1){
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
  I2C0_MSA_R &= ~0x01;             // MSA[0] is 0 for send
  I2C0_MDR_R = data1&0xFF;         // prepare first byte
  I2C0_MCS_R = (0
                    //   & ~I2C_MCS_ACK     // no data ack (no data on send)
                    //   | I2C_MCS_STOP     // generate stop
                         | I2C_MCS_START    // generate start/restart
                         | I2C_MCS_RUN);    // master enable
  while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
                                          // return error bits
  return (I2C0_MCS_R&(I2C_MCS_DATACK|I2C_MCS_ADRACK|I2C_MCS_ERROR));
}

unsigned long I2C_Recv(unsigned long slave){
  int retryCounter = 1;
  do{
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
    I2C0_MSA_R = (slave<<1)&0xFE;    // MSA[7:1] is slave address
    I2C0_MSA_R |= 0x01;              // MSA[0] is 1 for receive
    I2C0_MCS_R = (0
                        // & ~I2C_MCS_ACK     // negative data ack (last byte)
                         | I2C_MCS_STOP     // generate stop
                         | I2C_MCS_START    // generate start/restart
                         | I2C_MCS_RUN);    // master enable
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
    retryCounter = retryCounter + 1;        // increment retry counter
  }                                         // repeat if error
  while(((I2C0_MCS_R&(I2C_MCS_ADRACK|I2C_MCS_ERROR)) != 0) && (retryCounter <= MAXRETRIES));
  return (I2C0_MDR_R&0xFF);          // usually returns 0xFF on error
}


void SystemInit (void){}
	
int main (void){
I2C0_Init();
Slave_Address (0x1E);        // Slave Address is 0x1E according to HMC5883L datasheet

//initialization process for “continuous-measurement mode (HMC5883L) Page 18
   
 //(8-average, 15 Hz default, normal measurement)
	I2C_Send_NO_STOP (0x3C);
	I2C_Send_NO_START (0x00);
	I2C_Send_NO_START (0x70);

 //(Gain=5, or any other desired gain)
	I2C_Send_NO_STOP (0x3C);
	I2C_Send_NO_START (0x01);
	I2C_Send_NO_START (0xA0);

 //(Continuous-measurement mode)
  I2C_Send_NO_STOP  (0x3C);
	I2C_Send_NO_START (0x02);
	I2C_Send_NO_START (0x00);

//Delay
	for ( i =0 ; i< 100000; i++){};
	for ( i =0 ; i< 100000; i++){};

// End Transmission
EndTransmission ();


while (1){

Slave_Address (0x1E);
I2C_Send_NO_STOP (0x3D);		// I2C Address to Read Data according to HMC5883L datasheet page 2
I2C_Send_NO_START (0x03);		// Address location 03 which is X-MSB  
DATA = I2C_Recv(0x1E);			//Reading X-MSB  

}

}

  • #include "tm4c123gh6pm.h"

    //Global Variables
    int i=0;
    unsigned long DATA;

    //


    #define I2C_MCS_ACK 0x00000008 // Data Acknowledge Enable
    #define I2C_MCS_DATACK 0x00000008 // Acknowledge Data
    #define I2C_MCS_ADRACK 0x00000004 // Acknowledge Address
    #define I2C_MCS_STOP 0x00000004 // Generate STOP
    #define I2C_MCS_START 0x00000002 // Generate START
    #define I2C_MCS_ERROR 0x00000002 // Error
    #define I2C_MCS_RUN 0x00000001 // I2C Master Enable
    #define I2C_MCS_BUSY 0x00000001 // I2C Busy
    #define I2C_MCR_MFE 0x00000010 // I2C Master Function Enable

    #define MAXRETRIES 5 // number of receive attempts before giving up

    void I2C0_Init(void){
    SYSCTL_RCGCI2C_R |= 0x0001; // activate I2C0
    SYSCTL_RCGCGPIO_R |= 0x0002; // activate port B
    while((SYSCTL_PRGPIO_R&0x0002) == 0){};// ready?

    GPIO_PORTB_AFSEL_R |= 0x0C; // 3) enable alt funct on PB2,3
    GPIO_PORTB_ODR_R |= 0x08; // 4) enable open drain on PB3 only
    GPIO_PORTB_DEN_R |= 0x0C; // 5) enable digital I/O on PB2,3
    // 6) configure PB2,3 as I2C
    GPIO_PORTB_PCTL_R = (GPIO_PORTB_PCTL_R&0xFFFF00FF)+0x00003300;
    GPIO_PORTB_AMSEL_R &= ~0x0C; // 7) disable analog functionality on PB2,3
    I2C0_MCR_R = I2C_MCR_MFE; // 9) master function enable
    I2C0_MTPR_R = 0x07; // 8) configure for 100 kbps clock
    // 16MHZ*(TPR+1)*20ns => TPR=7
    }

    void Slave_Address (unsigned long slaveAddress){

    I2C1_MSA_R= ((slaveAddress) << 1);

    }

    void EndTransmission (void){
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
    //I2C0_MSA_R &= ~0x01; // MSA[0] is 0 for send
    // I2C0_MDR_R = data1&0xFF; // prepare first byte
    I2C0_MCS_R = (0
    // & ~I2C_MCS_ACK // no data ack (no data on send)
    | I2C_MCS_STOP // generate stop
    // | I2C_MCS_START // no start/restart
    | I2C_MCS_RUN); // master enable
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done

    }

    unsigned long I2C_Send_NO_START ( unsigned long data1){
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
    I2C0_MSA_R &= ~0x01; // MSA[0] is 0 for send
    I2C0_MDR_R = data1&0xFF; // prepare first byte
    I2C0_MCS_R = (0
    // & ~I2C_MCS_ACK // no data ack (no data on send)
    // | I2C_MCS_STOP // no stop
    // | I2C_MCS_START // no start/restart
    | I2C_MCS_RUN); // master enable
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
    // return error bits
    return (I2C0_MCS_R&(I2C_MCS_DATACK|I2C_MCS_ADRACK|I2C_MCS_ERROR));
    }


    unsigned long I2C_Send_NO_STOP ( unsigned long data1){
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
    I2C0_MSA_R &= ~0x01; // MSA[0] is 0 for send
    I2C0_MDR_R = data1&0xFF; // prepare first byte
    I2C0_MCS_R = (0
    // & ~I2C_MCS_ACK // no data ack (no data on send)
    // | I2C_MCS_STOP // generate stop
    | I2C_MCS_START // generate start/restart
    | I2C_MCS_RUN); // master enable
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
    // return error bits
    return (I2C0_MCS_R&(I2C_MCS_DATACK|I2C_MCS_ADRACK|I2C_MCS_ERROR));
    }

    unsigned long I2C_Recv(unsigned long slave){
    int retryCounter = 1;
    do{
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for I2C ready
    I2C0_MSA_R = (slave<<1)&0xFE; // MSA[7:1] is slave address
    I2C0_MSA_R |= 0x01; // MSA[0] is 1 for receive
    I2C0_MCS_R = (0
    // & ~I2C_MCS_ACK // negative data ack (last byte)
    | I2C_MCS_STOP // generate stop
    | I2C_MCS_START // generate start/restart
    | I2C_MCS_RUN); // master enable
    while(I2C0_MCS_R&I2C_MCS_BUSY){};// wait for transmission done
    retryCounter = retryCounter + 1; // increment retry counter
    } // repeat if error
    while(((I2C0_MCS_R&(I2C_MCS_ADRACK|I2C_MCS_ERROR)) != 0) && (retryCounter <= MAXRETRIES));
    return (I2C0_MDR_R&0xFF); // usually returns 0xFF on error
    }


    void SystemInit (void){}

    int main (void){
    I2C0_Init();
    Slave_Address (0x1E); // Slave Address is 0x1E according to HMC5883L datasheet

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

    //(8-average, 15 Hz default, normal measurement)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x00);
    I2C_Send_NO_START (0x70);

    //(Gain=5, or any other desired gain)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x01);
    I2C_Send_NO_START (0xA0);

    //(Continuous-measurement mode)
    I2C_Send_NO_STOP (0x3C);
    I2C_Send_NO_START (0x02);
    I2C_Send_NO_START (0x00);

    //Delay
    for ( i =0 ; i< 100000; i++){};
    for ( i =0 ; i< 100000; i++){};

    // End Transmission
    EndTransmission ();


    while (1){

    Slave_Address (0x1E);
    I2C_Send_NO_STOP (0x3D); // I2C Address to Read Data according to HMC5883L datasheet page 2
    I2C_Send_NO_START (0x03); // Address location 03 which is X-MSB
    DATA = I2C_Recv(0x1E); //Reading X-MSB

    }

    }
  • Hello Ashkan,

    Please avoid using the DRM method to access the slave device. We do not recommend this method as analysis for supporting a debug is tough and error-prone. I would rather suggest using TivaWare APIs before we can best support you.
  • Hi Amit,

    Thanks for your time. I will try to do that as well. Have a good one

  • Hello Ashklan,

    Thank you.