收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
需要这些体系化资料的朋友,可以加我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 \*)¶,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
既有适合小白学习的零基础资料,也有适合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)**