⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stm8l15x_i2c.c

📁 STM8L的tim4定时器使用
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
  ******************************************************************************
  * @file    stm8l15x_i2c.c
  * @author  MCD Application Team
  * @version V1.5.0
  * @date    13-May-2011
  * @brief   This file provides firmware functions to manage the following
  *          functionalities of the Inter-integrated circuit (I2C)
  *           - Initialization and Configuration
  *           - Data transfers
  *           - PEC management
  *           - DMA transfers management
  *           - Interrupts, events and flags management
  *
  *  @verbatim
  *
  *          ===================================================================
  *                                 How to use this driver
  *          ===================================================================
  *          1. Enable peripheral clock using CLK_PeripheralClockConfig(CLK_Peripheral_I2Cx,
  *             ENABLE) function (Refer to the product datasheet for the available I2C
  *           	peripherals)
  *
  *
  *          2. Program the Mode, duty cycle , Own address, Ack, Speed and Acknowledged
  *             Address using the I2C_Init() function.
  *
  *          3. Optionally you can enable/configure the following parameters without
  *             re-initialization (i.e there is no need to call again I2C_Init() function):
  *              - Enable the acknowledge feature using I2C_AcknowledgeConfig() function
  *              - Enable the dual addressing mode using I2C_DualAddressCmd() function
  *              - Enable the general call using the I2C_GeneralCallCmd() function
  *              - Enable the clock stretching using I2C_StretchClockCmd() function
  *              - Enable the fast mode duty cycle using the I2C_FastModeDutyCycleConfig()
  *                function
  *              - Enable the PEC Calculation using I2C_CalculatePEC() function
  *              - For SMBus Mode:
  *                   - Enable the Address Resolution Protocol (ARP) using I2C_ARPCmd() function
  *                   - Configure the SMBusAlert pin using I2C_SMBusAlertConfig() function
  *
  *          4. Enable the interrupt using the function I2C_ITConfig() if you need
  *             to use interrupt mode.
  *
  *          5. When using the DMA mode
  *                   - Configure the DMA using DMA_Init() function
  *                   - Active the needed channel Request using I2C_DMACmd() or
  *                     I2C_DMALastTransferCmd() function
  *              Note: When using DMA mode, I2C interrupts may be used at the same time to
  *                    control the communication flow (Start/Stop/Ack... events and errors).
  *
  *          6. Enable the I2C using the I2C_Cmd() function.
  *
  *          7. Enable the DMA using the DMA_Cmd() function when using DMA mode in the
  *             transfers.
  *
  *         Note: The external Pull-up resistors must be connected on SDA and SCL.
  *
  *  @endverbatim
  *
  ******************************************************************************
  * @attention
  *
  * 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>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm8l15x_i2c.h"
#include "stm8l15x_clk.h"

/** @addtogroup STM8L15x_StdPeriph_Driver
  * @{
  */

/** @defgroup I2C
  * @brief I2C driver modules
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup I2C_Private_Define
  * @{
  */

/* I2C register mask */
#define REGISTER_Mask               ((uint16_t)0x3000)
#define REGISTER_SR1_Index          ((uint16_t)0x0100)
#define REGISTER_SR2_Index          ((uint16_t)0x0200)
/* I2C Interrupt Enable mask */
#define ITEN_Mask                   ((uint16_t)0x0700)
/* I2C FLAG mask */
#define FLAG_Mask                   ((uint16_t)0x00FF)
/* I2C ADD0 mask */
#define OAR1_ADD0_Set               ((uint8_t)0x01)
#define OAR1_ADD0_Reset             ((uint8_t)0xFE)

