STM32F4 HAL库 MPU6050 软件I2C DMP库读取,可获得稳定偏航角yaw

之前在使用mpu6050的过程中,发现大部分教程基于stm32f1系列的软件i2c的dmp读取方案,对于f4系列的有点欠缺,而且f4系列的操作与f1在模拟i2c上有一些不同,本文基于f4系列的软件i2c与dmp库读取欧拉角。

cubemx配置

只需要打开时钟,用最大的时钟频率,和两个io口(output模式),再开启一个10ms定时中断

时钟树
时钟树
GPIO选两个就好
GPIO
开个中断不断读取,然后可以开个串口方便查看

代码部分

可以移植到自己工程中,完整代码太多,只提供delay与ioi2c的部分,其实软件mpu6050主要代码就是在这部分,其余的都是引入dmp库。

注意:.h文件只引入main.h的原因是因为我的工程头文件都统一放在main.h中,需要根据实际情况引入

delay.h

#ifndef __DELAY_H
#define __DELAY_H 			   
#include "main.h"

void delay_ms(uint16_t ms);
void delay_us(uint32_t us);

#endif

delay.c

#include "delay.h"

void delay_us(uint32_t us)
{
  uint32_t startval,tickn,delays,wait;
 
  startval = SysTick->VAL;
  tickn = HAL_GetTick();
  delays =us * 84; //sysc / 1000 * us 这个地方的84就是时钟主频
  if(delays > startval)
    {
      while(HAL_GetTick() == tickn)
        {
 
        }
      wait = 84000 + startval - delays;  //84000根据自己单片机的频率更改
      while(wait < SysTick->VAL)
        {
 
        }
    }
  else
    {
      wait = startval - delays;
      while(wait < SysTick->VAL && HAL_GetTick() == tickn)
        {
 
        }
    }
}

void delay_ms(uint16_t ms) //1ms重复1000us
{
	uint32_t i;
	for(i=0;i<ms;i++) delay_us(1000);
}

ioi2c.h

#ifndef __IOI2C_H
#define __IOI2C_H

#include "main.h"

#define SDA_IN()	{GPIOB->MODER &= ~(3<<(7*2)); GPIOB->MODER |= 0<<7*2;} //PB7  更换io口把7改成对应序号
#define SDA_OUT()	{GPIOB->MODER &= ~(3<<(7*2)); GPIOB->MODER |= 1<<7*2;} //PB7
 
#define SCL_PIN	GPIO_PIN_6
#define SDA_PIN	GPIO_PIN_7
#define GPIO_PORT	GPIOB
#define GPIO_CLK_ENABLE()	__HAL_RCC_GPIOB_CLK_ENABLE()

#define IIC_SCL(PIN_STATE)		HAL_GPIO_WritePin(GPIO_PORT, SCL_PIN, PIN_STATE)
#define IIC_SDA(PIN_STATE)		HAL_GPIO_WritePin(GPIO_PORT, SDA_PIN, PIN_STATE)
#define IIC_Read_SDA()	HAL_GPIO_ReadPin(GPIO_PORT, SDA_PIN)

int IIC_Start(void); 
void IIC_Stop(void); 
void IIC_Send_Byte(uint8_t data); 
uint8_t IIC_Read_Byte(unsigned char ack); 
int8_t IIC_Wait_Ack(void);
void IIC_Ack(void); 
void IIC_NAck(void); 

void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
uint8_t IIC_Read_One_Byte(uint8_t daddr,uint8_t addr);	 
unsigned char I2C_Readkey(unsigned char I2C_Addr);

unsigned char I2C_ReadOneByte(unsigned char I2C_Addr,unsigned char addr);
unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data);
uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data);
uint8_t IICwriteBits(uint8_t dev,uint8_t reg,uint8_t bitStart,uint8_t length,uint8_t data);
uint8_t IICwriteBit(uint8_t dev,uint8_t reg,uint8_t bitNum,uint8_t data);
uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data);

int i2cWrite(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *data);
int i2cRead(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf);

#endif

ioi2c.c

#include "ioi2c.h"

int IIC_Start(void)
{
	SDA_OUT();
	IIC_SDA(GPIO_PIN_SET); 
	if(!IIC_Read_SDA()) return 0;
	IIC_SCL(GPIO_PIN_SET);
	delay_us(1); 
	IIC_SDA(GPIO_PIN_RESET);
	if(IIC_Read_SDA()) return 0;
	delay_us(1);
	IIC_SCL(GPIO_PIN_RESET);
	return 1;
}

void IIC_Stop(void)
{
	SDA_OUT(); 
	IIC_SCL(GPIO_PIN_RESET);
	IIC_SDA(GPIO_PIN_RESET); 
	delay_us(1); 
	IIC_SCL(GPIO_PIN_SET);
	IIC_SDA(GPIO_PIN_SET);
	delay_us(1);
}
 
int8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime = 0;
	delay_us(1);
	SDA_IN(); 
	IIC_SDA(GPIO_PIN_SET);
	delay_us(1);
	IIC_SCL(GPIO_PIN_SET);
	delay_us(1);
	while(IIC_Read_SDA())
	{
		ucErrTime++;
		if(ucErrTime > 50)
		{
			IIC_Stop();
			return 0;
		}
		delay_us(1);
	}
	IIC_SCL(GPIO_PIN_RESET); 
	return 1;
}

void IIC_Ack(void)
{
	IIC_SCL(GPIO_PIN_RESET); 
	SDA_OUT(); 
	IIC_SDA(GPIO_PIN_RESET);
	delay_us(1);
	IIC_SCL(GPIO_PIN_SET);
	delay_us(1);
	IIC_SCL(GPIO_PIN_RESET); 
}
 
