手撸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]