Bootstrap

ANO匿名上位机V7协议&STM32_ano协议

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

前言

提示:以下内容需用到C语言中的指针、结构体、枚举、及大小端储存方式,需提前知晓其中的基本用法&高级用法。


一、Ano V7上位机功能介绍

1,基本数据接收

注:使用基本收发时需开启显示功能
在这里插入图片描述

2,协议通信

界面如下所示,会显示出协议数据中的所有数据
在这里插入图片描述

a,格式设置

点击右边的边框,展开格式设置界面,用于配置用户数据,可用于波形显示
在这里插入图片描述
其中用户帧是从F1~FA共10帧
在这里插入图片描述
而每一帧里面可以携带10个数据,数据类型可为"uint8_t"、“uint16_t”、“int16_t”、“uint32_t"和"int32_t”
在这里插入图片描述
要使用那个帧就勾上使能该帧,否则该帧的数据无效
若要传输小数则需改变后面的传输缩放"1.0E+0"表示没缩放,"1.0E+1"表示缩放10倍

数据容器配置界面中,一共有20个用户的数据容器,可用于显示波形,只需要设置容器对应的数据位就行,后面会显示当前数据位的数据值
在这里插入图片描述

b,协议通信

协议通信界面可以进行发送命令、发送读取命令、发送写入命令
在这里插入图片描述

3,数据波形显示

在这里插入图片描述
在波形显示界面要配置需要显示的数据,右击波形名称,选择用户数据,找到对应的用户数据,并且在需要显示的数据前打勾在这里插入图片描述
其他详细操作请自行体会。

4,飞控参数

在这里插入图片描述
其中我们需要用到PID参数,Ano给我们留了18组PID
在这里插入图片描述

a,读取设备信息

在ANO V7上位机中,飞控参数界面需要指定的设备才能使用
在这里插入图片描述
所以,我们在连接串口后点击“读取信息”,会读取设备信息,此处我们只是借用“拓空者飞控”的ID
在这里插入图片描述
在这里插入图片描述

b,读取参数

点击读取参数,会显示出PID参数,直接点击参数值可进行更改,然后点击写入参数即可
在这里插入图片描述

二、程序

1,协议解析程序

MyAno.c

#include "MyAno.h"
#include "string.h"
#include "usart.h"
#include "math.h"

_ano MyAno = {0};			//发送的数据
_Para MPara = {0};			//参数

/\*\* 
 \* 函数名: 参数初始化
 \* 形 参: 无
 \* 返回值: 无
\*\*/
void Ano\_Init(void) 
{
	MyAno.Head = 0xAA;
	MyAno.Addr = 0xFF;
	MyAno.Lenth = 0;
}

/\*\* 
 \* 函数名: 发送ID对应的参数
 \* 形 参: Id - 参数ID
 \* para - 参数数据
 \* 返回值: 无
\*\*/
static void SendParaData(uint8\_t Id,int32\_t para)
{
	Ano\_Set\_Mdata(0xE2,(uint16\_t \*)&Id,2,1);	//加载ID
	Ano\_Set\_Mdata(0xE2,(int32\_t \*)&para,4,2);	//加载参数数据
	Ano\_SendMdata();	//发送数据
}

/\*\*
 \* 函数名: 发送数据校验帧0x00
 \* 形 参: id - 帧的ID 
 \* sumcheck 和校验数据
 \* addcheck 附加校验数据
 \* 返回值:无
\*\*/
static void SendCheckAnalysis(uint8\_t id,uint8\_t \*sumcheck,uint8\_t \*addcheck)
{
	Ano\_Set\_Mdata(0x00,(uint8\_t \*)&id,1,1);
	Ano\_Set\_Mdata(0x00,(uint8\_t \*)sumcheck,1,2);
	Ano\_Set\_Mdata(0x00,(uint8\_t \*)addcheck,1,3);
	Ano\_SendMdata();
}

/\*\* 
 \* 函数名: 接收数据校验检测
 \* 形 参: \_da数据
 \* 返回值: 1校验成功 0校验失败 
