linux串口读取mpu9250数据,模拟 I2C 读取 MPU9250 数据的测试笔记

硬件:STM32F103ZET6 + GY9250

软件:Keil MDK(v5.27)+ STM32CUBEMX(v5.2.1)

这里我在使用STM32CUBEMX最新版本(v5.5.0)生成Keil工程时出现了“MDK-ARM v5.27 project generation have a problem.”的问题(并不是路径问题)。换用了较低的v5.2.1版本后顺利生成工程。

STM32CUBEMX使用HAL库建立工程。

在方法完全相同的情况下(STM32CUBEMX工程配置相同,main.c文件代码相同),使用IAR(v8.32.4)建立的工程无法顺利读取磁力计数据。(???)

由于MPU9250内部采用I2C与磁力计通信,使用I2C读取会相对简单。

Here we go!

1、使用STM32CubeMX配置工程

(1)RCC选取HSE:Crystal/Ceramic Resonator(石英/陶瓷 晶振);

(2)在Clock Configuration中设置HCLK为72(MHz);

(3)配置USART1的MODE为Asynchronous,用来向上位机发送接收到的数据;

(4)配置PB6、PB7为GPIO_Output,修改GPIO mode为Output Open Drain(开漏输出),将Maximum output speed设置为Medium(10MHz);

其余设置保持默认,记得勾选“Generate peripheral initialization as a pair of '.c/.h' files per peripheral”,然后生成代码。

2、USART1发送

#define usart1_print(...) HAL_UART_Transmit(&huart1, u_buf, sprintf((char *)u_buf, __VA_ARGS__), 0xffff);

在使用前需要包含头文件“stdio.h”并且定义缓冲区。

#include "stdio.h"

uint8_t u_buf[0xff];

3、宏定义GPIO操作

#define SCL_H GPIOB->BSRR = 0x0040 //GPIO_Pin_6

#define SCL_L GPIOB->BRR = 0x0040 //GPIO_Pin_6

#define SDA_H GPIOB->BSRR = 0x0080 //GPIO_Pin_7

#define SDA_L GPIOB->BRR = 0x0080 //GPIO_Pin_7

#define SCL_read GPIOB->IDR & 0x0040 //GPIO_Pin_6

#define SDA_read GPIOB->IDR & 0x0080 //GPIO_Pin_7

4、模拟I2C

函数声明

void I2C_Delay(void);

int I2C_Start(void);

void I2C_Stop(void);

void I2C_Ack(void);

void I2C_NoAck(void);

int I2C_WaitAck(void);

void I2C_SendByte(uint8_t SendByte);

unsigned char I2C_ReadByte(void);

int Single_Write(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char REG_data);

unsigned char Single_Read(unsigned char SlaveAddress, unsigned char REG_Address);

函数定义

void I2C_Delay(void)

{

uint8_t i=20; //可以适当调整

while(i)

{

i--;

}

}

int I2C_Start(void)

{

SDA_H;

SCL_H;

I2C_Delay();

if(!SDA_read)return 0; //SDA线为低电平则总线忙,退出

SDA_L;

I2C_Delay();

if(SDA_read)return 0; //SDA线为高电平则总线出错,退出

SDA_L;

I2C_Delay();

return 1;

}

void I2C_Stop(void)

{

SCL_L;

I2C_Delay();

SDA_L;

I2C_Delay();

SCL_H;

I2C_Delay();

SDA_H;

I2C_Delay();

}

void I2C_Ack(void)

{

SCL_L;

I2C_Delay();

SDA_L;

I2C_Delay();

SCL_H;

I2C_Delay();

SCL_L;

I2C_Delay();

}

void I2C_NoAck(void)

{

SCL_L;

I2C_Delay();

SDA_H;

I2C_Delay();

SCL_H;

I2C_Delay();

SCL_L;

I2C_Delay();

}

int I2C_WaitAck(void)

{

SCL_L;

I2C_Delay();

SDA_H;

I2C_Delay();

SCL_H;

I2C_Delay();

if(SDA_read)

{

SCL_L;

I2C_Delay();

return 0;

}

SCL_L;

I2C_Delay();

return 1;

}

void I2C_SendByte(uint8_t SendByte)

