Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Demo / ARMCM4_STM32F405_Power_Management_GCC / Boot / lib / stdperiphlib / STM32F4xx_StdPeriph_Driver / src / stm32f4xx_i2c.c @ 69661903

History | View | Annotate | Download (52.9 KB)

1
/**
2
  ******************************************************************************
3
  * @file    stm32f4xx_i2c.c
4
  * @author  MCD Application Team
5
  * @version V1.1.0
6
  * @date    11-January-2013
7
  * @brief   This file provides firmware functions to manage the following 
8
  *          functionalities of the Inter-integrated circuit (I2C)
9
  *           + Initialization and Configuration
10
  *           + Data transfers
11
  *           + PEC management
12
  *           + DMA transfers management
13
  *           + Interrupts, events and flags management 
14
  *           
15
    @verbatim    
16
 ===============================================================================
17
                    ##### How to use this driver #####
18
 ===============================================================================
19
    [..]
20
      (#) Enable peripheral clock using RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2Cx, ENABLE)
21
          function for I2C1, I2C2 or I2C3.
22
  
23
      (#) Enable SDA, SCL  and SMBA (when used) GPIO clocks using 
24
          RCC_AHBPeriphClockCmd() function. 
25
  
26
      (#) Peripherals alternate function: 
27
        (++) Connect the pin to the desired peripherals' Alternate 
28
             Function (AF) using GPIO_PinAFConfig() function
29
        (++) Configure the desired pin in alternate function by:
30
             GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
31
        (++) Select the type, pull-up/pull-down and output speed via 
32
             GPIO_PuPd, GPIO_OType and GPIO_Speed members
33
        (++) Call GPIO_Init() function
34
             Recommended configuration is Push-Pull, Pull-up, Open-Drain.
35
             Add an external pull up if necessary (typically 4.7 KOhm).      
36
          
37
      (#) Program the Mode, duty cycle , Own address, Ack, Speed and Acknowledged
38
          Address using the I2C_Init() function.
39
  
40
      (#) Optionally you can enable/configure the following parameters without
41
          re-initialization (i.e there is no need to call again I2C_Init() function):
42
        (++) Enable the acknowledge feature using I2C_AcknowledgeConfig() function
43
        (++) Enable the dual addressing mode using I2C_DualAddressCmd() function
44
        (++) Enable the general call using the I2C_GeneralCallCmd() function
45
        (++) Enable the clock stretching using I2C_StretchClockCmd() function
46
        (++) Enable the fast mode duty cycle using the I2C_FastModeDutyCycleConfig()
47
             function.
48
        (++) Configure the NACK position for Master Receiver mode in case of 
49
             2 bytes reception using the function I2C_NACKPositionConfig().  
50
        (++) Enable the PEC Calculation using I2C_CalculatePEC() function
51
        (++) For SMBus Mode: 
52
          (+++) Enable the Address Resolution Protocol (ARP) using I2C_ARPCmd() function
53
          (+++) Configure the SMBusAlert pin using I2C_SMBusAlertConfig() function
54
  
55
      (#) Enable the NVIC and the corresponding interrupt using the function 
56
          I2C_ITConfig() if you need to use interrupt mode. 
57
  
58
      (#) When using the DMA mode 
59
        (++) Configure the DMA using DMA_Init() function
60
        (++) Active the needed channel Request using I2C_DMACmd() or
61
             I2C_DMALastTransferCmd() function.
62
        -@@- When using DMA mode, I2C interrupts may be used at the same time to
63
             control the communication flow (Start/Stop/Ack... events and errors).
64
   
65
      (#) Enable the I2C using the I2C_Cmd() function.
66
   
67
      (#) Enable the DMA using the DMA_Cmd() function when using DMA mode in the 
68
          transfers. 
69
  
70
    @endverbatim  
71
  ******************************************************************************
72
  * @attention
73
  *
74
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
75
  *
76
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
77
  * You may not use this file except in compliance with the License.
78
  * You may obtain a copy of the License at:
79
  *
80
  *        http://www.st.com/software_license_agreement_liberty_v2
81
  *
82
  * Unless required by applicable law or agreed to in writing, software 
83
  * distributed under the License is distributed on an "AS IS" BASIS, 
84
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
85
  * See the License for the specific language governing permissions and
86
  * limitations under the License.
87
  *
88
  ******************************************************************************  
89
  */ 
90

    
91
/* Includes ------------------------------------------------------------------*/
92
#include "stm32f4xx_i2c.h"
93
#include "stm32f4xx_rcc.h"
94

    
95
/** @addtogroup STM32F4xx_StdPeriph_Driver
96
  * @{
97
  */
98

    
99
/** @defgroup I2C 
100
  * @brief I2C driver modules
101
  * @{
102
  */ 
