[嵌入式开发模块]GY25倾斜角度传感器 驱动模块
文章目录
- 前言
- GY25简介
- 概述
- 通信协议
- 驱动文件
- GY25Driver.h
- GY25Recver.c
- GY25Cmder.c
- 依赖
- 使用示例
- 更新历史
前言
干活中用到了GY25传感器模块,写了相应的驱动程序,放出来。
这个模块本身的协议比较简单,所以模块的驱动也很小巧。
驱动被设计为拥有指令器和接收机两个部分,完全被动方式运行,与具体的平台解耦,只支持串口通讯。
GY25简介
概述
GY-25 是一款低成本倾斜度模块。工作电压3-5v 功耗小,体积小。其工作原理,是通过陀螺仪与加速度传感器经过数据融合算法最后得到直接的角度数据。此倾斜度模块以串口TTL 电平全双工方式与上位机进行通信。该产品精度高,稳定性高。能够在任意位置得到准确的角度,输出的波特率有9600bps 与115200bps有连续输出与询问输出两种方式,可适应不同的工作环境。与所有的单片机及电脑连接。
通信协议
(1)串口通信参数(默认波特率值115200 bps,)
波特率:9600 bps 校验位:N 数据位:8 停止位:1
波特率:115200 bps 校验位:N 数据位:8 停止位:1
注意:波特率选择可通过PCB 上焊接点选择。
(2)模块输出格式,每帧包含8 个字节(十六进制):
①.Byte0: 0xAA 帧头标志
②.Byte1: 0x00~0xFF 航向角高8 位
③.Byte2: 0x00~0xFF 航向角低8 位
④.Byte3: 0x00~0xFF 俯仰角高8 位
⑤.Byte4: 0x00~0xFF 俯仰角低8 位
⑥.Byte5: 0x00~0xFF 横滚角高8 位
⑦.Byte6: 0x00~0xFF 横滚角低8 位
⑧.Byte7: 0x55 帧结束标志
计算方法: 角度= 高8 位<<8|低8 位(结果为实际角度乘以100)
例:一帧数据 <0xAA-0x00-0x64-0x03-0XE8-0x27-0x10-0x55>
表示:航向角=1.00 度
俯仰角=10.00 度
横滚角=100.00 度
(3)命令字节,由外部控制器发送至模块(十六进制)
①.0xA5+0x51: 查询模式,直接返回角度值,需每次读取都发送
②.0xA5+0x52: 自动模式,直接返回角度值,只需要初始化时发一次
③.0xA5+0x53: 自动模式,ASCII 码输出,便于直接电脑串口助手查看
④.0xA5+0x54: 校正模式,校正俯仰横滚角0 度,需要保持水平时候发送
⑤.0xA5+0x55: 校正模式,校正航向0 度,航向任意角度清零
驱动文件
GY25Driver.h
/*
*******************************************************************************************
*
* GY25 DRIVER MODULE
* GY25驱动模块
*
* File : GY25Driver.h
* By : Lin Shijun(https://blog.csdn.net/lin_strong)
* Date: 2020/04/29
* version: V1.0
* History: 2020/04/29 V1.0 the prototype
* Note : The GY25 driver is divided into two part, i.e. cmder and recver. The cmder is for
* sending the GY25 command. The recver is for resolving data from the GY25.
********************************************************************************************
*/#ifndef GY25DRIVER_H
#define GY25DRIVER_H/*
******************************************************************************************
* INCLUDE
******************************************************************************************
*/#include <stdint.h>/*
******************************************************************************************
* DEBUG CONFIGURATION
******************************************************************************************
*/// to enable debug messages in this module
// #define GY25_DEBUG /*
******************************************************************************************
* CONSTANT
******************************************************************************************
*/// Frame Header byte of data frame
#define GY25DF_HEADER 0xAA
// Frame Ender byte of data frame
#define GY25DF_ENDER 0x55
// length (in byte) of data frame
#define GY25DF_LENGTH 8// Frame Header byte of command frame
#define GY25CF_HEADER 0xA5
// Query mode
#define GY25CMD_QUERY 0x51
// Automatic mode
#define GY25CMD_AUTO 0x52
// Automatic mode(ASCII)
#define GY25CMD_AUTO_ASCII 0x53
// Calibrate pitch and roll angle
#define GY25CMD_CALI_PITCHROLL 0x54
// Calibrate course angle
#define GY25CMD_CALI_COURSE 0x55/*
******************************************************************************************
* TYPE DEFINE
******************************************************************************************
*/typedef struct GY25STRUCT_DATA{int16_t angleCourse; // = 'real angle' * 100int16_t anglePitch ; // = 'real angle' * 100int16_t angleRoll ; // = 'real angle' * 100
} GY25Data;typedef void (* GY25FUNC_DATA)(GY25Data data);/*
******************************************************************************************
* INTERFACES
******************************************************************************************
*/void GY25Cmder_Init(void (* outChannel)(uint8_t b));
void GY25Cmder_Query(void);
void GY25Cmder_EnterModeAuto(void);
void GY25Cmder_EnterModeAuto_ASCII(void);
void GY25Cmder_CalibratePitchRoll(void);
void GY25Cmder_CalibrateCourse(void);
void GY25Cmder_Destroy(void);void GY25Recver_Init(GY25FUNC_DATA onRecvData);
// Call it to modify the call-back function.
void GY25Recver_RegisterCallback(GY25FUNC_DATA onRecvData);
void GY25Recver_CleanupBuffer(void);
// Feed the receiver every byte received so that receiver can notify user
// the resolved data for each frame.
void GY25Recver_Feed(uint8_t nextByte);
void GY25Recver_Destroy(void);#endif // of GY25DRIVER_H
GY25Recver.c
/*
*******************************************************************************************
*
* GY25 RECEIVER MODULE
* GY25驱动模块 - 接收机
*
* File : GY25Recver.c
* By : Lin Shijun(https://blog.csdn.net/lin_strong)
* Date: 2020/04/29
* version: V1.0
* History: 2020/04/29 V1.0 the prototype
* Note : only for hex format
********************************************************************************************
*//*
*********************************************************************************************
* INCLUDES
*********************************************************************************************
*/#include "GY25Driver.h"
#include "BufferExternalArray.h"#ifndef GY25_DEBUG
#undef _DEBUG
#endif#include "DebugMsg.h"
/*
*********************************************************************************************
* LOCAL FUNCTION
*********************************************************************************************
*/#define ARRAYSIZE(arr) (sizeof(arr)/ sizeof(arr[0]))
#define _bufGet(index) BufferUINT8Indexed_get((BufferUINT8Indexed)_buf, index)/*
*********************************************************************************************
* LOCAL VARIABLE
*********************************************************************************************
*/static const char * _str_GY25Recver = "GY25Recver";static GY25FUNC_DATA _onRecvData;static uint8_t _frameBuf[GY25DF_LENGTH];
static BufferUINT8Array _buf;/*
*********************************************************************************************
* INTERFACE IMPLEMENTATION
*********************************************************************************************
*/void GY25Recver_Init(GY25FUNC_DATA onRecvData){_onRecvData = onRecvData;_buf = BufferUINT8ExternalArray_Create(_frameBuf, GY25DF_LENGTH);if(_buf == NULL)for(;;); // fatal error
}void GY25Recver_RegisterCallback(GY25FUNC_DATA onRecvData){_onRecvData = onRecvData;
}void GY25Recver_CleanupBuffer(void){Buffer_Cleanup((Buffer)_buf);
}void GY25Recver_Feed(uint8_t nextByte){GY25Data data;if(Buffer_isFull(_buf))BufferUINT8_FrontOut((BufferUINT8)_buf);BufferUINT8_BackIn((BufferUINT8)_buf, nextByte);// if we haven't received GY25DF_LENGTH bytes.if(!Buffer_isFull(_buf) || // or it's not a frame._bufGet(0) != GY25DF_HEADER || _bufGet(GY25DF_LENGTH - 1) != GY25DF_ENDER){_dbg_printf1("%s: got corrupt frame.\r\n", _str_GY25Recver);return; // then bye.}// if found a data frame.data.angleCourse = (_bufGet(1) << 8) | _bufGet(2);data.anglePitch = (_bufGet(3) << 8) | _bufGet(4);data.angleRoll = (_bufGet(5) << 8) | _bufGet(6);_dbg_printf4("%s: got data-Course(%i),Pitch(%i),Roll(%i)\r\n", _str_GY25Recver, data.angleCourse, data.anglePitch, data.angleRoll);if(_onRecvData)_onRecvData(data);Buffer_Cleanup((Buffer)_buf);
}void GY25Recver_Destroy(){_onRecvData = NULL;Buffer_Destroy(_buf);_buf = NULL;
}
GY25Cmder.c
/*
*******************************************************************************************
*
* GY25 COMMANDER MODULE
* GY25驱动模块 - 指令器
*
* File : GY25Cmder.c
* By : Lin Shijun(https://blog.csdn.net/lin_strong)
* Date: 2020/04/29
* version: V1.0
* History: 2020/04/29 V1.0 the prototype
* Note :
********************************************************************************************
*//*
*********************************************************************************************
* INCLUDES
*********************************************************************************************
*/#include "GY25Driver.h"/*
*********************************************************************************************
* LOCAL FUNCTION DECLARATION
*********************************************************************************************
*/static void _sendCmd(uint8_t cmdByte);/*
*********************************************************************************************
* LOCAL VARIABLE
*********************************************************************************************
*/
static void (* _out)(uint8_t b) = NULL;/*
*********************************************************************************************
* INTERFACE IMPLEMENTATION
*********************************************************************************************
*/void GY25Cmder_Init(void (* outChannel)(uint8_t b)){_out = outChannel;
}void GY25Cmder_Destroy(){_out = NULL;
}void GY25Cmder_Query(void){_sendCmd(GY25CMD_QUERY);
}void GY25Cmder_EnterModeAuto(void){_sendCmd(GY25CMD_AUTO);
}void GY25Cmder_EnterModeAuto_ASCII(void){_sendCmd(GY25CMD_AUTO_ASCII);
}void GY25Cmder_CalibratePitchRoll(void){_sendCmd(GY25CMD_CALI_PITCHROLL);
}void GY25Cmder_CalibrateCourse(void){_sendCmd(GY25CMD_CALI_COURSE);
}
/*
*********************************************************************************************
* LOCAL FUNCTION IMPLEMENTATION
*********************************************************************************************
*/
static void _sendCmd(uint8_t cmdByte){if(_out == NULL)return;_out(GY25CF_HEADER);_out(cmdByte);
}
依赖
接收器的实现依赖于我实现的环形缓冲区:
环形缓冲区/循环队列C语言面向对象实现(二)Buffer类源码
至于DebugMsg.h则是我自己使用的调试信息的模块:
#ifndef _DEBUG_MSG_H
#define _DEBUG_MSG_H
#include <stdio.h>
#ifdef _DEBUG#define _dbg_printf0(format) ((void)printf(format))#define _dbg_printf1(format,p1) ((void)printf(format,p1))#define _dbg_printf2(format,p1,p2) ((void)printf(format,p1,p2))#define _dbg_printf3(format,p1,p2,p3) ((void)printf(format,p1,p2,p3))#define _dbg_printf4(format,p1,p2,p3,p4) ((void)printf(format,p1,p2,p3,p4))#define _dbg_printf5(format,p1,p2,p3,p4,p5) ((void)printf(format,p1,p2,p3,p4,p5))#define _dbg_printf6(format,p1,p2,p3,p4,p5,p6) ((void)printf(format,p1,p2,p3,p4,p5,p6))#define _dbg_printf7(format,p1,p2,p3,p4,p5,p6,p7) \((void)printf(format,p1,p2,p3,p4,p5,p6,p7))#define _dbg_printf8(format,p1,p2,p3,p4,p5,p6,p7,p8) \((void)printf(format,p1,p2,p3,p4,p5,p6,p7,p8))#define _dbg_printf9(format,p1,p2,p3,p4,p5,p6,p7,p8,p9) \((void)printf(format,p1,p2,p3,p4,p5,p6,p7,p8,p9))
#else#define _dbg_printf0(format)#define _dbg_printf1(format,p1)#define _dbg_printf2(format,p1,p2)#define _dbg_printf3(format,p1,p2,p3)#define _dbg_printf4(format,p1,p2,p3,p4)#define _dbg_printf5(format,p1,p2,p3,p4,p5)#define _dbg_printf6(format,p1,p2,p3,p4,p5,p6)#define _dbg_printf7(format,p1,p2,p3,p4,p5,p6,p7)#define _dbg_printf8(format,p1,p2,p3,p4,p5,p6,p7,p8)#define _dbg_printf9(format,p1,p2,p3,p4,p5,p6,p7,p8,p9)
#endifint dummyprintf(const char *format, ...);#endif
这样在项目中同时宏定义 _DEBUG 和 GY25_DEBUG 时才会打印调试信息。不需要的话删除相关语句就好。
想要了解相关技巧的话详见:
C语言宏配置的各种奇淫技巧
使用示例
使用此模块基本分几步:
- 初始化模块
- 如需要发送指令则实现并注册信道给指令器;注册回调函数给接收器,这样接收器在发现完整的数据帧时就会通过回调函数进行通知。
- 不断接收数据,并喂(Feed)给接收器;如需要发指令,随时调用指令器的接口。
以下代码示例了在上电后发送校准指令,然后进入自动模式,之后不断读取数据并进行解析(假设使用标准输入输出上的串口和GY25通信):
#include "GY25Driver.h"
#include <stdio.h>
#include <stdint.h>
……
// 收到数据的回调函数
static void onDataResolved(GY25Data data);
// 发送信道
static void sendChannel(uint8_t b);void main(){uint8_t b;……GY25Recver_Init(onDataResolved);GY25Cmder_Init(sendChannel);// 延迟一小段时间(void)MyOS_DlyHMSM(0, 0, 0, 100);// 校准角度GY25Cmder_CalibratePitchRoll();// 延迟一小段时间(void)MyOS_DlyHMSM(0, 0, 0, 200);// 进入自动模式GY25Cmder_EnterModeAuto();for(;;){// 不断得到下一个字节并喂给接收机// 接收机会通过回调函数实时传递解析出来的值b = (uint8_t)getchar();GY25Recver_Feed(b);}
}static void onDataResolved(GY25Data data){// data中就是实时解析到的数据,具体怎么使用是你的事// 注意里头的整型值是 真实角度 * 100 后的值
}static void sendChannel(uint8_t b){// 往标准输出输出这个字节putchar((char)b);
}
注意:GY25可以选择用ASCII格式输出,但此模块不支持也并不打算支持解析ASCII格式的数据帧。
更新历史
2020/06/06 放出V1.0
[嵌入式开发模块]GY25倾斜角度传感器 驱动模块相关推荐
- [嵌入式开发模块]JY61姿态角度传感器 驱动模块
文章目录 前言 JY61简介 概述 通信协议 驱动文件 JY61Driver.h JY61Recver.c JY61Cmder.c 依赖 使用示例 更新历史 前言 干活中用到了JY61姿态角度传感器, ...
- [嵌入式开发模块]AD转换芯片ADS8344驱动模块
文章目录 芯片简介 代码 头文件 源文件 使用及示例代码 芯片简介 ADS8344是一个8通道16位模数转换器,使用SPI接口. 其可以使用单端或差分输入,单端模式时,每个CHX独立作为采样输入,测其 ...
- 嵌入式开发模块]AD转换芯片ADS8344驱动模块16位分辨率,程序实例
文章目录 芯片简介 代码 头文件 源文件 使用及示例代码 芯片简介 ADS8344是一个8通道16位模数转换器,使用SPI接口. 其可以使用单端或差分输入,单端模式时,每个CHX独立作为采样输入,测其 ...
- c语言数组实现环形缓冲区,[嵌入式开发模块]环形缓冲区/循环队列 C语言实现
忙着毕设,很久没有写文章了,终于答辩完了,得了个校优秀毕业设计.毕设做的是个智能接口模块,用一周时间入门了,MC9S12XEP100的开发,又用一周时间入门了uC/OS-II嵌入式操作系统,在做毕设的 ...
- [嵌入式开发模块]SHT30/20 温湿度传感器 驱动模块
文章目录 前言 SHT30简介 概述 通信协议 驱动文件 SHT30Driver.h SHT30Recver.c SHT30Cmder.c 依赖 使用示例 更新历史 前言 干活中用到了SHT30,其实 ...
- [嵌入式开发模块]通用接收状态机模块
文章目录 前言 模块相关概念和逻辑 接收机状态 标志字符序列 flush 接收机类 过滤器 onGetHeader事件 接收机运行逻辑 边际条件 相关代码 接收机代码 RxMac.h RxMacPri ...
- [嵌入式开发模块]MC9S12XEP100 IIC模块 驱动程序
此为本人写的MC9S12XEP100的IIC集成电路总线的硬件驱动程序. 文章目录 前言 相关理论 驱动模块简介 代码 驱动模块 基于UCOS-II的驱动 示例代码 代码下载 前言 相关理论 相关理论 ...
- [嵌入式开发模块]DS3231时钟芯片 驱动程序
刚刚写完DS3231时钟芯片的驱动程序.这里开源出来供大家使用.需要的自取. 先简单介绍下这个芯片,然后直接给驱动代码以及示例代码. DS3231简介 简介 DS3231是一款低成本.高精度I2C实时 ...
- 与一线Linux嵌入式开发工程师的对话
2019独角兽企业重金招聘Python工程师标准>>> 原文地址:与一线Linux嵌入式开发工程师的对话 作者:kjpioo kjpioo的说明:这篇文章转载自陈莉君老师的博客,文章 ...
最新文章
- 改名 Meta,打元宇宙牌,老龄化的 Facebook 能否再换新颜
- 使用golang求出A-Z的所有子集
- 网站推广——网站推广专员浅析企业网站验收和交付要注意哪些问题
- [转] Windows系统Net命令使用技巧
- 用神经网络迭代次数曲线模拟原子光谱
- 全球及中国水产加工市场消费潜力分析与投资规模建议报告2022版
- Ubuntu16.04 +cuda8.0+cudnn+opencv+caffe+theano+tensorflow配置明细
- C语言创建一个节点Node(附完整源码)
- 如何访问云端的tcpserver_远程读写FTP文件,花生壳盒子+Serv-U快速实现远程访问...
- 第六章 XaaS和IT服务标准
- DP Big Event in HDU
- 江苏2021年新高考八省联考成绩查询,2021八省联考成绩什么时候出 2021八省联考江苏成绩公布...
- DP专题训练之HDU 1087 	Super Jumping!
- 河北职称计算机Excel一,2012年河北省职称计算机Excel操作练习一.doc
- Bailian4022 买房子【迭代】
- matlab中的高阶导数,如何用matlab求函数的导数与高阶导数 需要技巧
- Mysql深入浅出学习
- 数据库增删改查的基本语法
- 苹果小白笔记本_苹果笔记本重装系统windows教程
- 一文理解CPU进行简单加法(计算机组成原理5.1CPU的功能和基本结构)
热门文章
- 有孚专有云如何助力高校数智化转型
- Linux utimensat/futimens/utime/utimes等等 函数(修改文件时间)
- HEVC标准(draft)翻译--帧间预测1
- HP541 XP驱动下载地址
- 软件开发方案设计文档ppt
- 详解python框架django为例,还没开始写代码前的花式坑——解决办法和排错思路。pycharm解释器配置,虚拟环境venv配置,使用命令行。
- matlab电流表怎么找,电压表、电流表到底在测量谁?小编教你快速“找对象”!...
- 学习笔记(02):XCX微信小程序基础教程-XCX微信小程序基础教程-1:小程序简介和注册1 ... ......
- Linux驱动——驱动分离思想和总线设备驱动模型
- 【python】前程无忧招聘——多线程、正则、伪造请求头、保存(excel\csv\json\mysql)、直条图展示