{

uint8_t i = 8;

while(i--)

{

SCL_L;

I2C_Delay();

if(SendByte & 0x80)

SDA_H;

else

SDA_L;

SendByte<<=1;

I2C_Delay();

SCL_H;

I2C_Delay();

}

SCL_L;

}

unsigned char I2C_ReadByte(void)

{

uint8_t i = 8;

uint8_t ReceiveByte = 0;

SDA_H;

while(i--)

{

ReceiveByte<<=1;

SCL_L;

I2C_Delay();

SCL_H;

I2C_Delay();

if(SDA_read)

{

ReceiveByte | = 0x01;

}

}

SCL_L;

return ReceiveByte;

}

int Single_Write(unsigned char SlaveAddress, unsigned char REG_Address, unsigned char REG_data)

{

if(!I2C_Start())return 0;

I2C_SendByte(SlaveAddress);

if(!I2C_WaitAck()){I2C_Stop();return 0;}

I2C_SendByte(REG_Address);

I2C_WaitAck();

I2C_SendByte(REG_data);

I2C_WaitAck();

I2C_Stop();

HAL_Delay(2);

return 1;

}

unsigned char Single_Read(unsigned char SlaveAddress, unsigned char REG_Address)

{

unsigned char REG_data;

if(!I2C_Start())return 0;

I2C_SendByte(SlaveAddress);

if(!I2C_WaitAck()){I2C_Stop(); return 0;}

I2C_SendByte((uint8_t) REG_Address);

I2C_WaitAck();

I2C_Start();

I2C_SendByte(SlaveAddress+1);

I2C_WaitAck();

REG_data=I2C_ReadByte();

I2C_NoAck();

I2C_Stop();

return REG_data;

}

5、根据 MPU9250 的 Register Map and Descriptions 宏定义

#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)

#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)

#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)

#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)

#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)

#define ACCEL_XOUT_H 0x3B

#define ACCEL_XOUT_L 0x3C

#define ACCEL_YOUT_H 0x3D

#define ACCEL_YOUT_L 0x3E

#define ACCEL_ZOUT_H 0x3F

#define ACCEL_ZOUT_L 0x40

#define TEMP_OUT_H 0x41

#define TEMP_OUT_L 0x42

#define GYRO_XOUT_H 0x43

#define GYRO_XOUT_L 0x44

#define GYRO_YOUT_H 0x45

#define GYRO_YOUT_L 0x46

#define GYRO_ZOUT_H 0x47

#define GYRO_ZOUT_L 0x48

#define MAG_XOUT_L 0x03

#define MAG_XOUT_H 0x04

#define MAG_YOUT_L 0x05

#define MAG_YOUT_H 0x06

#define MAG_ZOUT_L 0x07

#define MAG_ZOUT_H 0x08

#define GYRO_ADDRESS 0xD0

#define MAG_ADDRESS 0x18

#define ACCEL_ADDRESS 0xD0

6、MPU9250的相关操作

void Init_MPU9250(void)

{

Single_Write(GYRO_ADDRESS,PWR_MGMT_1,0x00);

Single_Write(GYRO_ADDRESS,SMPLRT_DIV,0x07);

Single_Write(GYRO_ADDRESS,CONFIG,0x06);

Single_Write(GYRO_ADDRESS,GYRO_CONFIG,0x18);

Single_Write(GYRO_ADDRESS,ACCEL_CONFIG,0x01);

}

void READ_MPU9250_ACCEL(void)

{

BUF[0]=Single_Read(ACCEL_ADDRESS,ACCEL_XOUT_L);

BUF[1]=Single_Read(ACCEL_ADDRESS,ACCEL_XOUT_H);

T_X=(BUF[1]<<8)|BUF[0];

T_X/=164;

BUF[2]=Single_Read(ACCEL_ADDRESS,ACCEL_YOUT_L);

BUF[3]=Single_Read(ACCEL_ADDRESS,ACCEL_YOUT_H);

T_Y=(BUF[3]<<8)|BUF[2];

T_Y/=164;

BUF[4]=Single_Read(ACCEL_ADDRESS,ACCEL_ZOUT_L);

BUF[5]=Single_Read(ACCEL_ADDRESS,ACCEL_ZOUT_H);

T_Z=(BUF[5]<<8)|BUF[4];

T_Z/=164;

}

