学习 STM32之九轴姿态传感器(BWT901CL)串口通信读取数据

news/2024/11/13 3:56:40/

由于个人应用到3轴传感器,所以买了直接买了一个9轴的,用于学习STM32Core平台串口2连接维特智能串口Normal协议,然后通过串口1直接打印数据,接收传感器数据和与传感器进行通信;需要看产品文档的可以直接官网搜索文档,咱直接接线上代码开始测试。

官方产品网址
在查看这个例程前请阅读相关传感器说明书,了解传感器所使用的协议,以及传感器的基本功能
点击查看BWT901BCL姿态传感器

请添加图片描述
实物图图下
请添加图片描述

硬件操作流程

传感器---------usert2------------->stm32-------------usart1-------------------->上位机(显示效果)

官方的接线图
首先准备维特智能标准传感器,这里以JY901S为例、STM32Core开发板和一个串口三合一模块。接线方式如下图
请添加图片描述

我的接线图
下面我用自己的开发板接的如下如 ,(九轴姿态传感器(BWT901CL,2.0 蓝牙版—HC-02)
设计采用的芯片是STM32F103ZET6,采用的传感器是BWT901CL姿态传感器,自主进行电路设计,通过串口传输,完成BWT901CL姿态传感器原始数据的读取与显示,以及依靠其内部的DMP模块对原始传感器数据进行滤波、融合处理,得到解算后的姿态角,再通过串口通信的方式,将数据输出到电脑上位机上。
请添加图片描述

下面直接上示例代码,(可下载官方的代码参考移植,上面有官网地址)-

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h" //串口1
#include "uart.h"  //串口2
#include "bool.h"
#include "jy901.h"  //官方数据模型**JY61** 模式一样的//jy61
//struct SAcc 		stcAcc;
//struct SGyro 		stcGyro;
//struct SAngle 	stcAngle;//jy901  https://wit-motion.yuque.com/docs/share/68d5aebd-703a-473a-836a-9bef2e5c0b4a?#%20%E3%80%8AWIT%E7%A7%81%E6%9C%89%E5%8D%8F%E8%AE%AE%E3%80%8B
struct STime		stcTime;  
struct SAcc 		stcAcc;
struct SGyro 		stcGyro;
struct SAngle 	stcAngle;
struct SMag 		stcMag;
struct SDStatus stcDStatus;
struct SPress 	stcPress;
struct SLonLat 	stcLonLat;
struct SGPSV 		stcGPSV;
struct SQ       stcQ;char ACCCALSW[5] = {0XFF,0XAA,0X01,0X01,0X00};//进入加速度校准模式
char SAVACALSW[5]= {0XFF,0XAA,0X00,0X00,0X00};//保存当前配置//用串口2给JY模块发送指令
void sendcmd(char cmd[])
{char i;for(i=0;i<5;i++)UART2_Put_Char(cmd[i]);
}//CopeSerialData为串口2中断调用函数,串口每收到一个数据,调用一次这个函数。
void CopeSerial2Data(unsigned char ucData)
{static unsigned char ucRxBuffer[250];static unsigned char ucRxCnt = 0;	LED2=!LED2;//LED_REVERSE();					//接收到数据,LED灯闪烁一下ucRxBuffer[ucRxCnt++]=ucData;	//将收到的数据存入缓冲区中if (ucRxBuffer[0]!=0x55) //数据头不对,则重新开始寻找0x55数据头{ucRxCnt=0;return;}if (ucRxCnt<11) {return;}//数据不满11个,则返回else{switch(ucRxBuffer[1])//判断数据是哪种数据,然后将其拷贝到对应的结构体中,有些数据包需要通过上位机打开对应的输出后,才能接收到这个数据包的数据{
//			//memcpy为编译器自带的内存拷贝函数,需引用"string.h",将接收缓冲区的字符拷贝到数据结构体里面,从而实现数据的解析。
//			case 0x51:	memcpy(&stcAcc,&ucRxBuffer[2],8);break;
//			case 0x52:	memcpy(&stcGyro,&ucRxBuffer[2],8);break;
//			case 0x53:	memcpy(&stcAngle,&ucRxBuffer[2],8);break;case 0x50:	memcpy(&stcTime,&ucRxBuffer[2],8);break;//memcpy为编译器自带的内存拷贝函数,需引用"string.h",将接收缓冲区的字符拷贝到数据结构体里面,从而实现数据的解析。case 0x51:	memcpy(&stcAcc,&ucRxBuffer[2],8);break;case 0x52:	memcpy(&stcGyro,&ucRxBuffer[2],8);break;case 0x53:	memcpy(&stcAngle,&ucRxBuffer[2],8);break;case 0x54:	memcpy(&stcMag,&ucRxBuffer[2],8);break;case 0x55:	memcpy(&stcDStatus,&ucRxBuffer[2],8);break;case 0x56:	memcpy(&stcPress,&ucRxBuffer[2],8);break;case 0x57:	memcpy(&stcLonLat,&ucRxBuffer[2],8);break;case 0x58:	memcpy(&stcGPSV,&ucRxBuffer[2],8);break;case 0x59:	memcpy(&stcQ,&ucRxBuffer[2],8);break;//0x50	时间//0x51	加速度//0x52	角速度//0x53	角度//0x54	磁场//0x55	端口状态//0x56	气压高度//0x57	经纬度//0x58	地速//0x59	四元数//0x5A	GPS定位精度//0x5F	读取}ucRxCnt=0;//清空缓存区}
}void CopeSerial1Data(unsigned char ucData)
{	UART2_Put_Char(ucData);//转发串口1收到的数据给串口2(JY模块)
}/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/int main()
{u8 i=0;SysTick_Init(72);Initial_UART1(9600);//串口初始化为9600Initial_UART2(9600);//接JY-901模块的串口	LED_Init();delay_ms(1000);delay_ms(1000);//等等JY-91初始化完成while(1){delay_ms(1000);i++;if(i%20==0){LED1=!LED1;}if(i>20){i = 0;printf("正在进行加速度校准\r\n");sendcmd(ACCCALSW);delay_ms(100);//等待模块内部自动校准好,模块内部会自动计算需要一定的时间sendcmd(SAVACALSW);delay_ms(100);//保存当前配置printf("加速度校准完成\r\n");}//输出时间printf("Time:20%d-%d-%d %d:%d:%.3f\r\n",stcTime.ucYear,stcTime.ucMonth,stcTime.ucDay,stcTime.ucHour,stcTime.ucMinute,(float)stcTime.ucSecond+(float)stcTime.usMiliSecond/1000);delay_ms(10);//输出加速度//串口接受到的数据已经拷贝到对应的结构体的变量中了,根据说明书的协议,以加速度为例 stcAcc.a[0]/32768*16就是X轴的加速度,printf("Acc:%.3f %.3f %.3f\r\n",(float)stcAcc.a[0]/32768*16,(float)stcAcc.a[1]/32768*16,(float)stcAcc.a[2]/32768*16);delay_ms(10);//输出角速度printf("Gyro:%.3f %.3f %.3f\r\n",(float)stcGyro.w[0]/32768*2000,(float)stcGyro.w[1]/32768*2000,(float)stcGyro.w[2]/32768*2000);delay_ms(10);//输出角度printf("Angle:%.3f %.3f %.3f\r\n",(float)stcAngle.Angle[0]/32768*180,(float)stcAngle.Angle[1]/32768*180,(float)stcAngle.Angle[2]/32768*180);delay_ms(10);//输出磁场printf("Mag:%d %d %d\r\n",stcMag.h[0],stcMag.h[1],stcMag.h[2]);	delay_ms(10);//输出气压、高度printf("Pressure:%ld Height%.2f\r\n",stcPress.lPressure,(float)stcPress.lAltitude/100);delay_ms(10);//输出端口状态printf("DStatus:%d %d %d %d\r\n",stcDStatus.sDStatus[0],stcDStatus.sDStatus[1],stcDStatus.sDStatus[2],stcDStatus.sDStatus[3]);delay_ms(10);//输出经纬度printf("Longitude:%ldDeg%.5fm Lattitude:%ldDeg%.5fm\r\n",stcLonLat.lLon/10000000,(double)(stcLonLat.lLon % 10000000)/1e5,stcLonLat.lLat/10000000,(double)(stcLonLat.lLat % 10000000)/1e5);delay_ms(10);//输出地速printf("GPSHeight:%.1fm GPSYaw:%.1fDeg GPSV:%.3fkm/h\r\n",(float)stcGPSV.sGPSHeight/10,(float)stcGPSV.sGPSYaw/10,(float)stcGPSV.lGPSVelocity/1000);delay_ms(10);//输出四元素printf("Four elements:%.5f %.5f %.5f %.5f\r\n\r\n",(float)stcQ.q[0]/32768,(float)stcQ.q[1]/32768,(float)stcQ.q[2]/32768,(float)stcQ.q[3]/32768);delay_ms(10);//等待传输完成}//主循环}		

串口文件参考

#include <stdio.h>
#include "system.h"  //#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_rcc.h"
#include "misc.h"static unsigned char TxBuffer[256];
static unsigned char TxCounter=0;
static unsigned char count=0; 
extern void CopeSerial1Data(unsigned char ucData);void Initial_UART1(unsigned long baudrate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = baudrate;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_TXE, DISABLE);  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);        USART_ClearFlag(USART1,USART_FLAG_TC);USART_Cmd(USART1, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void UART1_Put_Char(unsigned char DataToSend)
{TxBuffer[count++] = DataToSend;  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  
}void UART1_Put_String(unsigned char *Str)
{while(*Str){if(*Str=='\r')UART1_Put_Char(0x0d);else if(*Str=='\n')UART1_Put_Char(0x0a);else UART1_Put_Char(*Str);Str++;}
}//重定义fputc函数 
int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
}void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET){   USART_SendData(USART1, TxBuffer[TxCounter++]); if(TxCounter == count) {USART_ITConfig(USART1, USART_IT_TXE, DISABLE);// 全部发送完成}USART_ClearITPendingBit(USART1, USART_IT_TXE); }else if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){CopeSerial1Data((unsigned char)USART1->DR);//处理数据USART_ClearITPendingBit(USART1, USART_IT_RXNE);}USART_ClearITPendingBit(USART1,USART_IT_ORE);}

JY901 官方参数直接下载拿过来用

#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

测试效果如下 (测试的效果)测试过程,注意细节,接线和程序,都会导致没有效果,

请添加图片描述


http://www.ppmy.cn/news/669509.html

相关文章

BWT压缩算法及FM搜索算法详解

BWT压缩算法其经典地位无可撼动&#xff0c; 思想真是个奇妙的东西&#xff0c; 废话不多说&#xff0c; 让我们来看看她的奇妙之处吧。 假设有一串字符串S"acaacg"&#xff0c; 长度为6&#xff0c; 如果直接对此串进行压缩&#xff0c; 可能是a 1, c 1, a 2, c 1, …

Spring计时器StopWatch

文章目录 StopWatch介绍StopWatch属性详解StopWatch方法详解StopWatch使用示例 StopWatch介绍 StopWatch类是Spring框架中用于测量代码执行时间的工具类&#xff0c;它提供了一系列属性来记录监测信息。 本文基于spring-boot-starter-web:2.2.2RELEASE版本。 源码&#xff1…

BWA/BWT 比对软件

名称 bwa – Burrows-Wheeler Alignment Tool 内容 摘要 描述 命令行与选项 SAM 比对格式 短序列比对注意事项 比对精确性 估计插入大小分布 内存需求 速度 Bwa-0.6中的改变 其他 作者 引用与授权 历史 摘要 b w a i n d e x r e f . f a b w a m e m r e f . f …

STM32读取BWT901CL传感器数据

1 简述 最近想做一个检测小孩或者是老人&#xff0c;在家摔倒项目。大致和大家说一下项目的框架。 要用到一个能检测运动姿态的传感器&#xff0c;最好是无线的。于是我在网上找了一款带蓝牙的姿态角度传感器。给大家看下这个模块。 下面和大家分享下代码 2 程序设计 串口…

BWT算法解码

博文复制了原博客&#xff0c;做了少许修改 将原始序列经过BWT转换后&#xff0c; 可以更方便的进行压缩&#xff1b;而且BWT转换是一个可逆的转换&#xff0c;能够根据转换后的序列还原出原始序列&#xff1b; BWT转换首先将序列进行在序列的末尾插入一个字符&#xff0c;并…

双正交小波基 BWT

Berkeley小波变换&#xff08;BWT&#xff09;由四个方向上的四对母小波组成。在每对中&#xff0c;一个小波具有奇数对称性&#xff0c;另一个具有偶数对称性。通过对整个集合&#xff08;加上一个常数项&#xff09;的平移和缩放&#xff0c;小波在二维中形成一个完整的正交基…

MATLAB读取BWT901BLECL5.0

MATLAB读取BWT901BLECL5.0 这个太简单了&#xff0c;使用BWT901CL的MATLAB程序改了一下参数。 代码 clear all; close all; clc; instrreset; disp(Press CtrlC to stop collecting data!) sserial(com4,baudrate,115200); fopen(s) ;%Open Com Port 请将COM19换成电脑识别…

BWT901BLECL5.0连接Ubuntu

ubuntu下使用维特智能蓝牙5.0 1、这里我们用的是VMwaer虚拟机&#xff0c;共用本地物理机的串口,18.04版本系统自带CH340驱动插上直接用即可&#xff08;更低版本安装ch340请参考该博客&#xff09; 2、这里我们打开ubuntu自带的串口助手&#xff0c;如果没有自带串口助手需要…