|
一直想做四轴,就是没有行动。直到最近有点时间,开始着手做,之前在论坛里看了不少四轴的资料(烈火、圆点、匿名等),决定自己先做些底层的硬件平台熟悉熟悉,然后画板子。TB上买了STM32F103C8最小系统板+烧写器+MPU6050,开始调试:
因为之前没有用过ARM芯片,所以先花了两周的时间把IIC外设调通,之后再连接MPU6050。用了两种方法:分开读取加速度计数据、连续一次性读取加速度和角速度数据(时钟都是400K)。废话不多说上图:
方法一:一次读取一个数据(包含高低位)
unsigned int Read_MPU6050_2Bytes(uint8_t DeviceAddress,uint8_t Start_MemoryAddress)
{
unsigned int Received_data;
I2C_AcknowledgeConfig(I2C2,ENABLE);//开应答
while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));//等待总线空闲
I2C_GenerateSTART(I2C2,ENABLE); //START
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//等待START 完成
I2C_SendDeviceAddress(I2C2,DeviceAddress,Write);//发送MPU6050地址+写入指令
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);//等待上一步完成
I2C_SendData(I2C2,Start_MemoryAddress);//写入要操作的寄存器地址
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);//等待上一步完成
I2C_GenerateSTART(I2C2,ENABLE); //再次START
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//等待上一步完成
I2C_SendDeviceAddress(I2C2,DeviceAddress,Read);//发送MPU6050地址+读出指令
I2C_PECPositionConfig(I2C2,I2C_PECPosition_Next);//indicates that the next byte is PEC
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);//wait for ADDR BUZY MSL to be set
I2C_AcknowledgeConfig(I2C2,DISABLE);//Clear ACK
while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BTF)!=SET);//wait for BTF
I2C_GenerateSTOP(I2C2,ENABLE);////Stop
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);//
Received_data=I2C_ReceiveData(I2C2);//
Received_data=Received_data<<8;
Received_data|=I2C_ReceiveData(I2C2);//连续读两次数据寄存器把数据寄存器和移位寄存器的数据都读出来
return Received_data;
}
示波器抓到的读取加速度和角速度(6个数据,包含高低位)的总时间:740uS
方法2:一次读取加速度+角速度+温度数据(包含高低位)
连续读取要好好看看下图的这个时序(755Page Reference)
程序(直接粘贴中文注释成乱码):
void Get_Mpu6050_Data(void)
{
uint8_t i=0;
I2C_AcknowledgeConfig(I2C2,ENABLE);//
while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));//µÈ´ý¿ÕÏÐ
//START£¬Ö÷¶¯Çл»³ÉMASTERģʽ
I2C_GenerateSTART(I2C2,ENABLE);//²úÉú¿ªÊ¼ÐźÅ
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
//´Ó»úµØÖ·+дָÁî
I2C_SendDeviceAddress(I2C2,MPU6050_ADDR,Write);//·¢ËÍ´Ó»úµØÖ·+дÈëÖ¸Áî
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);
//дÈëÒª¶ÁÈ¡µÄ¼Ä´æÆ÷µØÖ·
I2C_SendData(I2C2,ACCEL_XOUT_H);//дÈë±»²Ù×÷µÄ¼Ä´æÆ÷µØÖ·
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);//µÈ´ý·¢ËÍÍê±Ï
//START
I2C_GenerateSTART(I2C2,ENABLE);//Ôٴη¢Æð¿ªÊ¼ÐźÅ
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);
//´Ó»úµØÖ·+¶ÁÖ¸Áî
I2C_SendDeviceAddress(I2C2,MPU6050_ADDR,Read);//·¢ËÍ´Ó»úµØÖ·+¶ÁÖ¸Áî
//I2C_PECPositionConfig(I2C2,I2C_PECPosition_Next);
//I2C_AcknowledgeConfig(I2C2,ENABLE);
while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);//wait for ADDR BUZY MSL to be set
for(i=0;i<12;)
{
if(i<11)
{
while(I2C_GetFlagStatus(I2C2,I2C_FLAG_RXNE)!=SET);//µÈ´ý½ÓÊÕµ½Êý¾Ý
Data_Mpu6050=I2C_ReceiveData(I2C2);//¶ÁÈ¡¸Õ¸ÕÊÕµ½µÄÊý¾Ý
i++;
}
//最后三个数据收取需要小动作
if(i>=11){
//等待数据进来把data register & shift register灌满,放心不会丢失后面的数据
while((I2C_GetFlagStatus(I2C2,I2C_FLAG_RXNE)!=SET)&&(I2C_GetFlagStatus(I2C2,I2C_FLAG_BTF)!=SET));
I2C_AcknowledgeConfig(I2C2,DISABLE);//Clear ACK
Data_Mpu6050=I2C_ReceiveData(I2C2);//读取Data N-2
I2C_GenerateSTOP(I2C2,ENABLE);////Stop
i++;
Data_Mpu6050=I2C_ReceiveData(I2C2);//读取Data N-1
while(I2C_GetFlagStatus(I2C2,I2C_FLAG_RXNE)!=SET);//等待Data N进来
i++;
Data_Mpu6050=I2C_ReceiveData(I2C2);//读取Data N
}
}
}
实际测试的时间:370uS
读取数据就是这些,程序在附件里。
======================================分割线=====================================
MPU6050的数据读出来了,处理的时候遇到了问题,InvenSense在RM文件里没说清楚,16位的数据到底怎么scale,-2g对应0,0g对应0xffff/2?好疑惑(按这个处理的结果不对)。于是走上了瞎猜的路,还好最后蒙对了。0xffff对应+0g,0x0000对应-0g,2g对应(0xffff/2)+1,-2g对应(0xffff/2)-1。(按这个处理结果是对的,下面是图):
欢迎拍砖。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|