#include <stm32f10x.h>
#include <delay.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_i2c.h>
#include <string.h>
#define I2Cx I2C2
#define I2C_GPIO GPIOB
#define I2C_GPIO_SDA GPIO_Pin_11
#define I2C_GPIO_SCL GPIO_Pin_10
#define LED GPIO_Pin_13
#define LEDport GPIOC
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_address_direction(uint8_t address, uint8_t direction);
void i2c_transmit(uint8_t byte);
uint8_t i2c_receive_ack(void);
uint8_t i2c_receive_nack(void);
void i2c_write(uint8_t address, uint8_t data);
void i2c_read(uint8_t address, uint8_t* data);
#define SLAVE_ADDRESS 0x68 //when ADO is low, 0x69 when ADO is high
#define PWR_MGMT_R 0x6B //config. register
#define AccelX_H_R 0x3B //accel X axis High bit register
#define AccelX_L_R 0x3C //accel X axis low bit register
//#define AccelZ_R 0x3D
char displayString[7];
uint8_t dataStorage[4];
void blinkOnBoardLed(uint8_t a);
uint8_t Accel_X_data;
uint8_t receivedByte1; //msb
uint8_t receivedByte2; //lsb
uint8_t receivedByte3; //xlsb
uint32_t full20BitData;
uint32_t register_data;
int main(void)
{
//1. Configure pins B11 & B10 as alternate function, output and pull up
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_Init_struct = {
.GPIO_Pin = I2C_GPIO_SDA | I2C_GPIO_SCL,
.GPIO_Mode = GPIO_Mode_AF_OD,
.GPIO_Speed = GPIO_Speed_2MHz};
GPIO_Init(I2C_GPIO, &GPIO_Init_struct);
//1b. initialize an output pin for the onboard Led
GPIO_InitTypeDef GPIO_Init_struct_b = {
.GPIO_Pin = LED,
.GPIO_Mode = GPIO_Mode_Out_PP,
.GPIO_Speed = GPIO_Speed_50MHz};
GPIO_Init(LEDport, &GPIO_Init_struct_b);
//2. initialize i2c on pins B11 and B10
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
I2C_InitTypeDef I2C_Init_struct = {
.I2C_ClockSpeed = 100000,
.I2C_Mode = I2C_Mode_I2C,
.I2C_DutyCycle = I2C_DutyCycle_2,
.I2C_OwnAddress1 = 0x00,
.I2C_Ack = I2C_Ack_Disable,
.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit};
I2C_Init(I2Cx, &I2C_Init_struct);
I2C_Cmd(I2Cx, ENABLE);
DelayInit();
while(1){
strcpy(displayString, "0");
//start
i2c_start();
//send slave address and recieve ack
i2c_address_direction(SLAVE_ADDRESS<<1, I2C_Direction_Transmitter);
//send register address and recieve ack
i2c_transmit(PWR_MGMT_R);
//send data to write to RA (register address)
i2c_transmit(0x00);
//Nack and stop
i2c_stop();
blinkOnBoardLed(3);
strcpy(displayString, "1");
DelayMs(1000);
//start
i2c_start();
//send slave address and recieve ack
i2c_address_direction(SLAVE_ADDRESS<<1, I2C_Direction_Transmitter);
//send register address to read from and recieve ack
i2c_transmit(AccelX_L_R );
//start again
// Generate start condition
I2C_GenerateSTART(I2Cx, ENABLE);
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
//send slave address to receive
i2c_address_direction(SLAVE_ADDRESS<<1, I2C_Direction_Receiver);
// Disable ACK of received data
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// Wait for I2C EV7
// It means that the data has been received in I2C data register
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
Accel_X_data = I2C_ReceiveData(I2Cx);
//Nack and stop
i2c_stop();
blinkOnBoardLed(5);
strcpy(displayString, "2");
DelayMs(2000);
}
}
void i2c_start()
{
// Wait until I2Cx is not busy anymore
while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// Generate start condition
I2C_GenerateSTART(I2Cx, ENABLE);
// Wait for I2C EV5.
// It means that the start condition has been correctly released
// on the I2C bus (the bus is free, no other devices is communicating))
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
}
void i2c_stop()
{
// Generate I2C stop condition
I2C_GenerateSTOP(I2Cx, ENABLE);
// Wait until I2C stop condition is finished
while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF));
}
void i2c_address_direction(uint8_t address, uint8_t direction)
{
// Send slave address
I2C_Send7bitAddress(I2Cx, address, direction);
// Wait for I2C EV6
// It means that a slave acknowledges his address
if (direction == I2C_Direction_Transmitter)
{
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if (direction == I2C_Direction_Receiver)
{
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
void i2c_transmit(uint8_t byte)
{
// Send data byte
I2C_SendData(I2Cx, byte);
// Wait for I2C EV8_2.
// It means that the data has been physically shifted out and
// output on the bus)
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
uint8_t i2c_receive_ack()
{
// Enable ACK of received data
I2C_AcknowledgeConfig(I2Cx, ENABLE);
// Wait for I2C EV7
// It means that the data has been received in I2C data register
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
// Read and return data byte from I2C data register
return I2C_ReceiveData(I2Cx);
}
uint8_t i2c_receive_nack()
{
// Disable ACK of received data
I2C_AcknowledgeConfig(I2Cx, DISABLE);
// Wait for I2C EV7
// It means that the data has been received in I2C data register
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
// Read and return data byte from I2C data register
return I2C_ReceiveData(I2Cx);
}
void i2c_write(uint8_t address, uint8_t data)
{
i2c_start();
i2c_address_direction(address << 1, I2C_Direction_Transmitter);
i2c_transmit(data);
i2c_stop();
}
void i2c_read(uint8_t address, uint8_t* data)
{
i2c_start();
i2c_address_direction(address << 1, I2C_Direction_Receiver);
*data = i2c_receive_nack();
i2c_stop();
}
void i2c_burst_read(uint8_t address, uint8_t* data1, uint8_t* data2, uint8_t* data3){
i2c_start();
i2c_address_direction(address<<1, I2C_Direction_Receiver);
*data1 = i2c_receive_ack();
*data2 = i2c_receive_ack();
*data3 = i2c_receive_nack();
i2c_stop();
}
void blinkOnBoardLed(uint8_t a){
for(int i = 0; i < a; i++){
DelayMs(100);
GPIO_SetBits(LEDport, LED);
DelayMs(100);
GPIO_ResetBits(LEDport, LED);
}
}