|
@@ -1,237 +0,0 @@
|
|
|
-/**
|
|
|
- \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();
|
|
|
- I2C_timeout = 2;
|
|
|
- while (!(I2C->SR1 & I2C_SR1_RXNE) && I2C_timeout);
|
|
|
- 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
|
|
|
------------------------------------------------------------------------------*/
|