/** \file i2c.h \author G. Icking-Konert \date 2013-11-22 \version 0.1 \brief implementation of I2C functions/macros implementation of functions for I2C bus communication For I2C bus, see http://en.wikipedia.org/wiki/I2C */ /*----------------------------------------------------------------------------- INCLUDE FILES -----------------------------------------------------------------------------*/ #include "stm8s.h" /*----------------------------------------------------------------------------- DEFINITION OF GLOBAL MACROS/#DEFINES -----------------------------------------------------------------------------*/ #define I2C_FAST 1 #define F_MASTER_MHZ 16UL #define F_MASTER_HZ 16000000UL #ifdef I2C_FAST //400 kHz #define F_I2C_HZ 400000UL #else //100 kHz #define F_I2C_HZ 100000UL #endif // I2C_FAST //CCR = Fmaster/2*Fiic = 16MHz/2*100kHz = 80 #define CCR (uint16_t)(F_MASTER_HZ / (2 * F_I2C_HZ)) /* Таймаут ожидания события I2C */ extern __IO uint8_t I2C_timeout; /*---------------------------------------------------------- FUNCTIONS ----------------------------------------------------------*/ static uint8_t i2c_read(void); /** \fn void i2c_init(void) \brief configure I2C bus configure I2C bus as master in standard mode, BR=100kHz, 7bit address, 250ns rise time */ void i2c_init() { //Частота тактирования периферии MHz I2C->FREQR = (uint8_t)(F_MASTER_MHZ); //Отключаем I2C I2C->CR1 &= (uint8_t)(~I2C_CR1_PE); //Выбираем режим #ifdef I2C_FAST I2C->CCRH = I2C_CCRH_FS; // | I2C_CCRH_DUTY; #else I2C->CCRH = 0; #endif //Set Maximum Rise Time: 1000ns max in Standard Mode //= [1000ns/(1/InputClockFrequencyMHz.10e6)]+1 //= InputClockFrequencyMHz+1 I2C->TRISER = (uint8_t)(F_MASTER_MHZ + 1); I2C->CCRL = (uint8_t)CCR; I2C->CCRH |= (uint8_t)((uint8_t)(CCR >> 8) & I2C_CCRH_CCR); //Включаем I2C I2C->CR1 |= I2C_CR1_PE; //Разрешаем подтверждение в конце посылки I2C->CR2 |= I2C_CR2_ACK; } // i2c_init /** \fn uint8_t i2c_waitFree(void) \brief wait until bus is free \return error code (0=ok; 1=timeout) wait until bus is free with timeout */ uint8_t i2c_waitFree() { // wait until bus free with timeout I2C_timeout = 10; while (((I2C->SR3 & I2C_SR3_BUSY)) && I2C_timeout); // on I2C timeout return error if ((I2C->SR3 & I2C_SR3_BUSY)) { i2c_init(); return(1); } // return success return(0); } // i2c_waitFree /** \fn uint8_t i2c_start(void) \brief generate I2C start condition \return error code (0=ok; 1=timeout) generate I2C start condition with timeout */ uint8_t i2c_start() { // wait until bus free with timeout I2C_timeout = 10; while (((I2C->SR3 & I2C_SR3_BUSY)) && I2C_timeout); // on I2C timeout return error if ((I2C->SR3 & I2C_SR3_BUSY)) { i2c_init(); return(2); } // generate start condition with timeout I2C->CR2 |= I2C_CR2_START; I2C_timeout = 10; while (!(I2C->SR1 & I2C_SR1_SB) && I2C_timeout); // on I2C timeout return error if (!(I2C->SR1 & I2C_SR1_SB)) { i2c_init(); return(1); } // return success return(0); } // i2c_start /** \fn uint8_t i2c_stop(void) \brief generate I2C stop condition \return error code (0=ok; 1=timeout) generate I2C stop condition with timeout */ uint8_t i2c_stop() { // generate stop condition with timeout I2C->CR2 |= I2C_CR2_STOP; I2C_timeout = 10; while ((I2C->SR3 & I2C_SR3_MSL) && I2C_timeout); // on I2C timeout set error flag if (I2C->SR3 & I2C_SR3_MSL) { i2c_init(); return(1); } // return success return(0); } // i2c_stop /** \fn uint8_t i2c_send(uint8_t addr, uint8_t numTx, uint8_t *bufTx) \brief write data via I2C \param[in] addr 7b address [6:0] of I2C slave \param[in] numTx number of bytes to send \param[in] bufTx send buffer \return error code (0=ok; 1=timeout) write data to I2C slave with frame timeout. Note that no start or stop condition is generated. */ uint8_t i2c_send(uint8_t addr, uint8_t numTx, uint8_t *bufTx) { uint8_t i; // send 7b slave adress [7:1] + write flag (LSB=0) I2C->DR = (uint8_t) ((addr << 1) & ~0x01); // shift left and set LSB (write=0, read=1) I2C_timeout = 10; while ((!(I2C->SR1 & I2C_SR1_ADDR)) && I2C_timeout); // wait until address sent or timeout I2C_timeout = 10; while ((!(I2C->SR3 & I2C_SR3_BUSY)) && I2C_timeout); // seems to be required...??? // no I2C timeout -> send data if (I2C_timeout) { for (i=0; iDR = bufTx[i]; I2C_timeout = 2; while ((!(I2C->SR1 & I2C_SR1_TXE)) && I2C_timeout); // wait until DR buffer empty or timeout } } // on I2C timeout return error else { i2c_init(); return(1); } // return success return(0); } // i2c_send static uint8_t i2c_read(void) { I2C->CR2 &= ~I2C_CR2_ACK; i2c_stop(); while (!(I2C->SR1 & I2C_SR1_RXNE)); return I2C->DR; } /** \fn uint8_t i2c_request(uint8_t slaveAddr, uint8_t numRx, uint8_t *bufRx) \brief request data via I2C as master with i2c_stop() \param[in] slaveAddr 7b address [6:0] of I2C slave \param[in] numRx number of bytes to receive \param[out] bufRx receive buffer \return error code (0=ok; 1=timeout) request data from I2C slave with frame timeout. Note that no start or stop condition is generated. */ uint8_t i2c_request(const uint8_t slaveAddr, const uint8_t numRx, uint8_t *bufRx) { uint8_t i = numRx; // send 7b slave adress [7:1] + read flag (LSB=1) I2C->DR = (uint8_t) ((slaveAddr << 1) | 0x01); // shift left and set LSB (write=0, read=1) I2C_timeout = 10; while ((!(I2C->SR1 & I2C_SR1_ADDR)) && I2C_timeout); // wait until adress sent or timeout I2C_timeout = 2; while ((!(I2C->SR3 & I2C_SR3_BUSY)) && I2C_timeout); // seems to be required...??? while (i-- > 1) { I2C_timeout = 2; while ((!(I2C->SR1 & I2C_SR1_RXNE)) && I2C_timeout); // wait until DR buffer not empty or timeout *(bufRx++) = I2C->DR; } *bufRx = i2c_read(); // on I2C timeout return error if (I2C_timeout == 0) { i2c_init(); return(1); } // return success return(0); } // i2c_request /*----------------------------------------------------------------------------- END OF MODULE -----------------------------------------------------------------------------*/