無錫高端網(wǎng)站建設(shè)咨詢磁力王
單片機(jī)學(xué)習(xí)!
目錄
前言
一、I2C_DeInit函數(shù)
二、I2C_Init函數(shù)
三、I2C_StructInit函數(shù)
四、I2C_Cmd函數(shù)
五、I2C_GenerateSTART函數(shù)
六、I2C_GenerateSTOP函數(shù)
七、I2C_AcknowledgeConfig函數(shù)
八、I2C_SendData函數(shù)
九、I2C_ReceiveData函數(shù)
十、I2C_Send7bitAddress函數(shù)
十一、I2C狀態(tài)監(jiān)控功能
十二、標(biāo)志位函數(shù)
12.1 I2C_GetFlagStatus函數(shù)
12.2 I2C_ClearFlag函數(shù)
12.3 I2C_GetITStatus函數(shù)
12.4 I2C_ClearITPendingBit函數(shù)
前言
????????本文介紹了I2C硬件配置常用的一些庫(kù)函數(shù)。
一、I2C_DeInit函數(shù)
????????I2C_DeInit函數(shù)將外設(shè) I2Cx 寄存器重設(shè)為缺省值。
二、I2C_Init函數(shù)
????????I2C_Init函數(shù)用于I2C的初始化。函數(shù)第二個(gè)參數(shù)是初始化的結(jié)構(gòu)體。
I2C_Mode 用以設(shè)置 I2C 的模式。下表給出了該參數(shù)可取的值:
I2C_DutyCycle 用以設(shè)置 I2C 的占空比。下表給出了該參數(shù)可取的值:
注意:該參數(shù)只有在 I2C 工作在快速模式(時(shí)鐘工作頻率高于 100KHz)下才有意義。
I2C_OwnAddress1 該參數(shù)用來設(shè)置第一個(gè)設(shè)備自身地址,它可以是一個(gè) 7 位地址或者一個(gè) 10 位地址。
I2C_Ack 使能或者失能應(yīng)答(ACK),下表給出了該參數(shù)可取的值:
I2C_AcknowledgedAddress 定義了應(yīng)答 7 位地址還是 10 位地址。下表給出了該參數(shù)可取的值:
I2C_ClockSpeed 該參數(shù)用來設(shè)置時(shí)鐘頻率,這個(gè)值不能高于 400KHz。
三、I2C_StructInit函數(shù)
下表給出了 I2C_InitStruct 各個(gè)成員的缺省值:
四、I2C_Cmd函數(shù)
????????使能或失能I2C外設(shè)用I2C_Cmd函數(shù)來完成。
五、I2C_GenerateSTART函數(shù)
????????調(diào)用I2C_GenerateSTART函數(shù),就可以生成起始條件。
?程序源碼:
/*** @brief Generates I2Cx communication START condition.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @param NewState: new state of the I2C START condition generation.* This parameter can be: ENABLE or DISABLE.* @retval None.*/
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Generate a START condition */I2Cx->CR1 |= CR1_START_Set;}else{/* Disable the START condition generation */I2Cx->CR1 &= CR1_START_Reset;}
}
如果 NewState 不等于?DISABLE,就把CR1寄存器的 START 位置1;否則,把 START 位清0.
????????START 位意義可以從手冊(cè)里的寄存器描述中來了解:
START 置1
- 在從模式下是產(chǎn)生起始條件。
- 在主模式下是產(chǎn)生重復(fù)起始條件。
就是 START 這一位置1,產(chǎn)生起始條件。
六、I2C_GenerateSTOP函數(shù)
????????調(diào)用I2C_GenerateSTOP函數(shù),生成終止條件。
程序源碼:
/*** @brief Generates I2Cx communication STOP condition.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @param NewState: new state of the I2C STOP condition generation.* This parameter can be: ENABLE or DISABLE.* @retval None.*/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Generate a STOP condition */I2Cx->CR1 |= CR1_STOP_Set;}else{/* Disable the STOP condition generation */I2Cx->CR1 &= CR1_STOP_Reset;}
}
????????I2C_GenerateSTOP函數(shù)其實(shí)就是操作 CR1 的 STOP 位,查詢手冊(cè)中I2C寄存器的內(nèi)容:
????????STOP 是產(chǎn)生停止條件的。STOP位置1,產(chǎn)生停止條件。
七、I2C_AcknowledgeConfig函數(shù)
????????I2C_AcknowledgeConfig函數(shù)是用來配置 CR1 的 ACK 這一位。就是配置,在收到一個(gè)字節(jié)后是否給從機(jī)應(yīng)答。
程序源碼:
/*** @brief Enables or disables the specified I2C acknowledge feature.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @param NewState: new state of the I2C Acknowledgement.* This parameter can be: ENABLE or DISABLE.* @retval None.*/
void I2C_AcknowledgeConfig(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 acknowledgement */I2Cx->CR1 |= CR1_ACK_Set;}else{/* Disable the acknowledgement */I2Cx->CR1 &= CR1_ACK_Reset;}
}
手冊(cè)ACK寄存器描述:
????????ACK就是應(yīng)答使能。STM32作為主機(jī),在接收到一個(gè)字節(jié)后,是給從機(jī)應(yīng)答還是非應(yīng)答,就取決于ACK這一位。
在應(yīng)答的時(shí)候:
- 如果ACK是1,就給從機(jī)應(yīng)答。
- 如果ACK是0,就不給從機(jī)應(yīng)答。
八、I2C_SendData函數(shù)
????????I2C_SendData函數(shù)用于寫數(shù)據(jù)到數(shù)據(jù)寄存器DR。
程序源碼:
/*** @brief Sends a data byte through the I2Cx peripheral.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @param Data: Byte to be transmitted..* @retval None*/
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
{/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));/* Write in the DR register the data to be sent */I2Cx->DR = Data;
}
? ? ? ? 分析源碼,I2C_SendData函數(shù)實(shí)際就是把Data這個(gè)數(shù)據(jù)直接寫入到DR寄存器。
手冊(cè)DR寄存器描述:
????????DR數(shù)據(jù)寄存器用于存放接收到的數(shù)據(jù)或放置用于發(fā)送到總線的數(shù)據(jù)。在發(fā)送器模式下,當(dāng)寫一個(gè)字節(jié)至DR寄存器時(shí),自動(dòng)啟動(dòng)數(shù)據(jù)傳輸。一旦傳輸開始,也就是TxE=1,發(fā)送寄存器空,如果能及時(shí)把下一個(gè)需傳輸?shù)臄?shù)據(jù)寫入DR寄存器,I2C模塊將保持連續(xù)的數(shù)據(jù)流。
? ? ? ? 從上面可以看出兩個(gè)信息:
- 一個(gè)是,寫入DR,自動(dòng)啟動(dòng)數(shù)據(jù)傳輸。也就是產(chǎn)生發(fā)送一個(gè)字節(jié)的波形。
- 另一個(gè)是,在上一個(gè)數(shù)據(jù)移位傳輸過程中,如果及時(shí)把下一個(gè)數(shù)據(jù)放在DR里等著,這樣就能保持連續(xù)的數(shù)據(jù)流。
九、I2C_ReceiveData函數(shù)
????????I2C_ReceiveData函數(shù)用于讀取DR數(shù)據(jù),作為返回值。
程序源碼:
/*** @brief Returns the most recent received data by the I2Cx peripheral.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @retval The value of the received data.*/
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
{/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));/* Return the data in the DR register */return (uint8_t)I2Cx->DR;
}
?手冊(cè)DR寄存器描述:
????????
? ? ? ? 在接收器模式下,接收到的字節(jié)被拷貝到DR寄存器,這時(shí)就是RxNE=1,接收寄存器非空。在接收到下一個(gè)字節(jié)(RxNE=1)之前讀出數(shù)據(jù)寄存器,即可實(shí)現(xiàn)連續(xù)的數(shù)據(jù)傳送。
? ? ? ? 這里也可以看出兩個(gè)信息:
- 一個(gè)是,接收移位完成時(shí),收到的一個(gè)字節(jié)由移位寄存器轉(zhuǎn)到數(shù)據(jù)寄存器。讀取數(shù)據(jù)寄存器就能接收一個(gè)字節(jié)了。
- 另一個(gè)是,要在下一個(gè)字節(jié)收到之前,及時(shí)把上一個(gè)字節(jié)取走,防止數(shù)據(jù)覆蓋。這樣才能實(shí)現(xiàn)連續(xù)的數(shù)據(jù)流。
十、I2C_Send7bitAddress函數(shù)
????????I2C_Send7bitAddress函數(shù)是發(fā)送7位地址的專用函數(shù)。
程序源碼:
/*** @brief Transmits the address byte to select the slave device.* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.* @param Address: specifies the slave address which will be transmitted* @param I2C_Direction: specifies whether the I2C device will be a* Transmitter or a Receiver. This parameter can be one of the following values* @arg I2C_Direction_Transmitter: Transmitter mode* @arg I2C_Direction_Receiver: Receiver mode* @retval None.*/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
{/* Check the parameters */assert_param(IS_I2C_ALL_PERIPH(I2Cx));assert_param(IS_I2C_DIRECTION(I2C_Direction));/* Test on the direction to set/reset the read/write bit */if (I2C_Direction != I2C_Direction_Transmitter){/* Set the address bit0 for read */Address |= OAR1_ADD0_Set;}else{/* Reset the address bit0 for write */Address &= OAR1_ADD0_Reset;}/* Send the address */I2Cx->DR = Address;
}
????????從源碼可以看出,Address這個(gè)參數(shù)實(shí)際上也是通過DR發(fā)送的。只不過是Address參數(shù)在發(fā)送之前設(shè)置了Address最低位的讀寫位。
????????代碼意思是:如果I2C_Direction不是發(fā)送,就把Address的最低位置1,也就是讀;否則就把Address的最低位清0,也就是寫。
? ? ? ? 在發(fā)送地址的時(shí)候,可以用一下這個(gè)函數(shù)。當(dāng)然也可以手動(dòng)設(shè)置最低位,調(diào)用I2C_SendData函數(shù)來發(fā)送地址。
十一、I2C狀態(tài)監(jiān)控功能
源碼說明:
/*** @brief****************************************************************************************** I2C State Monitoring Functions* **************************************************************************************** * This I2C driver provides three different ways for I2C state monitoring* depending on the application requirements and constraints:* * * 1) Basic state monitoring:* Using I2C_CheckEvent() function:* It compares the status registers (SR1 and SR2) content to a given event* (can be the combination of one or more flags).* It returns SUCCESS if the current status includes the given flags * and returns ERROR if one or more flags are missing in the current status.* - When to use:* - This function is suitable for most applications as well as for startup * activity since the events are fully described in the product reference manual * (RM0008).* - It is also suitable for users who need to define their own events.* - Limitations:* - If an error occurs (ie. error flags are set besides to the monitored flags),* the I2C_CheckEvent() function may return SUCCESS despite the communication* hold or corrupted real state. * In this case, it is advised to use error interrupts to monitor the error* events and handle them in the interrupt IRQ handler.* * @note * For error management, it is advised to use the following functions:* - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).* - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs.* Where x is the peripheral instance (I2C1, I2C2 ...)* - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler()* in order to determine which error occurred.* - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()* and/or I2C_GenerateStop() in order to clear the error flag and source,* and return to correct communication status.* ** 2) Advanced state monitoring:* Using the function I2C_GetLastEvent() which returns the image of both status * registers in a single word (uint32_t) (Status Register 2 value is shifted left * by 16 bits and concatenated to Status Register 1).* - When to use:* - This function is suitable for the same applications above but it allows to* overcome the limitations of I2C_GetFlagStatus() function (see below).* The returned value could be compared to events already defined in the * library (stm32f10x_i2c.h) or to custom values defined by user.* - This function is suitable when multiple flags are monitored at the same time.* - At the opposite of I2C_CheckEvent() function, this function allows user to* choose when an event is accepted (when all events flags are set and no * other flags are set or just when the needed flags are set like * I2C_CheckEvent() function).* - Limitations:* - User may need to define his own events.* - Same remark concerning the error management is applicable for this * function if user decides to check only regular communication flags (and * ignores error flags).* ** 3) Flag-based state monitoring:* Using the function I2C_GetFlagStatus() which simply returns the status of * one single flag (ie. I2C_FLAG_RXNE ...). * - When to use:* - This function could be used for specific applications or in debug phase.* - It is suitable when only one flag checking is needed (most I2C events * are monitored through multiple flags).* - Limitations: * - When calling this function, the Status register is accessed. Some flags are* cleared when the status register is accessed. So checking the status* of one Flag, may clear other ones.* - Function may need to be called twice or more in order to monitor one * single event.* */
以上描述的是I2C的狀態(tài)監(jiān)控函數(shù)。
STM32有的狀態(tài)可能會(huì)同時(shí)置多個(gè)標(biāo)志位,
- 如果只檢查某一個(gè)標(biāo)志位就認(rèn)為這個(gè)狀態(tài)已經(jīng)發(fā)生了,就不太嚴(yán)謹(jǐn)。
- 如果用I2C_GetFlagStatus函數(shù)讀多次,再進(jìn)行判斷,又可能比較麻煩。
所以這里庫(kù)函數(shù)就給了多種監(jiān)控標(biāo)志位的方案:
第一種,基本狀態(tài)監(jiān)控,使用I2C_CheckEvent函數(shù)。這種方式就是同時(shí)判斷一個(gè)或多個(gè)標(biāo)志位,來確定幾個(gè)EVx,從而判斷某個(gè)狀態(tài)是否發(fā)生。和下圖的流程是對(duì)應(yīng)的。
第二種,高級(jí)狀態(tài)監(jiān)控,使用I2C_GetLastEvent函數(shù),是直接把SR1和SR2這兩個(gè)狀態(tài)寄存器拼接成16位的數(shù)據(jù)。
第三種,基于標(biāo)志位的狀態(tài)監(jiān)控,使用I2C_GetFlagStatus函數(shù)判斷某一個(gè)標(biāo)志位是否置1了。
十二、標(biāo)志位函數(shù)
12.1 I2C_GetFlagStatus函數(shù)
????????I2C_GetFlagStatus函數(shù)用于讀取標(biāo)志位。
?下表給出了所有可以被函數(shù) I2C_ GetFlagStatus 檢查的標(biāo)志位列表:
12.2 I2C_ClearFlag函數(shù)
????????I2C_ClearFlag函數(shù)用于清除標(biāo)志位。
下表給出了所有可以被函數(shù) I2C_ ClearFlag 清除的標(biāo)志位列表:
12.3 I2C_GetITStatus函數(shù)
????????I2C_GetITStatus函數(shù)用于讀取中斷標(biāo)志位。
下表給出了所有可以被函數(shù) I2C_ GetITStatus 檢查的中斷標(biāo)志位列表:
12.4 I2C_ClearITPendingBit函數(shù)
????????I2C_ClearITPendingBit函數(shù)用于清除中斷標(biāo)志位。
下表給出了所有可以被函數(shù) I2C_ ClearITPendingBit 清除的中斷待處理位列表: