【惯性导航姿态仪】 07 Mini INS/GPS 数据输出处理以及 C语言实现

【惯性导航姿态仪】 07 Mini INS/GPS 数据输出YIJI

连接实现

在这里插入图片描述

数据帧分析

在这里插入图片描述

结算后的数据帧格式

在这里插入图片描述

数据接收的程序编写

特别提示 为了使你的系统软件更快地响应数据字节的接收,建议使用中断方式接收数据。 而不是使用查询模式接收字节。中断程序越精简越好,下面给出一个数据帧接收的范例程序。基于 单片机。移植需要开启串口中断,并在相应的中断程序中编写以下代码STM32F

数据接收与程序编写

在这里插入图片描述

数据的校验

在这里插入图片描述

C语言实现

/* 
编写者:lisn3188
网址:www.chiplab7.com
作者E-mail:lisn3188@163.com
编译环境:MDK-Lite  Version: 4.23
初版时间: 2012-05-25
测试: 本程序已在第七实验室的mini IMU上完成测试
功能:
使用串行中断程序接收mini IMU 的数据。
移植者需在自己编写对应的串口初始化程序,并开启接收中断。
在中断子程序中 需要做相应的改动

为了使用这个程序,你需要:
1.初始化你的串口,将波特率与模块的波特率设置成一致的
2.开启串口的接收中断,并参考以下程序编写中断子程序
  参考 void USART2_IRQHandler(void) 
3.在主程序的循环体中,定时调用子程序:
  void UART2_CommandRoute(void)
  以检查是否收到新的数据帧
  所有的姿态数据和ADC值都会在 UART2_CommandRoute
  中进行更新。
4.使用 以下值会自动更新:

float 	yaw,  //偏航角
		pitch,//俯仰
		roll, //滚转
		alt,  //高度
		tempr,//温度
		press;//气压
int16_t ax, ay, az;//加速度计
int16_t gx, gy, gz;//陀螺仪
int16_t hx, hy, hz;//磁力计
------------------------------------
*/
 




//uart reicer flag

#define b_uart_head  0x80  //收到A5 头 标志位
#define b_rx_over    0x40  //收到完整的帧标志
// USART Receiver buffer
#define RX_BUFFER_SIZE 100 //接收缓冲区字节数

volatile unsigned char rx_buffer[RX_BUFFER_SIZE]; //接收数据缓冲区
volatile unsigned char rx_wr_index; //缓冲写指针
volatile unsigned char RC_Flag;  //接收状态标志字节

//解算后的角度值
float 	yaw,  //偏航角
		pitch,//俯仰
		roll, //滚转
		alt,  //高度
		tempr,//温度
		press;//气压
//ADC值
int16_t ax, ay, az;//加速度计
int16_t gx, gy, gz;//陀螺仪
int16_t hx, hy, hz;//磁力计
//GPS位置信息
float GPS_Altitude , //天线离海平面的高度,-9999.9到9999.9米
	  Latitude_GPS , //纬度	 单位为度
	  Longitude_GPS , //经度  单位为度
	  Speed_GPS , //地面速率  单位  米每秒
	  Course_GPS ; //地面航向(000.0~359.9度,以真北为参考基准)
unsigned char GPS_STA_Num ;

//在接收完一帧IMU姿态报告后,调用这个子程序来取出姿态数据
void UART2_Get_IMU(void)
{
	int16_t temp;
	
	temp = 0;
	temp = rx_buffer[2];
	temp <<= 8;
	temp |= rx_buffer[3];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	yaw=(float)temp / 10.0f; //偏航角
	
	temp = 0;
	temp = rx_buffer[4];
	temp <<= 8;
	temp |= rx_buffer[5];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	pitch=(float)temp / 10.0f;//俯仰
	
	temp = 0;
	temp = rx_buffer[6];
	temp <<= 8;
	temp |= rx_buffer[7];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	roll=(float)temp / 10.0f;//滚转

	temp = 0;
	temp = rx_buffer[8];
	temp <<= 8;
	temp |= rx_buffer[9];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	alt=(float)temp / 10.0f;//高度
	
	temp = 0;
	temp = rx_buffer[10];
	temp <<= 8;
	temp |= rx_buffer[11];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	tempr=(float)temp / 10.0f;//温度
	
	temp = 0;
	temp = rx_buffer[12];
	temp <<= 8;
	temp |= rx_buffer[13];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	press=(float)temp * 10.0f;//气压

}

//在接收一帧ReportMotion 后调用这个子程序来取出ADC数据
void UART2_Get_Motion(void)
{
	int16_t temp;
	
	temp = 0;
	temp = rx_buffer[2];
	temp <<= 8;
	temp |= rx_buffer[3];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	ax=temp;//加速度计 X轴的ADC值
	
	temp = 0;
	temp = rx_buffer[4];
	temp <<= 8;
	temp |= rx_buffer[5];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	ay=temp;//加速度计 Y轴的ADC值
	
	temp = 0;
	temp = rx_buffer[6];
	temp <<= 8;
	temp |= rx_buffer[7];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	az=temp;//加速度计 Z轴的ADC值
	
	temp = 0;
	temp = rx_buffer[8];
	temp <<= 8;
	temp |= rx_buffer[9];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	gx=temp;//陀螺仪 X轴的ADC值
	
	temp = 0;
	temp = rx_buffer[10];
	temp <<= 8;
	temp |= rx_buffer[11];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	gy=temp;//陀螺仪 Y轴的ADC值
	
	temp = 0;
	temp = rx_buffer[12];
	temp <<= 8;
	temp |= rx_buffer[13];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	gz=temp;//陀螺仪 Z轴的ADC值
	
	temp = 0;
	temp = rx_buffer[14];
	temp <<= 8;
	temp |= rx_buffer[15];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	hx=temp;//磁力计 X轴的ADC值
	
	temp = 0;
	temp = rx_buffer[16];
	temp <<= 8;
	temp |= rx_buffer[17];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	hy=temp;//磁力计 Y轴的ADC值
	
	temp = 0;
	temp = rx_buffer[18];
	temp <<= 8;
	temp |= rx_buffer[19];
	if(temp&0x8000){
	temp = 0-(temp&0x7fff);
	}else temp = (temp&0x7fff);
	hz=temp;//磁力计 Z轴的ADC值
}

//在接收完一帧GPS位置报告后,调用这个子程序来取出姿态数据
void UART2_Get_GPS(void)
{
	long int temp;
	//经度值,单位0.0001度。当传送的值为 1234567  表示 123.4567度
	temp = 0;
	temp = ((long int)rx_buffer[2]<<24);
	temp |= ((long int)rx_buffer[3]<<16);
	temp |= ((long int)rx_buffer[4]<<8);
	temp |= ((long int)rx_buffer[5]); 
	Longitude_GPS = ((float)temp) / ((float)10000.0);
	//纬度值,单位0.0001度。当传送的值为 123456  表示  12.4567度
	temp = 0;
	temp = ((long int)rx_buffer[6]<<24);
	temp |= ((long int)rx_buffer[7]<<16);
	temp |= ((long int)rx_buffer[8]<<8);
	temp |= ((long int)rx_buffer[9]);
	Latitude_GPS = ((float)temp) / ((float)10000.0);
	//GPS海拔高度值,单位0.1米。当传送值为 1623  表示当前海拔为 162.3米
	temp = 0;
	temp |= ((long int)rx_buffer[10]<<8);
	temp |= ((long int)rx_buffer[11]);
	GPS_Altitude = ((float)temp) / ((float)10.0);
	//锁定的卫星数量, 0 表示没有定位、
	GPS_STA_Num = rx_buffer[12];
	//GPS航向值,单位0.1度。当传送值为 125时,表示12.5度。
	temp = 0;
	temp |= ((long int)rx_buffer[13]<<8);
	temp |= ((long int)rx_buffer[14]);
	Course_GPS = ((float)temp) / ((float)10.0);
	//GPS速度,单位0.1米/S  当传送的值为 255时,表示 25.5M/S
	temp = 0;
	temp |= ((long int)rx_buffer[15]<<8);
	temp |= ((long int)rx_buffer[16]);
	Speed_GPS = ((float)temp) / ((float)10.0);

}

//以下中断子程序是基于STM32的,如果你使用的不是STM32 请做相应的修改
//------------------------------------------------------
void USART2_IRQHandler(void) //接收中断子程序
{
  unsigned char data;
 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //是否收到数据?
  {
  data=USART_ReceiveData(USART2); //读取接收到的字节
  if(data==0xa5) 
  { 
	RC_Flag|=b_uart_head; //如果接收到A5 置位帧头标专位
    rx_buffer[rx_wr_index++]=data; //保存这个字节.
  }
  else if(data==0x5a)
       { 
	   if(RC_Flag&b_uart_head) //如果上一个字节是A5 那么认定 这个是帧起始字节
	     { rx_wr_index=0;  //重置 缓冲区指针
		   RC_Flag&=~b_rx_over; //这个帧才刚刚开始收
         }
         else //上一个字节不是A5
		  rx_buffer[rx_wr_index++]=data;
         RC_Flag&=~b_uart_head; //清帧头标志
       }
	   else
	   { rx_buffer[rx_wr_index++]=data;
		 RC_Flag&=~b_uart_head;
		 if(rx_wr_index==rx_buffer[0]) //收够了字节数.
	     {  
			RC_Flag|=b_rx_over; //置位 接收完整的一帧数据
          }
	   }

  if(rx_wr_index==RX_BUFFER_SIZE) //防止缓冲区溢出
  rx_wr_index--;
  /* Clear the USART2 Recive interrupt */
  USART_ClearITPendingBit(USART2, USART_IT_RXNE); //清中断标志.
  }
  
}


//--校验当前接收到的一帧数据是否 与帧校验字节一致
unsigned char Sum_check(void)
{ 
  unsigned char i;
  unsigned int checksum=0; 
  for(i=0;i<rx_buffer[0]-2;i++)
   checksum+=rx_buffer[i];
  if((checksum%256)==rx_buffer[rx_buffer[0]-2])
   return(0x01); //Checksum successful
  else
   return(0x00); //Checksum error
}



//--这个子程序需要在主程序中 定时调用,以检查 串口是否接收完一帧数据
void UART2_CommandRoute(void)
{
 if(RC_Flag&b_rx_over){  //已经接收完一帧?
		RC_Flag&=~b_rx_over; //清标志先
		if(Sum_check()){ 
		//校验通过
		if(rx_buffer[1]==0xA1){ //UART2_ReportIMU 的数据
		 UART2_Get_IMU();	//取数据
		}
		if(rx_buffer[1]==0xA2){ //UART2_ReportMotion 的数据
		 UART2_Get_Motion();	 //取数据
		} 
		if(rx_buffer[1]==0xA3){ //UART2_ReportPosition 的数据
			UART2_Get_GPS();	 //取数据
		} 
		}//校验是否通过?
	}
}

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-ATAO----

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值