103

    
104
/* Private typedef -----------------------------------------------------------*/
105
/* Private define ------------------------------------------------------------*/
106

    
107
#define CR1_CLEAR_MASK    ((uint16_t)0xFBF5)      /*<! I2C registers Masks */
108
#define FLAG_MASK         ((uint32_t)0x00FFFFFF)  /*<! I2C FLAG mask */
109
#define ITEN_MASK         ((uint32_t)0x07000000)  /*<! I2C Interrupt Enable mask */
110

    
111
/* Private macro -------------------------------------------------------------*/
112
/* Private variables ---------------------------------------------------------*/
113
/* Private function prototypes -----------------------------------------------*/
114
/* Private functions ---------------------------------------------------------*/
115

    
116
/** @defgroup I2C_Private_Functions
117
  * @{
118
  */
119

    
120
/** @defgroup I2C_Group1 Initialization and Configuration functions
121
 *  @brief   Initialization and Configuration functions 
122
 *
123
@verbatim   
124
 ===============================================================================
125
            ##### Initialization and Configuration functions #####
126
 ===============================================================================  
127

128
@endverbatim
129
  * @{
130
  */
131

    
132
/**
133
  * @brief  Deinitialize the I2Cx peripheral registers to their default reset values.
134
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
135
  * @retval None
136
  */
137
void I2C_DeInit(I2C_TypeDef* I2Cx)
138
{
139
  /* Check the parameters */
140
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
141

    
142
  if (I2Cx == I2C1)
143
  {
144
    /* Enable I2C1 reset state */
145
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
146
    /* Release I2C1 from reset state */
147
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);    
148
  }
149
  else if (I2Cx == I2C2)
150
  {
151
    /* Enable I2C2 reset state */
152
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
153
    /* Release I2C2 from reset state */
154
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);      
155
  }
156
  else 
157
  {
158
    if (I2Cx == I2C3)
159
    {
160
      /* Enable I2C3 reset state */
161
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C3, ENABLE);
162
      /* Release I2C3 from reset state */
163
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C3, DISABLE);     
164
    }
165
  }
166
}
167

    
168
/**
169
  * @brief  Initializes the I2Cx peripheral according to the specified 
170
  *         parameters in the I2C_InitStruct.
171
  *           
172
  * @note   To use the I2C at 400 KHz (in fast mode), the PCLK1 frequency 
173
  *         (I2C peripheral input clock) must be a multiple of 10 MHz.  
174
  *           
175
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
176
  * @param  I2C_InitStruct: pointer to a I2C_InitTypeDef structure that contains 
177
  *         the configuration information for the specified I2C peripheral.
178
  * @retval None
179
  */
180
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
181
{
182
  uint16_t tmpreg = 0, freqrange = 0;
183
  uint16_t result = 0x04;
184
  uint32_t pclk1 = 8000000;
185
  RCC_ClocksTypeDef  rcc_clocks;
186
  /* Check the parameters */
187
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
188
  assert_param(IS_I2C_CLOCK_SPEED(I2C_InitStruct->I2C_ClockSpeed));
189
  assert_param(IS_I2C_MODE(I2C_InitStruct->I2C_Mode));
190
  assert_param(IS_I2C_DUTY_CYCLE(I2C_InitStruct->I2C_DutyCycle));
191
  assert_param(IS_I2C_OWN_ADDRESS1(I2C_InitStruct->I2C_OwnAddress1));
192
  assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->I2C_Ack));
193
  assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_InitStruct->I2C_AcknowledgedAddress));
194

    
195
/*---------------------------- I2Cx CR2 Configuration ------------------------*/
196
  /* Get the I2Cx CR2 value */
197
  tmpreg = I2Cx->CR2;
198
  /* Clear frequency FREQ[5:0] bits */
199
  tmpreg &= (uint16_t)~((uint16_t)I2C_CR2_FREQ);
200
  /* Get pclk1 frequency value */
201
  RCC_GetClocksFreq(&rcc_clocks);
202
  pclk1 = rcc_clocks.PCLK1_Frequency;
203
  /* Set frequency bits depending on pclk1 value */
204
  freqrange = (uint16_t)(pclk1 / 1000000);
205
  tmpreg |= freqrange;
206
  /* Write to I2Cx CR2 */
207
  I2Cx->CR2 = tmpreg;
208

    
209
/*---------------------------- I2Cx CCR Configuration ------------------------*/
210
  /* Disable the selected I2C peripheral to configure TRISE */
211
  I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_PE);
212
  /* Reset tmpreg value */
213
  /* Clear F/S, DUTY and CCR[11:0] bits */
214
  tmpreg = 0;
215

    
216
  /* Configure speed in standard mode */
217
  if (I2C_InitStruct->I2C_ClockSpeed <= 100000)
218
  {
219
    /* Standard mode speed calculate */
220
    result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1));
221
    /* Test if CCR value is under 0x4*/
222
    if (result < 0x04)
223
    {
224
      /* Set minimum allowed value */
225
      result = 0x04;  
226
    }
227
    /* Set speed value for standard mode */
228
    tmpreg |= result;          
229
    /* Set Maximum Rise Time for standard mode */
230
    I2Cx->TRISE = freqrange + 1; 
231
  }
232
  /* Configure speed in fast mode */
233
  /* To use the I2C at 400 KHz (in fast mode), the PCLK1 frequency (I2C peripheral
234
     input clock) must be a multiple of 10 MHz */
