文章目录

  • 1 介绍
  • 2 开发准备
    • 2.1硬件、软件准备
    • 2.2 接线方式
  • 3 程序讲解
    • 3.1程序思路讲解
    • 3.2 main函数
    • 3.3 串口1初始化
    • 3.4 串口2初始化
    • 3.5 串口2中断服务函数
    • 3.6 数据缓存区
    • 3.7 数据解析
    • 3.8 数据输出
  • 4输出结果显示

1 介绍

大家从标题中来看呢,大家可能会有些困惑,MPU6050只输出加速度、陀螺仪。没有角度。这个也是我今天想和大家说的。最近我做了一个倾角项目。老板基于成本考虑希望我能用MPU6050去算出来角度。说实话自己没接触这个东西,去搞的时候才知道挺难的,很地方看不懂。然后我去看过了正电原子的MPU6050的解算。但是那个角度的结果和我想要精度有点差别。无意中呢在淘宝上搜到了一个维特智能的JY61模块。这个模块的内置的就是MPU6050模块。这个商家说它的静态角度的精度为0.05度、动态0.1度。这个精度是很符合我的需求。给大家看下这个模块

这个模块体积很小巧就15×15×2mm大小。串口通讯用单片机去获取数据很简单,相比起直接去获取MPU6050简单不知道多少倍了。下面和大家说说我是怎么去用STM32F103读取JY61陀螺仪、加速度、角度的数据。

2 开发准备

讲程序之前呢,和大家简单的说说一些硬件、软件准备和JY61怎么和STM32F103接线的。

2.1硬件、软件准备

硬件:JY61模块、USB-TTL、STM32F103开发板、杜邦线。STM32F103的开发板呢,我用的也是维特智能32开发板做测试用。给大家上个图:

软件 :https://pan.baidu.com/s/1SEWmixu4jtUL2HH_3Hcn2g 提取码:zryo
这个是我的写的一个 示例代码大家有兴趣的可以看下:https://pan.baidu.com/s/1sXnlT89FTTs5tONLiaPihw

2.2 接线方式

1、使用USB-TTL将STM32F103C8T6与电脑连接通信
2、JY61与STM32F103C8T6使用杜邦线连接。具体接线如下图所示:
具体接线方式如下:

3 程序讲解

3.1程序思路讲解

好了到大家最关心的地方了。在这里呢。我先和大家说下。我的整体思路是什么。以一个整体框架给大家做一个说明

从上面来看呢,一共就分为主要的两个部分。串口初始化和while主循环。
1 、串口初始化又分为串口1初始化、串口2初始化。其中串口2初始化又多了一个串口2中断服务函数,这个函数用来接收JY61的传过来的数据,然后放在数据缓存区。
2、while主循环包括数据解析和数据输出。数据解析负责把从串口2中断服务函数得到的数据进行数据的一个处理。然后从串口1把数据输出到PC端。
下面分别和大家说下中间的一些重要的函数。

3.2 main函数

程序的执行都是在这个函数里面进行的。它包括串口初始化和while主循环。其中这个Initial_UART1函数就是串口1初始化。Initial_UART2是串口2初始化.

int main(void)
{  char str[100];unsigned char len,i;USB_Config();      //配置USB-HIDSysTick_init(72,10);//设置时钟频率Initial_UART1(9600);//接PC的串口Initial_UART2(9600);//接JY-901模块的串口   LED_ON();delay_ms(1000);//等等JY-91初始化完成while(1){         delay_ms(500);//输出时间sprintf(str,"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);UART1_Put_String(str);       delay_ms(10);//输出加速度sprintf(str,"Acc:%.3f %.3f %.3f\r\n",(float)stcAcc.a[0]/32768*16,(float)stcAcc.a[1]/32768*16,(float)stcAcc.a[2]/32768*16);UART1_Put_String(str);delay_ms(10);//输出角速度sprintf(str,"Gyro:%.3f %.3f %.3f\r\n",(float)stcGyro.w[0]/32768*2000,(float)stcGyro.w[1]/32768*2000,(float)stcGyro.w[2]/32768*2000);UART1_Put_String(str);delay_ms(10);//输出角度sprintf(str,"Angle:%.3f %.3f %.3f\r\n",(float)stcAngle.Angle[0]/32768*180,(float)stcAngle.Angle[1]/32768*180,(float)stcAngle.Angle[2]/32768*180);UART1_Put_String(str);delay_ms(10);//输出磁场sprintf(str,"Mag:%d %d %d\r\n",stcMag.h[0],stcMag.h[1],stcMag.h[2]);UART1_Put_String(str);       delay_ms(10);//输出气压、高度sprintf(str,"Pressure:%ld Height%.2f\r\n",stcPress.lPressure,(float)stcPress.lAltitude/100);UART1_Put_String(str); delay_ms(10);//输出端口状态sprintf(str,"DStatus:%d %d %d %d\r\n",stcDStatus.sDStatus[0],stcDStatus.sDStatus[1],stcDStatus.sDStatus[2],stcDStatus.sDStatus[3]);UART1_Put_String(str);delay_ms(10);//输出经纬度sprintf(str,"Longitude:%ldDeg%.5fm Lattitude:%ldDeg%.5fm\r\n",stcLonLat.lLon/10000000,(double)(stcLonLat.lLon % 10000000)/1e5,stcLonLat.lLat/10000000,(double)(stcLonLat.lLat % 10000000)/1e5);UART1_Put_String(str);delay_ms(10);//输出地速sprintf(str,"GPSHeight:%.1fm GPSYaw:%.1fDeg GPSV:%.3fkm/h\r\n",(float)stcGPSV.sGPSHeight/10,(float)stcGPSV.sGPSYaw/10,(float)stcGPSV.lGPSVelocity/1000);UART1_Put_String(str);delay_ms(10);//输出四元素sprintf(str,"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);UART1_Put_String(str);delay_ms(10);//等待传输完成}//主循环
}

3.3 串口1初始化

串口1初始化就是对串口1进行使能。打开UART1_Put_String函数。通过这个函数把结果输出到PC端的。

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);
}

3.4 串口2初始化

串口2初始化两个作用,第一打开串口2这个通道。第二就是打开串口2的中断服务函数。

void Initial_UART2(unsigned long baudrate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;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_3;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(USART2, &USART_InitStructure); USART_ITConfig(USART2, USART_IT_TXE, DISABLE);    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);USART_ClearFlag(USART2,USART_FLAG_TC);    USART_Cmd(USART2, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}

3.5 串口2中断服务函数

这个函数的功能就是不停的把JY61的数据放到数据缓存区,就是往这个CopeSerial2Data函数发数据。

void USART2_IRQHandler(void)
{if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET){   USART_SendData(USART2, TxBuffer[TxCounter++]); USART_ClearITPendingBit(USART2, USART_IT_TXE);if(TxCounter == count) USART_ITConfig(USART2, USART_IT_TXE, DISABLE);}else if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){CopeSerial2Data((unsigned char)USART2->DR);//处理数据USART_ClearITPendingBit(USART2, USART_IT_RXNE);}USART_ClearITPendingBit(USART2,USART_IT_ORE);
}

3.6 数据缓存区

数据缓存区是从串口2中断服务函数过来的。把数据最终放在stcAcc、stcGyro、stcAngle这些结构体里等待数据解析来处理。

void CopeSerial2Data(unsigned char ucData)
{static unsigned char ucRxBuffer[250];static unsigned char ucRxCnt = 0;    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;}ucRxCnt=0;//清空缓存区}
}

3.7 数据解析

从数据缓存区过来的数据,根据商家的协议都是16进制的数据。因此,我还需要进一步的把数据进行处理把16进制的数据处理成10进制的数据方便阅读。怎么处理呢?还是根据商家的协议去处理的。我们就以角度为例。商家协议在下图:

从上图看呢。角度输出的格式呢应该是55 53 RollL RollH PitchL PitchH YawL YawH TL TH SUM。这个格式就是放在数据缓存区的格式。怎么把数据缓存区的16进制转换成10进制呢?这个还要根据商家给的公式(如下图所示)。

写成程序就是下面这样的。

(float)stcAngle.Angle[0]/32768*180,(float)stcAngle.Angle[1]/32768*180,(float)stcAngle.Angle[2]/32768*180)

3.8 数据输出

数据输出相比较前面的就比较简单了。它的原理就是把上面解析好的数据直接通过一个函数就发出来了。

sprintf(str,"Angle:%.3f %.3f %.3f\r\n",(float)stcAngle.Angle[0]/32768*180,(float)stcAngle.Angle[1]/32768*180,(float)stcAngle.Angle[2]/32768*180);UART1_Put_String(str);delay_ms(10);

发送的函数就很简单了。就是一个UART1_Put_String打印函数。把解析的结果直接从串口1打印出来到PC端。

4输出结果显示

在电脑上正确连接好板子,首先打开串口调试助手,找到相应的端口,然后打开串口,注意这里波特率设置为9600,然后就可以观察到左边的窗口有数据输出了。如图所示:

用STM32读取6轴角度传感器JY61的陀螺仪、加速度、角度数据MPU6050相关推荐

  1. 用arduino uno的串口读取JY61角度传感器的角速度、加速度、角度数据MPU6050

    1 介绍 大家从标题中来看呢,大家可能会有些困惑,MPU6050只输出加速度.陀螺仪.没有角度.这个也是我今天想和大家说的.最近我做了一个倾角项目.老板基于成本考虑希望我能用MPU6050去算出来角度 ...

  2. STM32实现六轴姿态测量陀螺仪模块JY61P(标准库与HAL库实现)

    本模块支持串口采用串口实现数据采集和处理 设备型号选择 目录 设备型号选择 六轴姿态测量陀螺仪模块简介 产品概述 产品特点 引脚说明 模块UART与MCU连接 应用领域 模块与单片机的接线表设计 标准 ...

  3. STM32读取MPU6050陀螺仪芯片数据核心程序

    1 简 介 最近,想学角度融合算法在网上买一个JY61的模块.他们家的模块用起来还不错.模块分为串口通讯和IIC通讯的.串口读取数据他们家有例程,我就不说了.想分享给大家这个模块的IIC是怎么去读取M ...

  4. stm32读取目标芯片_STM32通过IIC读取MPU6050陀螺仪芯片数据核心程序

    1  简 介 最近,想学角度融合算法在网上买一个JY61的模块.他们家的模块用起来还不错.模块分为串口通讯和IIC通讯的.串口读取数据他们家有例程,我就不说了.想分享给大家这个模块的IIC是怎么去读取 ...

  5. linux 串口读取陀螺仪,stm32读取陀螺仪MPU6050发送数据到串口

    [实例简介] IAR环境下,stm32读取MPU6050数据,发送到串口. [实例截图] [核心代码] 6b42b05e-a094-444f-b033-eda513b6cc49 └── tly01 ├ ...

  6. STM32读取SHT3x系列温湿度传感器,标准库和HAL库

    STM32读取SHT3x系列(SHT30.SHT31.SHT35)温湿度传感器的数据并显示在0.96寸OLED屏上. 我下面提供两份代码,一份是标准库使用硬件I2C的,另一份是HAL库使用软件模拟II ...

  7. stm32 读取sd卡图片显示_「正点原子STM32Mini板资料连载」第三十五章 汉字显示实验...

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十五章 汉字显示实验 汉字显示在 ...

  8. 使用ESP32驱动QMA7981读取三轴加速度(带例程)

    使用ESP32驱动QMA7981读取三轴加速度(带例程) 1.简介 ESP32是国产乐鑫公司生产的32位单片机,双核240MHz,带有蓝牙和wifi功能,本例中使用的是ESP32-S模组.QMA798 ...

  9. 如何用Stm32读取NPN型颜色传感器

    近期在一个项目中接触到了一款NPN型颜色传感器,想用stm32f103读取它的输出状态. 首先明白一下NPN和PNP的概念: NPN: 常开:无信号时断开,有信号时输出低电平 常闭:无信号时低电平,有 ...

最新文章

  1. OpenStack入门修炼之实战--实现阿里云ESC多FLAT网络(21)
  2. 首个测试博客搜索引擎等你来体验!
  3. Maven手动将jar包放入本地仓库
  4. ArrayList的实现原理
  5. 微信小程序入门(一)
  6. webpack打包原理_对于webpack打包原理你知道有多少?
  7. BPSK调制解调matlab仿真
  8. Windows 进程激活服务
  9. gp数据库日常运维sql语句笔记
  10. 赢在CSDN——谈谈程序员为什么要持续学习和创作?对CSDN的期待、个人创作的规划
  11. 协议分析(微信网页版 wx2.qq.com)
  12. APP如何在应用商店获取较高的排名?
  13. 喵星史话(一)——猫的起源
  14. GIMP 快速入门(2)
  15. github如何上传代码到仓库(从本地上传代码到github)
  16. C语言进程——进程间的通信方式
  17. [Vue warn]: Duplicate keys detected: ‘user‘. This may cause an update error. 解决方法
  18. OpenGL核心技术之GPU编程
  19. Matlab GUI/APP 浅谈(附计算器源码)
  20. 2021年中国城镇居民基本医疗保险参保人数、受待遇情况及异地就医情况分析[图]

热门文章

  1. 解决一个GAN训练过程中的报错:one of the variables needed for gradient computation has been modified by an inplace
  2. html颜色块选择器,ColorPick:网页颜色选择器
  3. 高级软件工程-课程总结
  4. 泛微数据连接配置路径
  5. Adobe Acrobat将网页保存成PDF
  6. MS08067 11月份千人白帽免费公开课(5场)轮番来袭~
  7. 一些相见恨晚的 JavaScript 技巧 脚本之家
  8. Netty干货分享:京东京麦的生产级TCP网关技术实践总结
  9. http代理动态转发,什么是动态转发代理ip?
  10. Android平板电脑应用开发的技巧和注意点