一、JY61P是什么?

  JY61P是一个可以获取物体姿态(角速度,加速度,角度)的陀螺仪模块,它和常规的mpu6050陀螺仪一样,但是该模块的精度更加细,有两种传输方式,1种是I2C,还有1种是串口usart传输。很多人在移植mpu6050时苦不堪言,搞不懂I2C协议,不会移植。现在可以通过一种更简单的方式串口,获取数据。关于JY61P的更多资料请看网址:六轴姿态角度传感器模组

二、串口协议?

  首先列出网址:WIT私有协议 · 深圳维特智能科技有限公司

    官方的资料对一些小白不是很友好,对官方的协议做出详细解释,不管是JY6,JY91都可以用官方的WT61协议,一下图片来源于:WT61协议 · 深圳维特智能科技有限公司

首先看官方协议:

  这几句话,首先明确1点数据包发的是十六机制数,每个数据拆分成了两个字节,将两个高低字节和一组成shortl类型的数据,但是这不是最终数据,真正的数据还有经过计算得出。

 这是JY61P串口发送的数据包,帧头是0x55,在判断第一个数据帧头0x51后,后面就是加速度的数据内容,其他角速度,角度一样。

 

 由上图可知数据包是先发送协议帧头0x55,在发送数据帧头0x53,这里是角度所以帧头是0x53,余下就是8个数据位,加上一个停止位。这样就清楚了,我只要将每两个数据整合成一个short类型数据,在根据公式(float)Data=(short)Data/32768*180,就可以了,这样问题的关键在于怎么将数据整合,在c语言的库中有 memcpy()这个函数可以选择将一个存储区的多少字节复制的另一个存储区中:C 库函数 – memcpy() | 菜鸟教程,这样我只需要将这8个数据位,即8个字节复制到我定义的short类型数组中就可以了,因为short类型占两个字节,所以会自动将前两个字节存放在第一个short类型的数组中,开始贴代码

/***********采集JY61P数据**************/
void Get_Jy61(uint16_t Data)
{
    static u8 RX_Data[250];
    static u8 len = 0;
    RX_Data[len++]=Data;    //将收到的数据存入缓冲区中
    if (RX_Data[0]!=0x55) //数据头不对,则重新开始寻找0x55数据头
    {
        len=0;
        return;
    }
    if (len<11) return;//数据不满11个,则返回
    else
    {
     switch(RX_Data[1])//判断数据是哪种数据,然后将其拷贝到对应的结构体中,有些数据包需要通过上位机打开对应的输出后,才能接收到这个数据包的数据
     {
        case 0x51:
                        memcpy(&SAcc,&RX_Data[2],8);
                        for(uint8_t j = 0; j < 3; j++)
                            {
                                SAcc.Acc[j] = (float)SAcc.Acc_S[j]/32768*16;
                            }
                        break;
        case 0x52:
                        memcpy(&SGyro,&RX_Data[2],8);
                        for(uint8_t j = 0; j < 3; j++)
                            {
                                SGyro.Gyro[j] = (float)SGyro.Gyro_S[j]/32768*2000;
                            }
                        break;
        case 0x53:
                        memcpy(&SAngle,&RX_Data[2],8);
                        for(uint8_t j = 0; j < 3; j++)
                            {
                               SAngle.Angle[j] = (float)SAngle.Angle_S[j]/32768*180;
                            }
                        break;
     }
     len=0;//清空缓存区
 }
}

这样通过串口中断函数将数据传入Get_Jy61(uint16_t Data)函数中,就可以完成数据的解包了,另外官方协议上表示串口是以char类型传输,可以将类型改成char,我用u8也可以。我写的是串口二

void JY61_Init(uint32_t bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);

    GPIO_PinAFConfig(GPIOD,GPIO_PinSource6,GPIO_AF_USART2);//IO口用作串口引脚要配置复用模式
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_5;//TX引脚
    GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;//IO口用作串口引脚要配置复用模式
    GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;
    GPIO_Init(GPIOD,&GPIO_InitStructure);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_6;//RX引脚
    GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;
    GPIO_Init(GPIOD,&GPIO_InitStructure);

    USART_InitTypeDef USART_InitStructure;//定义配置串口的结构体变量

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//开启串口二的时钟

    USART_DeInit(USART2);//清除TIM2的相关配置

    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate              = (uint32_t)(115200);//设置波特率
    USART_InitStructure.USART_WordLength            = USART_WordLength_8b;//字节长度为8bit
    USART_InitStructure.USART_StopBits              = USART_StopBits_1;//1个停止位
    USART_InitStructure.USART_Parity                = USART_Parity_No ;//没有校验位
    USART_InitStructure.USART_Mode                  = USART_Mode_Rx | USART_Mode_Tx;//将串口配置为收发模式
    USART_InitStructure.USART_HardwareFlowControl   = USART_HardwareFlowControl_None; //不提供流控
    USART_Init(USART2,&USART_InitStructure);//将相关参数初始化给串口二

    NVIC_InitTypeDef NVIC_InitStructure;//中断控制结构体变量定义
    NVIC_InitStructure.NVIC_IRQChannel                    = USART2_IRQn;//中断通道指定为USART2
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 0;//主优先级为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 1;//次优先级为1
    NVIC_InitStructure.NVIC_IRQChannelCmd                 = ENABLE;//确定使能
    NVIC_Init(&NVIC_InitStructure);//初始化配置此中断通道

    USART_ClearFlag(USART2,USART_FLAG_RXNE);//初始配置时清除接受置位

    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//初始配置接受中断

    USART_Cmd(USART2,ENABLE);//开启串口二
}


/******** 串口二 中断服务函数 ***********/
void USART2_IRQHandler(void)
{
    if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)//判断是不是真的有中断发生
    {
        //USART_SendData(USART2,USART_ReceiveData(USART2));//又将数据发回去(用于验证)
        //Get_Jy61(USART_ReceiveData(USART2));
        uint16_t Data=(USART2->DR & (uint16_t)0x01FF);
        Get_Jy61(Data);
    }
    USART_ClearITPendingBit(USART2, USART_IT_RXNE); //清除标志位
}

三、总结

 JY61P的协议需要花心思了解,希望看完我这篇文章的朋友能有所收获,以上代码除了.h文件没有贴上去以外.c文件全部贴上去了,我这篇文章上的是基于STM32F4固件库的代码,本人还写了F4寄存器的代码,F1的标准库和寄存器的代码,都可用。需要的私信我就可以了

JY61P代码

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