📄 stm32f0xx_i2c.c
字号:
/**
******************************************************************************
* @file stm32f0xx_i2c.c
* @author MCD Application Team
* @version V1.0.0
* @date 23-March-2012
* @brief This file provides firmware functions to manage the following
* functionalities of the Inter-Integrated circuit (I2C):
* + Initialization and Configuration
* + Communications handling
* + SMBUS management
* + I2C registers management
* + Data transfers management
* + DMA transfers management
* + Interrupts and flags management
*
* @verbatim
============================================================================
##### How to use this driver #####
============================================================================
[..]
(#) Enable peripheral clock using RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2Cx, ENABLE)
function for I2C1 or I2C2.
(#) Enable SDA, SCL and SMBA (when used) GPIO clocks using
RCC_AHBPeriphClockCmd() function.
(#) Peripherals alternate function:
(++) Connect the pin to the desired peripherals' Alternate
Function (AF) using GPIO_PinAFConfig() function.
(++) Configure the desired pin in alternate function by:
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
(++) Select the type, OpenDrain and speed via
GPIO_PuPd, GPIO_OType and GPIO_Speed members
(++) Call GPIO_Init() function.
(#) Program the Mode, Timing , Own address, Ack and Acknowledged Address
using the I2C_Init() function.
(#) 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 PEC Calculation using I2C_CalculatePEC() function.
(++) For SMBus Mode:
(+++) Enable the SMBusAlert pin using I2C_SMBusAlertCmd() function.
(#) Enable the NVIC and the corresponding interrupt using the function
I2C_ITConfig() if you need to use interrupt mode.
(#) When using the DMA mode
(++) Configure the DMA using DMA_Init() function.
(++) Active the needed channel Request using I2C_DMACmd() function.
(#) Enable the I2C using the I2C_Cmd() function.
(#) Enable the DMA using the DMA_Cmd() function when using DMA mode in the
transfers.
[..]
(@) When using I2C in Fast Mode Plus, SCL and SDA pin 20mA current drive capability
must be enabled by setting the driving capability control bit in SYSCFG.
@endverbatim
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_i2c.h"
#include "stm32f0xx_rcc.h"
/** @addtogroup STM32F0xx_StdPeriph_Driver
* @{
*/
/** @defgroup I2C
* @brief I2C driver modules
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CR1_CLEAR_MASK ((uint32_t)0x00CFE0FF) /*<! I2C CR1 clear register Mask */
#define CR2_CLEAR_MASK ((uint32_t)0x07FF7FFF) /*<! I2C CR2 clear register Mask */
#define TIMING_CLEAR_MASK ((uint32_t)0xF0FFFFFF) /*<! I2C TIMING clear register Mask */
/* 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 #####
===============================================================================
[..] This section provides a set of functions allowing to initialize the I2C Mode,
I2C Timing, I2C filters, I2C Addressing mode, I2C OwnAddress1.
[..] The I2C_Init() function follows the I2C configuration procedures (these procedures
are available in reference manual).
[..] When the Software Reset is performed using I2C_SoftwareResetCmd() function, the internal
states machines are reset and communication control bits, as well as status bits come
back to their reset value.
[..] Before enabling Stop mode using I2C_StopModeCmd() I2C Clock source must be set to
HSI and Digital filters must be disabled.
[..] Before enabling Own Address 2 via I2C_DualAddressCmd() function, OA2 and mask should be
configured using I2C_OwnAddress2Config() function.
[..] I2C_SlaveByteControlCmd() enable Slave byte control that allow user to get control of
each byte in slave mode when NBYTES is set to 0x01.
@endverbatim
* @{
*/
/**
* @brief Deinitializes the I2Cx peripheral registers to their default reset values.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @retval None
*/
void I2C_DeInit(I2C_TypeDef* I2Cx)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
if (I2Cx == I2C1)
{
/* Enable I2C1 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Release I2C1 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
}
else
{
/* Enable I2C2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
/* Release I2C2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
}
}
/**
* @brief Initializes the I2Cx peripheral according to the specified
* parameters in the I2C_InitStruct.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_InitStruct: pointer to a I2C_InitTypeDef structure that
* contains the configuration information for the specified I2C peripheral.
* @retval None
*/
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_ANALOG_FILTER(I2C_InitStruct->I2C_AnalogFilter));
assert_param(IS_I2C_DIGITAL_FILTER(I2C_InitStruct->I2C_DigitalFilter));
assert_param(IS_I2C_MODE(I2C_InitStruct->I2C_Mode));
assert_param(IS_I2C_OWN_ADDRESS1(I2C_InitStruct->I2C_OwnAddress1));
assert_param(IS_I2C_ACK(I2C_InitStruct->I2C_Ack));
assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_InitStruct->I2C_AcknowledgedAddress));
/* Disable I2Cx Peripheral */
I2Cx->CR1 &= (uint32_t)~((uint32_t)I2C_CR1_PE);
/*---------------------------- I2Cx FILTERS Configuration ------------------*/
/* Get the I2Cx CR1 value */
tmpreg = I2Cx->CR1;
/* Clear I2Cx CR1 register */
tmpreg &= CR1_CLEAR_MASK;
/* Configure I2Cx: analog and digital filter */
/* Set ANFOFF bit according to I2C_AnalogFilter value */
/* Set DFN bits according to I2C_DigitalFilter value */
tmpreg |= (uint32_t)I2C_InitStruct->I2C_AnalogFilter |(I2C_InitStruct->I2C_DigitalFilter << 8);
/* Write to I2Cx CR1 */
I2Cx->CR1 = tmpreg;
/*---------------------------- I2Cx TIMING Configuration -------------------*/
/* Configure I2Cx: Timing */
/* Set TIMINGR bits according to I2C_Timing */
/* Write to I2Cx TIMING */
I2Cx->TIMINGR = I2C_InitStruct->I2C_Timing & TIMING_CLEAR_MASK;
/* Enable I2Cx Peripheral */
I2Cx->CR1 |= I2C_CR1_PE;
/*---------------------------- I2Cx OAR1 Configuration ---------------------*/
/* Clear tmpreg local variable */
tmpreg = 0;
/* Clear OAR1 register */
I2Cx->OAR1 = (uint32_t)tmpreg;
/* Clear OAR2 register */
I2Cx->OAR2 = (uint32_t)tmpreg;
/* Configure I2Cx: Own Address1 and acknowledged address */
/* Set OA1MODE bit according to I2C_AcknowledgedAddress value */
/* Set OA1 bits according to I2C_OwnAddress1 value */
tmpreg = (uint32_t)((uint32_t)I2C_InitStruct->I2C_AcknowledgedAddress | \
(uint32_t)I2C_InitStruct->I2C_OwnAddress1);
/* Write to I2Cx OAR1 */
I2Cx->OAR1 = tmpreg;
/* Enable Own Address1 acknowledgement */
I2Cx->OAR1 |= I2C_OAR1_OA1EN;
/*---------------------------- I2Cx MODE Configuration ---------------------*/
/* Configure I2Cx: mode */
/* Set SMBDEN and SMBHEN bits according to I2C_Mode value */
tmpreg = I2C_InitStruct->I2C_Mode;
/* Write to I2Cx CR1 */
I2Cx->CR1 |= tmpreg;
/*---------------------------- I2Cx ACK Configuration ----------------------*/
/* Get the I2Cx CR2 value */
tmpreg = I2Cx->CR2;
/* Clear I2Cx CR2 register */
tmpreg &= CR2_CLEAR_MASK;
/* Configure I2Cx: acknowledgement */
/* Set NACK bit according to I2C_Ack value */
tmpreg |= I2C_InitStruct->I2C_Ack;
/* Write to I2Cx CR2 */
I2Cx->CR2 = tmpreg;
}
/**
* @brief Fills each I2C_InitStruct member with its default value.
* @param I2C_InitStruct: pointer to an I2C_InitTypeDef structure which will be initialized.
* @retval None
*/
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
{
/*---------------- Reset I2C init structure parameters values --------------*/
/* Initialize the I2C_Timing member */
I2C_InitStruct->I2C_Timing = 0;
/* Initialize the I2C_AnalogFilter member */
I2C_InitStruct->I2C_AnalogFilter = I2C_AnalogFilter_Enable;
/* Initialize the I2C_DigitalFilter member */
I2C_InitStruct->I2C_DigitalFilter = 0;
/* Initialize the I2C_Mode member */
I2C_InitStruct->I2C_Mode = I2C_Mode_I2C;
/* Initialize the I2C_OwnAddress1 member */
I2C_InitStruct->I2C_OwnAddress1 = 0;
/* Initialize the I2C_Ack member */
I2C_InitStruct->I2C_Ack = I2C_Ack_Disable;
/* Initialize the I2C_AcknowledgedAddress member */
I2C_InitStruct->I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
}
/**
* @brief Enables or disables the specified I2C peripheral.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C peripheral */
I2Cx->CR1 |= I2C_CR1_PE;
}
else
{
/* Disable the selected I2C peripheral */
I2Cx->CR1 &= (uint32_t)~((uint32_t)I2C_CR1_PE);
}
}
/**
* @brief Enables or disables the specified I2C software reset.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C software reset.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Peripheral under reset */
I2Cx->CR1 |= I2C_CR1_SWRST;
}
else
{
/* Peripheral not under reset */
I2Cx->CR1 &= (uint32_t)~((uint32_t)I2C_CR1_SWRST);
}
}
/**
* @brief Enables or disables the specified I2C interrupts.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_IT: specifies the I2C interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg I2C_IT_ERRI: Error interrupt mask
* @arg I2C_IT_TCI: Transfer Complete interrupt mask
* @arg I2C_IT_STOPI: Stop Detection interrupt mask
* @arg I2C_IT_NACKI: Not Acknowledge received interrupt mask
* @arg I2C_IT_ADDRI: Address Match interrupt mask
* @arg I2C_IT_RXI: RX interrupt mask
* @arg I2C_IT_TXI: TX interrupt mask
* @param NewState: new state of the specified I2C interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint32_t I2C_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_I2C_CONFIG_IT(I2C_IT));
if (NewState != DISABLE)
{
/* Enable the selected I2C interrupts */
I2Cx->CR1 |= I2C_IT;
}
else
{
/* Disable the selected I2C interrupts */
I2Cx->CR1 &= (uint32_t)~((uint32_t)I2C_IT);
}
}
/**
* @brief Enables or disables the I2C Clock stretching.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx Clock stretching.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable clock stretching */
I2Cx->CR1 &= (uint32_t)~((uint32_t)I2C_CR1_NOSTRETCH);
}
else
{
/* Disable clock stretching */
I2Cx->CR1 |= I2C_CR1_NOSTRETCH;
}
}
/**
* @brief Enables or disables I2C wakeup from stop mode.
* @param I2Cx: where x can be 1 to select the I2C peripheral.
* @param NewState: new state of the I2Cx stop mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_StopModeCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_1_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -