2023-12-16 21:50:10 [显示全部楼层]
1049浏览
查看: 1049|回复: 0

[求助] 手撸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("未发现寄存器");
    }
}





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail