匿名上位机V7波形显示教程-简单能用

匿名上位机V7波形显示教程-简单能用

匿名上位机V7下位机数据格式

DATA区域内容:

举例说明DATA区域格式,例如上文,需要发送ABC三个数据,AB为int16 型,C为int32 型,那么ABC三个数据共2+2+4=8字节,那么LEN字节为8,帧ID 为0xF1,DATA区域依次放入ABC三个数据,然后计算SC、AC,完成后将本帧发送至上位机即可。

根据匿名上位机V7的手册说明文档,编写对应的指令

stm32程序使用H库,串口和其他的初始化就不在这里解说各位大佬一定很熟悉了,这里主要生成驱动匿名上位机的代码。

粘贴生成.h头文件

ANDmessage.h

c 复制代码
#ifndef  _ANDmessage_H
#define  _ANDmessage_H
//#include "stm32f205xx.h"
#include <string.h>
#include "main.h"

//目标地址宏定义
#define FRAME_HEADER 		  0XAA   //<匿名协议固定帧头
#define GENERAL_OUTPUT_ADDR	  0XFF   //<广播型输出
#define HOST_ADDR			  0XAF   //<向上位机输出
#define PRO_ADDR			  0X05   //<拓空者PRO飞控
#define SHUCHUAN_ADDR		  0X10   //<匿名数传
#define GUANGLIU_ADDR		  0X22   //<匿名光流
#define UWB_ADDR			  0X30   //<匿名UWB
#define IMU_ADDR			  0X60   //<匿名凌霄IMU
#define LINGXIAO_ADDR		  0X61   //<匿名凌霄飞控

#define HWTYPE            0X01   //<用于存储下位机的类型信息
#define ID_INFO5 		  0X05   //<预留位
#define ID_INFO6	      0X06   //<预留位
#define ID_INFO7		  0X07   //<预留位
#define ID_INFO8		  0X08   //<预留位
#define ID_INFO9		  0X09   //<预留位
#define ID_INFO10		  0X0A   //<预留位

#define ANO_BLACK         0X00  //<字符黑色打印
#define ANO_RED           0X01  //<字符红色打印
#define ANO_GREEN         0X02  //<字符绿色打印


//32位数据进行四个字节剥离拆分,从低位到高位
#define BYTE0(temp)	   (*(char*)(&temp))
#define BYTE1(temp)	   (*((char*)(&temp)+1))
#define BYTE2(temp)	   (*((char*)(&temp)+2))
#define BYTE3(temp)	   (*((char*)(&temp)+3))
	

typedef struct 							
{
	uint16_t par_id;                 //<参数id
	int32_t  par_val;                //<参数值
}par_struct;

/****通信帧对象结构体****/
typedef struct
{
	uint8_t head;					 //<帧头
	uint8_t target_addr;			 //<目标地址
	uint8_t function_id;			 //<该帧要实现某功能的功能码id
	uint8_t data_len;				 //<数据长度
	uint8_t data[40];				 //<数据内容,协议最高只支持40字节数据  
	uint8_t sum_check;				 //<和校验
	uint8_t add_check;				 //<附加校验
	
	par_struct* parameter;           //<参数
}ano_frameStruct;

/*共同点:形参都含ano_frameStruct*类型指针*/
extern void ano_frame_reset(ano_frameStruct* frame);
extern void ano_check_calculate(ano_frameStruct* frame);
extern uint8_t ano_check(ano_frameStruct* frame);
extern void frame_turn_to_array(ano_frameStruct* frame,uint8_t*str);
//.....


extern void ano_send_string(uint8_t color,char* str);
extern void ano_send_message(char* str,int32_t value);
extern void ano_send_flexible_frame(uint8_t id,int32_t x_coordinate,int32_t y_coordinate);
extern void ano_frame_init(void);

#endif

粘贴生成.c文件

ANDmessage.c

c 复制代码
#include "stm32f4xx_hal.h"
#include "main.h"
#include "usart.h"
#include "ANDmessage.h"




static par_struct      send_parameter;       //<发送帧中的参数;	
static par_struct      rec_parameter;        //<接收帧的参数;
static ano_frameStruct send_frame_struct;    //<(发送)通信帧结构体
__IO ano_frameStruct   rec_frame_struct;     //<(接收)通信帧结构体,因不止在本.c文件使用,故不用static修饰






/**
  * @brief   初始化通信帧结构体,使用前必须调用
  * @param   无输入参数
  * @retval  无返回
  **/
void ano_frame_init(void)
{
    /*参数结构体初始化*/
	send_frame_struct.parameter=&send_parameter;
	rec_frame_struct.parameter=&rec_parameter;
	send_frame_struct.parameter->par_id=0;
	send_frame_struct.parameter->par_val=0;
	rec_frame_struct.parameter->par_id=0;
	rec_frame_struct.parameter->par_val=0;
	
	send_frame_struct.head=rec_frame_struct.head=FRAME_HEADER;//帧头固定是0XAA
	send_frame_struct.target_addr=rec_frame_struct.target_addr=HOST_ADDR;
	send_frame_struct.function_id=0XFF;//<协议中没有定义的功能ID,这样初始化目的是为了启动瞬间不做任何动作


	memset(send_frame_struct.data,0,40);//<缓存默认全部置0
	memset(rec_frame_struct.data,0,40);
}



/**
  * @brief   复位通信帧结构体,ano_frame_init()必须要运行过一次
  * @param   通信帧结构体对象
  * @retval  无返回
  **/
void ano_frame_reset(ano_frameStruct* frame)
{
  frame->function_id=0XFF;						
  frame->data_len=0;
  memset(frame->data,0,40);
  frame->add_check=0;
  frame->sum_check=0;
}



/**
  * @brief   通信帧中参数结构体内成员的配置
  * @param   通信帧结构体对象,参数ID与参数值
  * @retval 
  **/
void ano_par_struct_config(ano_frameStruct* frame,uint16_t id,int32_t val)
{
	frame->parameter->par_id=id;
	frame->parameter->par_val=val;
}



/**
  * @brief   通信帧校验计算
  * @param   通信帧结构体对象
  * @retval  无返回值
  **/
static void ano_check_calculate(ano_frameStruct* frame)
{
	frame->sum_check=0;
	frame->add_check=0;
	
	//除去和校验,附加校验及数据部分,有4个部分4个字节,长度固定
	for(uint32_t i=0;i<4;i++)
	{
	  frame->sum_check+= *(uint8_t*)(&frame->head+i);
	  frame->add_check+=frame->sum_check;
	}
	//获取数据长度部位,把数据部分全加上
	for(uint32_t i=0;i<frame->data_len;i++)
	{
	  frame->sum_check+=*((uint8_t*)(frame->data)+i);
	  frame->add_check+=frame->sum_check;
	} 
 }



/**
  * @brief   通信帧校验检查(接收上位机通信帧时用)
  * @param   通信帧结构体对象
 * @retval   1:校验成功 0:校验失败
  **/
static uint8_t ano_check(ano_frameStruct* frame)
{
	uint8_t sum_check=0;
	uint8_t add_check=0;

	for(uint32_t i=0;i<4;i++)
	{
	  sum_check+= *(uint8_t*)(&frame->head+i);
	  add_check+=sum_check;
	}
	for(uint32_t i=0;i<frame->data_len;i++)
	{
	  sum_check+=*((uint8_t*)(frame->data)+i);
	  add_check+=sum_check;
	}
    //如果计算与获取的相等,校验成功
	if((sum_check==frame->sum_check)&&(add_check==frame->add_check))
	 return 1;
	else
	 return 0;
}



/**
  * @brief  匿名串口发送
  * @param  字符串,数据字节个数
  * @retval 
  */
static void ano_usart_send(uint8_t*str,uint16_t num)
{
 uint16_t cnt=0;
 do
	{
		HAL_UART_Transmit(&huart1,((uint8_t*)(str))+cnt,1,1000);
		cnt++;
	}while(cnt<=num);
}



/**
  * @brief   通信帧结构体转化为线性数组
  * @param   要转换的通信帧,缓存数组
  * @retval 
  **/
static void frame_turn_to_array(ano_frameStruct* frame,uint8_t*str)
{
	memcpy(str,(uint8_t*)frame,4);
	memcpy(str+4,(uint8_t*)frame->data,frame->data_len);
	memcpy(str+4+frame->data_len,(uint8_t*)(&frame->sum_check),2);
}



 /**
  * @brief  向上位机发送ASCII字符串
  * @param  color:希望上位机显示的字符串颜色,str:要发送的字符串
  * @retval 无返回值
  */
void ano_send_string(uint8_t color,char* str)
{
	uint8_t i=0,cnt=0;
	uint8_t buff[46];										
	memset(send_frame_struct.data,0,40);
	send_frame_struct.function_id=0XA0;           //<信息输出--字符串(功能码0XA0)
	send_frame_struct.data[cnt++]=color;          //<选择上位机打印的颜色
	/*字符串数据直接存入数据部分*/
	while(*(str+i)!='\0')
	{
		send_frame_struct.data[cnt++]=*(str+i++);
		if(cnt>40)                                //<若字符串长度超过40,强制结束
			break;
	}
	send_frame_struct.data_len=cnt;               //<记录下数据部分长度
	
	ano_check_calculate(&send_frame_struct);      //<计算校验和
	frame_turn_to_array(&send_frame_struct,buff); //<通信帧转线性数组
	ano_usart_send(buff,6+send_frame_struct.data_len);
}



