STM32---------- I2C
来源:互联网 发布:贵州省大数据局电话 编辑:程序博客网 时间:2024/05/23 01:23
I2C主模式接收(Receiver)过程: (注意事件为EV7)
I2C主模式发送(Transmitter)过程: (注意事件为EV8)
先发一个起始信号S ,再发一个地址,接着等待一个回应A ,然后发数据,再回应(在发完一个S后,要等待一个事件EVENT,比如
while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT) ) I2C_EVENT_MASTER_MODE_SELECT 就是EV5
发送地址 I2C_Send7bitAddress(I2C1, DevAddr, I2C_Direction_Transmitter);//发送器件地址 DevAddr是外部如EEPROM等设备的地址,Transmitter是指STM32要从外部设备读取数据,因为外部数据要发送(Transmitter)
发完地址要等一个EV6的事件while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)
I2C在STM32中使用的步骤如下:
1、开启时钟,APB2 的GPIOB 和APB1的I2C2
2、设置GPIOB的10和11引脚,注意要设置为复用开漏输出GPIO_MODE_AF_OD
3、I2C 的配置(Mode 设置为I2C_Mode_I2C DutyCycle是一种快速模式)
使能和初始化I2C模块
4、完整例程
/* Includes ------------------------------------------------------------------*/#include "stm32f10x_lib.h"#include "i2c_ee.h"#include"delay.h"/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*/#define I2C_Speed 10000#define I2C1_SLAVE_ADDRESS7 0xA0#define I2C_PageSize 4/* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*/u16 EEPROM_ADDRESS;/* Private function prototypes -----------------------------------------------*/void I2C_Configuration(void);/******************************************************************************** Function Name : I2C_Configuration* Description : I2C Configuration* Input : None* Output : None* Return : None*******************************************************************************/void I2C_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure;/* Configure I2C1 pins: SCL and SDA */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//开漏输出GPIO_Init(GPIOB, &GPIO_InitStructure);/* I2C configuration */I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//设置 I2C为 I2C模式I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速模式 Tlow / Thigh = 2 I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;//设置第一个设备地址I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//使能应答I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//应答 7位地址I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//设置时钟频率/* I2C Peripheral Enable */I2C_Cmd(I2C1, ENABLE);//使能I2C外设/* Apply I2C configuration after enabling it */I2C_Init(I2C1, &I2C_InitStructure);}/******************************************************************************** Function Name : I2C_EE_Init* Description : Initializes peripherals used by the I2C EEPROM driver.* Input : None* Output : None* Return : None*******************************************************************************/void I2C_EE_Init(){/* I2C configuration */I2C_Configuration();/* depending on the EEPROM Address selected in the i2c_ee.h file */#ifdef EEPROM_Block0_ADDRESS/* Select the EEPROM Block0 to write on */EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;#endif#ifdef EEPROM_Block1_ADDRESS/* Select the EEPROM Block1 to write on */EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;#endif#ifdef EEPROM_Block2_ADDRESS/* Select the EEPROM Block2 to write on */EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;#endif#ifdef EEPROM_Block3_ADDRESS/* Select the EEPROM Block3 to write on */EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;#endif}/******************************************************************************** Function Name : I2C_EE_BufferWrite* Description : Writes buffer of data to the I2C EEPROM.* Input : - pBuffer : pointer to the buffer containing the data to be * written to the EEPROM.* - WriteAddr : EEPROM's internal address to write to.* - NumByteToWrite : number of bytes to write to the EEPROM.* Output : None* Return : NonepBuffer:指向要写入数据数组的指针WriteAddr:24c02中要写入数据的首地址NumByteToWrite:写入的字节数*******************************************************************************/void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)//将缓冲器的数据写入EEPROM{u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;Addr = WriteAddr % I2C_PageSize;//写入地址是每页的第几位count = I2C_PageSize - Addr;//在开始的一页要写入的个数NumOfPage = NumByteToWrite / I2C_PageSize;//要写入的页数NumOfSingle = NumByteToWrite % I2C_PageSize;//不足一页的个数I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态/* If WriteAddr is I2C_PageSize aligned */if(Addr == 0) //写入地址是页的开始{ /* If NumByteToWrite < I2C_PageSize */ if(NumOfPage == 0) //数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 } /* If NumByteToWrite > I2C_PageSize */ else //数据大于等于一页 { while(NumOfPage--)//要写入的页数 { I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //写一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; } if(NumOfSingle!=0)//剩余数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 } }}/* If WriteAddr is not I2C_PageSize aligned */else //写入地址不是页的开始{ /* If NumByteToWrite < I2C_PageSize */ if(NumOfPage== 0) //数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写少于一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 } /* If NumByteToWrite > I2C_PageSize */ else//数据大于等于一页 { NumByteToWrite -= count; NumOfPage = NumByteToWrite / I2C_PageSize; //重新计算要写入的页数 NumOfSingle = NumByteToWrite % I2C_PageSize;//重新计算不足一页的个数 if(count != 0)//在此处count一定不为0,此判断条件好象有点多余 { I2C_EE_PageWrite(pBuffer, WriteAddr, count);//将开始的空间写满一页 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 WriteAddr += count; pBuffer += count; } while(NumOfPage--)//要写入的页数 { I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);//写一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; } if(NumOfSingle != 0)//剩余数据小于一页 { I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle); //写少于一页的数据 I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态 } }}}/******************************************************************************** Function Name : I2C_EE_ByteWrite* Description : Writes one byte to the I2C EEPROM.* Input : - pBuffer : pointer to the buffer containing the data to be * written to the EEPROM.* - WriteAddr : EEPROM's internal address to write to.* Output : None* Return : NonepBuffer:指向要写入数据数组的指针WriteAddr:24c02中要写入数据的首地址*******************************************************************************/void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)//写一个字节到EEPROM{/* Send STRAT condition */I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件/* Test on EV5 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件/* Send EEPROM address for write */I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向/* Test on EV6 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件 /* Send the EEPROM's internal address to write to */I2C_SendData(I2C1, WriteAddr);//通过外设 I2Cx发送地址/* Test on EV8 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件/* Send the byte to be written */I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据 /* Test on EV8 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件/* Send STOP condition */I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件}/******************************************************************************** Function Name : I2C_EE_PageWrite* Description : Writes more than one byte to the EEPROM with a single WRITE* cycle. The number of byte can't exceed the EEPROM page size.* Input : - pBuffer : pointer to the buffer containing the data to be * written to the EEPROM.* - WriteAddr : EEPROM's internal address to write to.* - NumByteToWrite : number of bytes to write to the EEPROM.* Output : None* Return : NonepBuffer:指向要写入数据数组的指针WriteAddr:24c02中要写入数据的首地址NumByteToWrite:写入的字节数*******************************************************************************/void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)//写少于一页的数据{/* Send START condition */I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件/* Test on EV5 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //检查最近一次 I2C事件是否是输入的事件/* Send EEPROM address for write */I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向/* Test on EV6 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查最近一次 I2C事件是否是输入的事件/* Send the EEPROM's internal address to write to */ I2C_SendData(I2C1, WriteAddr); //通过外设 I2Cx发送地址/* Test on EV8 and clear it */while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //检查最近一次 I2C事件是否是输入的事件/* While there is data to be written */while(NumByteToWrite--) { /* Send the current byte */ I2C_SendData(I2C1, *pBuffer); //通过外设 I2Cx发送数据 /* Point to the next byte to be written */ pBuffer++; /* Test on EV8 and clear it */ while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件}/* Send STOP condition */I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件}/******************************************************************************** Function Name : I2C_EE_BufferRead* Description : Reads a block of data from the EEPROM.* Input : - pBuffer : pointer to the buffer that receives the data read * from the EEPROM.* - ReadAddr : EEPROM's internal address to read from.* - NumByteToRead : number of bytes to read from the EEPROM.* Output : None* Return : NonepBuffer:指向要保存读出数据的数组的指针ReadAddr:24c02中要读出数据的首地址NumByteToRead:读出的字节数*******************************************************************************/void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//将EEPROM的数据读入缓冲器{ I2C_EE_WaitEepromStandbyState();//EEPROM设为待命状态/* Send START condition */I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件/* Test on EV5 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件/* In the case of a single data transfer disable ACK before reading the data */if(NumByteToRead==1) { I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能}/* Send EEPROM address for write */I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向/* Test on EV6 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件/* Clear EV6 by setting again the PE bit */I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外设/* Send the EEPROM's internal address to write to */I2C_SendData(I2C1, ReadAddr); //通过外设 I2Cx发送地址/* Test on EV8 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件/* Send STRAT condition a second time */ I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件/* Test on EV5 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件/* Send EEPROM address for read */I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的从 I2C设备传送地址字,选择接收方向/* Test on EV6 and clear it */while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件/* While there is data to be read */while(NumByteToRead) { /* Test on EV7 and clear it */ if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检查最近一次 I2C事件是否是输入的事件 { if(NumByteToRead == 2) { /* Disable Acknowledgement */ I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能 } if(NumByteToRead == 1) { /* Send STOP Condition */ I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件 } /* Read a byte from the EEPROM */ *pBuffer = I2C_ReceiveData(I2C1);//返回通过 I2Cx最近接收的数据 /* Point to the next location where the byte read will be saved */ pBuffer++; /* Decrement the read bytes counter */ NumByteToRead--; } }/* Enable Acknowledgement to be ready for another reception */I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的应答功能}/******************************************************************************** Function Name : I2C_EE_WaitEepromStandbyState* Description : Wait for EEPROM Standby state* Input : None* Output : None* Return : None*******************************************************************************/void I2C_EE_WaitEepromStandbyState(void) //EEPROM设为待命状态 {vu16 SR1_Tmp = 0;do{ /* Send START condition */ I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件 /* Read I2C1 SR1 register */ SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);//读取指定的 I2C寄存器 I2C_SR1 并返回其值 /* Send EEPROM address for write */ I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字 ,选择发送方向}while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//地址发送结束/* Clear AF flag */I2C_ClearFlag(I2C1, I2C_FLAG_AF);//清除 I2Cx的应答错误标志位}
- STM32---------- I2C
- STM32--硬件I2C-2402
- STM32-寄存器I2C--2402
- STM32-I2C-appcat延时
- stm32 I2C问题 I2C_CheckEvent()
- STM32学习之I2C
- STM32 I2C 难点
- STM32 I2C读写
- stm32 I2C问题 I2C_CheckEvent()
- STM32--硬件I2C-2402
- STM32-寄存器I2C--2402
- STM32-I2C-appcat延时
- STM32 I2C 难点
- STM32 I2C读写
- STM32之I2C
- STM32之I2C
- STM32 I2C硬件
- STM32——I2C
- PageRank算法简介及Map-Reduce实现
- html5 最强大脑最强记忆游戏
- CodeChef January Long Challenge 2016 - SEAKAM
- java--继承中函数覆盖图解
- 脑洞大开:为啥帧率达到 60 fps 就流畅?
- STM32---------- I2C
- libjpeg 库的安装
- CentOS Zookeeper+Kafka单机搭建
- iOS-制作Framework
- Android IntentService
- UVA 10008 whats cryptanalysis 水题
- Crazepony开源四轴飞行器
- 玩转OpenCV之一:关于OpenCV学习版本的选择
- HDU1584 蜘蛛牌 [DFS简单题]