📄 stm8s_i2c.c
字号:
/**
******************************************************************************
* @file stm8s_i2c.c
* @brief This file contains all the functions for the I2C peripheral.
* @author STMicroelectronics - MCD Application Team
* @version V1.1.1
* @date 06/05/2009
******************************************************************************
*
* 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>
* @image html logo.bmp
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm8s_i2c.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
/**
* @addtogroup I2C_Public_Functions
* @{
*/
/**
* @brief Deinitializes the I2C peripheral registers to their default reset values.
* @par Parameters:
* None
* @retval None
*/
void I2C_DeInit(void)
{
I2C->CR1 = I2C_CR1_RESET_VALUE;
I2C->CR2 = I2C_CR2_RESET_VALUE;
I2C->FREQR = I2C_FREQR_RESET_VALUE;
I2C->OARL = I2C_OARL_RESET_VALUE;
I2C->OARH = I2C_OARH_RESET_VALUE;
I2C->ITR = I2C_ITR_RESET_VALUE;
I2C->CCRL = I2C_CCRL_RESET_VALUE;
I2C->CCRH = I2C_CCRH_RESET_VALUE;
I2C->TRISER = I2C_TRISER_RESET_VALUE;
}
/**
* @brief Initializes the I2C according to the specified parameters in standard or fast mode.
* @param[in] OutputClockFrequencyHz : Specifies the output clock frequency in Hz.
* @param[in] OwnAddress : Specifies the own address.
* @param[in] DutyCycle : Specifies the duty cycle to apply.
* This parameter can be any of the @ref I2C_DutyCycle_TypeDef enumeration.
* @param[in] Ack : Specifies the acknowledge mode to apply.
* This parameter can be any of the @ref I2C_Ack_TypeDef enumeration.
* @param[in] AddMode : Specifies the addressing mode to apply.
* This parameter can be any of the @ref I2C_AddMode_TypeDef enumeration.
* @param[in] InputClockFrequencyMHz : Specifies the input clock frequency in MHz.
* @retval None
*/
void I2C_Init(u32 OutputClockFrequencyHz, u16 OwnAddress, I2C_DutyCycle_TypeDef DutyCycle, I2C_Ack_TypeDef Ack, I2C_AddMode_TypeDef AddMode, u8 InputClockFrequencyMHz )
{
u16 result = 0x0004;
u16 tmpval = 0;
u8 tmpccrh = 0;
/* Check the parameters */
assert_param(IS_I2C_ACK_OK(Ack));
assert_param(IS_I2C_ADDMODE_OK(AddMode));
assert_param(IS_I2C_OWN_ADDRESS_OK(OwnAddress));
assert_param(IS_I2C_INPUT_CLOCK_FREQ_OK(InputClockFrequencyMHz));
assert_param(IS_I2C_OUTPUT_CLOCK_FREQ_OK(OutputClockFrequencyHz));
/*------------------------- I2C FREQ Configuration ------------------------*/
/* Clear frequency bits */
I2C->FREQR &= (u8)(~I2C_FREQR_FREQ);
/* Write new value */
I2C->FREQR |= InputClockFrequencyMHz;
/*--------------------------- I2C CCR Configuration ------------------------*/
/* Disable I2C to configure TRISER */
I2C->CR1 &= (u8)(~I2C_CR1_PE);
/* Clear CCRH & CCRL */
I2C->CCRH &= (u8)(~(I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR));
I2C->CCRL &= (u8)(~I2C_CCRL_CCR);
/* Detect Fast or Standard mode depending on the Output clock frequency selected */
if (OutputClockFrequencyHz > I2C_MAX_STANDARD_FREQ) /* FAST MODE */
{
/* Set F/S bit for fast mode */
tmpccrh = I2C_CCRH_FS;
if (DutyCycle == I2C_DUTYCYCLE_2)
{
/* Fast mode speed calculate: Tlow/Thigh = 2 */
result = (u16) ((InputClockFrequencyMHz * 1000000) / (OutputClockFrequencyHz * 3));
}
else /* I2C_DUTYCYCLE_16_9 */
{
/* Fast mode speed calculate: Tlow/Thigh = 16/9 */
result = (u16) ((InputClockFrequencyMHz * 1000000) / (OutputClockFrequencyHz * 25));
/* Set DUTY bit */
tmpccrh |= I2C_CCRH_DUTY;
}
/* Verify and correct CCR value if below minimum value */
if (result < (u16)0x01)
{
/* Set the minimum allowed value */
result = (u16)0x0001;
}
/* Set Maximum Rise Time: 300ns max in Fast Mode
= [300ns/(1/InputClockFrequencyMHz.10e6)]+1
= [(InputClockFrequencyMHz * 3)/10]+1 */
tmpval = ((InputClockFrequencyMHz * 3) / 10) + 1;
I2C->TRISER = (u8)tmpval;
}
else /* STANDARD MODE */
{
/* Calculate standard mode speed */
result = (u16)((InputClockFrequencyMHz * 1000000) / (OutputClockFrequencyHz << (u8)1));
/* Verify and correct CCR value if below minimum value */
if (result < (u16)0x0004)
{
/* Set the minimum allowed value */
result = (u16)0x0004;
}
/* Set Maximum Rise Time: 1000ns max in Standard Mode
= [1000ns/(1/InputClockFrequencyMHz.10e6)]+1
= InputClockFrequencyMHz+1 */
I2C->TRISER = (u8)(InputClockFrequencyMHz + 1);
}
/* Write CCR with new calculated value */
I2C->CCRL = (u8)result;
I2C->CCRH = (u8)(((u8)(result >> 8) & I2C_CCRH_CCR) | tmpccrh);
/* Enable I2C */
I2C->CR1 |= I2C_CR1_PE;
/* Configure I2C acknowledgement */
I2C_AcknowledgeConfig(Ack);
/*--------------------------- I2C OAR Configuration ------------------------*/
I2C->OARL = (u8)(OwnAddress);
I2C->OARH = (u8)((u8)AddMode |
I2C_OARH_ADDCONF |
(u8)((OwnAddress & (u16)0x0300) >> (u8)7));
}
/**
* @brief Enables or disables the I2C peripheral.
* @param[in] NewState : Indicate the new I2C peripheral state.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_Cmd(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Enable I2C peripheral */
I2C->CR1 |= I2C_CR1_PE;
}
else /* NewState == DISABLE */
{
/* Disable I2C peripheral */
I2C->CR1 &= (u8)(~I2C_CR1_PE);
}
}
/**
* @brief Enables or disables the I2C General Call feature.
* @param[in] NewState : State of the General Call feature.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_GeneralCallCmd(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Enable General Call */
I2C->CR1 |= I2C_CR1_ENGC;
}
else /* NewState == DISABLE */
{
/* Disable General Call */
I2C->CR1 &= (u8)(~I2C_CR1_ENGC);
}
}
/**
* @brief Generates I2C communication START condition.
* @param[in] NewState : Enable or disable the start condition.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
* @par Required preconditions:
* CCR must be programmed i.e. I2C_Init function must have been called with a valid I2C_ClockSpeed
*/
void I2C_GenerateSTART(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Generate a START condition */
I2C->CR2 |= I2C_CR2_START;
}
else /* NewState == DISABLE */
{
/* Disable the START condition generation */
I2C->CR2 &= (u8)(~I2C_CR2_START);
}
}
/**
* @brief Generates I2C communication STOP condition.
* @param[in] NewState : Enable or disable the stop condition.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_GenerateSTOP(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Generate a STOP condition */
I2C->CR2 |= I2C_CR2_STOP;
}
else /* NewState == DISABLE */
{
/* Disable the STOP condition generation */
I2C->CR2 &= (u8)(~I2C_CR2_STOP);
}
}
/**
* @brief Enables or disables I2C software reset.
* @param[in] NewState : Specifies the new state of the I2C software reset.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_SoftwareResetCmd(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Peripheral under reset */
I2C->CR2 |= I2C_CR2_SWRST;
}
else /* NewState == DISABLE */
{
/* Peripheral not under reset */
I2C->CR2 &= (u8)(~I2C_CR2_SWRST);
}
}
/**
* @brief Enables or disables the I2C clock stretching.
* @param[in] NewState : Specifies the new state of the I2C Clock stretching.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_StretchClockCmd(FunctionalState NewState)
{
/* Check function parameters */
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Clock Stretching Enable */
I2C->CR1 &= (u8)(~I2C_CR1_NOSTRETCH);
}
else /* NewState == DISABLE */
{
/* Clock Stretching Disable (Slave mode) */
I2C->CR1 |= I2C_CR1_NOSTRETCH;
}
}
/**
* @brief Enable or Disable the I2C acknowledge and position acknowledge feature.
* @param[in] Ack : Specifies the acknowledge mode to apply.
* This parameter can be any of the @ref I2C_Ack_TypeDef enumeration.
* @retval None
* @par Required preconditions:
* This function must be called before data reception starts.
*/
void I2C_AcknowledgeConfig(I2C_Ack_TypeDef Ack)
{
/* Check function parameters */
assert_param(IS_I2C_ACK_OK(Ack));
if (Ack == I2C_ACK_NONE)
{
/* Disable the acknowledgement */
I2C->CR2 &= (u8)(~I2C_CR2_ACK);
}
else
{
/* Enable the acknowledgement */
I2C->CR2 |= I2C_CR2_ACK;
if (Ack == I2C_ACK_CURR)
{
/* Configure (N)ACK on current byte */
I2C->CR2 &= (u8)(~I2C_CR2_POS);
}
else
{
/* Configure (N)ACK on next byte */
I2C->CR2 |= I2C_CR2_POS;
}
}
}
/**
* @brief Enables or disables the specified I2C interrupt.
* @param[in] ITName : Name of the interrupt to enable or disable.
* This parameter can be any of the @ref I2C_IT_TypeDef enumeration.
* @param[in] NewState : State of the interrupt to apply.
* This parameter can be any of the @ref FunctionalState enumeration.
* @retval None
*/
void I2C_ITConfig(I2C_IT_TypeDef ITName, FunctionalState NewState)
{
/* Check functions parameters */
assert_param(IS_I2C_INTERRUPT_OK(ITName));
assert_param(IS_FUNCTIONALSTATE_OK(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C interrupts */
I2C->ITR |= (u8)ITName;
}
else /* NewState == DISABLE */
{
/* Disable the selected I2C interrupts */
I2C->ITR &= (u8)(~(u8)ITName);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -