I am a noob. I am able to get the TM4C123 working with an IO expander but I am getting frustrated trying to get this compass working. With this code, I get back zeros. Is there anyone with some experience with this sensor that can give me a nudge in the right direction.
I have 4.7K resistors on sda/scl
here is the datasheet: http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf
Thank you !
#include <stdint.h>
#include "PLL.h"
#include "TM4C123GH6PM.h"
uint8_t rc;
__asm void Delay(unsigned long ulCount)
{
subs r0, #1
bne Delay
bx lr
}
// ************************************************************
// (1<<0) run
// (1<<1) start
// (1<<2) stop
// (1<<3) ack
// ************************************************************
#define run_start_stop 0x7
#define run_start_ack 0xB
#define run_ack 0x9
#define run_stop_ack 0xD
#define run_start 0x3
#define run_stop 0x5
void setSlaveAddress(uint8_t slaveAddress){
// ************************************************************
// setSlaveAddress(uint8_t slaveAddress)
//
// MSA = Master Slave Address
// ************************************************************
I2C1_MSA_R = (slaveAddress<<1);
}
void setRW(uint8_t mode){
// ************************************************************
// setRW(uint8_t mode)
//
// ************************************************************
if(mode==0)
{
I2C1_MSA_R &= ~(1<<0); // Writing - Clear the bit
}else{
I2C1_MSA_R |= (1<<0); // Revieving - Set the bit
}
}
// ************************************************************
// checkMCS
// ************************************************************
void checkMCS()
{
rc = I2C1_MCS_R;
if((rc & (1<<1)) != 0){
if((rc & (1<<4)) != 0){
rc = 99; // controller lost arbitration
}else if((rc & (1<<3)) != 0){
rc = 98; // The transmitted data was not acknowledged.
}else if((rc & (1<<2)) != 0){
rc = 97; // The transmitted address was not acknowledged.
}else if((rc & (1<<1)) != 0){
rc = 96; // An error occurred on the last operation.
}else{
I2C1_MCS_R = (1<<2); // send stop bit
while((I2C1_MCR_R & (1<<0)) != 0); // Wait for not busy
}
}
}
// ************************************************************
// writeByte( uint8_t dataByte, uint8_t conditions )
// ************************************************************
void writeByte( uint8_t dataByte, uint8_t conditions )
{
I2C1_MDR_R = dataByte; // Set the data
I2C1_MCS_R = conditions; // run, start, etc
while((I2C1_MCS_R & (1<<0)) != 0); // Wait for not busy
checkMCS();
}
// ************************************************************
// readByte()
// ************************************************************
uint8_t readByte(){
int retryCounter = 1;
do{
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for I2C ready
// I2C1_MSA_R = (0x3D<<1)&0xFE; // MSA[7:1] is slave address
I2C1_MSA_R |= 0x01; // MSA[0] is 1 for receive
I2C1_MCS_R = run_start_stop;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
checkMCS();
retryCounter = retryCounter + 1; // increment retry counter
} // repeat if error
while(((I2C1_MCS_R&(I2C_MCS_ADRACK|I2C_MCS_ERROR)) != 0) && (retryCounter <= 100));
return (I2C1_MDR_R&0xFF); // usually returns 0xFF on error
}
uint16_t x, y, z;
// ************************************************************
// read2Bytes()
//
// (1<<0) run
// (1<<1) start
// (1<<2) stop
// (1<<3) ack
// ************************************************************
uint16_t read2Bytes(){
uint8_t data1,data2;
int retryCounter = 1;
do{
data1=0xAB;
data2=0xAB;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for I2C ready
I2C1_MCS_R = run_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
checkMCS();
data1 = (I2C1_MDR_R); // MSB data sent first
I2C1_MCS_R = run_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
data2 = (I2C1_MDR_R); // LSB data sent last
x = (data1<<8)+data2;
//
// y
//
data1=0xAB;
data2=0xAB;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for I2C ready
I2C1_MCS_R = run_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
data1 = (I2C1_MDR_R&0xFF); // MSB data sent first
I2C1_MCS_R = run_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
data2 = (I2C1_MDR_R&0xFF); // LSB data sent last
y = (data1<<8)+data2;
//
// z
//
data1=0xAB;
data2=0xAB;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for I2C ready
I2C1_MCS_R = run_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
data1 = (I2C1_MDR_R&0xFF); // MSB data sent first
I2C1_MCS_R = run_stop_ack;
while(I2C1_MCS_R&I2C_MCS_BUSY){}; // wait for transmission done
data2 = (I2C1_MDR_R&0xFF); // LSB data sent last
z = (data1<<8)+data2;
retryCounter = retryCounter + 1; // increment retry counter
} // repeat if error
while(((I2C1_MCS_R&(I2C_MCS_ADRACK|I2C_MCS_ERROR)) != 0) && (retryCounter <= 100));
return (data1<<8)+data2; // usually returns 0xFFFF on error
}
void GPIO_I2C1_Init(){
// ***********************************************************************
// I2C_Init()
//
// PA6-SCL, PA7-SDA
// ***********************************************************************
SYSCTL_RCGCI2C_R = (1<<1); // Enable the I2C clock using I2C1
SYSCTL_RCGCGPIO_R = (1<<0); // Enable clock on PortA
GPIO_PORTA_AFSEL_R = (1<<6)|(1<<7); // Alternate function Select
GPIO_PORTA_DEN_R = (1<<6)|(1<<7); // Digital Enable
GPIO_PORTA_ODR_R = (1<<7); // Enable open drain (SDA) pin.
GPIO_PORTA_PCTL_R = (3<<28)|(3<<24); // Configure PCM Fields
I2C1_MCR_R = (1<<4); // Identify as Master
I2C1_MTPR_R = (7<<0); // Set the clock speed.
}
uint16_t msb_x, msb_y;
int main(void){
// ***********************************************************************
// main()
//
// (1<<4) == Move a 1 into position 4
// 0x1E 0x3C 0x3D
// ***********************************************************************
PLL_Init();
GPIO_I2C1_Init();
setSlaveAddress(0x1E); // write address
setRW(0); // write
// (8-average, 15 Hz default, normal measurement)
writeByte(0x3C,run_ack);
writeByte(0x00,run_ack);
writeByte(0x70,run_stop_ack);
// (Gain=5, or any other desired gain)
writeByte(0x3C,run_ack);
writeByte(0x01,run_ack);
writeByte(0xA0,run_stop_ack);
// (Continuous-measurement mode)
writeByte(0x3C,run_ack);
writeByte(0x02,run_ack);
writeByte(0x00,run_stop_ack);
Delay(10000);
while(1)
{
writeByte(0x3D,run_ack);
writeByte(0x06,run_stop_ack);
setRW(1);
read2Bytes();
setRW(0);
writeByte(0x3C,run_ack);
writeByte(0x03,run_stop_ack);
}
}