MiniFly微型四轴学习与开发日志(五)——遥控器任务详解

2023-05-16

文章目录

    • radiolinkTask无线连接任务
    • usblinkTxTask usb发送任务
    • usblinkRxTask usb接收任务
    • commanderTask飞控指令发送任务
    • keyTask按键扫描任务
    • displayTask显示任务
    • configParamTask参数配置任务
    • radiolinkDataProcessTask无线通信数据处理任务
    • usblinkDataProcessTaskUSB通信数据处理任务

radiolinkTask无线连接任务

xTaskCreate(radiolinkTask, "RADIOLINK", 100, NULL, 6, &radiolinkTaskHandle);/*创建无线连接任务*/

radiolinkTask 主要功能是发送 ATKP 数据包给四轴,并接收四轴返回的应答包。
radiolinkTask 函数在 radiolink.c 中。

/*无线连接任务*/
void radiolinkTask(void* param)
{
	u8 rx_len;
	atkp_t rx_p;
	while(1)
	{
		nrf_txPacket((u8*)&tx_p, tx_p.dataLen+2);
		xSemaphoreTake(nrfIT, 1000);
		nrfEvent_e status = nrf_checkEventandRxPacket((u8*)&rx_p, &rx_len);
		if(status == RX_DR)//发送成功
		{	
			LED_BLUE = 0;
			LED_RED  = 1;
			statusCount = 0;
			connectStatus = true;
			if(rx_p.dataLen <= ATKP_MAX_DATA_SIZE)
			{
				xQueueSend(rxQueue, &rx_p, portMAX_DELAY);
			}
			if(xQueueReceive(txQueue, &tx_p, 0) == pdFALSE)
			{
				tx_p.msgID = DOWN_RADIO;
				tx_p.dataLen = 1;
				tx_p.data[0] = D_RADIO_HEARTBEAT;
			}
		}
		else if(status == MAX_RT)//发送失败
		{
			LED_BLUE = 1;
			LED_RED  = 0;
			failRxCount++;
			if(++statusCount > 10)//连续10次无应答则通讯失败
			{
				statusCount = 0;
				connectStatus = false;
			}
		}
		
		/*1000ms统计一次收发失败次数*/
		if(connectStatus==true && xTaskGetTickCount()>=failRxcountTime+1000)
		{
			failRxcountTime = xTaskGetTickCount();
			failReceiveNum = failRxCount;
			failRxCount = 0;
		}
		
	}
}

① 定义8位数据rx_len、通讯数据结构体rx_p
nrf_txPacket()发送数据包(PTX模式);
nrf_checkEventandRxPacket()查询事件并接收数据包;
④ 若发送成功,则蓝灯亮,执行相应操作;若发送失败,则红灯亮,如果连续10次无应答则通讯失败;
⑤ 1000ms统计一次收发失败次数。

usblinkTxTask usb发送任务

xTaskCreate(usblinkTxTask, "USBLINK_TX", 100, NULL, 5, NULL);	/*创建usb发送任务*/

usblinkTxTask 主要功能是给 ATKP 数据包加上帧头和校验并发送给上位机。
usblinkTxTask 函数在 usblink.c 中。

/*usb连接发送任务*/
void usblinkTxTask(void* param)
{
	atkp_t p;
	u8 sendBuffer[64];
	u8 cksum;
	u8 dataLen;
	while(bDeviceState != CONFIGURED)//等usb配置成功
	{
		vTaskDelay(1000);
	}
	while(1)
	{
		xQueueReceive(txQueue, &p, portMAX_DELAY);
		if(p.msgID != UP_RADIO)/*NRF51822的数据包不上传*/
		{
			if(p.msgID == UP_PRINTF)/*打印数据包去掉帧头*/
			{
				memcpy(&sendBuffer, p.data, p.dataLen);
				dataLen = p.dataLen;
			}
			else
			{
				sendBuffer[0] = UP_BYTE1;
				sendBuffer[1] = UP_BYTE2;
				sendBuffer[2] = p.msgID;
				sendBuffer[3] = p.dataLen;
				memcpy(&sendBuffer[4], p.data, p.dataLen);
				cksum = 0;
				for (int i=0; i<p.dataLen+4; i++)
				{
					cksum += sendBuffer[i];
				}
				dataLen = p.dataLen+5;
				sendBuffer[dataLen - 1] = cksum;
			}
			usbsendData(sendBuffer, dataLen);
		}		
	}
}

① 定义相关数据与结构体,然后等待usb配置成功;
② 当NRF51822的数据包不上传时,若p.msgID == UP_PRINTF,则打印数据包去掉帧头;否则执行相应操作。

usblinkRxTask usb接收任务

xTaskCreate(usblinkRxTask, "USBLINK_RX", 100, NULL, 5, NULL);	/*创建usb接收任务*/

usblinkRxTask 主要功能是接收上位机发下来的串口数据,按照 ATKP 格式打包。
usblinkRxTask 函数在 usblink.c 中。

/*usb连接接收任务*/
void usblinkRxTask(void *param)
{
	u8 c;
	u8 dataIndex = 0;
	u8 cksum = 0;
	rxState = waitForStartByte1;
	while(1)
	{
		if (usbGetDataWithTimout(&c))
		{
			switch(rxState)
			{
				case waitForStartByte1:
					rxState = (c == DOWN_BYTE1) ? waitForStartByte2 : waitForStartByte1;
					cksum = c;
					break;
				case waitForStartByte2:
					rxState = (c == DOWN_BYTE2) ? waitForMsgID : waitForStartByte1;
					cksum += c;
					break;
				case waitForMsgID:
					rxPacket.msgID = c;
					rxState = waitForDataLength;
					cksum += c;
					break;
				case waitForDataLength:
					if (c <= ATKP_MAX_DATA_SIZE)
					{
						rxPacket.dataLen = c;
						dataIndex = 0;
						rxState = (c > 0) ? waitForData : waitForChksum1;	/*c=0,数据长度为0,校验1*/
						cksum += c;
					} else 
					{
						rxState = waitForStartByte1;
					}
					break;
				case waitForData:
					rxPacket.data[dataIndex] = c;
					dataIndex++;
					cksum += c;
					if (dataIndex == rxPacket.dataLen)
					{
						rxState = waitForChksum1;
					}
					break;
				case waitForChksum1:
					if (cksum == c)/*所有校验正确*/
					{
						xQueueSend(rxQueue, &rxPacket, 0);
					} 
					else
					{
						rxState = waitForStartByte1;
					}
					rxState = waitForStartByte1;
					break;
				default:
					break;
			}
		}
		else	/*超时处理*/
		{
			rxState = waitForStartByte1;
		}
	}
}

① 相关数据与结构体的定义与赋值;
② 若满足usbGetDataWithTimout(&c)的条件,根据rxState的值执行相应操作,其中rxState = (c > 0) ? waitForData : waitForChksum1则为c=0,数据长度为0,校验1,cksum == c为所有校验正确。

commanderTask飞控指令发送任务

xTaskCreate(commanderTask, "COMMANDER", 100, NULL, 4, NULL);	/*创建飞控指令发送任务*/

commanderTask 主要功能是将采集摇杆电位器的 AD 值转换为姿态控制命令,并以 10ms的周期通过 radiolink 链路发送给四轴。
commanderTask 函数在 remoter_ctrl.c 中。

/*发送飞控命令任务*/
void commanderTask(void* param)
{
	float max_thrust = LOW_SPEED_THRUST;
	float max_pitch = LOW_SPEED_PITCH;
	float max_roll = LOW_SPEED_ROLL;
	joystickFlyf_t  percent;
	
	while(1)
	{
		vTaskDelay(10);
		switch(configParam.flight.speed)
		{
			case LOW_SPEED:
				max_thrust = LOW_SPEED_THRUST;
				max_pitch = LOW_SPEED_PITCH;
				max_roll = LOW_SPEED_ROLL;
				break;
			case MID_SPEED:
				max_thrust = MID_SPEED_THRUST;
				max_pitch = MID_SPEED_PITCH;
				max_roll = MID_SPEED_ROLL;
				break;
			case HIGH_SPEED:
				max_thrust = HIGH_SPEED_THRUST;
				max_pitch = HIGH_SPEED_PITCH;
				max_roll = HIGH_SPEED_ROLL;
				break;
		}
		
		ADCtoFlyDataPercent(&percent);
		
		//THRUST
		if(configParam.flight.ctrl == ALTHOLD_MODE || configParam.flight.ctrl == THREEHOLD_MODE)/*定高模式 和定点模式*/
		{
			flydata.thrust = percent.thrust * ALT_THRUST;
			flydata.thrust += ALT_THRUST;
			flydata.thrust = limit(flydata.thrust, 0, 100);
		}
		else
		{
			flydata.thrust = percent.thrust * (max_thrust - MIN_THRUST);
			flydata.thrust += MIN_THRUST;
			flydata.thrust = limit(flydata.thrust, MIN_THRUST, max_thrust);
		}
		//ROLL
		flydata.roll = percent.roll * max_roll;
		flydata.roll = limit(flydata.roll, -max_roll, max_roll);
		//PITCH
		flydata.pitch = percent.pitch * max_pitch;
		flydata.pitch = limit(flydata.pitch, -max_pitch, max_pitch);
		//YAW
		flydata.yaw = percent.yaw * MAX_YAW;
		flydata.yaw = limit(flydata.yaw, -MAX_YAW, MAX_YAW);
		
		/*发送飞控数据*/
		if(getRCLock()==false && radioinkConnectStatus()==true && getIsMFCanFly()==true)
		{	
			remoterData_t send;
			switch(configParam.flight.mode)
			{
				case HEAD_LESS:
					send.flightMode = 1;
					break;
				case X_MODE:
					send.flightMode = 0;
					break;
			}
			
			switch(configParam.flight.ctrl)
			{
				case ALTHOLD_MODE:
					send.ctrlMode = 1;
					break;
				case MANUAL_MODE:
					send.ctrlMode = 0;
					break;
				case THREEHOLD_MODE:
					send.ctrlMode = 3;
					break;
			}
			
			if(flydata.thrust<=MIN_THRUST && send.ctrlMode==0)
			{
				send.thrust = 0;
			}
			else
			{
				send.thrust = flydata.thrust;
			}
			
			if(getTrimFlag() == true)
			{
				send.pitch = 0;
				send.roll = 0;
			}
			else
			{
				send.pitch = flydata.pitch ;
				send.roll = flydata.roll;
			}
			send.yaw = flydata.yaw;
			send.trimPitch = configParam.trim.pitch;
			send.trimRoll = configParam.trim.roll;
			
			/*发送飞控数据*/
			sendRmotorData((u8*)&send, sizeof(send));
		}
		
		/*发送遥感数据至匿名上位机*/
		if(radioinkConnectStatus()==true)
		{
			atkp_t p;
			joystickFlyui16_t rcdata;
			
			rcdata.thrust = flydata.thrust*10 + 1000;
			rcdata.pitch = percent.pitch*500 + 1500;
			rcdata.roll = percent.roll*500 + 1500;
			rcdata.yaw = percent.yaw*500 + 1500;
			
			p.msgID = DOWN_RCDATA;
			p.dataLen = sizeof(rcdata);
			memcpy(p.data, &rcdata, p.dataLen);
			radiolinkSendPacket(&p);
		}
	}
}

/*获取飞控数据*/
joystickFlyf_t getFlyControlData(void)
{
	return flydata;
}

