第10章
I2C串列通訊
10.1 STM32 I2C簡介
1. I²C使用兩條雙向開放集極(Open Drain),串列資料(SDA)及串列時脈(SCL)並利用電阻將電位上拉。
2. I²C允許相當大的工作電壓範圍,但典型的電壓準位為+3.3v或+5v。
3. 由SDA和SCL構成的串列匯流排,可發送和接收資料。在CPU與被控IC之間、IC與IC之間進行雙向傳送。
4. I2C匯流排在傳送資料過程中共有三種類型信號, 它們分別是:START信號、FINISH信號和ACK信號。
STM32F10x處理器I2C結構圖
1. START:SCL為high時,SDA由high變成low,開始傳送資料。
2. FINISH:SCL為high時,SDA由low變成high,結束傳送資料。
3. ACK:接收資料的IC在接收到8bit資料後,向發送資料的IC發出特定的低電平脈衝,表示已收到資料。
10.2 I2C Standard Driver Library
本節說明ST提供I2C Standard Driver Library
Function name |
Description |
I2C_DeInit |
Resets the I2Cx peripheral registers to their default reset values. |
I2C_Init |
Initializes the I2Cx peripheral according to the specified parameters in the I2C_InitStruct. |
I2C_StructInit |
Fills each I2C_InitStruct member with its default value. |
I2C_Cmd |
Enables or disables the specified I2C peripheral. |
I2C_DMACmd |
Enables or disables the specified I2C DMA requests. |
I2C_DMALastTransferCmd |
Specifies that the next DMA transfer is the last one. |
I2C_GenerateSTART |
Generates I2Cx communication Start condition. |
I2C_GenerateSTOP |
Generates I2Cx communication Stop condition. |
I2C_ITConfig |
Enables or disables the specified I2C interrupts. |
I2C_SendData |
Sends a data byte through the I2Cx peripheral. |
I2C_ReceiveData |
Returns the most recent received data by the I2Cx peripheral. |
I2C_Send7bitAddress |
Transmits the address byte to select the slave device. |
I2C_ReadRegister |
Reads the specified I2C register and returns its value. |
I2C_SoftwareResetCmd |
Enables or disables the specified I2C software reset. |
I2C_SMBusAlertConfig |
Drives the SMBAlert pin high or low for the specified I2C. |
I2C_TransmitPEC |
Enables or disables the specified I2C PEC transfer. |
I2C_PECPositionConfig |
Selects the specified I2C PEC position. |
I2C_CalculatePEC |
Enables or disables the PEC value calculation of the transferred bytes. |
I2C_GetPEC |
Returns the PEC value for the specified I2C. |
I2C_ARPCmd |
Enables or disables the specified I2C ARP. |
I2C_StretchClockCmd |
Enables or disables the specified I2C clock stretching. |
I2C_FastModeDutyCycleConfig |
Selects the specified I2C fast mode duty cycle. |
I2C_GetLastEvent |
Returns the last I2Cx event |
I2C_CheckEvent |
Checks whether the last I2Cx event is equal to the one passed as parameter. |
I2C_GetFlagStatus |
Checks whether the specified I2C flag is set or not. |
I2C_ClearFlag |
Clears the I2Cx’s pending flags. |
I2C_GetITStatus |
Checks whether the specified I2C interrupt has occurred or not. |
I2C_ClearITPendingBit |
Clears the I2Cx’s interrupt pending bits. |
10.2 .1 I2C_Mode
I2C_Mode is used to configure the I2C mode. See tablefor the values taken by this
member.
I2C_Mode |
Description |
I2C_Mode_I2C |
I2C is configured in I2C mode |
I2C_Mode_SMBusDevice |
I2C is configured in SMBus device mode |
I2C_Mode_SMBusHost |
I2C is configured in SMBus host mode |
10.2 .2 I2C_DutyCycle
I2C_DutyCycle is used to select the I2C fast mode duty cycle. See for the values
taken by this member.
I2C_DutyCycle |
Description |
I2C_DutyCycle_16_9 |
I2C fast mode Tlow/Thigh=16/9 |
I2C_DutyCycle_2 |
I2C fast mode Tlow/Thigh=2 |
Note: This member is meaningful only when the I2C operates in Fast mode (working clock speed greater than 100 kHz).
10.2 .3 I2C_OwnAddress1
This member is used to configure the first device own address. It can be a 7-bit or 10-bit
address.
I2C_OwnAddress1 |
Description |
I2C1_SLAVE_ADDRESS7 |
This member is used to configure the first device own address.
|
I2C2_SLAVE_ADDRESS7 |
10.2 .4 I2C_Ack
I2C_Ack enables or disables the acknowledgement. See for the values taken by
this member.
I2C_Ack |
Description |
I2C_Ack_Enable |
Enables the acknowledgement |
I2C_Ack_Disable |
Disables the acknowledgement |
10.2 .5 I2C_Cmd function
describes the I2C_Cmd function.
Function name |
I2C_Cmd |
Function prototype |
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState) |
Behavior description |
Enables or disables the specified I2C peripheral. |
Input parameter1 |
I2Cx: where x can be 1or 2 to select the I2C peripheral. |
Input parameter2 |
NewState: new state of the I2Cx peripheral. This parameter can be set to ENABLE or DISABLE. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Enable I2C1 peripheral */
I2C_Cmd(I2C1, ENABLE);
10.2 .6 I2C_GenerateSTART function
describes the I2C_GenerateSTART function.
Function name |
I2C_GenerateSTART |
Function prototype |
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState) |
Behavior description |
Generates I2Cx communication Start condition.. |
Input parameter1 |
I2Cx: where x can be 1or 2 to select the I2C peripheral. |
Input parameter2 |
NewState: new state of the I2C Start condition generation. This parameter can be: ENABLE or DISABLE. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Generate a Start condition on I2C1 */
I2C_GenerateSTART(I2C1, ENABLE);
10.2 .7 I2C_GenerateSTOP function
describes the I2C_GenerateSTOP function.
Function name |
I2C_GenerateSTOP |
Function prototype |
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState) |
Behavior description |
Generates I2Cx communication Stop condition. |
Input parameter1 |
I2Cx: where x can be 1or 2 to select the I2C peripheral. |
Input parameter2 |
NewState: new state of the I2C Stop condition generation. This parameter can be: ENABLE or DISABLE. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Generate a Stop condition on I2C2 */
I2C_GenerateSTOP(I2C2, ENABLE);
10.2 .8 I2C_ITConfig function
describes the I2C_ITConfig function.
Function name |
I2C_ITConfig |
Function prototype |
void I2C_ITConfig(I2C_TypeDef* I2Cx, u16 I2C_IT, FunctionalState NewState) |
Behavior description |
Enables or disables the specified I2C interrupts. |
Input parameter1 |
I2Cx: where x can be 1 or 2 to select the I2C peripheral. |
Input parameter2 |
I2C_IT: I2C interrupts sources to be enabled or disabled. Refer to I2C_IT for more details on the allowed values for this parameter. |
Input parameter3 |
NewState: new state of the specified I2C interrupts. This parameter can be set to ENABLE or DISABLE. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
I2C_IT
This parameter enables or disables I2C interrupts. One or a combination of the following
values can be used:
I2C_IT |
Description |
I2C_IT_BUF |
Buffer interrupt mask |
I2C_IT_EVT |
Event interrupt mask |
I2C_IT_ERR |
Error interrupt mask |
Example:
/* Enable I2C2 event and buffer interrupts */
I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
I2C_SendData function
describes the I2C_SendData function.
Function name |
I2C_SendData |
Function prototype |
void I2C_SendData(I2C_TypeDef* I2Cx, u8 Data) |
Behavior description |
Sends a data byte through the I2Cx peripheral. |
Input parameter1 |
I2Cx: where x can be 1or 2 to select the I2C peripheral. |
Input parameter2 |
Data: byte to be transmitted. |
Output parameter |
None |
Return parameter |
None |
Required preconditions |
None |
Called functions |
None |
Example:
/* Transmit 0x5D byte on I2C2 */
I2C_SendData(I2C2, 0x5D);
11.2.15 I2C_ReceiveData function
describes the I2C_ReceiveData function.
Function name |
I2C_ReceiveData |
Function prototype |
u8 I2C_ReceiveData(I2C_TypeDef* I2Cx) |
Behavior description |
Returns the most recent received data by the I2Cx peripheral. |
Input parameter |
I2Cx: where x can be 1 or 2 to select the I2C peripheral.. |
Output parameter |
None |
Return parameter |
Received byte. |
Required preconditions |
None |
Called functions |
None |
Example:
/* Read the received byte on I2C1 */
u8 ReceivedData;
ReceivedData = I2C_ReceiveData(I2C1);
10.3實例演練
實驗一 SIOC使用I2C通訊介面傳收資料
實驗說明:如何使用interrupt讓I2C_1(master)能傳送data給 I2C_2(slave),其中使用7 bits address模式,clock rate是200KHz。
主要程式碼說明:
I2C main.c程式碼
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"
#include "hw_config.h"
#include "stm32f10x_i2c.h"
/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
#define I2C1_SLAVE_ADDRESS7 0x30
#define I2C2_SLAVE_ADDRESS7 0x30
#define BufferSize 4
#define ClockSpeed 200000 // 200 KHz
#define I2C1_EV_IRQChannel ((u8)0x1F) /* I2C1 Event Interrupt */
#define I2C1_ER_IRQChannel ((u8)0x20) /* I2C1 Error Interrupt */
#define I2C2_EV_IRQChannel ((u8)0x21) /* I2C2 Event Interrupt */
#define I2C2_ER_IRQChannel ((u8)0x22) /* I2C2 Error Interrupt */
/* Private variables ---------------------------------------------------------*/
I2C_InitTypeDef I2C_InitStructure;
u8 I2C1_Buffer_Tx[BufferSize] = {1,2,3,4};
u8 I2C2_Buffer_Rx[BufferSize];
vu8 Tx_Idx = 0, Rx_Idx = 0, PEC_Value = 0;
volatile TestStatus TransferStatus = FAILED;
/* Private functions ---------------------------------------------------------*/
void Delay(vu32 nCount);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
TestStatus Buffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength);
/*******************************************************************************
* Function Name : main.
* Description : Main routine.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int main(void)
{
int temp;
Set_System();
getchar();
NVIC_Configuration();
GPIO_Configuration();
/* I2C1 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //快速模式下的選項,100KHZ以上才有用
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7; //slave address長度
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //每次都會回送ACK
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = ClockSpeed; // I2C 速度配置,這個範例是200KHz,一般是40KHZ,400KHZ是極限,一般到不了那麼高
I2C_Init(I2C1, &I2C_InitStructure);
printf("I2C1 configuration\r\n");
/* I2C2 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;
I2C_Init(I2C2, &I2C_InitStructure);
printf("I2C2 configuration\r\n");
/*----- Transmission Phase -----*/
/* Send I2C1 START condition */
/* Enable I2C1 and I2C2 event and buffer interrupt */
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
/* Enable I2C1 and I2C2 ----------------------------------------------------*/
I2C_Cmd(I2C1, ENABLE);
I2C_Cmd(I2C2, ENABLE);
I2C_GenerateSTART(I2C1, ENABLE);
printf("Send I2C1 START condition\r\n");
/* Send data */
while(Rx_Idx < (BufferSize+1))
{
}
/* Check the corectness of written data */
printf("Check the corectness of written data\r\n");
TransferStatus = Buffercmp(I2C1_Buffer_Tx, I2C2_Buffer_Rx, BufferSize);
printf("Buffercmp Finish\r\n");
/* TransferStatus = PASSED, if the transmitted and received data are equal */
/* TransferStatus = FAILED, if the transmitted and received data are different */
if(TransferStatus) printf("Transmission SUCESS\r\n");
else printf("Transmission FAILED\r\n");
while(1)
{
}
}
/*******************************************************************************
* Function Name : Delay
* Description : Inserts a delay time.
* Input : nCount: specifies the delay time length.
* Output : None
* Return : None
*******************************************************************************/
void Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure I2C1 pins: SCL and SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 |GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures NVIC and Vector Table base location.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(0x8003000, 0x0);
#endif
/* 1 bit for pre-emption priority, 3 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Configure and enable I2C1 interrupt -------------------------------------*/
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure and enable I2C2 interrupt -------------------------------------*/
NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : Buffercmp
* Description : Compares two buffers.
* Input : - pBuffer1, pBuffer2: buffers to be compared.
* : - BufferLength: buffer's length
* Output : None
* Return : PASSED: pBuffer1 identical to pBuffer2
* FAILED: pBuffer1 differs from pBuffer2
*******************************************************************************/
TestStatus Buffercmp(u8* pBuffer1, u8* pBuffer2, u16 BufferLength)
{
while(BufferLength--)
{
if(*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
I2C 中斷stm32f10x_it.c程式碼
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "stm32f10x_i2c.h"
#include "usb_lib.h"
#include "usb_istr.h"
#include "hw_config.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define BufferSize 4
#define I2C2_SLAVE_ADDRESS7 0x30
/* Private variables ---------------------------------------------------------*/
extern vu8 Tx_Idx, Rx_Idx, PEC_Value, DataToTransfer;
extern u8 I2C1_Buffer_Tx[], I2C2_Buffer_Rx[];
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M3 Processor Exceptions Handlers */
/******************************************************************************/
#ifndef STM32F10X_CL
/*******************************************************************************
* Function Name : USB_LP_CAN1_RX0_IRQHandler
* Description : This function handles USB Low Priority or CAN RX0 interrupts
* requests.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
USB_Istr();
}
#endif /* STM32F10X_CL */
#if defined (USE_STM3210B_EVAL) || defined (USE_STM3210E_EVAL)
/*******************************************************************************
* Function Name : USART1_IRQHandler
* Description : This function handles USART1 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
/* Send the received data to the PC Host*/
USART_To_USB_Send_Data();
}
/* If overrun condition occurs, clear the ORE flag and recover communication */
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
{
(void)USART_ReceiveData(USART1);
}
}
#endif /* USE_STM3210B_EVAL or USE_STM3210E_EVAL */
#ifdef USE_STM3210C_EVAL
/*******************************************************************************
* Function Name : USART2_IRQHandler
* Description : This function handles USART2 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
/* Send the received data to the PC Host*/
USART_To_USB_Send_Data();
}
/* If overrun condition occurs, clear the ORE flag and recover communication */
if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)
{
(void)USART_ReceiveData(USART2);
}
}
#endif /* USE_STM3210C_EVAL */
#ifdef STM32F10X_CL
/*******************************************************************************
* Function Name : OTG_FS_IRQHandler
* Description : This function handles USB-On-The-Go FS global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void OTG_FS_IRQHandler(void)
{
STM32_PCD_OTG_ISR_Handler();
}
#endif /* STM32F10X_CL */
/*******************************************************************************
* Function Name : I2C1_EV_IRQHandler
* Description : This function handles I2C1 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C1_EV_IRQHandler(void)
{
switch (I2C_GetLastEvent(I2C1))
{
/* Test on I2C1 EV5 and clear it */
case I2C_EVENT_MASTER_MODE_SELECT:
/* Send I2C2 slave Address for write */
I2C_Send7bitAddress(I2C1, I2C2_SLAVE_ADDRESS7, I2C_Direction_Transmitter);
break;
/* Test on I2C1 EV6 and first EV8 and clear them */
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
/* I2C1 and I2C2 PEC Transmission Enable */
I2C_CalculatePEC(I2C1, ENABLE);
I2C_CalculatePEC(I2C2, ENABLE);
/* Send the first data */
I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx++]); //EV8 just after EV6
break;
/* Test on I2C1 EV8 and clear it */
case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
if(Tx_Idx < BufferSize)
{
/* Send buffer data */
I2C_SendData(I2C1, I2C1_Buffer_Tx[Tx_Idx++]);
}
else
{
/* Disable I2C1 interrupts */
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
/* Enable Transfer PEC next for I2C1 and I2C2 */
I2C_TransmitPEC(I2C2, ENABLE);
I2C_TransmitPEC(I2C1, ENABLE);
}
break;
default:
break;
}
}
/*******************************************************************************
* Function Name : I2C1_ER_IRQHandler
* Description : This function handles I2C1 Error interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C1_ER_IRQHandler(void)
{
}
/*******************************************************************************
* Function Name : I2C2_EV_IRQHandler
* Description : This function handles I2C2 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C2_EV_IRQHandler(void)
{
switch (I2C_GetLastEvent(I2C2))
{
/* Test on I2C2 EV1 and clear it */
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
break;
/* Test on I2C2 EV2 and clear it */
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
if (Rx_Idx < BufferSize)
{
/* Store received data buffer */
I2C2_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData(I2C2);
}
else
{
/* Store received PEC value */
PEC_Value = I2C_ReceiveData(I2C2);
Rx_Idx++;
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
}
break;
/* Test on I2C2 EV4 and clear it */
case I2C_EVENT_SLAVE_STOP_DETECTED:
/* Clear STOPF flag */
I2C_ClearFlag(I2C2, I2C_FLAG_STOPF);
/* Disable I2C2 interrupts */
I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
break;
default:
break;
}
}
/*******************************************************************************
* Function Name : I2C2_ER_IRQHandler
* Description : This function handles I2C2 Error interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C2_ER_IRQHandler(void)
{
}
接線示意圖
實驗結果
實驗二 可變資料筆數的傳收
實驗說明:如何使用interrupt讓能傳送使用者指定多少筆數目的data給I2C_2,其中使用7 bits address模式,clock rate是200KHz。接續實驗一的設定,修改main.c和I2C 中斷stm32f10x_it.c程式碼
主要程式碼說明:
I2C main.c程式碼
int main(void)
{
u8 num;
Set_System();
getchar();
NVIC_Configuration();
GPIO_Configuration();
printf("How many data do you want to send\r\n");
scanf("%d", &num);
DataSize = num;
printf("DataSize %d\r\n", DataSize);
/* I2C1 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //快速模式下的選項,100KHZ以上才有用
I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7; //slave address長度
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //每次都會回送ACK
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = ClockSpeed; // I2C 速度配置,這個範例是200KHz,一般是40KHZ,400KHZ是極限,一般到不了那麼高
I2C_Init(I2C1, &I2C_InitStructure);
printf("I2C1 configuration\r\n");
/* I2C2 configuration ------------------------------------------------------*/
I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;
I2C_Init(I2C2, &I2C_InitStructure);
printf("I2C2 configuration\r\n");
/*----- Transmission Phase -----*/
/* Send I2C1 START condition */
/* Enable I2C1 and I2C2 event and buffer interrupt */
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
/* Enable I2C1 and I2C2 ----------------------------------------------------*/
I2C_Cmd(I2C1, ENABLE);
I2C_Cmd(I2C2, ENABLE);
I2C_GenerateSTART(I2C1, ENABLE);
printf("Send I2C1 START condition\r\n");
/* Send data */
//修改部分
while(Rx_Idx < (num+1))
{
}
/* Check the corectness of written data */
printf("Check the corectness of written data\r\n");
TransferStatus = Buffercmp(I2C1_Buffer_Tx, I2C2_Buffer_Rx, num);
printf("Buffercmp Finish\r\n");
/* TransferStatus = PASSED, if the transmitted and received data are equal */
/* TransferStatus = FAILED, if the transmitted and received data are different */
if(TransferStatus) printf("Transmission SUCESS\r\n");
else printf("Transmission FAILED\r\n");
while(1)
{
}
}
I2C 中斷stm32f10x_it.c程式碼
/*******************************************************************************
* Function Name : I2C1_EV_IRQHandler
* Description : This function handles I2C1 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C1_EV_IRQHandler(void)
{
vu8 num;
switch (I2C_GetLastEvent(I2C1))
{
/* Test on I2C1 EV5 and clear it */
case I2C_EVENT_MASTER_MODE_SELECT:
/* Send I2C2 slave Address for write */
I2C_Send7bitAddress(I2C1, I2C2_SLAVE_ADDRESS7, I2C_Direction_Transmitter);
break;
/* Test on I2C1 EV6 and first EV8 and clear them */
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
/* I2C1 and I2C2 PEC Transmission Enable */
I2C_CalculatePEC(I2C1, ENABLE);
I2C_CalculatePEC(I2C2, ENABLE);
/* Send the first data */
num = Tx_Idx++;
I2C_SendData(I2C1, I2C1_Buffer_Tx[num]); //EV8 just after EV6
printf("Send Data %d...\r\n", I2C1_Buffer_Tx[num]);
break;
/* Test on I2C1 EV8 and clear it */
case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
if(Tx_Idx < DataSize)
{
/* Send buffer data */
num = Tx_Idx++;
I2C_SendData(I2C1, I2C1_Buffer_Tx[num]);
printf("Send Data %d...\r\n", I2C1_Buffer_Tx[num]);
}
else
{
/* Disable I2C1 interrupts */
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
/* Enable Transfer PEC next for I2C1 and I2C2 */
I2C_TransmitPEC(I2C2, ENABLE);
I2C_TransmitPEC(I2C1, ENABLE);
}
break;
default:
break;
}
}
/*******************************************************************************
* Function Name : I2C2_EV_IRQHandler
* Description : This function handles I2C2 Event interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void I2C2_EV_IRQHandler(void)
{
switch (I2C_GetLastEvent(I2C2))
{
/* Test on I2C2 EV1 and clear it */
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
break;
/* Test on I2C2 EV2 and clear it */
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
if (Rx_Idx < DataSize)
{
/* Store received data buffer */
I2C2_Buffer_Rx[Rx_Idx++] = I2C_ReceiveData(I2C2);
}
else
{
/* Store received PEC value */
PEC_Value = I2C_ReceiveData(I2C2);
Rx_Idx++;
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE);
}
break;
/* Test on I2C2 EV4 and clear it */
case I2C_EVENT_SLAVE_STOP_DETECTED:
/* Clear STOPF flag */
I2C_ClearFlag(I2C2, I2C_FLAG_STOPF);
/* Disable I2C2 interrupts */
I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
break;
default:
break;
}
}
實驗結果
COM4為SPI1結果,COM9為SPI2結果
留言列表