/* ----------------------------- */ /* I2C Low Level Routinen */ /* ----------------------------- */ #include "i2c_basic.h" uint16_t Timeout; #define Timed(x) Timeout = 0xFFFF; while (x) { if (Timeout-- == 0) goto errReturn;} /* Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR)); */ /* -------------------- Zusätzliche Include Files ------------------ */ #include "i2c_basic.h" // --------------------------------------------------------------- // Initialisiere den I2C Bus // --------------------------------------------------------------- void I2C1_Init() { static _Bool initialized = false; GPIO_InitTypeDef GPIO_InitStruct; // Port Init Struct I2C_InitTypeDef I2C_InitStruct; // I2C Init Struct if (initialized) return; // Peripherie Takt einschalten I2C3: PB6 (I2C1 SCL) und PB7 (I2C1_SDA) RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Port mit SCL/SCA einrichten GPIO_InitStruct.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; // Pins als Alternate Function einstellen GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // IO Speed, nicht Baudrate, 2 Mhz reicht GPIO_Init(I2C_SCL_PORT, &GPIO_InitStruct); // Struktur Parameter fuer I2C setzen I2C_StructInit(&I2C_InitStruct); // Rücksetzen auf Default I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED; // 100 khz Busfrequenz I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; // Normaler I2C Mode I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 50:50 Duty Cycle I2C_InitStruct.I2C_OwnAddress1 = 0x00; // Dummy Adresse I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; // ACK senden I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 Bit Adressierung // I2C3 mit den obigen Parametern konfigurieren I2C_Init(I2Cx, &I2C_InitStruct); // I2C einschalten I2C_Cmd(I2Cx, ENABLE); initialized = true; } void I2C1_Disable() { I2C_Cmd(I2Cx, DISABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE); } /* ----- Erzeuge Start Bedingung ------ */ ErrorStatus i2c_start() { I2C_GenerateSTART(I2Cx, ENABLE); /* Warte auf I2C EV5. Bus frei, Start akzeptiert */ Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); return SUCCESS; errReturn: return ERROR; } /* --------- Erzeuge Stop Bedingung ------- */ ErrorStatus i2c_stop() { I2C_GenerateSTOP(I2Cx, ENABLE); Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); return SUCCESS; errReturn: return ERROR; } /* ---------- Adressiere den Slave -------- Write: I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED Read: I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED */ ErrorStatus i2c_address_direction(uint8_t address, uint8_t direction) { /* Adressiere den Slave mit Datenrichtung */ I2C_Send7bitAddress(I2Cx, address, direction); /* Warte auf I2C EV6, Slave hat seine Adressierung akzeptiert */ if (direction == I2C_Direction_Transmitter) { Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); } if (direction == I2C_Direction_Receiver) { Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); } return SUCCESS; errReturn: return ERROR; } /* ------- Uebertrage 1 Byte an Slave ----- */ ErrorStatus i2c_write(uint8_t byte) { I2C_SendData(I2Cx, byte); /* Warte auf Ev8_2, Datum wurde heraus geschoben */ Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); return SUCCESS; errReturn: return ERROR; } /* Ein Byte vom Slave lesen und mit ACK bestätigen, dass noch ein weiteres Byte angefordert wird */ uint8_t i2c_receive_ack() { I2C_AcknowledgeConfig(I2Cx, ENABLE); /* Warte fuer I2C EV7, d.h. Daten sind im Register empfangen worden. */ Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); return(I2C_ReceiveData(I2Cx)); errReturn: return ERROR; } /* Ein Byte vom Slave lesen und mit NACK bestätigen, dass KEIN weiteres Byte angefordert wird. */ uint8_t i2c_receive_nack() { I2C_AcknowledgeConfig(I2Cx, DISABLE); // Warte fuer EV7 = Daten sind empfangen worden Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); I2C_GenerateSTOP(I2Cx, ENABLE); Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); // Read and return data byte from I2C data register return (I2C_ReceiveData(I2Cx)); errReturn: return ERROR; } /* E2PROM ACK Polling */ // // Warte bis Byte weggeschrieben wurde (Slave sendet solange kein ACK) // do{ // I2C_GenerateSTART(I2Cx, ENABLE); // while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // I2C_Send7bitAddress(I2Cx, 0x00, I2C_Direction_Transmitter); // } while (I2C_CheckEvent(I2Cx,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=0);