\*\*/
static uint8\_t Receive\_CheckData(uint8\_t \*_da)
{
	uint8\_t i = 0;
	uint8\_t sumcheck = 0,addcheck = 0;
	for(i = 0;i < _da[3] + 4;i++)
	{
		sumcheck += _da[i];
		addcheck += sumcheck;
	}	
	if((sumcheck == _da[_da[3] + 4]) && (addcheck == _da[_da[3] + 5]))		//校验通过
		return 1;
	else
		return 0;
}

/\*\* 
 \* 函数名: 发送数据和校验&附加校验计算
 \* 形 参: ano结构体
 \* 返回值: 1->校验成功 0->校验失败
\*\*/
static uint8\_t Send\_CheckData(_ano \*ano)	
{
	uint8\_t i = 0;
	uint8\_t sumcheck = 0,addcheck = 0;
	for(i = 0;i < ano->Lenth + 4;i++)
	{
		sumcheck += ano->SendBuff[i];
		addcheck += sumcheck;
	}	
	memcpy(ano->SendBuff + 4 + ano->Lenth,(uint8\_t\*)&sumcheck,sizeof(sumcheck));
	memcpy(ano->SendBuff + 5 + ano->Lenth,(uint8\_t\*)&addcheck,sizeof(addcheck));
	/\* 其中 ano->SendBuff[3] 表示数据长度 \*/
	if(sumcheck == ano->SendBuff[ano->SendBuff[3] + 4] && addcheck == ano->SendBuff[ano->SendBuff[3] + 5])
		return 1;
	else
		return 0;
}

/\*\*
 \* 函数名: 控制指令
 \* 形 参: \_Ord命令
 \* 返回值: 无
\*\*/
__weak void ControlOrder(uint8\_t _Ord)
{
	switch (_Ord)	//命令
	{
		case Stop:			//程序停止
			Ano\_SendString("程序停止运行!\r\n",Color_Red);
		break;

		case Operation:		//运行程序
			Ano\_SendString("程序开始运行!\r\n",Color_Green);
		break;

		case Store:			//储存参数
			Ano\_SendString("参数储存成功!\r\n",Color_Green);
		break;
	}
}

/\*\*
 \* 函数名: 参数回传设置
 \* 形 参: \_id参数的ID
 \* 返回值: 无
\*\*/
__weak void ParaOfReturn\_Set(uint16\_t _id)
{
	memset(MyAno.SendBuff,0x00,sizeof(MyAno.SendBuff));
	MyAno.Lenth = 0;
	switch (_id)
	{
		case 1:		SendParaData((uint8\_t )_id,(int32\_t)HWTYPE);	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_1_P:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par1_P);	break;	
		case PID_1_I:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par1_I);	break;	
		case PID_1_D:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par1_D);	break;	//参数回传(第一组PID)

		case PID_2_P:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par2_P);	break;	
		case PID_2_I:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par2_I);	break;	
		case PID_2_D:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par2_D);	break;	//参数回传(第二组PID)

		case PID_3_P:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par3_P);	break;	
		case PID_3_I:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par3_I);	break;	
		case PID_3_D:	SendParaData((uint8\_t )_id,(int32\_t)MPara.PID_Par3_D);	break;	//参数回传(第三组PID)

		default: SendParaData((uint8\_t )_id,(int32\_t)0x00);	break;	//若为其他参数则返回0 
	}
}

/\*\*
 \* 函数名: 参数数据读取设置
 \* 形 参: \_id参数的ID
 \* \_val参数数据
 \* 返回值: 无
\*\*/
__weak void ParaRead\_Set(uint16\_t _id,int32\_t _val)
{
	switch (_id)
	{
		case PID_1_P:	MPara.PID_Par1_P = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_1_I:	MPara.PID_Par1_I = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_1_D:	MPara.PID_Par1_D = _val;	break;	//参数回传硬件版本(此处借用拓空者)

		case PID_2_P:	MPara.PID_Par2_P = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_2_I:	MPara.PID_Par2_I = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_2_D:	MPara.PID_Par2_D = _val;	break;	//参数回传硬件版本(此处借用拓空者)

		case PID_3_P:	MPara.PID_Par3_P = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_3_I:	MPara.PID_Par3_I = _val;	break;	//参数回传硬件版本(此处借用拓空者)
		case PID_3_D:	MPara.PID_Par3_D = _val;	break;	//参数回传硬件版本(此处借用拓空者)
	}
}

