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("未发现寄存器"); } } |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed