|
@@ -1,329 +0,0 @@
|
|
-/**
|
|
|
|
- ******************************************************************************
|
|
|
|
- * @file i2c_master_poll.c
|
|
|
|
- * @author MCD Application Team
|
|
|
|
- * @version V0.0.3
|
|
|
|
- * @date Oct 2010
|
|
|
|
- * @brief This file contains optimized drivers for I2C master
|
|
|
|
- ******************************************************************************
|
|
|
|
- * @copy
|
|
|
|
- *
|
|
|
|
- * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
|
|
|
- * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
|
|
|
- * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
|
|
|
- * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
|
|
|
- * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
|
|
|
- * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
|
|
|
- *
|
|
|
|
- * <h2><center>© COPYRIGHT 2009 STMicroelectronics</center></h2>
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-#include "i2c_master_poll.h"
|
|
|
|
-
|
|
|
|
-/* Таймаут ожидания события I2C */
|
|
|
|
-extern __IO uint8_t I2C_timeout;
|
|
|
|
-
|
|
|
|
-/* flag clearing sequence - uncoment next for peripheral clock under 2MHz */
|
|
|
|
-#define dead_time() { /* _asm("nop"); _asm("nop"); */ }
|
|
|
|
-#define tout() (I2C_timeout)
|
|
|
|
-#define set_tout_ms(a) { I2C_timeout = a; }
|
|
|
|
-
|
|
|
|
-/******************************************************************************
|
|
|
|
-* Function name : I2C_Init
|
|
|
|
-* Description : Initialize I2C peripheral
|
|
|
|
-* Input param : None
|
|
|
|
-* Return : None
|
|
|
|
-* See also : None
|
|
|
|
-*******************************************************************************/
|
|
|
|
-void I2C_Init(void) {
|
|
|
|
- //define SDA, SCL outputs, HiZ, Open drain, Fast
|
|
|
|
- GPIOB->ODR |= (GPIO_PIN_4 | GPIO_PIN_5);
|
|
|
|
- GPIOB->DDR |= (GPIO_PIN_4 | GPIO_PIN_5);
|
|
|
|
- GPIOB->CR2 |= (GPIO_PIN_4 | GPIO_PIN_5);
|
|
|
|
-
|
|
|
|
-#ifdef FAST_I2C_MODE
|
|
|
|
- I2C->FREQR = 16; // input clock to I2C - 16MHz
|
|
|
|
- I2C->CCRL = 15; // 900/62.5= 15, (SCLhi must be at least 600+300=900ns!)
|
|
|
|
- I2C->CCRH = 0x80; // fast mode, duty 2/1 (bus speed 62.5*3*15~356kHz)
|
|
|
|
- I2C->TRISER = 5; // 300/62.5 + 1= 5 (maximum 300ns)
|
|
|
|
-#else
|
|
|
|
- I2C->FREQR = 8; // input clock to I2C - 8MHz
|
|
|
|
- I2C->CCRL = 40; // CCR= 40 - (SCLhi must be at least 4000+1000=5000ns!)
|
|
|
|
- I2C->CCRH = 0; // standard mode, duty 1/1 bus speed 100kHz
|
|
|
|
- I2C->TRISER = 9; // 1000ns/(125ns) + 1 (maximum 1000ns)
|
|
|
|
-#endif
|
|
|
|
- I2C->OARL = 0xA0; // own address A0;
|
|
|
|
- I2C->OARH |= 0x40;
|
|
|
|
- //I2C->ITR = 1; // enable error interrupts
|
|
|
|
- I2C->CR2 |= 0x04; // ACK=1, Ack enable
|
|
|
|
- I2C->CR1 |= 0x01; // PE=1
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/******************************************************************************
|
|
|
|
-* Function name : I2C_ReadRegister
|
|
|
|
-* Description : Read defined number bytes from slave memory starting with defined offset
|
|
|
|
-* Input param : offset in slave memory, number of bytes to read, starting address to store received data
|
|
|
|
-* Return : None
|
|
|
|
-* See also : None
|
|
|
|
-*******************************************************************************/
|
|
|
|
-void I2C_ReadRegister(u8 u8_regAddr, u8 u8_NumByteToRead, u8 *ReadBuffer)
|
|
|
|
-{
|
|
|
|
- /*--------------- BUSY? -> STOP request ---------------------*/
|
|
|
|
- while(I2C->SR3 & I2C_SR3_BUSY && tout()) // Wait while the bus is busy
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- while(I2C->CR2 & I2C_CR2_STOP && tout()); // Wait until stop is performed
|
|
|
|
- }
|
|
|
|
- I2C->CR2 |= I2C_CR2_ACK; // ACK=1, Ack enable
|
|
|
|
- /*--------------- Start communication -----------------------*/
|
|
|
|
- I2C->CR2 |= I2C_CR2_START; // START=1, generate start
|
|
|
|
- while((I2C->SR1 & I2C_SR1_SB)==0 && tout()); // Wait for start bit detection (SB)
|
|
|
|
- /*------------------ Address send ---------------------------*/
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = (u8)(SLAVE_ADDRESS << 1); // Send 7-bit device address & Write (R/W = 0)
|
|
|
|
- }
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_ADDR) && tout()); // test EV6 - wait for address ack (ADDR)
|
|
|
|
- dead_time(); // ADDR clearing sequence
|
|
|
|
- I2C->SR3;
|
|
|
|
- /*--------------- Register/Command send ----------------------*/
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_TXE) && tout()); // Wait for TxE
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = u8_regAddr; // Send register address
|
|
|
|
- } // Wait for TxE & BTF
|
|
|
|
- while((I2C->SR1 & (I2C_SR1_TXE | I2C_SR1_BTF)) != (I2C_SR1_TXE | I2C_SR1_BTF) && tout());
|
|
|
|
- dead_time(); // clearing sequence
|
|
|
|
- /*-------------- Stop/Restart communication -------------------*/
|
|
|
|
- #ifdef NO_RESTART // if 7bit address and NO_RESTART setted
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // STOP=1, generate stop
|
|
|
|
- while(I2C->CR2 & I2C_CR2_STOP && tout()); // wait until stop is performed
|
|
|
|
- #endif // NO_RESTART
|
|
|
|
- /*--------------- Restart communication ---------------------*/
|
|
|
|
- I2C->CR2 |= I2C_CR2_START; // START=1, generate re-start
|
|
|
|
- while((I2C->SR1 & I2C_SR1_SB)==0 && tout()); // Wait for start bit detection (SB)
|
|
|
|
- /*------------------ Address send ---------------------------*/
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = (u8)(SLAVE_ADDRESS << 1) | 1; // Send 7-bit device address & Write (R/W = 1)
|
|
|
|
- }
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_ADDR) && tout()); // Wait for address ack (ADDR)
|
|
|
|
- /*------------------- Data Receive --------------------------*/
|
|
|
|
- if (u8_NumByteToRead > 2) // *** more than 2 bytes are received? ***
|
|
|
|
- {
|
|
|
|
- I2C->SR3; // ADDR clearing sequence
|
|
|
|
- while(u8_NumByteToRead > 3 && tout()) // not last three bytes?
|
|
|
|
- {
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Reading next data byte
|
|
|
|
- --u8_NumByteToRead; // Decrease Numbyte to reade by 1
|
|
|
|
- }
|
|
|
|
- //last three bytes should be read
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK; // Clear ACK
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 1st byte
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 2nd byte
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_RXNE) && tout()); // Wait for RXNE
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 3rd Data byte
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if(u8_NumByteToRead == 2) // *** just two bytes are received? ***
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= I2C_CR2_POS; // Set POS bit (NACK at next received byte)
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->SR3; // Clear ADDR Flag
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK; // Clear ACK
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 1st Data byte
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- *ReadBuffer = I2C->DR; // Read 2nd Data byte
|
|
|
|
- }
|
|
|
|
- else // *** only one byte is received ***
|
|
|
|
- {
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK;; // Clear ACK
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->SR3; // Clear ADDR Flag
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // generate stop here (STOP=1)
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_RXNE) && tout()); // test EV7, wait for RxNE
|
|
|
|
- *ReadBuffer = I2C->DR; // Read Data byte
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- /*--------------- All Data Received -----------------------*/
|
|
|
|
- while((I2C->CR2 & I2C_CR2_STOP) && tout()); // Wait until stop is performed (STOPF = 1)
|
|
|
|
- I2C->CR2 &=~I2C_CR2_POS; // return POS to default state (POS=0)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/******************************************************************************
|
|
|
|
-* Function name : I2C_WriteRegister
|
|
|
|
-* Description : write defined number bytes to slave memory starting with defined offset
|
|
|
|
-* Input param : offset in slave memory, number of bytes to write, starting address to send
|
|
|
|
-* Return : None.
|
|
|
|
-* See also : None.
|
|
|
|
-*******************************************************************************/
|
|
|
|
-void I2C_WriteRegister(u8 u8_regAddr, u8 u8_NumByteToWrite, u8 *ReadBuffer)
|
|
|
|
-{
|
|
|
|
- while((I2C->SR3 & 2) && tout()) // Wait while the bus is busy
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= 2; // STOP=1, generate stop
|
|
|
|
- while((I2C->CR2 & 2) && tout()); // wait until stop is performed
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- I2C->CR2 |= 1; // START=1, generate start
|
|
|
|
- while(((I2C->SR1 & 1)==0) && tout()); // Wait for start bit detection (SB)
|
|
|
|
- dead_time(); // SB clearing sequence
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = (u8)(SLAVE_ADDRESS << 1); // Send 7-bit device address & Write (R/W = 0)
|
|
|
|
- }
|
|
|
|
- while(!(I2C->SR1 & 2) && tout()); // Wait for address ack (ADDR)
|
|
|
|
- dead_time(); // ADDR clearing sequence
|
|
|
|
- I2C->SR3;
|
|
|
|
- while(!(I2C->SR1 & 0x80) && tout()); // Wait for TxE
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = u8_regAddr; // send Offset command
|
|
|
|
- }
|
|
|
|
- if(u8_NumByteToWrite)
|
|
|
|
- {
|
|
|
|
- while(u8_NumByteToWrite--)
|
|
|
|
- { // write data loop start
|
|
|
|
- while(!(I2C->SR1 & 0x80) && tout()); // test EV8 - wait for TxE
|
|
|
|
- I2C->DR = *ReadBuffer++; // send next data byte
|
|
|
|
- } // write data loop end
|
|
|
|
- }
|
|
|
|
- while(((I2C->SR1 & 0x84) != 0x84) && tout()); // Wait for TxE & BTF
|
|
|
|
- dead_time(); // clearing sequence
|
|
|
|
-
|
|
|
|
- I2C->CR2 |= 2; // generate stop here (STOP=1)
|
|
|
|
- while((I2C->CR2 & 2) && tout()); // wait until stop is performed
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * @brief
|
|
|
|
- *
|
|
|
|
- * @param NumByteToRead
|
|
|
|
- * @param ReadBuffer
|
|
|
|
- */
|
|
|
|
-void I2C_ReadBytes(const u8 Addr, const u8 NumByteToRead, u8 *ReadBuffer) {
|
|
|
|
- u8 adr = Addr << 1;
|
|
|
|
- u8 n = NumByteToRead;
|
|
|
|
- set_tout_ms(10);
|
|
|
|
-
|
|
|
|
- /*--------------- BUSY? -> STOP request ---------------------*/
|
|
|
|
- while(I2C->SR3 & I2C_SR3_BUSY && tout()) // Wait while the bus is busy
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- while(I2C->CR2 & I2C_CR2_STOP && tout()); // Wait until stop is performed
|
|
|
|
- }
|
|
|
|
- I2C->CR2 |= I2C_CR2_ACK; // ACK=1, Ack enable
|
|
|
|
- /*--------------- Start communication -----------------------*/
|
|
|
|
- I2C->CR2 |= I2C_CR2_START; // START=1, generate start
|
|
|
|
- while((I2C->SR1 & I2C_SR1_SB)==0 && tout()); // Wait for start bit detection (SB)
|
|
|
|
- /*------------------ Address send ---------------------------*/
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = (adr | 1); // Send 7-bit device address & Write (R/W = 1)
|
|
|
|
- }
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_ADDR) && tout()); // Wait for address ack (ADDR)
|
|
|
|
- /*------------------- Data Receive --------------------------*/
|
|
|
|
- if (n > 2) // *** more than 2 bytes are received? ***
|
|
|
|
- {
|
|
|
|
- I2C->SR3; // ADDR clearing sequence
|
|
|
|
- while(n > 3 && tout()) // not last three bytes?
|
|
|
|
- {
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Reading next data byte
|
|
|
|
- --n; // Decrease Numbyte to reade by 1
|
|
|
|
- }
|
|
|
|
- //last three bytes should be read
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK; // Clear ACK
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 1st byte
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 2nd byte
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_RXNE) && tout()); // Wait for RXNE
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 3rd Data byte
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if(n == 2) // *** just two bytes are received? ***
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= I2C_CR2_POS; // Set POS bit (NACK at next received byte)
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->SR3; // Clear ADDR Flag
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK; // Clear ACK
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_BTF) && tout()); // Wait for BTF
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // Generate stop here (STOP=1)
|
|
|
|
- *ReadBuffer++ = I2C->DR; // Read 1st Data byte
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- *ReadBuffer = I2C->DR; // Read 2nd Data byte
|
|
|
|
- }
|
|
|
|
- else // *** only one byte is received ***
|
|
|
|
- {
|
|
|
|
- I2C->CR2 &=~I2C_CR2_ACK;; // Clear ACK
|
|
|
|
- disableInterrupts(); // Errata workaround (Disable interrupt)
|
|
|
|
- I2C->SR3; // Clear ADDR Flag
|
|
|
|
- I2C->CR2 |= I2C_CR2_STOP; // generate stop here (STOP=1)
|
|
|
|
- enableInterrupts(); // Errata workaround (Enable interrupt)
|
|
|
|
- while(!(I2C->SR1 & I2C_SR1_RXNE) && tout()); // test EV7, wait for RxNE
|
|
|
|
- *ReadBuffer = I2C->DR; // Read Data byte
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- /*--------------- All Data Received -----------------------*/
|
|
|
|
- while((I2C->CR2 & I2C_CR2_STOP) && tout()); // Wait until stop is performed (STOPF = 1)
|
|
|
|
- I2C->CR2 &= ~I2C_CR2_POS; // return POS to default state (POS=0)
|
|
|
|
-}
|
|
|
|
-/**
|
|
|
|
- * @brief write defined number bytes to slave device
|
|
|
|
- *
|
|
|
|
- * @param Addr
|
|
|
|
- * @param NumByteToWrite
|
|
|
|
- * @param DataBuffer
|
|
|
|
- */
|
|
|
|
-void I2C_WriteBytes(const u8 Addr, const u8 NumByteToWrite, u8 *DataBuffer) {
|
|
|
|
- u8 adr = Addr << 1;
|
|
|
|
- u8 n = NumByteToWrite;
|
|
|
|
- set_tout_ms(10);
|
|
|
|
-
|
|
|
|
- while((I2C->SR3 & 2) && tout()) // Wait while the bus is busy
|
|
|
|
- {
|
|
|
|
- I2C->CR2 |= 2; // STOP=1, generate stop
|
|
|
|
- while((I2C->CR2 & 2) && tout()); // wait until stop is performed
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- I2C->CR2 |= 1; // START=1, generate start
|
|
|
|
- while(((I2C->SR1 & 1)==0) && tout()); // Wait for start bit detection (SB)
|
|
|
|
- dead_time(); // SB clearing sequence
|
|
|
|
- if(tout())
|
|
|
|
- {
|
|
|
|
- I2C->DR = adr; // Send 7-bit device address & Write (R/W = 0)
|
|
|
|
- }
|
|
|
|
- while(!(I2C->SR1 & 2) && tout()); // Wait for address ack (ADDR)
|
|
|
|
- dead_time(); // ADDR clearing sequence
|
|
|
|
- I2C->SR3;
|
|
|
|
- if(n)
|
|
|
|
- {
|
|
|
|
- while(n--)
|
|
|
|
- { // write data loop start
|
|
|
|
- while(!(I2C->SR1 & 0x80) && tout()); // test EV8 - wait for TxE
|
|
|
|
- I2C->DR = *DataBuffer++; // send next data byte
|
|
|
|
- } // write data loop end
|
|
|
|
- }
|
|
|
|
- while(((I2C->SR1 & 0x84) != 0x84) && tout()); // Wait for TxE & BTF
|
|
|
|
- dead_time(); // clearing sequence
|
|
|
|
-
|
|
|
|
- I2C->CR2 |= 2; // generate stop here (STOP=1)
|
|
|
|
- while((I2C->CR2 & 2) && tout()); // wait until stop is performed
|
|
|
|
-}
|
|
|