/\*\* 
 \* 函数名: 接收数据解析
 \* 形 参: \_da数据(需为完整的一帧数据)
 \* 返回值: 无
\*\*/
void Ano\_DataAnalysis(uint8\_t \*_da)
{
	uint16\_t HeadID = 0;
	int32\_t DataVal = 0;
	MPara.OrderState = 1;	//在接收命令
	
	if(_da[0] == 0xAA && (_da[1] == 0xFF || _da[1] == 0x05))	//判断帧头、和目标地址
	{
		if(_da[2] == 0xE0)	//判断功能码(命令帧)
		{
			if(_da[4] == 0x10 && _da[5] == 0x00)		//判断CID和CMD0
				ControlOrder(_da[6]);	//控制指令(通过CMD1来控制程序)
			SendCheckAnalysis((uint8\_t )0xE0,(uint8\_t \*)&(_da[_da[3] + 4]),(uint8\_t \*)&(_da[_da[3] + 5]));	//回传数据校验帧
			MPara.OrderState = 0;	//命令回传结束
		}
		else if(_da[2] == 0xE1)	//判断功能码(读参数)
		{
			if(Receive\_CheckData(_da))
			{
				HeadID = \*(uint16\_t\*)(&_da[4]);//(uint8\_t)(\_da[4] + (\_da[5] << 8));
				ParaOfReturn\_Set(HeadID);	//参数回传
				MPara.OrderState = 0;	//命令回传结束
			}
		}
		else if(_da[2] == 0xE2)	//判断功能码(写参数)
		{
			if(Receive\_CheckData(_da))
			{
				HeadID =  \*(uint16\_t\*)(&_da[4]);// (uint8\_t)(\_da[4] + (\_da[5] << 8)); //(\*(uint16\_t\*)(&\_da[4]))
				DataVal = \*(int32\_t\*)(&_da[6]);
				ParaRead\_Set(HeadID,DataVal);	//参数数据读取设置
				SendCheckAnalysis((uint8\_t )0xE2,(uint8\_t \*)&(_da[_da[3] + 4]),(uint8\_t \*)&(_da[_da[3] + 5]));	//回传数据校验帧
				MPara.OrderState = 0;	//命令回传结束
			}
		}
	}	
}

/\*\* 
 \* 函数名: 多数据配置函数(结合Ano\_SendMdata多数据发送函数使用)
 \* 形 参: id->功能码(0xF1-0xFA) \*data->发送的数据 len->数据长度(sizeof) num->用于指示第几个数据(可去除)
 \* 返回值: 无
\*\*/
void Ano\_Set\_Mdata(uint8\_t id,void \*data,uint8\_t len,uint8\_t num)
{
	MyAno.ID = id;
	memcpy(MyAno.SendBuff,(uint8\_t\*)&MyAno,3);
	memcpy(MyAno.SendBuff + 4 + MyAno.Lenth,(uint8\_t\*)data,len);
	MyAno.Lenth += len;
	memcpy(MyAno.SendBuff + 3,(uint8\_t\*)&MyAno.Lenth,1);
}

/\*\* 
 \* 函数名: 多数据发送(结合Ano\_Set\_Mdata多数据配置函数使用)
 \* 形 参: id->功能码(0xF1-0xFA) \*data->发送的数据 len->数据长度(sizeof) num->用于指示第几个数据(可去除)
 \* 返回值: 无
\*\*/
void Ano\_SendMdata(void)
{
	uint8\_t check;
	check = Send\_CheckData(&MyAno);
	if(check)
	{
		HAL\_UART\_Transmit(&huart2,MyAno.SendBuff,MyAno.Lenth + 6,100);
		memset(MyAno.SendBuff,0,sizeof(MyAno.SendBuff));
		MyAno.Lenth = 0;
	}
	else
	{
		memset(MyAno.SendBuff,0,sizeof(MyAno.SendBuff));
		MyAno.Lenth = 0;
	}
}

