stm32软件模拟IIC读取PX4FLOW光流传感器数据

时间:2021-12-28 15:55:06

这段时间在做全国光电设计大赛,用到了px4的px4flow光流传感器,用软件模拟iic读取数据不定期会导致px4flow死机,查了资料和光流的源码,发现这个光流用了stm32的硬件iic,所以对软件模拟iic的时序要求可能更高一点所以在原子哥的iic程序上做了修改,代码测验后已经不会死机,做个笔记,保存一下。

 #include "myiic.h"
 #include "delay.h"

 //初始化IIC
 void IIC_Init(void)
 {
 19   GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟

   //GPIOB10,B11初始化设置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
    IIC_SCL=;
    IIC_SDA=;
 }
 //产生IIC起始信号
 void IIC_Start(void)
 {
     SDA_OUT();     //sda线输出
     IIC_SDA=;          

     delay_us();    

     IIC_SCL=;
     delay_us();
     IIC_SDA=;//START:when CLK is high,DATA change form high to low
     delay_us();
     IIC_SCL=;//钳住I2C总线,准备发送或接收数据
 }
 //产生IIC停止信号
 void IIC_Stop(void)
 {
     SDA_OUT();//sda线输出
     IIC_SCL=;

     delay_us();

     IIC_SDA=;//STOP:when CLK is high DATA change form low to high
     delay_us();
     IIC_SCL=; 

     delay_us();

     IIC_SDA=;//发送I2C总线结束信号
     delay_us();
 }
 //等待应答信号到来
 //返回值:1,接收应答失败
 //        0,接收应答成功
 u8 IIC_Wait_Ack(void)
 {
     u8 ucErrTime=;
     SDA_IN();      //SDA设置为输入
     IIC_SDA=;
     delay_us();
     IIC_SCL=;
     delay_us();
     while(READ_SDA)                 //可能可以把数搞大点
     {
         ucErrTime++;
         )
         {
             IIC_Stop();
             ;
         }
     }
     IIC_SCL=;//时钟输出0
     ;
 }
 //产生ACK应答
 void IIC_Ack(void)
 {
     IIC_SCL=;

     delay_us();

     SDA_OUT();
     IIC_SDA=;
     delay_us();
     IIC_SCL=;
     delay_us();
     IIC_SCL=;
 }
 //不产生ACK应答
 void IIC_NAck(void)
 {
     IIC_SCL=;

     delay_us();

     SDA_OUT();
     IIC_SDA=;
     delay_us();
     IIC_SCL=;
     delay_us();
     IIC_SCL=;
 }
 //IIC发送一个字节
 //返回从机有无应答
 //1,有应答
 //0,无应答
 void IIC_Send_Byte(u8 txd)
 {
     u8 t;
     SDA_OUT();
     IIC_SCL=;//拉低时钟开始数据传输
     ;t<;t++)
     {
         IIC_SDA=(txd&;
         txd<<=;
         delay_us();
         IIC_SCL=;
         delay_us();
         IIC_SCL=;
         delay_us();
     }
 }
 //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
 u8 IIC_Read_Byte(unsigned char ack)
 {
     unsigned ;
     SDA_IN();//SDA设置为输入
     ;i<;i++ )
     {
         IIC_SCL=;
         delay_us();
         IIC_SCL=;
         receive<<=;
         if(READ_SDA)
             receive++;
         delay_us();
     }
     if (!ack)
         IIC_NAck();//发送nACK
     else
         IIC_Ack(); //发送ACK
     return receive;
 }

空行间隔的为新增延时,和注释不一样的为改了的延时