void IIC_NAck(void)
{
	IIC_SCL(GPIO_PIN_RESET);
	SDA_OUT();
	IIC_SDA(GPIO_PIN_SET);
	delay_us(1);
	IIC_SCL(GPIO_PIN_SET);
	delay_us(1);
	IIC_SCL(GPIO_PIN_RESET);
}

uint8_t IIC_Read_Byte(unsigned char ack)
{
	unsigned char i = 0;
	unsigned char recv = 0;
	SDA_IN();
	for(i=0; i<8; i++)
	{
		IIC_SCL(GPIO_PIN_RESET); 
		delay_us(2);
		IIC_SCL(GPIO_PIN_SET); 
		recv <<= 1;
		if(IIC_Read_SDA())
			recv |= 0x01;
		delay_us(2);
	}
	if(!ack)
		IIC_NAck();
	else
		IIC_Ack(); 
	return recv;
}

void IIC_Send_Byte(uint8_t data)
{
	uint8_t i = 0;
	SDA_OUT();
	IIC_SCL(GPIO_PIN_RESET);
	for(i=0; i<8; i++)
	{
		if(data & 0x80)
			IIC_SDA(GPIO_PIN_SET);
		else
			IIC_SDA(GPIO_PIN_RESET);
		data <<= 1;
		delay_us(1);
		IIC_SCL(GPIO_PIN_SET); 
		delay_us(1);
		IIC_SCL(GPIO_PIN_RESET);
	}
}

int i2cWrite(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *data)
{
    int i;
    if (!IIC_Start())
        return 1;
    IIC_Send_Byte(addr << 1 );
    if (!IIC_Wait_Ack()) {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
		for (i = 0; i < len; i++) {
        IIC_Send_Byte(data[i]);
        if (!IIC_Wait_Ack()) {
            IIC_Stop();
            return 0;
        }
    }
    IIC_Stop();
    return 0;
}

int i2cRead(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{
    if (!IIC_Start())
        return 1;
    IIC_Send_Byte(addr << 1);
    if (!IIC_Wait_Ack()) {
        IIC_Stop();
        return 1;
    }
    IIC_Send_Byte(reg);
    IIC_Wait_Ack();
    IIC_Start();
    IIC_Send_Byte((addr << 1)+1);
    IIC_Wait_Ack();
    while (len) {
        if (len == 1)
            *buf = IIC_Read_Byte(0);
        else
            *buf = IIC_Read_Byte(1);
        buf++;
        len--;
    }
    IIC_Stop();
    return 0;
}

unsigned char I2C_ReadOneByte(unsigned char I2C_Addr,unsigned char addr)
{
	unsigned char res=0;
	IIC_Start();	
	IIC_Send_Byte(I2C_Addr);
	res++;
	IIC_Wait_Ack();
	IIC_Send_Byte(addr); res++;
	IIC_Wait_Ack();	  
	IIC_Start();
	IIC_Send_Byte(I2C_Addr+1); res++;          		   
	IIC_Wait_Ack();
	res=IIC_Read_Byte(0);	   
    IIC_Stop();
	return res;
}

uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data){
    uint8_t count = 0;
	IIC_Start();
	IIC_Send_Byte(dev);	   
	IIC_Wait_Ack();
	IIC_Send_Byte(reg); 
  IIC_Wait_Ack();	  
	IIC_Start();
	IIC_Send_Byte(dev+1);  
	IIC_Wait_Ack();
    for(count=0;count<length;count++){
		 
		 if(count!=length-1)   data[count]=IIC_Read_Byte(1); 
		 else                  data[count]=IIC_Read_Byte(0); 
	}
    IIC_Stop();
    return count;
}

uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data){
  
 	uint8_t count = 0;
	IIC_Start();
	IIC_Send_Byte(dev);	  
	IIC_Wait_Ack();
	IIC_Send_Byte(reg); 
  IIC_Wait_Ack();	  
	for(count=0;count<length;count++){
		IIC_Send_Byte(data[count]); 
		IIC_Wait_Ack(); 
	 }
	IIC_Stop();
    return 1;
}

uint8_t IICreadByte(uint8_t dev, uint8_t reg, uint8_t *data){
	*data=I2C_ReadOneByte(dev, reg);
    return 1;
}

unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data){
    return IICwriteBytes(dev, reg, 1, &data);
}

uint8_t IICwriteBits(uint8_t dev,uint8_t reg,uint8_t bitStart,uint8_t length,uint8_t data)
{

    uint8_t b;
    if (IICreadByte(dev, reg, &b) != 0) {
        uint8_t mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);
        data <<= (8 - length);
        data >>= (7 - bitStart);
        b &= mask;
        b |= data;
        return IICwriteByte(dev, reg, b);
    } else {
        return 0;
    }
}

uint8_t IICwriteBit(uint8_t dev, uint8_t reg, uint8_t bitNum, uint8_t data){
    uint8_t b;
    IICreadByte(dev, reg, &b);
    b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
    return IICwriteByte(dev, reg, b);
}

main.h引入

#include "delay.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include "mpu6050.h"
#include "ioi2c.h"
#include "dmpKey.h"
#include "dmpmap.h"

#include <math.h>
#include <string.h> 
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

使用:

//在主函数中只需要  初始化一下
MPU6050_initialize();          
DMP_Init(); 

//读取输出
while(Read_DMP()) 
   printf("%.f,%.f,%.f \r\n",Pitch,Roll,Yaw);
   

上方链接内有dmp库代码,直接移植即可。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值