235
  else /*(I2C_InitStruct->I2C_ClockSpeed <= 400000)*/
236
  {
237
    if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2)
238
    {
239
      /* Fast mode speed calculate: Tlow/Thigh = 2 */
240
      result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 3));
241
    }
242
    else /*I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_16_9*/
243
    {
244
      /* Fast mode speed calculate: Tlow/Thigh = 16/9 */
245
      result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 25));
246
      /* Set DUTY bit */
247
      result |= I2C_DutyCycle_16_9;
248
    }
249

    
250
    /* Test if CCR value is under 0x1*/
251
    if ((result & I2C_CCR_CCR) == 0)
252
    {
253
      /* Set minimum allowed value */
254
      result |= (uint16_t)0x0001;  
255
    }
256
    /* Set speed value and set F/S bit for fast mode */
257
    tmpreg |= (uint16_t)(result | I2C_CCR_FS);
258
    /* Set Maximum Rise Time for fast mode */
259
    I2Cx->TRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1);  
260
  }
261

    
262
  /* Write to I2Cx CCR */
263
  I2Cx->CCR = tmpreg;
264
  /* Enable the selected I2C peripheral */
265
  I2Cx->CR1 |= I2C_CR1_PE;
266

    
267
/*---------------------------- I2Cx CR1 Configuration ------------------------*/
268
  /* Get the I2Cx CR1 value */
269
  tmpreg = I2Cx->CR1;
270
  /* Clear ACK, SMBTYPE and  SMBUS bits */
271
  tmpreg &= CR1_CLEAR_MASK;
272
  /* Configure I2Cx: mode and acknowledgement */
273
  /* Set SMBTYPE and SMBUS bits according to I2C_Mode value */
274
  /* Set ACK bit according to I2C_Ack value */
275
  tmpreg |= (uint16_t)((uint32_t)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack);
276
  /* Write to I2Cx CR1 */
277
  I2Cx->CR1 = tmpreg;
278

    
279
/*---------------------------- I2Cx OAR1 Configuration -----------------------*/
280
  /* Set I2Cx Own Address1 and acknowledged address */
281
  I2Cx->OAR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1);
282
}
283

    
284
/**
285
  * @brief  Fills each I2C_InitStruct member with its default value.
286
  * @param  I2C_InitStruct: pointer to an I2C_InitTypeDef structure which will be initialized.
287
  * @retval None
288
  */
289
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
290
{
291
/*---------------- Reset I2C init structure parameters values ----------------*/
292
  /* initialize the I2C_ClockSpeed member */
293
  I2C_InitStruct->I2C_ClockSpeed = 5000;
294
  /* Initialize the I2C_Mode member */
295
  I2C_InitStruct->I2C_Mode = I2C_Mode_I2C;
296
  /* Initialize the I2C_DutyCycle member */
297
  I2C_InitStruct->I2C_DutyCycle = I2C_DutyCycle_2;
298
  /* Initialize the I2C_OwnAddress1 member */
299
  I2C_InitStruct->I2C_OwnAddress1 = 0;
300
  /* Initialize the I2C_Ack member */
301
  I2C_InitStruct->I2C_Ack = I2C_Ack_Disable;
302
  /* Initialize the I2C_AcknowledgedAddress member */
303
  I2C_InitStruct->I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
304
}
305

    
306
/**
307
  * @brief  Enables or disables the specified I2C peripheral.
308
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
309
  * @param  NewState: new state of the I2Cx peripheral. 
310
  *          This parameter can be: ENABLE or DISABLE.
311
  * @retval None
312
  */
313
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
314
{
315
  /* Check the parameters */
316
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
317
  assert_param(IS_FUNCTIONAL_STATE(NewState));
318
  if (NewState != DISABLE)
319
  {
320
    /* Enable the selected I2C peripheral */
321
    I2Cx->CR1 |= I2C_CR1_PE;
322
  }
323
  else
324
  {
325
    /* Disable the selected I2C peripheral */
326
    I2Cx->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_PE);
327
  }
328
}
329

    
330
/**
331
  * @brief  Enables or disables the Analog filter of I2C peripheral.
332
  * @param  I2Cx: where x can be 1, 2 or 3 to select the I2C peripheral.
333
  * @param  NewState: new state of the Analog filter. 
334
  *          This parameter can be: ENABLE or DISABLE.
335
  * @note   This function should be called before initializing and enabling
336
            the I2C Peripheral.
337
  * @retval None
338
  */
339
void I2C_AnalogFilterCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
340
{
341
  /* Check the parameters */
342
  assert_param(IS_I2C_ALL_PERIPH(I2Cx));
343
  assert_param(IS_FUNCTIONAL_STATE(NewState));
344
  if (NewState != DISABLE)
345
  {
346
    /* Enable the analog filter */
347
    I2Cx->FLTR &= (uint16_t)~((uint16_t)I2C_FLTR_ANOFF);    
348
  }
349
  else
350
  {
351
    /* Disable the analog filter */
352
    I2Cx->FLTR |= I2C_FLTR_ANOFF;
353
  }
354
}
355