① 定义油门值、俯仰角与滚转角的最大值,定义飞控数据结构体percent,其中

//飞控数据结构
typedef struct 
{
	float roll;
	float pitch;
	float yaw;
	float thrust;
}joystickFlyf_t;

② 做简短延时后,根据配置参数中的速度speed来选择油门值、俯仰角与滚转角的值;
ADCtoFlyDataPercent(&percent)将ADC值转换成飞控数据百分比;
④ 根据飞行模式是定高模式/定点模式还是手动模式来配置飞控数据的油门值;
⑤ 配置飞控数据的滚转角、俯仰角与偏航角;
⑥ 发送飞控数据:定义遥控数据结构,根据相应参数的值配置要发送的遥控数据结构的值,通过sendRmotorData()发送遥控控制数据;
⑦ 发送遥感数据至匿名上位机。

keyTask按键扫描任务

xTaskCreate(keyTask, "BUTTON_SCAN", 100, NULL, 3, NULL);		/*创建按键扫描任务*/

keyTask 主要功能是扫描按键,根据按键按下的时间来区分长按和短按。
keyTask 函数在 keyTask.c 中。

void keyTask(void* param)
{
	while(1)
	{
		vTaskDelay(20);
		
		if(keyL_pressed==false && READ_KEY_L()==PRESSED)
		{
			keyL_pressed = true;
			pressedTime = xTaskGetTickCount();
		}
		if(keyR_pressed==false && READ_KEY_R()==PRESSED)
		{
			keyR_pressed = true;
			pressedTime = xTaskGetTickCount();
		}
		if(keyJ1_pressed==false && READ_KEY_J1()==PRESSED)
		{
			keyJ1_pressed = true;
			pressedTime = xTaskGetTickCount();
		}
		if(keyJ2_pressed==false && READ_KEY_J2()==PRESSED)
		{
			keyJ2_pressed = true;
			pressedTime = xTaskGetTickCount();
		}
		
		if(keyL_pressed==true)
		{
			if(READ_KEY_L()==RELEASED)
				keyL_pressed = false;
			if((xTaskGetTickCount() - pressedTime) > LONG_PRESS_COUNT)
				keyState = KEY_L_LONG_PRESS;
			else if(READ_KEY_L()==RELEASED)
				keyState = KEY_L_SHORT_PRESS;
		}
		if(keyR_pressed==true)
		{
			if(READ_KEY_R()==RELEASED)
				keyR_pressed = false;
			if((xTaskGetTickCount() - pressedTime) > LONG_PRESS_COUNT)
				keyState = KEY_R_LONG_PRESS;
			else if(READ_KEY_R()==RELEASED)
				keyState = KEY_R_SHORT_PRESS;
		}
		if(keyJ1_pressed==true)
		{
			if(READ_KEY_J1()==RELEASED)
				keyJ1_pressed = false;
			if((xTaskGetTickCount() - pressedTime) > LONG_PRESS_COUNT)
				keyState = KEY_J1_LONG_PRESS;
			else if(READ_KEY_J1()==RELEASED)
				keyState = KEY_J1_SHORT_PRESS;
		}
		if(keyJ2_pressed==true)
		{
			if(READ_KEY_J2()==RELEASED)
				keyJ2_pressed = false;
			if((xTaskGetTickCount() - pressedTime) > LONG_PRESS_COUNT)
				keyState = KEY_J2_LONG_PRESS;
			else if(READ_KEY_J2()==RELEASED)
				keyState = KEY_J2_SHORT_PRESS;
		}

	}
}

displayTask显示任务

xTaskCreate(displayTask, "DISPLAY", 200, NULL, 1, NULL);		/*创建显示任务*/

displayTask 主要功能是显示界面,50ms 刷新一次界面。
displayTask 函数在 display.c 中。

