123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /**
- \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; i<numTx; i++) {
- I2C->DR = 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
- -----------------------------------------------------------------------------*/
|