/**
  * @}
  */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup I2C_Private_Functions
  * @{
  */

/** @defgroup I2C_Group1 Initialization and Configuration functions
 *  @brief   Initialization and Configuration functions
 *
@verbatim
 ===============================================================================
                   Initialization and Configuration functions
 ===============================================================================

@endverbatim
  * @{
  */

/**
  * @brief  Deinitializes the I2C peripheral registers to their default reset values.
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @retval None
  */
void I2C_DeInit(I2C_TypeDef* I2Cx)
{
  I2Cx->CR1 = I2C_CR1_RESET_VALUE;
  I2Cx->CR2 = I2C_CR2_RESET_VALUE;
  I2Cx->FREQR = I2C_FREQR_RESET_VALUE;
  I2Cx->OARL = I2C_OARL_RESET_VALUE;
  I2Cx->OARH = I2C_OARH_RESET_VALUE;
  I2Cx->OAR2 = I2C_OAR2_RESET_VALUE;
  I2Cx->ITR = I2C_ITR_RESET_VALUE;
  I2Cx->CCRL = I2C_CCRL_RESET_VALUE;
  I2Cx->CCRH = I2C_CCRH_RESET_VALUE;
  I2Cx->TRISER = I2C_TRISER_RESET_VALUE;
}

/**
  * @brief  Initializes the I2C according to the specified parameters in standard
  *         or fast mode.
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @param  OutputClockFrequency: Specifies the output clock frequency in Hz.
  * @param  OwnAddress: Specifies the own address.
  * @param  I2C_Mode: Specifies the addressing mode to apply.
  *          This parameter can be one of the following values:
  *            @arg I2C_Mode_I2C: I2C mode
  *            @arg I2C_Mode_SMBusDevice: SMBus Device mode
  *            @arg I2C_Mode_SMBusHost: SMBus Host mode
  * @param  I2C_DutyCycle: Specifies the duty cycle to apply in fast mode.
  *          This parameter can be one of the following values:
  *            @arg I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2
  *            @arg I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9
  * @note   The I2C_DutyCycle parameter doesn't have impact when the OutputClockFrequency
  *         is lower than 100KHz.
  * @param  I2C_Ack: Specifies the acknowledge mode to apply.
  *          This parameter can be one of the following values:
  *            @arg I2C_Ack_Disable: No acknowledge
  *            @arg I2C_Ack_Enable: Acknowledge Enabled
  * @param  I2C_AcknowledgedAddress: Specifies the acknowledge address to apply.
  *          This parameter can be one of the following values:
  *            @arg I2C_AcknowledgedAddress_7bit: 7-bit slave address
  *            @arg I2C_AcknowledgedAddress_10bit: 10-bit slave address
  * @note   To use the I2C at 400 KHz (in fast mode), the PCLK frequency
  *         (I2C peripheral input clock) must be a multiple of 10 MHz.
  * @retval None
  */
void I2C_Init(I2C_TypeDef* I2Cx, uint32_t OutputClockFrequency, uint16_t OwnAddress,
              I2C_Mode_TypeDef I2C_Mode, I2C_DutyCycle_TypeDef I2C_DutyCycle,
              I2C_Ack_TypeDef I2C_Ack, I2C_AcknowledgedAddress_TypeDef I2C_AcknowledgedAddress)
{
  uint32_t result = 0x0004;
  uint16_t tmpval = 0;
  uint8_t tmpccrh = 0;
  uint8_t input_clock = 0;

  /* Check the parameters */
  assert_param(IS_I2C_MODE(I2C_Mode));
  assert_param(IS_I2C_ACK_STATE(I2C_Ack));
  assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_AcknowledgedAddress));
  assert_param(IS_I2C_DUTY_CYCLE(I2C_DutyCycle));
  assert_param(IS_I2C_OWN_ADDRESS(OwnAddress));
  assert_param(IS_I2C_OUTPUT_CLOCK_FREQ(OutputClockFrequency));


  /* Get system clock frequency */
  input_clock = (uint8_t) (CLK_GetClockFreq() / 1000000);

  /*------------------------- I2C FREQ Configuration ------------------------*/
  /* Clear frequency bits */
  I2Cx->FREQR &= (uint8_t)(~I2C_FREQR_FREQ);
  /* Write new value */
  I2Cx->FREQR |= input_clock;

  /*--------------------------- I2C CCR Configuration ------------------------*/
  /* Disable I2C to configure TRISER */
  I2Cx->CR1 &= (uint8_t)(~I2C_CR1_PE);

  /* Clear CCRH & CCRL */
  I2Cx->CCRH &= (uint8_t)(~(I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR));
  I2Cx->CCRL &= (uint8_t)(~I2C_CCRL_CCR);

  /* Detect Fast or Standard mode depending on the Output clock frequency selected */
  if (OutputClockFrequency > I2C_MAX_STANDARD_FREQ) /* FAST MODE */
  {
    /* Set F/S bit for fast mode */
    tmpccrh = I2C_CCRH_FS;

    if (I2C_DutyCycle == I2C_DutyCycle_2)
    {
      /* Fast mode speed calculate: Tlow/Thigh = 2 */
      result = (uint32_t) ((input_clock * 1000000) / (OutputClockFrequency * 3));
    }
    else /* I2C_DUTYCYCLE_16_9 */
    {
      /* Fast mode speed calculate: Tlow/Thigh = 16/9 */
      result = (uint32_t) ((input_clock * 1000000) / (OutputClockFrequency * 25));
      /* Set DUTY bit */
      tmpccrh |= I2C_CCRH_DUTY;
    }

    /* Verify and correct CCR value if below minimum value */
    if (result < (uint16_t)0x01)
    {
      /* Set the minimum allowed value */
      result = (uint16_t)0x0001;
    }

    /* Set Maximum Rise Time: 300ns max in Fast Mode
    = [300ns/(1/input_clock.10e6)]+1
    = [(input_clock * 3)/10]+1 */
    tmpval = ((input_clock * 3) / 10) + 1;
    I2Cx->TRISER = (uint8_t)tmpval;

  }
  else /* STANDARD MODE */
  {

    /* Calculate standard mode speed */
    result = (uint16_t)((input_clock * 1000000) / (OutputClockFrequency << (uint8_t)1));

    /* Verify and correct CCR value if below minimum value */
    if (result < (uint16_t)0x0004)
    {
      /* Set the minimum allowed value */
      result = (uint16_t)0x0004;
    }

    /* Set Maximum Rise Time: 1000ns max in Standard Mode
    = [1000ns/(1/input_clock.10e6)]+1
    = input_clock+1 */
    I2Cx->TRISER = (uint8_t)((uint8_t)input_clock + (uint8_t)1);

  }

  /* Write CCR with new calculated value */
  I2Cx->CCRL = (uint8_t)result;
  I2Cx->CCRH = (uint8_t)((uint8_t)((uint8_t)((uint8_t)result >> 8) & I2C_CCRH_CCR) | tmpccrh);

  /* Enable I2C and  Configure its mode*/
  I2Cx->CR1 |= (uint8_t)(I2C_CR1_PE | I2C_Mode);

  /* Configure I2C acknowledgement */
  I2Cx->CR2 |= (uint8_t)I2C_Ack;

  /*--------------------------- I2C OAR Configuration ------------------------*/
  I2Cx->OARL = (uint8_t)(OwnAddress);
  I2Cx->OARH = (uint8_t)((uint8_t)(I2C_AcknowledgedAddress | I2C_OARH_ADDCONF ) | \
                         (uint8_t)((uint16_t)( (uint16_t)OwnAddress &  (uint16_t)0x0300) >> 7));
}