/*显示任务*/
void displayTask(void* param)
{
	while(1)
	{
		vTaskDelay(50);
		switch(show_ui)
		{
			case MAIN_UI:
				main_ui();
				break;
			case TRIM_UI:
				trim_ui();
				break;
			case MENU_UI:
				Menu_Run();
				break;
			case DEBUG_UI:
				debug_ui();
				break;
			case JOYSTICK_CALIB_UI:
				joystickCalib_ui();
				break;
			case MATCH_UI:
				match_ui();
				break;
			case RESET_UI:
				reset_ui();
				break;
			default:break;
		}
		GUI_Refresh();
	}
}

configParamTask参数配置任务

xTaskCreate(configParamTask, "CONFIG_TASK", 100, NULL, 1, NULL);/*创建参数配置任务*/

configParamTask 主要功能是保存参数。任务中 1000ms 判断一次配置参数有无改变,当有参数改变后 6S 内不再改变则将新参数写入 Flash。这样做的目的是避免在微调四轴时频繁写 Flash,Flash 擦写次数是有限的。
configParamTask 函数在 config_param.c 中。

/*配置参数任务*/
void configParamTask(void* param)
{
	u8 cksum = 0;
	static u8 count = 0;
	while(1) 
	{	
		vTaskDelay(1000);
		cksum = calculate_cksum(&configParam);
		if(configParam.cksum != cksum)	
		{
			configParam.cksum = cksum;
			count = 1;
		}
		if(count)
		{
			count ++;
		}
		if(count > 6)/*参数有改变之后6S内不再变则写入flash*/
		{
			count = 0;
			STMFLASH_Write(CONFIG_PARAM_ADDR,(u16*)&configParam,sizeof(configParam)/2);
		}
	}
}

radiolinkDataProcessTask无线通信数据处理任务

xTaskCreate(radiolinkDataProcessTask, "DATA_PROCESS", 100, NULL, 6, NULL);	/*创建无线通信数据处理任务*/

radiolinkDataProcessTask 主要功能是处理四轴返回的应答包数据,处理完之后再通过usblink 链路转发给上位机。
radiolinkDataProcessTask 函数在 atkp.c 中。

/*无线连接数据处理任务*/
void radiolinkDataProcessTask(void *param) 
{
	atkp_t p;
	while(1)
	{
		radiolinkReceivePacketBlocking(&p); /*接收四轴上传的数据,包括四轴数据和遥控器数据*/
		atkpAnalyze(&p); /*atkp解析*/
		usblinkSendPacket(&p);	/*把接收到的四轴数据发送到上位机*/
		vTaskDelay(1);
	}
}

usblinkDataProcessTaskUSB通信数据处理任务

xTaskCreate(usblinkDataProcessTask, "DATA_PROCESS", 100, NULL, 6, NULL);	/*创建USB通信数据处理任务*/

usblinkDataProcessTask 主要功能是处理上位机发下来的 ATKP 数据包,处理完之后通过radiolink 链路转发给四轴。上位机发下来的 ATKP 数据包由 usblinkRxTask 打包。
usblinkDataProcessTask 函数在 atkp.c 中。

