You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.3 KiB

#include "i2c.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_gpio.h"
#include "porting.h"
void i2cInit(I2C_TypeDef* I2Cx)
{
if (I2Cx == I2C1) {
i2c1Init();
}
else {
THROW_ERROR(E_I2C_NON_EXISTANT);
}
}
void i2c1Init(void)
{
// Initialization structs
GPIO_InitTypeDef i2c_gpio;
I2C_InitTypeDef i2c;
// Turn on clocks
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
//Configure I2C module
i2c.I2C_ClockSpeed = 100000;
i2c.I2C_Mode = I2C_Mode_I2C;
i2c.I2C_DutyCycle = I2C_DutyCycle_2;
i2c.I2C_OwnAddress1 = 0x15;
i2c.I2C_Ack = I2C_Ack_Enable;
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &i2c);
//Additionally we need to initialize corresponding GPIOs
i2c_gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
i2c_gpio.GPIO_Mode = GPIO_Mode_AF_OD; // Open drain only if you have pull-up resistors
i2c_gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &i2c_gpio);
// Enable I2C 1
I2C_Cmd(I2C1, ENABLE);
DEBUG_MSG("I2C1 initialized.");
}
uint8_t i2cPing(I2C_TypeDef* I2Cx, uint8_t slave_addr)
{
DEBUG_MSG("Searching for: %d\n", slave_addr);
// Wait until I2Cx is not busy anymore
while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// Generate start condition
I2C_GenerateSTART(I2Cx, ENABLE);
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Send slave address
I2C_Send7bitAddress(I2Cx, slave_addr<<1, I2C_Direction_Transmitter);
// Wait for I2C EV5.
volatile uint32_t timeout = 0xFFFF;
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
if (timeout == 0) {
break;
} else {
timeout--;
}
}
I2C_GenerateSTOP(I2Cx, ENABLE);
if (timeout > 0) {
DEBUG_MSG("Slave found\n\r");
return 1;
} else {
DEBUG_MSG("Slave not found\n\r");
}
return 0;
}
void i2cStartTransmission(I2C_TypeDef* I2Cx, uint8_t dir, uint8_t slave_addr)
{
// Wait for I2C module to become ready
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// Generate I2C start condition
I2C_GenerateSTART(I2Cx, ENABLE);
// Waiting for EV5
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// The 7 bit address needs to be shifted by 1
I2C_Send7bitAddress(I2Cx, slave_addr<<1, dir);
// Depending on whether the master is reading or writing another event is triggered
if(dir== I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
if(dir== I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
void i2cWrite(I2C_TypeDef* I2Cx, uint8_t* data, uint16_t len, uint32_t timeout)
{
if(len-- >= 1) {
I2C_SendData(I2Cx, *data++);
}
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) && timeout) {
timeout--;
}
}
void i2cAckOn(I2C_TypeDef* I2Cx)
{
I2C_AcknowledgeConfig(I2Cx, ENABLE);
}
void i2cAckOff(I2C_TypeDef* I2Cx)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);
}
uint8_t i2cRead(I2C_TypeDef* I2Cx)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
void i2cEndTransmission(I2C_TypeDef* I2Cx)
{
I2C_GenerateSTOP(I2Cx, ENABLE);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));
}