/\*\* 
 \* 函数名: 发送数据函数
 \* 形 参: id->功能码(0xF1-0xFA) \*Data->发送的数据 lenth->数据长度(sizeof)
 \* 返回值: 无
\*\*/
void Ano\_Send\_Data(uint8\_t id, void \*Data, uint8\_t lenth)	//发送函数
{
	static uint8\_t check;
	MyAno.ID = id;
	MyAno.Lenth = lenth;
	
	memcpy(MyAno.SendBuff,(uint8\_t\*)&MyAno,4);
	memcpy(MyAno.SendBuff + 4,(uint8\_t\*)Data,lenth);
	
	check = Send\_CheckData(&MyAno);
	if(check)	//如果校验成功则发送数据,校验失败就丢弃此包
	{
		HAL\_UART\_Transmit(&huart2,MyAno.SendBuff,MyAno.Lenth + 6,100);
		memset(MyAno.SendBuff,0x00,sizeof(MyAno.SendBuff));
		MyAno.Lenth = 0;
	}	
}

/\*\*
 \* 函数名: 发送LOGO信息
 \* 形 参: 字符串\数字
 \* 返回值: 无
\*\*/
void Ano\_SendString(const char \*str,uint8\_t color)
{
	uint8\_t i = 0;
	Ano\_Set\_Mdata(0xA0,(uint8\_t\*)&color,1,1);	//加载颜色数据
	while (\*(str + i) != '\0')		//判断结束位
	{
		Ano\_Set\_Mdata(0xA0,(uint8\_t\*)(str+i++),1,2);	//加载字符串数据
	}
	Ano\_SendMdata();	//发送数据
}

/\*\*
 \* 函数名: 发送LOGO信息+数据信息
 \* 形 参: 字符串\数字
 \* 返回值: 无
\*\*/
void Ano\_SendStringVal(const char \*str,int32\_t Val)
{
	uint8\_t i = 0;
	Ano\_Set\_Mdata(0xA0,(int32\_t\*)&Val,4,1);	//加载数据信息
	while (\*(str + i) != '\0')		//判断结束位
	{
		Ano\_Set\_Mdata(0xA1,(uint8\_t\*)(str+i++),1,2);	//加载字符串数据
	}
	Ano\_SendMdata();	//发送数据
}

int16\_t Ano\_Show\_Sin(float x)	//SIN函数
{
	return 100\*sin(2\*x);
}

float Ano\_Show\_Cos(float x)	//COS函数
{
	return 100\*cos(2\*x);
}

float Ano\_Show\_SQU(float x)	//方波
{
	if(x > 0 && x < 3.14f)
		return 10;
	else
		return -10;
}
	
void Show\_Test(void)	//测试显示
{	
	int16\_t y1,y2,y3;
	uint8\_t nul = 0;
	static float x = 0;
	x += 0.01f;
	if(x > 3.14f)
		x = -3.14f;
	
	y1 = Ano\_Show\_Sin(x);		//数据\*10发送
	y2 = Ano\_Show\_Cos(x);		//数据\*10发送
	y3 = Ano\_Show\_SQU(x);
	
	Ano\_Set\_Mdata(0xF1,(int16\_t\*)&y1,sizeof(y1),1);
	Ano\_Set\_Mdata(0xF1,(int16\_t\*)&y2,sizeof(y2),2);
	Ano\_Set\_Mdata(0xF1,(int16\_t\*)&y3,sizeof(y3),3);
	Ano\_Set\_Mdata(0xF1,(uint8\_t\*)&nul,sizeof(nul),4);		//加载数据到对应的数据位
	Ano\_SendMdata();	//发送数据
}


MyAno.h

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

t_Mdata(0xF1,(uint8_t*)&nul,sizeof(nul),4); //加载数据到对应的数据位
Ano_SendMdata(); //发送数据
}


MyAno.h



[外链图片转存中...(img-QYtxhcbm-1715764278265)]
[外链图片转存中...(img-CdtuIuTB-1715764278265)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

;