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
}
}