之前在使用mpu6050的过程中,发现大部分教程基于stm32f1系列的软件i2c的dmp读取方案,对于f4系列的有点欠缺,而且f4系列的操作与f1在模拟i2c上有一些不同,本文基于f4系列的软件i2c与dmp库读取欧拉角。
cubemx配置
只需要打开时钟,用最大的时钟频率,和两个io口(output模式),再开启一个10ms定时中断
时钟树
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库代码,直接移植即可。