精华内容
下载资源
问答
  • 匿名上位机v7.zip

    2020-07-16 20:15:32
    匿名上位机v7.........史上最最强,史上最最强史上最最强功能最多可以显示波形的串口调试助手。你值得拥有
  • 匿名上位机

    2018-03-04 11:33:45
    ◤2:高级收码:高级收码从基本收码升级而来,上位机收到数据后,若高级收码的开关是打开的,那么就会对接收到的数据进行解析,数据的格式由通信协议定义。分为固定格式和自定义格式两大部分。自定义格式是留给大家...
  • 匿名上位机V7.rar

    2020-05-25 21:53:04
    匿名上位机V7版本,其包含飞控显示,波形显示的等功能,可用于调试encoder、PID等,亦可当作普通的串口显示助手来使用,其通信协议在软件内部,可自行查找。
  • 该文件为使用匿名4.3上位机发送协议,使用匿名上位机可以传输数据和显示波形,该协议编写可以支持IIC,SPI多种方式进行传输
  • 代码基于stm32f103c8t6,通过串口将数据发送到匿名上位机,并将数据波形显示出来,方便调试参数。
  • 匿名上位机V6.5版本,2018年11月3日发布 匿名上位机V7.0版本,2020年2月22日发布 最新上位机使用教程:https://www.bilibili.com/video/av90875255/
  • 移植性优良的匿名飞控上位机协议源码,支持V6版本上位机,稍加改动可支持其他任意版本。注释清楚,程序清晰易懂,包含使用例程。
  • 本压缩包里包含了三个版本匿名上位机,总用一个能够在电脑上使用。 三个版本分别为V2.6,V5.12和V6.0
  • 匿名上位机V6.5版本

    2018-11-03 10:42:21
    匿名上位机V6.5版本,2018年11月3日发布,本上位机使用讲解请移步:https://blog.csdn.net/wangjt1988/article/details/83684188
  • 匿名飞控新的上位机软件匿名上位机V7+新协议+波形分析功能,功能比以前更强大,优化做的更好。 有需要的自行下载
  • simulink通信实验仿真,实验指导手册,自编附件 @all right received by 扬州大学张伟
  • 调平衡车的时候用的软件,最新版本界面友好,稳定了很多,在win10上运行没有bug。自己写了一个教程,希望大家喜欢!
  • ANO_TC匿名上位机V6.72解决win10打开无图问题,以及不停跳出对话框问题
  • STM32L476官方NUCLEO开发板,通过串口实现和匿名上位机/山外上位机(自己DIY四轴或者参加过飞思卡尔智能车的都知道)数据双向通信
  • ANO_TC匿名上位机
  • 匿名上位机地面站-4.34
  • 芯片为为STM32F103ZET6(正点原子精英板),代码基于正点原子MPU6050六轴传感器实验,可实现使用匿名科创v4.34版本的上位机实时监测mpu6050的状态,在上位机显示飞控状态和数据波形。
  • 注意看清!只含程序哦!
  • 匿名上位机软件读取stm32数据,并显示波形,有教学视频,开发板 ZET6
  • 匿名上位机v2.6.docx
  • 匿名上位机 四轴代码 及 上位机
  • 中断收发源文件 基于hal库
  • 匿名科创地面站v4.34
  • ANO_TC匿名上位机V65.exe

    2020-09-11 13:02:52
    调车的可以用的,pid调参,界面友好,在win10上运行没有bug,可通提供通信代码,也可查看通信协议,自己编写。
  • 匿名飞控上位机
  • 匿名科创在V7版本的协议文档上给出了很详细的范例,所以下位机程序非常好写,笔者是第一次写匿名上位机的下位机程序。以STM32发送一个无符号16位的数据为例讲解下位机程序的书写。 1.1.1 官方协议文档 1.1.1.1 查找...

    1. 下位机程序

    1.1 协议文档分析

    匿名科创在V7版本的协议文档上给出了很详细的范例,所以下位机程序非常好写,笔者是第一次写匿名上位机的下位机程序。以STM32发送一个无符号16位的数据为例讲解下位机程序的书写。

    1.1.1 官方协议文档

    1.1.1.1 查找方法

    • 打开上位机,把鼠标慢慢移动到左侧的边框处,等待一会会弹出左侧菜单栏
      在这里插入图片描述
    • 点击弹出的菜单栏中的帮助信息子菜单
      在这里插入图片描述
    • 点击通信协议
      在这里插入图片描述
    • 自动使用pdf阅读器打开文件名为ANO_XIEYI.pdf的文档(如果电脑没有显示pdf阅读器,不知道是否能显示)
      在这里插入图片描述

    1.1.1.2 下位机协议分析

    1.1.1.2.1 协议总框架
    下位机协议由7部分组成,如下图所示,帧头(0xAA)、目标地址、功能码、数据长度、数据内容、和校验、附加校验。
    在这里插入图片描述

    各个部分详细解释:

    • 帧头: 每个数据包都得有帧头,其功能在于鉴别数据包的开始。
    • 目标地址:因为匿名通信协议是用于匿名科创的所有产品的通信,所以把数据不止发送给上位机,还有可能发送给其他的设备。所以需要该字段用于鉴别把数据发送给哪个设备。具体的地址在文档有介绍
      在这里插入图片描述
    • 功能码:表征该数据帧的功能,每个数据帧的功能有很多,用功能码作为数据的别称。
      常见功能码有如下:
    功能码数据名称
    0x00数据校验帧
    0x01惯性传感器数据
    0x02罗盘、气压、温度传感器数据
    0x03飞控姿态:欧拉角格式
    0x04飞控姿态:四元数格式
    0x05高度数据
    0x06飞控运行模式

    … 等等数据

    • 数据长度: 以字节作为单位,表示有效数据的长度(不包含帧头、目标地址、功能码、数据长度、和校验、附加校验)
    • 数据内容:采用小端模式,低字节在前,高字节在后,一个单元为一个字节。
    • 和校验:从帧头0xAA字节开始,一直到DATA区结束,对每一字节进行累加操作,只取低8位
    • 附加校验:计算和校验时,每进行一字节的加法运算,同时进行一次SUM CHECK的累加操作,只取低8位。
      校验程序示例:
    U8 sumcheck = 0; 
    U8 addcheck = 0; 
    For(u8 i=0; I < (data_buf[3]+4); i++) 
    { 
      sumcheck += data_buf[i];   //从帧头开始,对每一字节进行求和,直到DATA区结束 
      addcheck += sumcheck;    //每一字节的求和操作,进行一次sumcheck的累加 
    } 
    //如果计算出的sumcheck和addcheck和接收到的check数据相等,代表校验通过,反之数据有误 
    if(sumcheck == data_buf[data_buf[3]+4] && addcheck == data_buf[data_buf[3]+5]) 
      return true;    //校验通过 
    else 
      return false; //校验失败
    

    1.1.1.2.2 用户自定义数据协议分析
    文档页面: 6~7
    1.1.1.2.2.1 示例介绍
    灵活格式帧,我们也可以叫做用户自定义帧,也就是用户可以自己定义数据内容格式的数据帧。可能从名字无法很好的理解灵活格式帧有什么用,那么我们举一个简单的例子。
    加入我在调试一个自己写的滤波算法,传感器原始数据A,为int16 格式,使用滤波算法对A进行滤波后,得到滤波后数据B,B也是int16 格式。滤波后数据经过控制算法,输出一个控制量C,C是int32 格式。那我需要对滤波算法和控制算法进行调试,肯定是需要得到ABC三个数据的波形,根据波形进行数据分析。 那么如何将数据ABC发送至上位机进行显示呢,就要用到灵活格式帧了。灵活格式帧共10帧,帧ID 从0xF1到0xFA,每一帧最多可以携带10个数据,每一个数据可以分别设置为U8、S16、U16、S32的格式。如果您需要显示float型数据,可以根据数据范围以及精度要求,乘以1000或者100变成S32型整数进行传输。
    1.1.1.2.2.2 上位机配置

    • 点击左侧菜单栏中的协议通信,出现下图软件区域
      在这里插入图片描述

    • 点击右侧的边框
      在这里插入图片描述
      弹出了数据配置窗口
      在这里插入图片描述

    • 选中F1右侧的选择框,然后点击F1左侧的加号框
      在这里插入图片描述

    • 按照下图配置前三个数据的类型,这个类型是示例中的三个数据类型
      在这里插入图片描述

    • 我们配置数据容器。数据容器设置,什么是数据容器呢,就是刚才F1数据帧进行解析后,会解析出最多30个数据,那么用哪个数据进行波形显示,或者excel保存哪个数据呢,这就要数据容器了。匿名上位机设置有10个数据容器,对应本区域1到10选项卡。我们可以把数据容器想象成10个卡车,只有卡车能将数据传输到用户,那么这10辆卡车将哪个数据传输给用户呢,就是这数据容器配置区域进行配置了。
      具体配置如下图:
      在这里插入图片描述
      到此,上位机的配置完成,只需要单片机按照如下协议格式将数据发送至上位机,即可观察到对应的数据值
      开始刷新,并可绘制对应数据波形。

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

    1.1.1.2.2.4 代码实现
    驱动代码:
    ANO_DataProtocol.c

    #include "usart.h"
    #include "ANO_DataProtocol.h"
    #include "stm32f10x.h"
    
    #define BYTE0(dwTemp)       (*(char *)(&dwTemp))     //取出int型变量的低字节
    #define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))     //    取存储在此变量下一内存字节的内容,高字节
    #define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
    #define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))
    
    void AnoTc_SendUserTest(s16 A, s16 B, s32 C)
    {
    	// AA 05 AF F1 02 E4 01 36
    	unsigned char _cnt = 0;
    	unsigned char i;
    	unsigned char sumcheck = 0;
    	unsigned char addcheck = 0;
    	
    	Data_to_Send[_cnt++] = 0xAA;
    	Data_to_Send[_cnt++] = 0xFF;
    	Data_to_Send[_cnt++] = 0xF1;
    	Data_to_Send[_cnt++] = 8;
    	Data_to_Send[_cnt++] = BYTE0(A);
    	Data_to_Send[_cnt++] = BYTE1(A);
    	Data_to_Send[_cnt++] = BYTE0(B);
    	Data_to_Send[_cnt++] = BYTE1(B);
    	Data_to_Send[_cnt++] = BYTE0(C);
    	Data_to_Send[_cnt++] = BYTE1(C);
    	Data_to_Send[_cnt++] = BYTE2(C);
    	Data_to_Send[_cnt++] = BYTE3(C);
    	
    	for(i = 0; i < _cnt; i++)
    	{
    		sumcheck += Data_to_Send[i];
    		addcheck += sumcheck;
    	}
    	//if(sumcheck == Data_to_Send[Data_to_Send[3]+4] && addcheck == Data_to_Send[Data_to_Send[3]+5])
    	Data_to_Send[_cnt++]=sumcheck;
    	Data_to_Send[_cnt++]=addcheck;
    	USART_SendCharArr(USART1, Data_to_Send,_cnt);
    }
    

    ANO_DataProtocol.h

    #ifndef __ANO_DATA_PROTOCOL_H__
    #define __ANO_DATA_PROTOCOL_H__
    
    #include "sys.h"
    
    void AnoTc_SendUserTest(s16 A, s16 B, s32 C);
    
    #endif
    

    main.c

    #include "stm32f10x.h"
    #include "delay.h"
    #include "sys.h"
    #include "usart.h"
    #include "ANO_DataProtocol.h"
    
    int main()
    {
    	u16 i = 0;
    	
        u32 ECG1,ECG2,ECG3;
        SystemInit();//系统时钟等初始化
        delay_init();	     //延时初始化
        NVIC_Configuration();//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(115200);//串口初始化为9600//延时初始化
    
    	while(1)
    	{
    		for(i = 0; i < 400; i++)
    		{
    			AnoTc_SendUserTest(i, i+100, i+200);
    			delay_ms(100);
    		}
    		for(i = 400; i > 200; i--)
    		{
    			AnoTc_SendUserTest(i, i+100, i+200);
    			delay_ms(100);
    		}
    	}
    }
    

    2. 上位机波形

    在这里插入图片描述
    生成了奇怪的三角波

    3. 资源下载

    匿名上位机波形显示demo及协议文档: https://download.csdn.net/download/FourLeafCloverLLLS/34433481

    展开全文
  • 匿名上位机v6.72和v2.6两个版本,亲测都可用,需要的可以拿去用用,适合调试mpu6050飞控姿态
  • 如何使用匿名上位机

    千次阅读 多人点赞 2020-08-09 19:47:21
    如何使用匿名上位机显示波形 ** 1、首先打开匿名上位机,可以看到它有基本收发,高级收码和数据波形几项基本功能。 2、然后我们点击高级收码,在里面进行一些设置下面的数据容器设置中,数据位置和通道设置为一样。...

    **

    如何使用匿名上位机显示波形

    **
    1、首先打开匿名上位机,可以看到它有基本收发,高级收码和数据波形几项基本功能。
    在这里插入图片描述
    2、然后我们点击高级收码,在里面进行一些设置在这里插入图片描述下面的数据容器设置中,数据位置和通道设置为一样。上面是通道几,下面的数据位置就设为多少,如图所示:
    在这里插入图片描述
    在这里插入图片描述依次往下…
    在这里插入图片描述
    3、烧写好代码后,点击程序设置。
    在这里插入图片描述选择端口号和配置波特率,波特率应与代码中约定好的相同。

    在这里插入图片描述然后点击连接。
    在这里插入图片描述4、连接好后打开数据波形,就可以看到波形显示了
    在这里插入图片描述如果没有出现波形,注意前面高级收码中的配置,另外,波形显示的设置中要选择用户数据波形。如图所示
    在这里插入图片描述代码编写可参考帮助信息中的通信协议。
    在这里插入图片描述
    附代码:

    #include "bsp_usart.h"
    
    static void NVIC_Configuration(void)
    {
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 嵌套向量中断控制器组选择 */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      
      /* 配置USART为中断源 */
      NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
      /* 抢断优先级*/
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      /* 子优先级 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      /* 使能中断 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      /* 初始化配置NVIC */
      NVIC_Init(&NVIC_InitStructure);
    }
    
    void USART_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    
    	// 打开串口GPIO的时钟
    	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
    	
    	// 打开串口外设的时钟
    	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
    
    	// 将USART Tx的GPIO配置为推挽复用模式
    	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
    
      // 将USART Rx的GPIO配置为浮空输入模式
    	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
    	
    	// 配置串口的工作参数
    	// 配置波特率
    	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
    	// 配置 针数据字长
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    	// 配置停止位
    	USART_InitStructure.USART_StopBits = USART_StopBits_1;
    	// 配置校验位
    	USART_InitStructure.USART_Parity = USART_Parity_No ;
    	// 配置硬件流控制
    	USART_InitStructure.USART_HardwareFlowControl = 
    	USART_HardwareFlowControl_None;
    	// 配置工作模式,收发一起
    	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    	// 完成串口的初始化配置
    	USART_Init(DEBUG_USARTx, &USART_InitStructure);
    	
    	// 串口中断优先级配置
    	NVIC_Configuration();
    	
    	// 使能串口接收中断
    	USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);	
    	
    	// 使能串口
    	USART_Cmd(DEBUG_USARTx, ENABLE);	    
    }
    
    /*****************  发送一个字节 **********************/
    void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
    {
    	/* 发送一个字节数据到USART */
    	USART_SendData(pUSARTx,ch);
    		
    	/* 等待发送数据寄存器为空 */
    	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
    }
    
    /****************** 发送8位的数组 ************************/
    void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
    {
      uint8_t i;
    	
      for(i=0; i<num; i++)
      {
    	    /* 发送一个字节数据到USART */
    	 Usart_SendByte(pUSARTx,array[i]);	 
      }
    	/* 等待发送完成 */
      while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
    }
    
    //匿名上位机显示波形
    uint8_t testdatatosend[50];
    
    void Test_Send_User(uint16_t data1, uint16_t data2, uint16_t data3,uint16_t data4,uint16_t data5,uint16_t data6,uint16_t data7,uint16_t data8,uint16_t data9,uint16_t data10)	
    {
    	uint8_t _cnt=0;
    	
    	testdatatosend[_cnt++]=0xAA;
    	testdatatosend[_cnt++]=0x05;
    	testdatatosend[_cnt++]=0xAF;
    	testdatatosend[_cnt++]=0xF1;
    	testdatatosend[_cnt++]=0;
     
    	testdatatosend[_cnt++]=BYTE1(data1);
    	testdatatosend[_cnt++]=BYTE0(data1);
    	
    	testdatatosend[_cnt++]=BYTE1(data2);
    	testdatatosend[_cnt++]=BYTE0(data2);
    	
    	testdatatosend[_cnt++]=BYTE1(data3);
    	testdatatosend[_cnt++]=BYTE0(data3);
    	
    	testdatatosend[_cnt++]=BYTE1(data4);
    	testdatatosend[_cnt++]=BYTE0(data4);
    	
    	testdatatosend[_cnt++]=BYTE1(data5);
    	testdatatosend[_cnt++]=BYTE0(data5);
    	
    	testdatatosend[_cnt++]=BYTE1(data6);
    	testdatatosend[_cnt++]=BYTE0(data6);
    	
    	testdatatosend[_cnt++]=BYTE1(data7);
    	testdatatosend[_cnt++]=BYTE0(data7);
    	
    	testdatatosend[_cnt++]=BYTE1(data8);
    	testdatatosend[_cnt++]=BYTE0(data8);
    	
    	testdatatosend[_cnt++]=BYTE1(data9);
    	testdatatosend[_cnt++]=BYTE0(data9);
    	
    	testdatatosend[_cnt++]=BYTE1(data10);
    	testdatatosend[_cnt++]=BYTE0(data10);
    	
    	
     
    	testdatatosend[4] = _cnt-5;
    	
    	uint8_t sum = 0;	
    	for(uint8_t i=0;i<_cnt;i++)
    		sum += testdatatosend[i];
    	
    	testdatatosend[_cnt++]=sum;	
     
        Usart_SendArray(DEBUG_USARTx,testdatatosend,_cnt);
    }
    
    #ifndef __USART_H
    #define	__USART_H
    
    
    #include "stm32f10x.h"
    #include <stdio.h>
    
    	
    // 串口1-USART1
    #define  DEBUG_USARTx                   USART1
    #define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
    #define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
    #define  DEBUG_USART_BAUDRATE           115200
    
    // USART GPIO 引脚宏定义
    #define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
    #define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
        
    #define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
    #define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
    #define  DEBUG_USART_RX_GPIO_PORT       GPIOA
    #define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10
    
    #define  DEBUG_USART_IRQ                USART1_IRQn
    #define  DEBUG_USART_IRQHandler         USART1_IRQHandler
    
    void USART_Config(void);
    void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
    void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num);
    
    #define BYTE0(dwTemp)       ( *( (char *)(&dwTemp)	  ) )
    #define BYTE1(dwTemp)       ( *( (char *)(&dwTemp) + 1) )
    #define BYTE2(dwTemp)       ( *( (char *)(&dwTemp) + 2) )
    #define BYTE3(dwTemp)       ( *( (char *)(&dwTemp) + 3) )
    
    void Test_Send_User(uint16_t data1, uint16_t data2, uint16_t data3,uint16_t data4,uint16_t data5,uint16_t data6,uint16_t data7,uint16_t data8,uint16_t data9,uint16_t data10)	;
    
    #endif /* __USART_H */
    

    串口中断服务函数

    void DEBUG_USART_IRQHandler(void)
    {
        uint8_t ucTemp;
    	if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
    	{		
    	   ucTemp = USART_ReceiveData(DEBUG_USARTx);
           USART_SendData(DEBUG_USARTx,ucTemp);    
    	}	 
    }
    
    

    main函数

    #include "stm32f10x.h"
    #include "bsp_usart.h"
    
    int main(void)
    {	
      USART_Config();
    	
      uint8_t a=0,flag=0;
      uint32_t time = 0xfffff;
      printf("匿名上位机调试程序!\n");
    	
      while(1)
      {	
        time--;		
        if ( time == 0 ) 
        {
          time = 0xfffff;
          if(flag==0)
    	    a+=1;
    	  if(a>5|flag==1)
    	  {
    		a--;
    		flag=1;
    		if(a==0)
    		flag=0;
    	 }
         Test_Send_User(a,0,0,6,6,6,6,2,6,15);				
       } 
      }	
    }
    
    
    展开全文
  • 匿名上位机(V7)基于串口的简单使用

    千次阅读 多人点赞 2021-01-28 22:34:38
    匿名上位机(V7)简单使用 本文简介:本文主要介绍匿名上位机V7版本的一些基本的功能使用,以及基于匿名上位机协议写下位机代码。使用的下位机为STM32F103C8T6 匿名上位机 V7版本的选项简介,划线部分是比较基础的...

    匿名上位机(V7)简单使用

    本文简介:本文主要介绍匿名上位机V7版本的一些基本的功能使用,以及基于匿名上位机协议写下位机代码。使用的下位机为STM32F103C8T6

    匿名上位机

    V7版本的选项简介,划线部分是比较基础的部分,对于智能车调试,波行分析比较好用。
    在这里插入图片描述
    基本的功能是基本收发,类似串口精灵或者XCOM。

    连接设置

    通过连接设置(点击)可以设置通信方式,有串口通信和USB HID通信方式。本文主要介绍串口通信。
    连接设置好就可以打开连接了,下面是连接成功的状态。
    在这里插入图片描述

    基本收发界面

    你发送的数据下面会有发送计数,可以通过基本收发这里面判断上位机与下位机的连接情况
    在这里插入图片描述

    数据波形界面

    可以通过设置那里选择用户的自定义波形,有10个容器可以选择,也就是可以同时显示10个波形,在左边打上勾就可以显示波行了
    在这里插入图片描述

    小细节

    通过观察,发现软件界面左侧或者右侧会有虚线,把鼠标移动过去即可打开隐藏的选项。
    在这里插入图片描述
    帮助信息那里会有比较详细的使用资料和视频,具体使用可以查看帮助信息
    在这里插入图片描述
    通过上面介绍,我们了解到了怎么连接上位机与下位机,如何使用波形显示界面,下面将通过分析通信协议,写下位机代码。(具体协议请自行查看帮助信息的通信协议)

    通信协议简介:

    通过匿名协议的方式,确定一帧数据的构成,一帧数据的不同位置,功能不同,至于后面的校验和附加校验也不需要怎么理解,直接套用即可。需要注意的数据内容采取的是小端模式

    在这里插入图片描述

    灵活格式帧

    灵活格式帧,是用户能够自定义一帧数据的数据长度和数据内容,比较灵活,因此只是介绍它,这个也是发送到上位机的数据。
    组成:
    注意ID,是由0XF1~0XFA
    在这里插入图片描述
    C代码分析
    发送一帧数据代码

    /**********为了匿名四轴上位机的协议定义的变量****************************/
    //cup为小端模式存储,也就是在存储的时候,低位被存在0字节,高位在1字节
    #define BYTE0(dwTemp)       (*(char *)(&dwTemp))	 //取出int型变量的低字节
    #define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))	 //	取存储在此变量下一内存字节的内容,高字节
    #define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
    #define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))
    
    
    u8 BUFF[30];
    
    void sent_data(u16 A,u16 B,u8 C)
    {
    	int i;
    	u8 sumcheck = 0;
    	u8 addcheck = 0;
    	u8 _cnt=0;
    	BUFF[_cnt++]=0xAA;//帧头
    	BUFF[_cnt++]=0xFF;//目标地址
    	BUFF[_cnt++]=0XF1;//功能码
    	BUFF[_cnt++]=0x05;//数据长度
    	BUFF[_cnt++]=BYTE0(A);//数据内容,小段模式,低位在前
    	BUFF[_cnt++]=BYTE1(A);//需要将字节进行拆分,调用上面的宏定义即可。
    	BUFF[_cnt++]=BYTE0(B);
    	BUFF[_cnt++]=BYTE1(B);	
    	BUFF[_cnt++]=C;
    	//SC和AC的校验直接抄最上面上面简介的即可
    	for(i=0;i<BUFF[3]+4;i++) 
    	{
    		sumcheck+=BUFF[i];
    		addcheck+=sumcheck;
    	}
    	BUFF[_cnt++]=sumcheck;	
    	BUFF[_cnt++]=addcheck;	
    	
    	for(i=0;i<_cnt;i++) UsartSendByte(USART1,BUFF[i]);//串口逐个发送数据
    }
    

    串口初始化代码
    注意一下基础配置为,字长为8位数据格式,一个停止位
    无奇偶校验位,

    void usart1_init(u32 bound)
    {
    	//GPIO端口设置
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	 
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
    
    	//USART1_TX   GPIOA.9
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
    
    	//USART1_RX	  GPIOA.10初始化
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    
    	//Usart1 NVIC 配置
    	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级0
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级2
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
    
    	//USART 初始化设置
    
    	USART_InitStructure.USART_BaudRate = bound;//串口波特率
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
    
    	USART_Init(USART1, &USART_InitStructure); //初始化串口1
    	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
    	USART_Cmd(USART1, ENABLE);                    //使能串口1 
    }
    

    配置完上述,在定时器上调用发送数据函数即可

    //定时器3中断服务程序
    //10Khz的计数频率,计数到50为5ms 
    void TIM3_IRQHandler(void)   //TIM3中断
    {
    	static u16 A=0,B=2;
    	static u8 C;
    	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
    		{
    		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志
    			C=A+B;
    			A++;B++;
    			sent_data(A,B,C);		
    		}
    }
    
    

    至此,下位机配置完成。
    上位机再进行简单配置,即可进行波形显示

    波形显示配置

    进入上位机协议通信,打开右侧,进行自定义帧数配置,与下位机接收的数据进行匹配,如图。
    下面数据容量配置是与波形显示界面配置
    在这里插入图片描述
    在这里插入图片描述
    到此配置完成,烧录代码,打开上位机连接即可,通过查看下放的错码率可以知道自己的下位机代码是否写错了

    下面进行简单演示

    在这里插入图片描述
    右侧由数据值显示
    在这里插入图片描述
    A和B的波形重合到一起了(-。-)
    右下方的数据频率基本与发送频率一致
    在这里插入图片描述

    匿名上位机还要其他功能有趣的功能
    比如:波形分析
    在这里插入图片描述
    发送参数读取参数
    在这里插入图片描述

    展开全文
  • ANO匿名上位机V7协议&STM32 说明:以下程序为自己编写,若有误欢迎各位指出。 基于ANO匿名V7上位机的通信协议编写的代码 文章目录ANO匿名上位机V7协议&STM32前言一、Ano V7上位机功能介绍1,基本数据接收2,...

    ANO匿名上位机V7协议&STM32

    说明:以下程序为自己编写,若有误欢迎各位指出。

    基于ANO匿名V7上位机的通信协议编写的代码


    前言

    提示:以下内容需用到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

    #ifndef __MYANO_H
    #define __MYANO_H
    
    #include "stm32f3xx_hal.h"
    
    #define Color_Black  	0
    #define Color_Red  		1
    #define Color_Green  	2
    
    enum AnoID
    {
    	Stop = 0x00,		//停止运行
    	Operation,			//开始运行
    	Store,				//储存
    
    	HWTYPE = 0x05,	//硬件种类
    
    	PID_1_P = 11,
    	PID_1_I,
    	PID_1_D,		//第一组PID
    
    	PID_2_P,
    	PID_2_I,
    	PID_2_D,		//第二组PID
    
    	PID_3_P,
    	PID_3_I,
    	PID_3_D			//第三组PID
    };
    
    typedef struct
    {
    	uint8_t Head;
    	uint8_t Addr;
    	uint8_t ID;
    	uint8_t Lenth;
    	uint8_t SendBuff[1024];	//发送缓存数组
    	uint8_t ReceiveBuf[10];	//接收缓存数组
    }_ano;
    
    typedef struct 
    {
    	uint8_t OrderState;		//命令接收状态
    
    	int16_t PID_Par1_P;
    	int16_t PID_Par1_I;
    	int16_t PID_Par1_D;		//第一组PID
    
    	uint16_t PID_Par2_P;
    	uint16_t PID_Par2_I;
    	uint16_t PID_Par2_D;	//第二组PID
    
    	uint16_t PID_Par3_P;
    	uint16_t PID_Par3_I;
    	uint16_t PID_Par3_D;	//第三组PID
    	/* data */
    }_Para;
    
    extern _ano MyAno;		//声明外部变量
    extern _Para MPara;		//参数
    
    /****** 用户不可调用函数 ******/
    static void SendParaData(uint8_t Id,int32_t para);		//发送ID对应的参数
    static void SendCheckAnalysis(uint8_t id,uint8_t *sumcheck,uint8_t *addcheck);		//发送数据校验帧0x00
    static uint8_t Receive_CheckData(uint8_t *_da);		//接收数据校验检测
    static uint8_t Send_CheckData(_ano *ano);			//发送数据和校验&附加校验计算
    
    /****** 用户可调用函数 ******/
    void Ano_Init(void); 												//参数初始化
    void Ano_Send_Data(uint8_t id, void *Data, uint8_t lenth);			//发送数据函数
    void Ano_Set_Mdata(uint8_t id,void *data,uint8_t len,uint8_t num);	//多数据配置
    void Ano_SendMdata(void);											//多数据发送
    void Ano_DataAnalysis(uint8_t *_da);								//接收数据解析(放串口回调函数里面)
    void Ano_SendString(const char *str,uint8_t color);					//发送字符串
    void Ano_SendStringVal(const char *str,int32_t Val);				//发送字符串+数据值
    
    void Show_Test(void);	//测试显示函数
    
    /****** 用户可调用&重写函数 ******/
    __weak void ControlOrder(uint8_t _Ord);					//控制指令
    __weak void ParaOfReturn_Set(uint16_t _id);				//参数回传设置
    __weak void ParaRead_Set(uint16_t _id,int32_t _val);	//参数数据读取设置
    
    #endif 
    
    

    2,调用说明

    注:需先调用"Ano_Init"参数初始化函数,在确定回传参数与实际参数的关系,然后把"Ano_DataAnalysis"扔进串口回调函数中,传入一个完整的一帧数据进行解析。

    串口接收回调函数的示例:

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
      if(huart->Instance == huart2.Instance)  //判断是否是USART1
      {
        MPara.OrderState = 1;	        //在接收命令数据
        if(UsartBuffer[0] == 0xAA)    //判断帧头
        {
          UsartBuffer[Usart1_RxCnt++] = RxBuffer;
          if((Usart1_RxCnt == 8 && UsartBuffer[2] == 0xE1) || (Usart1_RxCnt == 12 && UsartBuffer[2] == 0xE2) || (Usart1_RxCnt == 17 && UsartBuffer[2] == 0xE0))
          {
            Ano_DataAnalysis((uint8_t *)&UsartBuffer);
            Usart1_RxCnt = 0;			
    			  memset(UsartBuffer,0x00,sizeof(UsartBuffer)); //清空数组
          }
        }
        else
        { 
          Usart1_RxCnt = 0;			
    			memset(UsartBuffer,0x00,sizeof(UsartBuffer)); //清空数组
          UsartBuffer[Usart1_RxCnt++] = RxBuffer;
        }
        HAL_UART_Receive_IT(&huart2, (uint8_t *)&RxBuffer, 1);   //再开启接收中断	
      }
    }
    

    注:在发送数据的时候写一个判断语句,进行判断接收命令的状态

    if(MPara.OrderState == 0) //命令接收结束
    {
    	//发送数据语句
    }
    
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 553
精华内容 221
关键字:

匿名上位机