/**
  * @brief  向上位机发送ASCII字符串+数字组合
  * @param  value:32位的数值,str:要发送的字符串
  * @retval 
  */
void ano_send_message(char* str,int32_t value)
{
	uint8_t i=0,cnt=0;
	uint8_t buff[46];										
	memset(send_frame_struct.data,0,40);
	send_frame_struct.function_id=0XA1;	          //信息输出--字符串+数字
	
	/*协议规定VAL在前,先对要求的32位数据进行截断*/
	send_frame_struct.data[cnt++]=BYTE0(value);
	send_frame_struct.data[cnt++]=BYTE1(value);
	send_frame_struct.data[cnt++]=BYTE2(value);
	send_frame_struct.data[cnt++]=BYTE3(value);
	/*再轮到字符串数据*/
	while(*(str+i)!='\0')
	{
		send_frame_struct.data[cnt++]=*(str+i++);
		if(cnt>40)
			break;
	}
	
	send_frame_struct.data_len=cnt;				  //<记录下数据部分长度
	
	ano_check_calculate(&send_frame_struct);	  //<计算校验和
	frame_turn_to_array(&send_frame_struct,buff); //<通信帧转线性数组
	ano_usart_send(buff,6+send_frame_struct.data_len);
}



/**
  * @brief  发送灵活格式帧
  * @param  id:0xF1~0XFA,x_coordinate:x轴坐标值 ,y_coordinate:y轴坐标值
  *         !!!要传多少个参数完全可以自己进行计算,最高只支持40字节的数据,低位先输出
  *         一般10个以内够用,40个字节限制,一个32位数据占4个字节,可以发送10个
  * @retval 
  */
void ano_send_flexible_frame(uint8_t id,int32_t x_coordinate,int32_t y_coordinate)
{
	uint8_t buff[46];
	
	memset(send_frame_struct.data,0,40);
	send_frame_struct.function_id=id;
	send_frame_struct.data_len=8;			   //<根据自己的参数数填写							
	
	/*第一个x_coordinate数据从低位到高位截断*/
	send_frame_struct.data[0]=BYTE0(x_coordinate);
	send_frame_struct.data[1]=BYTE1(x_coordinate);
	send_frame_struct.data[2]=BYTE2(x_coordinate);
	send_frame_struct.data[3]=BYTE3(x_coordinate);
	/*第二个数据y_coordinate从低位到高位截断*/
	send_frame_struct.data[4]=BYTE0(y_coordinate);
	send_frame_struct.data[5]=BYTE1(y_coordinate);
	send_frame_struct.data[6]=BYTE2(y_coordinate);
	send_frame_struct.data[7]=BYTE3(y_coordinate);
	/*第N个数据xxx从低位到高位截断*/
	//......用户自行添加

	ano_check_calculate(&send_frame_struct);
	frame_turn_to_array(&send_frame_struct,buff);


	ano_usart_send(buff,6+send_frame_struct.data_len);
}

在主函数中初始化ANDmessage驱动

简单测试程序。在循环函数中添加一个变量发送给匿名上位机的数据,填写了一个随着时间变化一直自加的数据

连接匿名上位机V7

选择连接设置

打开自己的硬件和程序所写的串口端号和波特率,后打开连接

1.打开 协议解析 图标

2.选择扳手,弹出高级收码设置。

3.我们使用自定义的F1头帧,勾选使能该帧

4.数据容量配置,自行修改数据位 观察是否是我们需要的数值,1数据位表示8bit;2数据位表示16bit,以此类推

打开数据波形,弹出以下

波形显示框图

注意勾选要显示的波形,如果不清楚全勾选就行。注意左下角要显示"波形刷新中"才行。

相关推荐
典则7 小时前
STM32FreeRtos入门(四)——任务状态和调度
stm32·单片机·嵌入式硬件
充哥单片机设计7 小时前
【STM32项目开源】基于STM32的智能天然气火灾监控
stm32·单片机·嵌入式硬件
充哥单片机设计7 小时前
【STM32项目开源】基于STM32的智能仓库火灾检测系统
stm32·单片机·嵌入式硬件
就叫飞六吧8 小时前
普中stm32大Dap烧录流程
stm32
A9better9 小时前
嵌入式开发学习日志38——stm32之看门狗
stm32·嵌入式硬件·学习
小莞尔10 小时前
【51单片机】【protues仿真】基于51单片机智能路灯控制系统
c语言·stm32·单片机·嵌入式硬件·51单片机
辰哥单片机设计19 小时前
TT直流减速电机(STM32)
stm32
A9better19 小时前
嵌入式开发学习日志36——stm32之USART串口通信前述
stm32·单片机·嵌入式硬件·学习
qq_4017004120 小时前
STM32低功耗Tickless模式
stm32·单片机
研猛男21 小时前
0、FreeRTOS编码和命名规则
笔记·stm32·freertos