电子商务网站建设 试卷,电子商务网站建设需求分析报告,重庆网站怎么做出来的,书写网站建设策划书I2C模块内部结构
I2C#xff08;Inter-Integrated Circuit#xff09;模块是一种由Philips公司开发的二线式串行总线协议#xff0c;用于短距离通信#xff0c;允许多个设备共享相同的总线。
硬件连接简单#xff1a;I2C通信仅需要两条总线#xff0c;即SCL…I2C模块内部结构
I2CInter-Integrated Circuit模块是一种由Philips公司开发的二线式串行总线协议用于短距离通信允许多个设备共享相同的总线。
硬件连接简单I2C通信仅需要两条总线即SCL时钟线和SDA数据线大大简化了系统的硬件设计12。支持多设备共享在I2C总线中可以挂载多个从设备每个设备都有一个唯一的地址主设备通过广播地址的方式与从设备进行通信25。传输速率灵活I2C总线传输模式具有向下兼容性传输速率在标准模式下可达100kbps快速模式下可达400kbps高速模式下更是可达3.4Mbps34。 引脚初始化
引脚映射表 引脚实现代码
void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed GPIO_Speed_2MHz;GPIO_Init(GPIOB,GPIO_InitStruct)
}
连接电路 波特率
I2C的波特率指的是I2C总线上的数据传输速率它可以根据不同的模式达到不同的速率。具体来说
在标准模式下I2C的波特率为100kHz12。在快速模式下I2C的波特率可以达到400kHz12。还有一些更高速的模式如快速模式波特率可以达到1MHz1。
I2C总线中的波特率由主机控制主机通过产生SCL时钟线信号来分配给所有从机因此主机可以通过控制时钟信号频率来调节波特率即控制通信速度。这种灵活性使得I2C总线能够适应不同的通信需求和应用场景。 占空比
在I2C总线通信中占空比是指数据线SDA上的高电平持续时间与整个时钟周期由时钟线SCL控制的比例。这个比例决定了数据传输的稳定性和可靠性12。 在没有明确的情况下我们选择2/1的占空比
初始化I2C模块代码
void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed GPIO_Speed_2MHz;GPIO_Init(GPIOB,GPIO_InitStruct);RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);//开启I2C的时钟RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,ENABLE);//施加复位信号RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1,DISABLE);//释放复位信号I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed 400000;//波特率400kI2C_InitStruct.I2C_Mode I2C_Mode_I2C;//标准的I2CI2C_InitStruct.I2C_DutyCycle I2C_DutyCycle_2;//占空比2:1I2C_Init(I2C1,I2C_InitStruct);I2C_Cmd(I2C1,ENABLE);//闭合I2C1的总开关
}
写数据
数据发送的流程 主设备向从设备发送数据
发送起始信号主设备在SCL时钟线为高电平时将SDA数据线从高拉低产生起始信号通知所有从设备准备接收数据。发送设备地址主设备紧接着发送从设备的7位地址以及一个写信号通常是低电平指示这是一个写操作。等待从设备响应从设备监测到自己的地址后通过在下一个时钟周期拉低SDA线发送ACK来响应确认它准备好了接收数据。发送数据主设备开始发送数据每个字节数据后会跟着等待接收来自从设备的响应ACK。从设备在接收到每个字节后都会发送一个ACK信号来确认。发送停止信号数据发送完毕后主设备发送停止信号SCL高时SDA从低变高终止传输。
从设备向主设备发送数据
主设备初始化读取操作主设备发送起始信号然后发送从设备的地址以及一个读取位通常是高电平指示这是一个读取操作。从设备响应从设备监测到自己的地址后通过发送ACK信号来响应。主设备发送重复开始信号或停止信号如果主设备计划在同一事务中连续读取多个从设备或进行连续读取它可以发送重复开始信号来保持总线控制权。如果仅从当前从设备读取且读取操作即将结束主设备在收到从设备的ACK后可直接发送停止信号。从设备发送数据在收到读取命令后从设备开始发送数据。主设备在接收到每个字节后都会发送一个ACK信号来确认。当接收到最后一个数据字节后主设备可能会发送一个无效响应NACK然后发送停止信号来终止传输。
等待总线空闲 发送数据前要监控总线是否繁忙从BUSY标志位来判断总线是否空闲I2C_GetFlagStatus函数用来获取BUSY标志。I2C_GetFlagStatus 函数是一个在 STM32 微控制器的 I2CInter-Integrated Circuit库函数中常用的函数用于检查 I2C 接口的状态标志。这个函数通常用于轮询polling方式以确定 I2C 总线上的特定事件或状态是否已经发生例如数据传输完成、接收到起始信号、检测到错误等。
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
I2Cx指向要检查的 I2C 接口的指针。例如对于 STM32F103 系列可能是 I2C1 或 I2C2。I2C_FLAG要检查的特定 I2C 状态标志。这些标志在 STM32 的 I2C 库头文件中定义通常是以 I2C_FLAG_ 开头的宏。返回值是 FlagStatus 枚举类型它通常有两个可能的值SET标志已设置和 RESET标志未设置。
发送起始位 发送起始位是向START寄存器内写数值1使用函数I2C_GenerateStart完成。 I2C_GenerateStart 函数是用于生成 I2C 通信起始条件START condition的函数。在 I2C 通信中起始条件是一个重要的信号用于通知所有连接到总线的设备即将开始数据传输。当 NewState 参数为 ENABLE 时I2C_GenerateStart 函数会设置相应的寄存器位从而在 I2C 总线上生成一个起始条件。起始条件是一个在 SCL时钟线为高电平时SDA数据线由高电平变为低电平的边沿。这个边沿会被所有连接到总线的 I2C 设备检测到并通知它们即将开始数据传输。
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
I2Cx指向要操作的 I2C 接口的指针。在 STM32 微控制器中这通常是 I2C1、I2C2 等。NewState这是一个 FunctionalState 枚举类型的值用于指定是否生成起始条件。它可以是 ENABLE生成起始条件或 DISABLE不生成起始条件。 在发送起止位后我们需要确定起止位是否发送完毕我们通过SB标志来判断。
while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB) RESET);
发送地址 AF标志位是ACK应答标志位当AF为1时ACK答应失败未收到答应ADDR寻址成功标志位当寻址成功值为1失败值为0。在发送地址前我们需要清理AF标志位的值然后发送地址。
I2C_ClearFlag(I2Cx,I2C_FLAG_AF);//清除AF
I2C_SendData(I2Cx,Addr 0xfe);//发送地址和RW
在发送的过程中需要持续判断AF和ADDR标识符的状态
while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR) SET){break;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -1;}
}
后续我们继续清除ADDR状态标示符
I2C_ReadRegister(I2Cx,I2C_Register_SR1);
I2C_ReadRegister(I2Cx,I2C_Register_SR2);
发送数据 发送数据过程中我们要持续监控ACK和发送数据寄存器的状态AF为1标示为响应ACK停止发送数据BTF负责监控发送数据寄存器内是否有数据保证在其空的情况下推送数据进入。
发送停止位 代码
int main(){My_I2C_Init();uint8_t commands[] {0x00,0x8d,0x14,0xaf,0xa5};My_I2C_SendBytes(I2C1,0x78,commands,5);
}void My_I2C_Init(){
//对I2C进行重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
//对PB8和PB9进行初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed GPIO_Speed_2MHz;GPIO_Init(GPIOB,GPIO_InitStruct);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//开启I2C的时钟RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,ENABLE);//施加复位信号RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1,DISABLE);//释放复位信号I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed 400000;//波特率400kI2C_InitStruct.I2C_Mode I2C_Mode_I2C;//标准的I2CI2C_InitStruct.I2C_DutyCycle I2C_DutyCycle_2;//占空比2:1I2C_Init(I2C1,I2C_InitStruct);I2C_Cmd(I2C1,ENABLE);//闭合I2C1的总开关
}int My_I2C_SendBytes(I2C_TypeDef *I2Cx,uint8_t Addr,uint8_t *pData,uint16_t Size){//等待总线空闲while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BUSY) SET){}//发送起止位I2C_GenerateSTART(I2C1,ENABLE);//确定起止位是否发送完毕 while(I2C_GetFlagStatus(I2Cx,I2C_FLAG_SB) RESET){}//发送地址//清除AFI2C_ClearFlag(I2Cx,I2C_FLAG_AF);I2C_SendData(I2Cx,Addr 0xfe);while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR) SET){break;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -1;//寻址失败}}//清除ADDRI2C_ReadRegister(I2Cx,I2C_Register_SR1);I2C_ReadRegister(I2Cx,I2C_Register_SR2);//发送数据 for(uint8_t i 0;iSize;i){while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE) SET){break;}}I2C_SendData(I2Cx,pData[i]);}while(1){if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_AF) SET){I2C_GenerateSTOP(I2Cx,ENABLE);return -2;}if(I2C_GetFlagStatus(I2Cx,I2C_FLAG_BTF) SET){break;}}//发送停止位I2C_GenerateSTOP(I2Cx,ENABLE);return 0;
}