STM32应用(七)JY901九轴姿态模块(串口DMA空闲中断和I2C通信)
文章目录
- 0.相关基础知识介绍
- 0.1六轴、九轴传感器有什么区别?
- 1.JY901模块简介
- 1.1 产品概述
- 1.2 性能参数
- 1.3 实物图和接线
- 2.软件和使用说明书
- 3.串口通信JY901
- 3.1 cubemx工程配置
- 3.2代码编写
- 3.2.1 DMA空闲中断的开启
- 3.2.2 添加JY901.h
- 3.2.3 重定义需要的结构体和JY901数据结构体
- 3.2.4 接收结构体初始化
- 3.2.5 数据解算
- 3.3现象观测
- 4.I2C通信JY901
0.相关基础知识介绍
IMU模块中6轴、9轴包含哪些模块?
欧拉角、旋转矩阵、四元数合辑
这个确实复杂,如果以后有机会接触到飞控,再好好看看。
0.1六轴、九轴传感器有什么区别?
加速度传感器(即加速计)、角速度传感器(即陀螺仪)、磁感应传感器(即电子罗盘)。这三类传感器测量的数据在空间坐标系中都可以被分解为X,Y,Z三个方向轴的力,因此也常常被称为3轴加速度计、3轴陀螺仪、3轴磁力计。
加速度传感器(即加速计) | 检测横向加速 |
---|---|
角速度传感器(即陀螺仪) | 检测角度旋转和平衡 |
磁感应传感器(即电子罗盘) | 获取磁场数据 |
气压传感器 | 获取海拔高度的数据 |
6轴 : 三轴(XYZ)加速度计 + 三轴(XYZ)陀螺仪(也叫角速度传感器)
9轴 : 6轴 + 三轴(XYZ)磁场传感器
1.JY901模块简介
以下内容来自JY901使用说明书V4.4,仅摘录了需要注意的内容。
1.1 产品概述
模块内部自带电压稳定电路, 工作电压 3.3v~5v, 引脚电平兼容 3.3V/5V 的嵌入式系统,连接方便。
模块内部集成了姿态解算器, 配合动态卡尔曼滤波算法, 能够在动态环境下准确输出模块的当前姿态, 姿态测量精度静态 0.05 度, 动态 0.1 度, 稳定性极高。
支持串口和 IIC 两种数字接口。 方便用户选择最佳的连接方式。 串口速率
2400bps~921600bps 可调, IIC 接口支持全速 400K 速率。(本博客采用串口通信)
1.2 性能参数
1、 电压: 3.3V~5V
2、 电流: <25mA
3、 测量维度: 加速度: 3 维; 角速度: 3 维; 磁场: 3 维;角度: 3 维, 气压:1 维(JY-901B);GPS: 3 维(接 GPS 模块)
4、 量程: 加速度:±2/4/8/16 g(可选) ; 角速度:±250/500/1000/2000 °/s(可选) ;角度 X,Z 轴±180°, Y 轴±90°。
5、 数据输出内容: 时间、 加速度、 角速度、 角度、 磁场、 端口状态、 气压(JY-901B) 、高度(JY-901B) 、 经纬度(需连接 GPS) 、 地速(需连接 GPS) 。
6、 数据接口: 串口(TTL 电平, 波特率支持 2400、 4800、 9600(默认) 、 19200、 38400、57600、 115200、 230400、 460800、 921600) , I2C(最大支持高速 IIC 速率 400K)
7.扩展口功能: 模拟输入(0~VCC) 、 数字输入、 数字输出、 PWM 输出(周期 1us-65535us,分辨率 1us)
1.3 实物图和接线
串口通信接线如下:
JY901 | 单片机 |
---|---|
VCC | 3.3V 或 5V |
RX | TX |
TX | RX |
GND | GND |
IIC通信接线如下:
JY901 | 单片机 |
---|---|
VCC | 3.3V 或 5V |
SCL | I2C 时钟线 |
SDA | I2C 数据线 |
GND | GND |
注意: 为了能在 IIC总线上面挂接多个模块, 模块的 IIC 总线是开漏输出的, MCU 在连接模块时需要将 IIC 总线通过一个 4.7K 的电阻上拉到 VCC。
注意: VCC 为 3.3V, 要另外接电源供电。 直接用模块上面的电源供电, 可能会产生压降, 使模块实际电压没有3.3~5V。
2.软件和使用说明书
上位机软件
提取码:nu3h
JY901使用说明书
提取码:apmd
3.串口通信JY901
3.1 cubemx工程配置
利用DMA空闲中断通信。
1.开启串口1并开启对应的中断
2.添加DMA通道
3.2代码编写
参考博客:
STM32 Cubemax(十) ——JY901陀螺仪数据的读取与简单数据处理
3.2.1 DMA空闲中断的开启
1.在usatr.c文件中添加DMA空闲中断
/* USER CODE BEGIN 0 */
extern User_USART JY901_data;//数据变量声明
/* USER CODE END 0 *//* USER CODE BEGIN USART1_Init 2 */__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); HAL_UART_Receive_DMA(&huart1,JY901_data.RxBuffer,RXBUFFER_LEN); /* USER CODE END USART1_Init 2 */
2.在stm32f4xxx_it.c文件中编写中断服务程序
/* USER CODE BEGIN PV */
extern User_USART JY901_data;
/* USER CODE END PV *//*** @brief This function handles USART1 global interrupt.*/
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */uint32_t temp_flag = 0;uint32_t temp;temp_flag = __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);if((temp_flag!=RESET)) {__HAL_UART_CLEAR_IDLEFLAG(&huart1);temp = huart1.Instance->SR; temp = huart1.Instance->DR; HAL_UART_DMAStop(&huart1); temp = hdma_usart1_rx.Instance->NDTR; //F1的板子 temp = hdma_usart3_rx.Instance->CNDTR; JY901_data.Rx_len = RXBUFFER_LEN-temp; JY901_Process(); //按照自己需求改写这个函数 JY901_data.Rx_flag = 1; }HAL_UART_Receive_DMA(&huart1,JY901_data.RxBuffer,RXBUFFER_LEN);/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}
3.2.2 添加JY901.h
淘宝客服提供。
#ifndef __JY901_H
#define __JY901_H#define SAVE 0x00
#define CALSW 0x01
#define RSW 0x02
#define RRATE 0x03
#define BAUD 0x04
#define AXOFFSET 0x05
#define AYOFFSET 0x06
#define AZOFFSET 0x07
#define GXOFFSET 0x08
#define GYOFFSET 0x09
#define GZOFFSET 0x0a
#define HXOFFSET 0x0b
#define HYOFFSET 0x0c
#define HZOFFSET 0x0d
#define D0MODE 0x0e
#define D1MODE 0x0f
#define D2MODE 0x10
#define D3MODE 0x11
#define D0PWMH 0x12
#define D1PWMH 0x13
#define D2PWMH 0x14
#define D3PWMH 0x15
#define D0PWMT 0x16
#define D1PWMT 0x17
#define D2PWMT 0x18
#define D3PWMT 0x19
#define IICADDR 0x1a
#define LEDOFF 0x1b
#define GPSBAUD 0x1c#define YYMM 0x30
#define DDHH 0x31
#define MMSS 0x32
#define MS 0x33
#define AX 0x34
#define AY 0x35
#define AZ 0x36
#define GX 0x37
#define GY 0x38
#define GZ 0x39
#define HX 0x3a
#define HY 0x3b
#define HZ 0x3c
#define Roll 0x3d
#define Pitch 0x3e
#define Yaw 0x3f
#define TEMP 0x40
#define D0Status 0x41
#define D1Status 0x42
#define D2Status 0x43
#define D3Status 0x44
#define PressureL 0x45
#define PressureH 0x46
#define HeightL 0x47
#define HeightH 0x48
#define LonL 0x49
#define LonH 0x4a
#define LatL 0x4b
#define LatH 0x4c
#define GPSHeight 0x4d
#define GPSYAW 0x4e
#define GPSVL 0x4f
#define GPSVH 0x50
#define q0 0x51
#define q1 0x52
#define q2 0x53
#define q3 0x54#define DIO_MODE_AIN 0
#define DIO_MODE_DIN 1
#define DIO_MODE_DOH 2
#define DIO_MODE_DOL 3
#define DIO_MODE_DOPWM 4
#define DIO_MODE_GPS 5 struct STime
{unsigned char ucYear;unsigned char ucMonth;unsigned char ucDay;unsigned char ucHour;unsigned char ucMinute;unsigned char ucSecond;unsigned short usMiliSecond;
};
struct SAcc//加速度
{short a[3];short T;
};
struct SGyro//角速度
{short w[3];short T;
};
struct SAngle//角度
{short Angle[3];short T;
};
struct SMag//磁场输出
{short h[3];short T;
};struct SDStatus//端口状态数据输出
{short sDStatus[4];
};struct SPress//气压高度
{long lPressure;long lAltitude;
};struct SLonLat//经纬度
{long lLon;long lLat;
};struct SGPSV
{short sGPSHeight;short sGPSYaw;long lGPSVelocity;
};
struct SQ //四元数
{ short q[4];
};#endif
3.2.3 重定义需要的结构体和JY901数据结构体
typedef struct
{float angle[3];
}Angle;typedef struct
{float a[3];
}Acc;typedef struct
{float w[3];
}SGyro;typedef struct//四元数
{ float q[4];
}SQ;typedef struct//磁场输出
{float h[3];
}SMag;typedef struct//气压高度
{float lPressure;float lAltitude;
}SPress;typedef struct//经纬度
{float lLon;float lLat;
}SLonLat;
typedef struct User_USART
{uint8_t Rx_flag; uint8_t Rx_len; uint8_t frame_head; //帧头uint8_t RxBuffer[RXBUFFER_LEN]; //接收缓冲Angle angle; //角度Acc acc; //加速度SGyro w; //角速度SMag h; //磁场SPress lPressure; //气压SPress lAltitude; //高度SLonLat lLon; //经度SLonLat lLat; //维度SQ q; //四元数
}User_USART;
3.2.4 接收结构体初始化
void User_USART_Init(User_USART *Data)
{for(uint16_t i=0; i < RXBUFFER_LEN; i++) Data->RxBuffer[i] = 0;Data->frame_head = 0x55;Data->Rx_flag = 0;Data->Rx_len = 0;
}
3.2.5 数据解算
#define RXBUFFER_LEN 99 //接收9类数据,一共99位User_USART JY901_data;
struct SAcc stcAcc;
struct SGyro stcGyro;
struct SAngle stcAngle;
struct SMag stcMag;
struct SPress stcPress;
struct SLonLat stcLonLat;
struct SQ stcQ;void JY901_Process()
{if(JY901_data.Rx_len < RXBUFFER_LEN) return; //如果位数不对for(uint8_t i=0;i<9;i++){if(JY901_data.RxBuffer[i*11]!= JY901_data.frame_head) return; //如果帧头不对switch(JY901_data.RxBuffer[i*11+1]){case 0x51: memcpy(&stcAcc,&JY901_data.RxBuffer[2 + i*11],8);for(uint8_t j = 0; j < 3; j++) JY901_data.acc.a[j] = (float)stcAcc.a[j]/32768*16;break;case 0x52: memcpy(&stcGyro,&JY901_data.RxBuffer[2 + i*11],8);for(uint8_t j = 0; j < 3; j++) JY901_data.w.w[j] = (float)stcGyro.w[j]/32768*2000;break;case 0x53: memcpy(&stcAngle,&JY901_data.RxBuffer[2 + i*11],8);for(uint8_t j = 0; j < 3; j++) JY901_data.angle.angle[j] = (float)stcAngle.Angle[j]/32768*180;break;case 0x54: //磁场解算memcpy(&stcMag,&JY901_data.RxBuffer[2 + i*11],8);for(uint8_t j = 0; j < 3; j++) JY901_data.h.h[j] = (float)stcMag.h[j];break;case 0x55: //D0-D3端口状态break;case 0x56: //气压高度memcpy(&stcPress,&JY901_data.RxBuffer[2 + i*11],8); JY901_data.lPressure.lPressure = (float)stcPress.lPressure;JY901_data.lPressure.lAltitude = (float)stcPress.lAltitude/100;break;case 0x57: //经纬度memcpy(&stcLonLat.lLat,&JY901_data.RxBuffer[2 + i*11],8);JY901_data.lLon.lLat = (float)stcLonLat.lLat/10000000+(double)(stcLonLat.lLat % 10000000)/1e5; JY901_data.lLon.lLat = (float)stcLonLat.lLon/10000000+(double)(stcLonLat.lLon % 10000000)/1e5;break;case 0x58: //GPSbreak;case 0x59: //四元数memcpy(&stcQ,&JY901_data.RxBuffer[2 + i*11],8);for(uint8_t j = 0; j < 4; j++) JY901_data.q.q[j] = (float)stcQ.q[j]/32768; break; }}
}
3.3现象观测
打开上位机软件,勾选需要测试的数据。
可以看到JY901读取到的数据,作为参考量。
在debug模式,读取到的数据。
4.I2C通信JY901
JY901的I2C通信的排针没有焊,以后抽空更。
I2C通信也可参见该博客。
STM32 CubeMx(六)I2C同步串行通信与EEPROM 24C02的读写
STM32应用(七)JY901九轴姿态模块(串口DMA空闲中断和I2C通信)相关推荐
- stm32的串口DMA空闲中断接收不等长数据,stm32F1的usart1-DMA-IDLE收发
stm32的DMA收发原理,和stm32F4 + USART2 +DMA +IDLE使用,见另一篇:https://blog.csdn.net/Mark_md/article/details/1072 ...
- stm32的串口DMA空闲中断接收不等长数据,stm32F4的usart2-DMA-IDLE收发
1. 串口为什么要使用DMA?好处? 提高系统实时性:stm32单片机的串口没有FIFO,使用字节中断的方式去接收,会频繁进入中断,影响系统实时性.好在stm32的串口可以级联DMA使用,在大数据量连 ...
- 学习 STM32之九轴姿态传感器(BWT901CL)串口通信读取数据
由于个人应用到3轴传感器,所以买了直接买了一个9轴的,用于学习STM32Core平台串口2连接维特智能串口Normal协议,然后通过串口1直接打印数据,接收传感器数据和与传感器进行通信:需要看产品文档 ...
- 使用扩展卡尔曼滤波(EKF)进行AHRS九轴姿态融合
AHRS九轴姿态融合 EKF滤波 卡尔曼滤波 在做九轴姿态融合的过程中,这里介绍一种融合算法,基于EKF的九轴姿态融合算法: 首先表明,该算法并非自己想到的,算法原理参考了这篇论文:Dale E. S ...
- 移动端点对点获取WeMos D1上搭载的JY-901九轴振动加速度传感器加速度数据
1 介绍 暑假里老师给布置了个任务,希望能够避开云端,使用移动端来获取 WeMos D1 上传感器的数据. 那么这里大致的思路就是: 通过串口获取传感器的数据: 在WeMos D1上开启服务以供移动端 ...
- 微型四轴飞行器(5)九轴姿态融合算法A
1 概述 所谓的九轴姿态融合就是将通过传感器获得的3轴加速度.3轴角速度.3轴磁场数据,在相应的算法处理后能够得到飞行器的姿态信息(欧拉角).输入输出如下图 在惯性导航领域的欧拉角分别表示的是航向角( ...
- arduino调试BNO080高精准度九轴传感器模块
arduino调试BNO080高精准度九轴传感器模块 原文链接:https://www.yourcee.com/newsinfo/2925867.html 1.简介 2.原理图 3.使用前准备 4.接 ...
- K_A14_003 基于STM32等单片机驱动APDS9960手势运动模块 串口与OLED0.96双显示
K_A14_003 基于STM32等单片机驱动APDS9960手势运动模块 串口与OLED0.96双显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 时序 对应程序: 四.部分代码说明 ...
- K_A14_012基于STM32等单片机驱动GY-25倾斜度角度模块 串口与OLED0.96双显示
K_A14_012基于STM32等单片机驱动GY-25倾斜度角度模块 串口与OLED0.96双显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 对应程序: 四.部分代码说明 1.接线引脚 ...
最新文章
- 伍六七带你学算法——被忽视的数学公式
- 使用Python、OpenCVImageMagick工具箱制作GIF动画
- RIPv1和v2综合实验(CCNP阶段)
- BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)
- java 拦截所有路径_Java或Web中解决所有路径问题
- 【linux】使用swap文件恢复非正常关闭的文件
- PHP自学3——在html的table标签中显示用户提交表单
- nginx-zabbix监控脚本
- Java静态变量注入配置值,工具类使用@Value将信息注入到静态变量中
- 微服务架构最强讲解,那叫一个通俗易懂!
- linux阻止程序,Linux:阻止某些应用程序/主机名的IPv6
- 均匀线阵常规波束形成 matlab程序,波束形成Matlab程序
- 脚本精灵for+android,脚本精灵 v3.0.8
- 【踩坑记录】.bss段;.bss段到底占不占目标文件的空间,有没有记录对应信息。
- java-php-python-ssm演唱会购票系统计算机毕业设计
- 记录,Cents 7 更改home和root的中文路径
- 【pandas】变形(长宽表变换)
- 长江雨课堂考试半自动答题python脚本
- 【简单】求英文句子的平均单词长度
- 物联网设备网络接入方式