恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
I2C数据抓取
首页
资讯中心
/
I2C数据抓取
I2C数据抓取
发布时间:2026/10/17 2:29:15
PB6:SCL PB7:SDA PD1:TEST脚(遇START/STOP/取反,读取sda电平)加了while(1)循环接收数据,START.STOP.SR会漏检测,数据也不对.开始我写的接收数据位流程是,SCL1读到SDA是多少就直接写进去了,如果说这时SDA数据发送变化了呢?SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化检测到start加了while(1)循环接收数据,SCL1时读取SDA,我们在读SDA确认要写入databuf之前要先判断sda是否有变化;如果说开始读到scl1,sda1,等scl1,sda1时序跑完变成scl1,sda0就是SR,是sr就继续接收数据goto receivesr; ,还是scl1,sda1 没变就写入databuf;如果说开始读到scl1,sda0,等scl1,sda0时序跑完变成scl1,sda1就是STOP,是STOP就重新去找起始条件goto start;//是STOP找START忽略应答位,只把他的时序走完不做任何操作I2C时序:空闲状态 起始条件-接收一个字节(8位)-应答位(1位)-停止条件空闲状态:SCL高电平,SDA高电平start:/*起始条件*/if((GPIOB-IDR 0x80) (GPIOB-IDR 0x40)) //SCL1 SDA1{起始条件(START):SCL高电平期间SDA从高电平切换到低电平;SCL从高电平切换到低电平,表示主机准备将数据位依次放到SDA线上高位先行while((GPIOB-IDR 0x40) (GPIOB-IDR 0x80)); //等待SCL1 SDA1跑完if((GPIOB-IDR 0x40) !(GPIOB-IDR 0x80)) //SCL1 SDA1跑完后,SCL1 SDA0 是起始条件{GPIOD-ODR ^ GPIO_Pin_1; //D1取反while((GPIOB-IDR 0x40) !(GPIOB-IDR 0x80)); //等待 SCL1 SDA0 起始条件 跑完while(GPIOB-IDR 0x40); //拉低scl等待下一时序接收一个字节:7位从机地址1位读(1)写(0)SCL低电平期间主机将数据位依次放到SDA线上高位先行然后释放SCL从机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化依次循环上述过程8次即可发送一个字节for(i0; i8; i) //接收8位数据{while(!(GPIOB-IDR 0x40)); //等待SCL拉高if(GPIOB-IDR 0x40) //SCL1{/*SCL1读取SDA,SDA为1就写1,为0默认写0*/if((GPIOB-IDR 0x80)) //SCL1 SDA1{/*在写期间判断SCL1时SDA是否有变化*/while((GPIOB-IDR 0x40) (GPIOB-IDR 0x80)); //等待SCL1 SDA1跑完if((GPIOB-IDR 0x40) (!(GPIOB-IDR 0x80))) //SCL1 SDA1跑完后,SCL1 SDA0, SCL1期间SDA由1-0是重复起始条件sr{GPIOD-ODR ^ GPIO_Pin_1;while((GPIOB-IDR 0x40) (!(GPIOB-IDR 0x80)));//等待SCL1 SDA0跑完while(GPIOB-IDR 0x40); //拉低scl等待下一时序goto receivesr; //是sr,继续接收}else{ //没有变化,直接接收1GPIOD-BSRR (11);//Hdatabuf | (0x80i); //置1}}else{ //SCL1 SDA0while((GPIOB-IDR 0x40) (!(GPIOB-IDR 0x80))); //等待SCL1 SDA0跑完if((GPIOB-IDR 0x40) (GPIOB-IDR 0x80))//SCL1 SDA0跑完后,SCL1 SDA1, SCL1期间SDA由0-1是结束条件STOP{GPIOD-ODR ^ GPIO_Pin_1;goto start; //是STOP找START}else{ //没有变化,直接接收0GPIOD-BRR (11);//Ldatabuf ~(0x80i); //置0}}}}接收应答位(先忽略):接收前释放SDA,避免干扰从机的数据发送;释放SCL,主机在SCL高电平期间读取SDA,拉低SCL开始下一个时序模块/*ACK*/while(!(GPIOB-IDR 0x40)); // 等 SCL 高if(GPIOB-IDR 0x80){GPIOD-BSRR (11);//Lack 1;}else{GPIOD-BRR (11);//Lack 0;}while(GPIOB-IDR 0x40); // 等 SCL 低终止条件SCL高电平期间SDA从低电平切换到高电平while((GPIOB-IDR 0x40) (!(GPIOB-IDR 0x80))); //等待SCL1 SDA0跑完if((GPIOB-IDR 0x40) (GPIOB-IDR 0x80))//SCL1 SDA0跑完后,SCL1 SDA1, SCL1期间SDA由0-1是结束条件STOP{GPIOD-ODR ^ GPIO_Pin_1;goto start; //是STOP找START