是CC啊 发表于 2023-12-16 21:50:10

手撸IIC通信协议,ACK信号有问题。

问题是寻IIC地址没问题,也就是调用findDevice() 功能正常,但是寻MPU6050的寄存器时总是收不到ACK。
开始也没想着去寻全部的寄存器地址的,只是想给0x6B寄存器发一个0唤醒MPU6050读取温度数据,
但是发送寄存器地址后收不到ACK

以下是我的 myWire.h文件部分
#pragma once
typedef unsigned char uchar;
class myWire
{
    private:
    uchar SDA;
    uchar SCL;
    //信号部分
    //由主机发出的部分
    void signStart();//开始通信的信号
    void signStop();//停止通信的信号
    void sendAck(bool ack);//发送应答信号
    bool readAck();//接收应答信号

    public:
    myWire(uchar sda,uchar scl);//构造函数,设置SDA,SCL引脚
    void sendByte(uchar data);//发送一个字节数据
    uchar readByte();//接收数据
    void sendAddr(uchar addr,bool WR);//0为写,1为读
    void findDevice();//查找设备
    void findRegister();
    void sendDataToRegister(uchar addr,uchar reg,uchar data);//向IIC设备的寄存器写入数据
};
// void myWire::sendDataToRegister(uchar addr,uchar reg,uchar data)//向IIC设备的寄存器写入数据
// {
//   this->sendAddr(addr,0);
//   this->readAck();
//   this->sendByte(reg);
//   this->readAck();
//   this->sendByte(data);
//   this->readAck();
//   this->signStop();
// }
void myWire::sendDataToRegister(uchar addr,uchar reg,uchar data)//向IIC设备的寄存器写入数据
{
    this->sendAddr(addr,0);
    if(this->readAck()==0)
    {
      Serial.println("写入IIC地址成功!");
      this->sendByte(0x6B);
      if(this->readAck()==0)
      {
            Serial.println("写入数据成功!");
            this->sendByte(0);
            this->readAck();
            this->signStop();
      }
      else this->signStop();
    }
    else this->signStop();
}
void myWire::sendAddr(uchar addr,bool WR)//0为写,1为读
{
    this->signStart();
    this->sendByte((addr<<1)|WR);
}
bool myWire::readAck()//接收应答信号
{
    bool data=0;
    pinMode(this->SDA,INPUT);
    digitalWrite(this->SCL,LOW);//时钟线为低时对方开始准备数据
    delayMicroseconds(5);//等待对方准备好数据
    digitalWrite(this->SCL,HIGH);//准备读数据
    delayMicroseconds(5);//数据稳定了,可以读取了
    data=digitalRead(this->SDA);
    digitalWrite(this->SCL,LOW);
    pinMode(this->SDA,OUTPUT);
    return data;
}
void myWire::sendAck(bool ack)//发送应答信号
{
    digitalWrite(this->SCL,LOW);
    //稳定SDA
    if(ack) digitalWrite(this->SDA,HIGH);
    else digitalWrite(this->SDA,LOW);
    delayMicroseconds(5);//等待准备的数据稳定
    //跳变SCL 发送SDA数据
    digitalWrite(this->SCL,HIGH);
    delayMicroseconds(5);
    digitalWrite(this->SCL,LOW);//拉低SCL,为下次发送做准备
}
uchar myWire::readByte()//接收数据
{
    uchar data=0;
    pinMode(this->SDA,INPUT);
    digitalWrite(this->SCL,LOW);//时钟线为低时对方开始准备数据
    for(int i=0;i<8;i++)
    {
      delayMicroseconds(5);//等待对方准备好数据
      digitalWrite(this->SCL,HIGH);//准备读数据
      delayMicroseconds(5);//数据稳定了,可以读取了
      data<<=1;
      data|=digitalRead(this->SDA);
      digitalWrite(this->SCL,LOW);
    }
    pinMode(this->SDA,OUTPUT);
    return data;
}

void myWire::sendByte(uchar data)//发送从机地址和读写位,0:写 1:读
{
    digitalWrite(this->SCL,LOW);
    for(int i=0;i<8;i++)
    {
      //稳定SDA
      if(data&(1<<(7-i))) digitalWrite(this->SDA,HIGH);
      else digitalWrite(this->SDA,LOW);
      delayMicroseconds(5);//等待准备的数据稳定
      //跳变SCL 发送SDA数据
      digitalWrite(this->SCL,HIGH);
      delayMicroseconds(5);
      digitalWrite(this->SCL,LOW);//拉低SCL,为下次发送做准备
    }
}


void myWire::signStop()//停止通信的信号
{
    digitalWrite(this->SDA,LOW);
    digitalWrite(this->SCL,HIGH);
    delayMicroseconds(5);   
    digitalWrite(this->SDA,HIGH);//SDA上跳,形成停止信号
    delayMicroseconds(5);
    digitalWrite(this->SCL,LOW);//空闲时钟为低
}
void myWire::signStart()//开始通信的信号
{
    digitalWrite(this->SDA,HIGH);
    digitalWrite(this->SCL,HIGH);
    delayMicroseconds(5);
    digitalWrite(this->SDA,LOW);//SDA下跳,形成启动信号
    delayMicroseconds(5);
    digitalWrite(this->SCL,LOW);//准备下次通信
}
myWire::myWire(uchar sda,uchar scl)//构造函数,设置SDA,SCL引脚
{
    this->SDA=sda;
    this->SCL=scl;
    pinMode(this->SCL,OUTPUT);
    pinMode(this->SDA,OUTPUT);
}
void myWire::findDevice()//查找设备
{
    int count=0;
    for(uchar i=0;i<128;i++)
    {
      this->signStart();
      this->sendByte((i<<1)|0);
      bool ask=this->readAck();
      this->signStop();
      if(ask==0)
      {
            Serial.print("0x");
            Serial.println(i,HEX);
            count++;
      }
    }
    if(count==0) Serial.println("未发现设备");
}
void myWire::findRegister()
{
    this->sendAddr(0x68,0);
    if(this->readAck()==0)
    {
      int count=0;
      for(uchar i=1;i<255;i++)
      {
            this->sendByte(i);
            bool ask=this->readAck();
            this->signStop();
            if(ask==0)
            {
                Serial.print("0x");
                Serial.println(i,HEX);
                count++;
            }
      }
      if(count==0) Serial.println("未发现寄存器");
    }
}





页: [1]
查看完整版本: 手撸IIC通信协议,ACK信号有问题。