void READ_MPU9250_GYRO(void)

{

BUF[0]=Single_Read(GYRO_ADDRESS,GYRO_XOUT_L);

BUF[1]=Single_Read(GYRO_ADDRESS,GYRO_XOUT_H);

T_X=(BUF[1]<<8)|BUF[0];

T_X/=16.4;

BUF[2]=Single_Read(GYRO_ADDRESS,GYRO_YOUT_L);

BUF[3]=Single_Read(GYRO_ADDRESS,GYRO_YOUT_H);

T_Y=(BUF[3]<<8)|BUF[2];

T_Y/=16.4;

BUF[4]=Single_Read(GYRO_ADDRESS,GYRO_ZOUT_L);

BUF[5]=Single_Read(GYRO_ADDRESS,GYRO_ZOUT_H);

T_Z=(BUF[5]<<8)|BUF[4];

T_Z/=16.4;

BUF[6]=Single_Read(GYRO_ADDRESS,TEMP_OUT_L);

BUF[7]=Single_Read(GYRO_ADDRESS,TEMP_OUT_H);

T_T=(BUF[7]<<8)|BUF[6];

T_T=(T_T-21)/333.87 +21; //顺便读温度

}

void READ_MPU9250_MAG(void)

{

Single_Write(GYRO_ADDRESS,0x37,0x02); //turn on Bypass Mode

HAL_Delay(20);

Single_Write(MAG_ADDRESS,0x0A,0x01);

HAL_Delay(20);

BUF[0]=Single_Read(MAG_ADDRESS,MAG_XOUT_L);

BUF[1]=Single_Read(MAG_ADDRESS,MAG_XOUT_H);

T_X=(BUF[1]<<8)|BUF[0];

BUF[2]=Single_Read(MAG_ADDRESS,MAG_YOUT_L);

BUF[3]=Single_Read(MAG_ADDRESS,MAG_YOUT_H);

T_Y=(BUF[3]<<8)|BUF[2];

BUF[4]=Single_Read(MAG_ADDRESS,MAG_ZOUT_L);

BUF[5]=Single_Read(MAG_ADDRESS,MAG_ZOUT_H);

T_Z=(BUF[5]<<8)|BUF[4];

}

7、格式化处理数据

void Format(unsigned char *s,short temp_data)

{

if(temp_data<0)

{

temp_data=-temp_data;

*s++='-';

}

else *s=' ';

*s++=temp_data/100+0x30;

temp_data=temp_data%100;

*s++=temp_data/10+0x30;

temp_data=temp_data%10;

*s++=temp_data+0x30;

*s=0;

}

8、Private variables

unsigned char BUF[20]; //接收数据缓存区

unsigned char TX_DATA[8]; //显示数据缓存区

short T_X, T_Y, T_Z, T_T; //X、Y、Z轴数据,时间

9、在主循环开始前初始化

Init_MPU9250();

10、主循环中的代码

READ_MPU9250_ACCEL(); //加速度计

Format(TX_DATA,T_X);

usart1_print("AX:%s\t", TX_DATA);

Format(TX_DATA,T_Y);

usart1_print("AY:%s\t", TX_DATA);

Format(TX_DATA,T_Z);

usart1_print("AZ:%s\t", TX_DATA);

usart1_print("\n");

READ_MPU9250_GYRO(); //陀螺仪

Format(TX_DATA,T_X);

usart1_print("GX:%s\t", TX_DATA);

Format(TX_DATA,T_Y);

usart1_print("GY:%s\t", TX_DATA);

Format(TX_DATA,T_Z);

usart1_print("GZ:%s\t", TX_DATA);

usart1_print("\n");

READ_MPU9250_MAG(); //磁力计

Format(TX_DATA,T_X);

usart1_print("MX:%s\t", TX_DATA);

Format(TX_DATA,T_Y);

usart1_print("MY:%s\t", TX_DATA);

Format(TX_DATA,T_Z);

usart1_print("MZ:%s\t", TX_DATA);

usart1_print("\n");

Format(TX_DATA,T_T);

usart1_print("T:%s\t", TX_DATA);

usart1_print("\n");

HAL_Delay(200);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值