/**
  * @brief  Enables or disables the I2C peripheral.
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @param  NewState: Indicate the new I2C peripheral state.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{

  /* Check function parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Enable I2C peripheral */
    I2Cx->CR1 |= I2C_CR1_PE;
  }
  else /* NewState == DISABLE */
  {
    /* Disable I2C peripheral */
    I2Cx->CR1 &= (uint8_t)(~I2C_CR1_PE);
  }
}

/**
  * @brief  Enables or disables the I2C General Call feature.
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @param  NewState: State of the General Call feature.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{

  /* Check function parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Enable General Call */
    I2Cx->CR1 |= I2C_CR1_ENGC;
  }
  else /* NewState == DISABLE */
  {
    /* Disable General Call */
    I2Cx->CR1 &= (uint8_t)(~I2C_CR1_ENGC);
  }
}

/**
  * @brief  Generates I2C communication START condition.
  * @note   CCR must be programmed, i.e. I2C_Init function must have been called
  *         with a valid I2C_ClockSpeed
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @param  NewState: Enable or disable the start condition.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
{

  /* Check function parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Generate a START condition */
    I2Cx->CR2 |= I2C_CR2_START;
  }
  else /* NewState == DISABLE */
  {
    /* Disable the START condition generation */
    I2Cx->CR2 &= (uint8_t)(~I2C_CR2_START);
  }
}

/**
  * @brief  Generates I2C communication STOP condition.
  * @param  I2Cx: where x can be 1 to select the specified I2C peripheral.
  * @param  NewState: Enable or disable the stop condition.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
{

  /* Check function parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    /* Generate a STOP condition */
    I2Cx->CR2 |= I2C_CR2_STOP;
  }
  else /* NewState == DISABLE */
  {
    /* Disable the STOP condition generation */
    I2Cx->CR2 &= (uint8_t)(~I2C_CR2_STOP);
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -