uint8_t u8g_com_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { register uint8_t *ptr = arg_ptr; switch(msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: init_i2c(); //I2C_WrReg(0x80, 0xAE); //I2C_WrReg(0x80, 0x8D); //I2C_WrReg(0x80, 0x14); //I2C_WrReg(0x80, 0xAF); u8g_MicroDelay(); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ if(arg_val == 0){ control = 0; //Send a Command (D/C# pin is low) } else{ control = 0x40; //send data } u8g_10MicroDelay(); break; case U8G_COM_MSG_CHIP_SELECT: break; case U8G_COM_MSG_RESET: break; case U8G_COM_MSG_WRITE_BYTE: I2C_WrReg(control, arg_val); //u8g_i2c_start(0x78); //u8g_i2c_send_byte(arg_val); //u8g_i2c_stop(); u8g_MicroDelay(); break; case U8G_COM_MSG_WRITE_SEQ: case U8G_COM_MSG_WRITE_SEQ_P: while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); I2C_TransferHandling(I2C1, 0x78, 1, I2C_Reload_Mode, I2C_Generate_Start_Write); //Ensure the transmit interrupted flag is set while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET); //Send the address of the register we wish to write to I2C_SendData(I2C1, control); //Ensure that the transfer complete reload flag is Set, essentially a standard //TC flag while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET); I2C_TransferHandling(I2C1, 0x78, arg_val+1, I2C_AutoEnd_Mode, I2C_No_StartStop); //Again, wait until the transmit interrupted flag is set while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET); //Send the value you wish you write to the register while( arg_val > 0 ) { I2C_SendData(I2C1, *ptr++); arg_val--; while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET); //Wait for the stop flag to be set indicating a stop condition has been sent } I2C_TransferHandling(I2C1, 0x78, 0, I2C_AutoEnd_Mode, I2C_Generate_Stop); //while(I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF) == RESET); //I2C_ClearFlag(I2C1, I2C_FLAG_STOPF); delay_micro_seconds(100); //u8g_MicroDelay(); break; } return 1; }
//The main! int main(void) { //Setup a systick interrupt every 1ms (1/1000 seconds) SysTick_Config(SystemCoreClock/1000); //Enable GPIOB clock, required for the I2C output RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //Enable the I2C peripheral clock RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); //Set the pins HMC_SDA and HMC_SCL as alternate function GPIO pins GP.GPIO_Pin = HMC_SDA | HMC_SCL; GP.GPIO_Mode = GPIO_Mode_AF; GP.GPIO_OType = GPIO_OType_OD; GP.GPIO_Speed = GPIO_Speed_Level_1; GPIO_Init(HMC_GPIO, &GP); //Configure the pins to the I2C AF GPIO_PinAFConfig(HMC_GPIO, HMC_SDA_PS, HMC_PIN_AF); GPIO_PinAFConfig(HMC_GPIO, HMC_SCL_PS, HMC_PIN_AF); //Setup the I2C struct. The timing variable is acquired //from the STM32F0 I2C timing calculator sheet. Pretty //standard stuff really, its using the Analog filter //to clean up any noisy edges (not really required though //if you wish to disable it, you will need a different //I2C_Timing value). IT.I2C_Ack = I2C_Ack_Enable; IT.I2C_AnalogFilter = I2C_AnalogFilter_Enable; IT.I2C_DigitalFilter = 0; IT.I2C_Mode = I2C_Mode_I2C; IT.I2C_OwnAddress1 = 0xAB; IT.I2C_Timing = 0x10805E89; IT.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(HMC_I2C, &IT); I2C_Cmd(HMC_I2C, ENABLE); //Write the configuration registers for the HMC5883L compass. const uint8_t SmplAverage = 0b11; //Average 8 samples const uint8_t OutputRate = 0b110; //Output at 75Hz (Why not!) const uint8_t MeasurementCfg = 0b00; //We don't want any bias on the sensors const uint8_t SnsrGain = 0b100; //A gain of 440LSb/Gauss, standard. const uint8_t HighSpeedI2C = 0; //We want standard speed I2C. const uint8_t SnsrMode = 0b00; //Continuous measurement mode //Config 1 register I2C_WrReg(R_Config1, (SmplAverage<<5)|(OutputRate<<3)|MeasurementCfg); //Config 2 register I2C_WrReg(R_Config2, (SnsrGain<<5)); //Mode register I2C_WrReg(R_Mode, (HighSpeedI2C<<7)|SnsrMode); //Give the sensor a breather before reading data! Delay(10); int8_t RecData[6] = {0,0,0,0,0,0}; int32_t XVal = 0, YVal = 0, ZVal = 0; while(1) { //Read status register, waiting for the data ready flag while(!(I2C_RdReg(R_Status, 0, 1) & 1)); //Receive 6 bytes of data from the value registers and store in //RecData variable I2C_RdReg(R_XRegister, &RecData[0], 6); //Construct the words containing the value data! //The HMC5883 is a little odd as it arranges its registers //in the order X,Z,Y as opposed to what I suppose you'd //expect from the normal order X,Y,Z. XVal = (RecData[0]<<8) | RecData[1]; ZVal = (RecData[2]<<8) | RecData[3]; YVal = (RecData[4]<<8) | RecData[5]; } }