/*USB连接数据处理任务*/
void usblinkDataProcessTask(void *param)
{
	atkp_t p;
	while(1)
	{
		usblinkReceivePacketBlocking(&p);	/*接收上位机发送的数据*/
		atkpAnalyze(&p);
		radiolinkSendPacket(&p);
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MiniFly微型四轴学习与开发日志(五)——遥控器任务详解 的相关文章

  • 超强整理!PCB设计之电流与线宽的关系

    关于pcb线宽和电流的经验公式 xff0c 关系表和软件网上都很多 xff0c 本文把网上的整理了一下 xff0c 旨在给广大工程师在设计PCB板的时候提供方便 以下总结了八种电流与线宽的关系公式 xff0c 表和计算公式 xff0c 虽然
  • nginx 主动健康检查搭建详解(nginx_upstream_check_module)

    版本信息 nginx 1 21 1 下载nginx upstream check module模块 nginx upstream check module master zip wget https codeload github com
  • paddle推理部署(cpu)

    我没按照官方文档去做 xff0c 吐槽一下 xff0c 官方文档有点混乱 一 概述 总结起来 xff0c 就是用c 43 43 示例代码 xff0c 用一个模型做推理 二 示例代码下载 https www paddlepaddle org
  • Vector的用法

    我不知道大家是怎么理解Vector和怎样使用的 xff0c 这篇文章主要是发表我自己对于Vector的看法 xff0c 仅仅属于个人理解 xff0c 如果有什么错误 xff0c 也希望大家指正哈 目录 1 xff1a Vector的概念 2
  • float的表示

    xfeff xfeff 先说一下计算机中二进制的算法 xff1a 整数 整数的二进制算法大家应该很熟悉 xff0c 就是不断的除以2取余数 xff0c 然后将余数倒序排列 比如求9的二进制 xff1a 9 2 61 4 余 1 4 2 61
  • cmake系列(三)

    目录 多个源文件 同一目录 xff0c 多个源文件 多个源文件 同一目录 xff0c 多个源文件 本小节对应的源代码所在目录 xff1a Demo2 上面的例子只有单个源文件 现在假如把 power 函数单独写进一个名为 MathFunct
  • ORACLE 字符串聚合函数 strcat

    create or replace type strcat type as object currentstr varchar2 4000 currentseprator varchar2 8 static function ODCIAgg
  • 无人机器件选择参考

    无人机飞控 xff0c 引脚预留数量 1 xff0c 四路pwm 2 xff0c 无线通信spi 3 xff0c 陀螺仪通信用iic 4 xff0c 串口调试用uart 5 xff0c led灯用普通io 6 xff0c 电量检测和电机堵塞
  • 字节对齐的规则总结

    一 什么是字节对齐 为什么要对齐 现代计算机中内存空间都是按照byte划分的 xff0c 从理论上讲似乎对任何类型的变量的访问可以从任何地址开始 xff0c 但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问 xff0c 这就需要
  • C++中第三方库的一般使用方式(libxl库为例)

    本篇介绍如何使用C C 43 43 的第三方库 xff0c 学会使用第三方库很重要 xff0c 尤其对于使用C C 43 43 语言的人来说 xff0c 标准库能做的事不能说太少 xff0c 恰当的说应该是没那么有趣 学会使用第三方库 xf
  • 三相电动机用单相电源

    三相电机改为单相运行 单相电机配用电容不是越大越好 三相电动机用单相电源 三相电机改为单相运行 介绍几种简便易行的方法 xff0c 可以不改动电机内部绕组而将三相电机改为单相运行 有6 种 xff1a 一 加电容法 xff39 形接法的三相
  • curl_init()和curl_multi_init()多线程的速度比较

    来源 http www webkaka com tutorial php 2013 102843 php中curl init 的作用很大 xff0c 尤其是在抓取网页内容或文件信息的时候 xff0c 例如之前文章curl获得header检测
  • 连接两字符串函数

    include lt stdio h gt include 34 string h 34 char Strcat char s1 char s2 printf 34 连接之后的字符串为 xff1a 34 for s1 61 39 0 39
  • CAN通信数据帧介绍

    CAN通信有五个帧 xff0c 其中最重要的是数据帧 xff01 xff01 xff01 xff01 我们下面开始讨论数据帧 一 数据帧的格式 xff08 数据帧有七个段组成 xff09 xff0c 帧起始 表示数据帧开始的段 xff0c
  • STM32压力传感器信号采集-24位AD HX720 HX711 原理介绍

    我做过很多工业用压力采集产品 xff0c 用过很多高分辨率的AD芯片 xff0c 其中有两款值得推荐 一个是海芯科技出的HX711等24位AD xff0c 一个是塞普拉斯出的CS5532等24位AD 国产芯片和进口芯片有差距 xff0c 但
  • stm32实现网络音频-原理图单片机程序C#上位机程序

    电子可以一边玩 xff0c 一边研究 xff0c 网络音频这个课题特别适合电子爱好者 几方面的挑战如下 xff0c 单片机实现对接以太网 实时对音频流解码播放 xff0c 上位机配合单片机做音频流传输控制 xff0c 音频信号的对接放大处理
  • rosdep init and update Error

    rosdep init Error sudo rosdep init ERROR default sources list file already exists br etc ros rosdep sources list d 20 de
  • Postman汉化版本竟如此简单,全中文真香

    对于国内程序员来说 xff0c 外国开发软件的一个使用门槛是全英文的 xff0c 对于不熟悉各种专业术语的同学 xff0c 上手比较麻烦 因此有种方法就是使用汉化版的外国软件 xff0c 但 Postman 并没有汉化版本 但是postma
  • YOLOv5识别目标的实时坐标打印

    引言 这个功能看似鸡肋 xff0c 但对于无人机目标识别与追踪有重要意义 xff0c 通过目标在摄像头视野的坐标位置 xff0c 可以推算出无人机相对与目标的位置 xff0c 从而对无人机进行位置矫正 因此 xff0c 添加代码打印坐标并不
  • 六、WebRTC中ICE的实现

    一 Candidate种类 amp 优先级 高到底 xff1a host srflx prflx relay 同一局域网内通过host类型的Candidate在内网建立连接 非同一局域网 xff0c 隔断从STUN TURN服务器中收集sr

随机推荐

  • 七、WebRTC中的SDP

    一 SDP标准规范 格式 xff1a lt type gt 61 lt value gt SDP 会话层 媒体层 媒体音频 媒体视频 二 WebRTC中的SDP的整体结构 1 媒体信息 m 61 行中描述媒体类型 传输类型 Playload
  • linux 信号量sem

    一 信号量 信号量如同一盏红绿信号灯 xff0c 用于临界资源 xff08 如公路 人行道 xff09 的管理 信号量是一种特殊的变量 xff0c 访问具有原子性 P等待 xff1a 信号量的值为0时 xff0c 不能减 xff0c 则进行
  • 1-4 实验3 串口通信

    串口通信 1 实验内容 xff1a PC端串口调试助手向板子发送数据 xff0c 板子接受到数据后 xff0c 再把数据发送回给PC端串口调试助手 2 串口发送接受数据的基本步骤 xff1a 初始化串口 xff08 设置波特率 中断等 xf
  • 1-6 实验5 无线温度检测实验

    无线温度检测实验 1 实验内容 xff1a 协调器建立ZigBee无线网络 xff0c 终端节点自动加入网络 xff0c 然后终端节点周期性地采集温度并将数据发送到协调器 协调器接受数据并通过串口把接受到的数据传给PC端的串口调试助手 2
  • 1-11 实验9 网络管理实验1 获取自身的和父节点网络地址、MAC地址

    p p p style color rgb 51 51 51 font family Arial font size 14px line height 26px 获取自身的和父节点网络地址 MAC地址 p p style color rgb
  • 1-14 实验11 获取网络拓扑

    获取网络拓扑 1 实验内容 xff1a PC端串口调试助手向协调器发送命名 topology 协调器接受到命令后 xff0c 将网络拓扑信息发送到PC机串口调试助手上 2 知识点 xff1a 在1 11 实验9 网络管理实验1 获取自身和父
  • S 串口编程 详解3 串口的初始化、打开/关闭

    串口编程 详解3 串口的初始化 程序打开串口 xff0c 采用两种方法 xff1a 1 程序启动 xff0c 调用OnInitDialog 函数 xff0c 打开串口 xff0c 缺省串口号为COM1 xff0c 如果COM1不存在或被占用
  • 求关键路径(包含邻接表的建立、拓扑排序)

    include lt stdio h gt include lt stdlib h gt typedef struct node int adjvex 邻接点域 int info 边上的信息 struct node next 指向下一个邻接
  • FPGA串口回环实验

    本文将从个人理解的角度 xff0c 解释FPGA串口通信的原理 xff0c 并进行实战演示 1 写在前面的话 串口通信是初学FPGA必过的一道坎 xff0c 如果能够在不参考任何资料的情况下自己手搓一套串口回环的代码 xff0c Verio
  • Debug Assertion Failed!解决方法详解

    1 野指针 2 内存泄露 解决方法 1 看一看你的程序里是不是有 ASSERT xff08 xff09 或 VERIFY xff08 xff09 语句 这两个宏是用来测试它的参数是否为真的 出现你说的 xff0c 这说明你的指针或表达试有问
  • 用tftp的方式在u_boot下 烧写uImage内核

    用 u boot 进行下载 uImage 一种 kernel 镜像文件 首先 把编译好的 uImage 文件放在 tftpboot 目录下 用网线把开发板和电脑连上 但PC上的网卡显示是没连接的 xff0c 这一点是没有关系的 xff0c
  • 利用NFS服务挂载NFS根文件系统

    嵌入式Linux根文件系统 xff0c 简单地说 xff0c 根文件系统就是一种目录结构 注意根文件系统和普通的文件系统的区别 常见的Linux根文件系统有 xff1a xff08 1 xff09 NFS xff08 网络根文件系统 xff
  • 数据校验之Checksum算法

    校验和 xff08 Checksum xff09 是网络协议使用的数据错误检测方法 xff0c 并且被认为比LRC xff08 纵向冗余校验 xff0c Longitudinal Redundancy Check xff0c LRC xff
  • 位序转字符串的一种高效方法

    include lt stdio h gt include lt stdlib h gt include lt malloc h gt include lt string h gt include lt arpa inet h gt def
  • OpenSIPS实战(一):OpenSIPS使用简介

    1 OpenSIPS是什么 OpenSIPS xff08 Open SIP Server xff09 是一个成熟的开源SIP服务器实现 可以作为SIP代理 路由器 但OpenSIPS不仅仅是一个SIP代理 路由器 xff0c 因为它包含了应
  • Floyd判圈算法(龟兔赛跑算法, Floyd's cycle detection)及其证明

    问题 xff1a 如何检测一个链表是否有环 xff08 循环节 xff09 xff0c 如果有 xff0c 那么如何确定环的起点以及环的长度 空间要求 xff1a 不能存储所经过的的每一个点 举例 xff1a x 0 61 1 x 0 61
  • Ubuntu配置GPU版本pytorch环境(含NVIDIA驱动+Cuda+Cudnn)

    本文更新于2018年8月底 概述 步骤如下 xff1a 1 安装Ubuntu 2 安装NVIDIA 显卡驱动 2 安装NVIDIA Cuda 3 安装NVIDIA CuDNN 4 安装GPU版本的PyTorch 安装Ubuntu 系统版本选
  • PyTorch中的Dataset、Dataloader和_DataloaderIter

    Dataset Pytorch中数据集被抽象为一个抽象类torch utils data Dataset xff0c 所有的数据集都应该继承这个类 xff0c 并override以下两项 xff1a len xff1a 代表样本数量 len
  • 彻底搞懂Lab 颜色空间

    本文参考wikipedia xff0c 并加入了自己的理解 xff0c 有不对的地方多多指教 名称 在开始之前 xff0c 先明确一下Lab颜色空间 xff08 Lab color space xff09 的名字 xff1a Lab的全称是
  • MiniFly微型四轴学习与开发日志(五)——遥控器任务详解

    文章目录 radiolinkTask无线连接任务usblinkTxTask usb发送任务usblinkRxTask usb接收任务commanderTask飞控指令发送任务keyTask按键扫描任务displayTask显示任务confi