RT-Thread+STM32L475VET6——USB鼠标模拟


文章目录

  • 前言
  • 一、板载资源
  • 二、具体步骤
    • 1.配置icm20608传感器
    • 2.打开CubeMX进行USB配置
    • 3. 配置USB
      • 3.1 打开USB驱动
      • 3.2 声明USB
      • 3.3 剪切stm32xxxx_hal_msp.c中的void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd)和void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd)函数至board.c
      • 3.4 使能USB
    • 4. 编译,烧录


前言

本文采用开发板为STM32L475VET6(潘多拉开发板),使用RT_Thread Studio基于芯片开发模式,系统版本为4.0.3,完成模拟鼠标实验,实现鼠标功能,左键为KEY0,右键为KEY2


一、板载资源

icm20608传感器采用I2C协议,本文采用软件模拟I2C
查阅数据手册:开发板使用的是 PC0 模拟时钟线SCL、PC1 模拟数据线 SDA,
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、具体步骤

1.配置icm20608传感器

RT-Thread+STM32L475VET6——icm20608传感器

2.打开CubeMX进行USB配置

在这里插入图片描述
生成工程

3. 配置USB

按照官方步骤配置
在这里插入图片描述

3.1 打开USB驱动

在这里插入图片描述

3.2 声明USB

在这里插入图片描述

3.3 剪切stm32xxxx_hal_msp.c中的void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd)和void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd)函数至board.c

在这里插入图片描述

3.4 使能USB

一般默认开启
在这里插入图片描述

4. 编译,烧录

示例代码

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>#include "icm20608.h"
#include <math.h>#define DBG_SECTION_NAME "3D_mouse"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>#define PIN_KEY0 GET_PIN(D,10)
#define PIN_KEY2 GET_PIN(D,8)static rt_sem_t mouse_sem = RT_NULL;static struct rt_thread usb_thread;
ALIGN(RT_ALIGN_SIZE)
static char usb_thread_stack[0x1000];static struct rt_thread icm_thread;
ALIGN(RT_ALIGN_SIZE)
static char icm_thread_stack[0x1000];static struct rt_thread key_thread;
ALIGN(RT_ALIGN_SIZE)
static char key_thread_stack[0x1000];/* 变动识别值 */
const static float mouse_rang_scope = 6.0f;
/* 读取角度有效角度 */
const static float mouse_angle_range = 80.0f;
/* 移动值的最大值 */
const static float mouse_move_range = 127.0f;
/* 角度移动比 */
#define mouse_ratio (mouse_move_range / mouse_angle_range)
/* 移动步长 */
const static rt_uint8_t mouse_pixel_len = 5;
/* 鼠标响应时间 */
const static rt_uint32_t mouse_sample_times = 0;static float mouse_cmp_last_x, mouse_cmp_last_y;#define Gyro_Gr 0.0010653f
#define pi 3.141593f
#define Kp 10.0f
#define Ki 0.008f
#define halfT 0.01fstatic float q0 = 1, q1 = 0, q2 = 0, q3 = 0;
static float exInt = 0, eyInt = 0, ezInt = 0;struct icm_position
{icm20608_device_t icm20608_device;rt_mutex_t lock;float x;           // 传感器 x 位置float y;           // 传感器 y 位置float z;           // 传感器 z 位置rt_int8_t buff[4]; // 发送鼠标的值
};
typedef struct icm_position *icm_position_t;icm_position_t icm_device = RT_NULL;static void mouse_meas_check(float *temp)
{if (*temp > mouse_angle_range){*temp = mouse_angle_range;}else if (*temp < -mouse_angle_range){*temp = -mouse_angle_range;}
}#ifdef __GNUC__const float __atan2f_lut[4] = {-0.0443265554792128, //p7-0.3258083974640975, //p3+0.1555786518463281, //p5+0.9997878412794807  //p1
};
const float __atan2f_pi_2 = 1.5707963;/* 求平方根 */
static float _sqrt(float x)
{float xhalf = 0.5f * x;int i = *(int *)&x;i = 0x5f375a86 - (i >> 1);x = *(float *)&i;x = x * (1.5f - xhalf * x * x);return 1.0 / x;
}/* 求绝对值 */
static float _fabs(float x)
{return (x >= 0 ? x : (-x));
}/* 求x / y的反正切值 */
static float _atan2f(float y, float x)
{float a, b, c, r, xx;int m;union {float f;int i;} xinv;xx = _fabs(x);xinv.f = xx;m = 0x3F800000 - (xinv.i & 0x7F800000);xinv.i = xinv.i + m;xinv.f = 1.41176471f - 0.47058824f * xinv.f;xinv.i = xinv.i + m;b = 2.0 - xinv.f * xx;xinv.f = xinv.f * b;b = 2.0 - xinv.f * xx;xinv.f = xinv.f * b;c = _fabs(y * xinv.f);xinv.f = c;m = 0x3F800000 - (xinv.i & 0x7F800000);xinv.i = xinv.i + m;xinv.f = 1.41176471f - 0.47058824f * xinv.f;xinv.i = xinv.i + m;b = 2.0 - xinv.f * c;xinv.f = xinv.f * b;b = 2.0 - xinv.f * c;xinv.f = xinv.f * b;xinv.f = xinv.f + c;a = (c > 1.0f);c = c - a * xinv.f;r = a * __atan2f_pi_2;xx = c * c;a = (__atan2f_lut[0] * c) * xx + (__atan2f_lut[2] * c);b = (__atan2f_lut[1] * c) * xx + (__atan2f_lut[3] * c);xx = xx * xx;r = r + a * xx;r = r + b;b = M_PI;b = b - 2.0f * r;r = r + (x < 0.0f) * b;b = (_fabs(x) < 0.000001f);c = !b;r = c * r;r = r + __atan2f_pi_2 * b;b = r + r;r = r - (y < 0.0f) * b;return r;
}static double _asin(double x)
{return _atan2f(x, _sqrt(1.0 - x * x));
}
#endif /* __GNUC__ *//* 获取俯仰角、偏航角、翻滚角 */
static void get_angle(icm_position_t dev, float ax, float ay, float az, float gx, float gy, float gz)
{float pitch = 0, roll = 0, yaw = 0;float norm;float vx, vy, vz;float ex, ey, ez;float q0q0 = q0 * q0;float q0q1 = q0 * q1;float q0q2 = q0 * q2;float q1q1 = q1 * q1;float q1q3 = q1 * q3;float q2q2 = q2 * q2;float q2q3 = q2 * q3;float q3q3 = q3 * q3;gx *= Gyro_Gr;gy *= Gyro_Gr;gz *= Gyro_Gr;if (az == 0)return;#ifdef __GNUC__norm = _sqrt(ax * ax + ay * ay + az * az);
#elsenorm = sqrt(ax * ax + ay * ay + az * az);
#endif /* __GNUC__ */ax = ax / norm;ay = ay / norm;az = az / norm;vx = 2 * (q1q3 - q0q2);vy = 2 * (q0q1 + q2q3);vz = q0q0 - q1q1 - q2q2 + q3q3;ex = (ay * vz - az * vy);ey = (az * vx - ax * vz);ez = (ax * vy - ay * vx);exInt = exInt + ex * Ki;eyInt = eyInt + ey * Ki;ezInt = ezInt + ez * Ki;gx = gx + Kp * ex + exInt;gy = gy + Kp * ey + eyInt;gz = gz + Kp * ez + ezInt;q0 = q0 + (-q1 * gx - q2 * gy - q3 * gz) * halfT;q1 = q1 + (q0 * gx + q2 * gz - q3 * gy) * halfT;q2 = q2 + (q0 * gy - q1 * gz + q3 * gx) * halfT;q3 = q3 + (q0 * gz + q1 * gy - q2 * gx) * halfT;#ifdef __GNUC__norm = _sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
#elsenorm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
#endif /* __GNUC__ */q0 = q0 / norm;q1 = q1 / norm;q2 = q2 / norm;q3 = q3 / norm;#ifdef __GNUC__pitch = -_asin(2 * (q0 * q2 - q1 * q3)) * 57.2957795f;roll = _asin(2 * (q0 * q1 + q2 * q3)) * 57.2957795f;yaw = -_atan2f(2 * (q1 * q2 + q0 * q3), (q0q0 + q1q1 - q2q2 - q3q3)) * 57.29578f;
#elsepitch = -asin(2 * (q0 * q2 - q1 * q3)) * 57.2957795f;roll = asin(2 * (q0 * q1 + q2 * q3)) * 57.2957795f;yaw = -atan2f(2 * (q1 * q2 + q0 * q3), (q0q0 + q1q1 - q2q2 - q3q3)) * 57.29578f;
#endif /* __GNUC__ */mouse_meas_check(&pitch);dev->x = pitch * mouse_ratio;mouse_meas_check(&roll);dev->y = roll * mouse_ratio;mouse_meas_check(&yaw);dev->z = yaw * mouse_ratio;
}static void mouse_get_pos(icm_position_t dev)
{rt_err_t result;rt_int16_t accel_x, accel_y, accel_z;rt_int16_t gyros_x, gyros_y, gyros_z;RT_ASSERT(dev);result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);if (result != RT_EOK){goto __exit;}result = icm20608_get_accel(dev->icm20608_device, &accel_x, &accel_y, &accel_z);if (result != RT_EOK){rt_mutex_release(dev->lock);goto __exit;}result = icm20608_get_gyro(dev->icm20608_device, &gyros_x, &gyros_y, &gyros_z);if (result != RT_EOK){rt_mutex_release(dev->lock);goto __exit;}get_angle(dev, (float)accel_x, (float)accel_y, (float)accel_z, (float)gyros_x, (float)gyros_y, (float)gyros_z);rt_mutex_release(dev->lock);__exit:if (result != RT_EOK){LOG_E("The sensor does not work");return;}
}static icm_position_t mouse_init_icm(void)
{rt_err_t result;rt_thread_mdelay(1000);icm_device = rt_calloc(1, sizeof(struct icm_position));if (icm_device == RT_NULL){LOG_E("Can't allocate memory for three-dimensional mouse ");return RT_NULL;}/* 初始化传感器 icm20608 */icm_device->icm20608_device = icm20608_init("i2c3");if (icm_device->icm20608_device == RT_NULL){LOG_E("The sensor initializes failure");rt_free(icm_device);return RT_NULL;}else{LOG_D("The 3D mouse initializes success");}icm_device->lock = rt_mutex_create("mutex_mouse", RT_IPC_FLAG_FIFO);if (icm_device->lock == RT_NULL){LOG_E("Can't create mutex for three-dimensional mouse");rt_free(icm_device);return RT_NULL;}mouse_sem = rt_sem_create("mouse_sem", 0, RT_IPC_FLAG_FIFO);if (mouse_sem == RT_NULL){LOG_E("Can't create sem for mouse device");rt_mutex_delete(icm_device->lock);rt_free(icm_device);return 0;}/* 传感器零值校准 */result = icm20608_calib_level(icm_device->icm20608_device, 10);if (result != RT_EOK){LOG_E("The sensor calibrates failure");rt_mutex_delete(icm_device->lock);rt_sem_delete(mouse_sem);rt_free(icm_device);return RT_NULL;}return icm_device;
}static void mouse_go_release_status(void)
{/* 初始状态值 */rt_int8_t buff[4] = {0x08, 0, 0, 0};icm_device->buff[0] = buff[0];icm_device->buff[1] = buff[1];icm_device->buff[2] = buff[2];icm_device->buff[3] = buff[3];
}static void mouse_send_data(rt_device_t device)
{RT_ASSERT(device != RT_NULL);rt_device_write(device, HID_REPORT_ID_MOUSE, icm_device->buff, 4);mouse_go_release_status();
}/* 负值表示向左移动,正值表示向右移动 */
static void mouse_move_x(rt_device_t device, float ratio_x)
{RT_ASSERT(device != RT_NULL);if (icm_device->x < 0){icm_device->buff[1] = (rt_int8_t)(-mouse_pixel_len * ratio_x);}else{icm_device->buff[1] = (rt_int8_t)(mouse_pixel_len * ratio_x);}mouse_send_data(device);
}/* 正值表示向下移动,负值表示向上移动 */
static void mouse_move_y(rt_device_t device, float ratio_y)
{RT_ASSERT(device != RT_NULL);if (icm_device->y < 0){icm_device->buff[2] = (rt_int8_t)(-mouse_pixel_len * ratio_y);}else{icm_device->buff[2] = (rt_int8_t)(mouse_pixel_len * ratio_y);}mouse_send_data(device);
}static void mouse_move_xy(rt_device_t device, float ratio_x, float ratio_y)
{RT_ASSERT(device != RT_NULL);if (icm_device->x < 0){icm_device->buff[1] = (rt_int8_t)(-mouse_pixel_len * ratio_x);}else{icm_device->buff[1] = (rt_int8_t)(mouse_pixel_len * ratio_x);}if (icm_device->y < 0){icm_device->buff[2] = (rt_int8_t)(-mouse_pixel_len * ratio_y);}else{icm_device->buff[2] = (rt_int8_t)(mouse_pixel_len * ratio_y);}mouse_send_data(device);
}static void usb_thread_entry(void *parameter)
{rt_device_t device = (rt_device_t)parameter;rt_uint8_t i = 0;while (1){if (rt_sem_take(mouse_sem, RT_WAITING_FOREVER) == RT_EOK){rt_uint8_t temp_x = 0, temp_y = 0, move_max = 0;float move_distance = 0.0f;rt_mutex_take(icm_device->lock, RT_WAITING_FOREVER);#ifdef __GNUC__temp_x = (rt_uint8_t)_fabs(icm_device->x);temp_y = (rt_uint8_t)_fabs(icm_device->y);move_distance = _sqrt(temp_x * temp_x + temp_y * temp_y);
#elsetemp_x = (rt_uint8_t)fabs(icm_device->x);temp_y = (rt_uint8_t)fabs(icm_device->y);move_distance = sqrt(temp_x * temp_x + temp_y * temp_y);
#endifmove_max = temp_x > temp_y ? temp_x : temp_y;/* 根据倾斜程度获取移动值 */for (i = 0; i < move_max / mouse_pixel_len; i++){LOG_D("move_max :%4d, x: %4d, y :%4d ", move_max, temp_x, temp_y);if (i < temp_x && i < temp_y){mouse_move_xy(device, temp_x / move_distance, temp_y / move_distance);}else if (i < temp_x && i >= temp_y){mouse_move_x(device, temp_x / move_distance);}else if (i >= temp_x && i < temp_y){mouse_move_y(device, temp_y / move_distance);}else{break;}}rt_mutex_release(icm_device->lock);}rt_thread_mdelay(mouse_sample_times);}
}static void icm_thread_entry(void *parameter)
{while (1){float temp_x = 0.0, temp_y = 0.0;rt_mutex_take(icm_device->lock, RT_WAITING_FOREVER);/* 获取鼠标移动范围 */mouse_get_pos(icm_device);/* 获取差值 */temp_x = icm_device->x - mouse_cmp_last_x;temp_y = icm_device->y - mouse_cmp_last_y;/* 避免抖动 */if (temp_x > mouse_rang_scope || temp_x < -mouse_rang_scope || temp_y > mouse_rang_scope || temp_y < -mouse_rang_scope){/* 存储这次鼠标位移值 */mouse_cmp_last_x = icm_device->x;mouse_cmp_last_y = icm_device->y;rt_sem_release(mouse_sem);}rt_mutex_release(icm_device->lock);rt_thread_mdelay(mouse_sample_times);}
}static void key_thread_entry(void *parameter)
{int mouse_key_2, mouse_key_0;rt_device_t device = (rt_device_t)parameter;rt_err_t result = -RT_ERROR;while (1){if (rt_pin_read(PIN_KEY0) == PIN_LOW){mouse_key_0 = 1;}else if (rt_pin_read(PIN_KEY2) == PIN_LOW){mouse_key_2 = 1;}else{mouse_key_2 = 0;mouse_key_0 = 0;}if (mouse_key_2 | mouse_key_0){result = rt_mutex_take(icm_device->lock, RT_WAITING_FOREVER);if (result == RT_EOK){/* 获取鼠标键值,默认为 0 */icm_device->buff[0] = 0x08 | mouse_key_2 | mouse_key_0 << 1;if (mouse_key_2 & mouse_key_0){LOG_D("left & right down");}else if (mouse_key_2){LOG_D("left down");}else if (mouse_key_0){LOG_D("right down");}mouse_send_data(device);rt_mutex_release(icm_device->lock);rt_thread_mdelay(50);}}rt_thread_mdelay(mouse_sample_times / 5);}
}static void mouse_init_key(void)
{/* 鼠标左键 */rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT);/* 鼠标右键 */rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT);
}int main(void)
{return 0;
}static int application_usb_init(void)
{/* 查找名称为 hidd 的设备 */rt_device_t device = rt_device_find("hidd");/* 初始化六轴传感器设备 */icm_device = mouse_init_icm();/* 初始化按键 */mouse_init_key();RT_ASSERT(device != RT_NULL);RT_ASSERT(icm_device != RT_NULL);/*打开查找到的 hid 设备 */rt_device_open(device, RT_DEVICE_FLAG_WRONLY);/* 初始化 USB 线程*/rt_thread_init(&usb_thread,"hidd",usb_thread_entry, device,usb_thread_stack, sizeof(usb_thread_stack),10, 20);rt_thread_startup(&usb_thread);/* 初始化六轴传感器线程 */rt_thread_init(&icm_thread,"icm20608",icm_thread_entry, RT_NULL,icm_thread_stack, sizeof(icm_thread_stack),10, 20);rt_thread_startup(&icm_thread);/* 初始化按键线程 */rt_thread_init(&key_thread,"key",key_thread_entry, device,key_thread_stack, sizeof(key_thread_stack),10, 20);rt_thread_startup(&key_thread);return 0;
}
INIT_APP_EXPORT(application_usb_init);

烧录完成后,将开发板上的USB OTG 连接PC端的USB接口,即可实现鼠标功能。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/23072.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 中单向数据流原则

做一个 ElementUI 弹框组件的二次封装 效果如下: 点击取消按钮发现弹出如下报错信息 : [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the …

前后端分离系统架构:基于Spring Boot的最佳实践

前后端分离系统架构图描绘了一个基于Springboot的前端后台分离的系统架构。它强调了前端&#xff08;客户端&#xff09;与远程&#xff08;服务器&#xff09;的解耦&#xff0c;通过API接口进行交互&#xff0c;分别独立开发和部署。 前后端分离系统架构图 从上到下&#xff…

Neo4j使用neo4j-admin导入csv数据方法

在neo4j desktop里创建project&#xff0c;创建dbms&#xff0c;创建database。 将csv文件放入如下import路径中&#xff0c;然后就可以使用相对路径来使用csv了。 在neo4j desktop中打开Terminal 键入导入数据语句&#xff1a; neo4j-admin database import full --nodes&qu…

【Transformer架构】

目录 一、Transformer介绍 1.1 Transformer的诞生 1.2 什么是Transformer 1.3 Transformer的优势 1.4 Transformer的市场 二、Transformer架构 2.1 Transformer模型的作用 2.2 Transformer总体架构图 2.2.1 Transformer总体架构 2.2.2 输入部分 2.2.3 输出部分 2.2.…

设计模式-组合模式、模板模式

组合模式 定义 将对象组合成树形结构以表示"部分-整体"的层次结构&#xff0c;组合模式使得用户对单个对象和组合对象的使用具有一致性&#xff1b; 组合模式实现的最关键的地方是-简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进…

Spring Boot 概要(官网文档解读)

Spring Boot 概述 Spring Boot 是一个高效构建 Spring 生产级应用的脚手架工具&#xff0c;它简化了基于 Spring 框架的开发过程。 Spring Boot 也是一个“构件组装门户”&#xff0c;何为构件组装门户呢&#xff1f;所谓的“构件组装门户”指的是一个对外提供的Web平台&#x…

SkyWalking集成Kafka实现日志异步采集经验总结

SkyWalking日志异步采集架构 【重点知识】 1、【Agent】kafka-reporter-plugin-x.x.x.jar包放plugins目录后必走kafka&#xff08;kafka没有正确配置就会报错&#xff09; 2、【Agent】异步如不开启数据压缩&#xff0c;日志数据较大&#xff0c;pod多、业务大时容易造成网络…

2025前端框架最新组件解析与实战技巧:Vue与React的革新之路

作者&#xff1a;飞天大河豚 引言 2025年的前端开发领域&#xff0c;Vue与React依然是开发者最青睐的框架。随着Vue 3的全面普及和React 18的持续优化&#xff0c;两大框架在组件化开发、性能优化、工程化支持等方面均有显著突破。本文将从最新组件特性、使用场景和编码技巧三…

Orange 单体架构 - 快速启动

1 后端服务 1.1 基础设施 组件说明版本MySQLMySQL数据库服务5.7/8JavaJava17redis-stackRedis向量数据库最新版本Node安装Node22.11.0 1.2 orange-dependencies-parent 项目Maven依赖版本管理 1.2.1 项目克隆 GitHub git clone https://github.com/hengzq/orange-depende…

Layer2 扩容解决方案详解

Layer2 扩容解决方案详解 &#x1f504; 1. Layer2 基础概念 1.1 什么是 Layer2&#xff1f; Layer2 是建立在以太坊主网&#xff08;Layer1&#xff09;之上的扩容解决方案&#xff0c;它&#xff1a; 继承以太坊的安全性提供更高的交易吞吐量降低交易费用保持去中心化特性…

小智机器人CMakeLists编译文件解析

编译完成后&#xff0c;成功烧录&#xff01; 这段代码是一个CMake脚本&#xff0c;用于配置和构建一个嵌入式项目&#xff0c;特别是针对ESP32系列芯片的项目。CMake是一个跨平台的构建系统&#xff0c;用于管理项目的编译过程。 set(SOURCES "audio_codecs/audio_code…

银河麒麟系统安装mysql5.7【亲测可行】

一、安装环境 cpu&#xff1a;I5-10代&#xff1b; 主板&#xff1a;华硕&#xff1b; OS&#xff1a;银河麒麟V10&#xff08;SP1&#xff09;未激活 架构&#xff1a;Linux 5.10.0-9-generic x86_64 GNU/Linux mysql版本&#xff1a;mysql-5.7.34-linux-glibc2.12-x86_64.ta…

【Linux】动静态库

目录 站在库提供者的角度 静态库 制作静态库 静态库的内容 发布静态库 用户使用静态库 找头文件 找库文件 动态库 制作动态库 动态库报错 动态库是怎么被加载的&#xff1f; 地址相关问题 程序加载前的地址 程序加载后的地址 如何执行第一条指令&#xff1f; …

500字理透react的hook闭包问题

在react中hook的闭包问题很容易在不经意间犯错&#xff0c;项目写大了之后更是难以找到到底是哪里出了问题。 为什么会出现闭包问题 出现闭包问题的原因就是函数中操作的变量不是最新的变量&#xff0c;什么意思呢&#xff0c;我们知道函数组件每次刷新都是重新运行一次函数&…

Unity Shader Graph 2D - 一个简单的魔法阵激活效果

前言 在魔幻类游戏里通常会有魔法阵的存在,而当某个机关被触发或者某个剧情被触发时,需要对魔法阵进行激活,这个时候就需要一个魔法阵的激活效果来让这个游戏的这一时刻的交互性更强,生动性更强,本文将用一种十分简单的方式来实现一个魔法阵的激活效果。 创建一个…

C++ 类和对象(友元、内部类、匿名对像)

目录 一、前言 二、正文 1.友元 1.1友元函数的使用 1.1.1外部友元函数可访问类的私有成员&#xff0c;友员函数仅仅是一种声明&#xff0c;他不是类的成员函数。 1.1.2一个函数可以是多个类的友元函数 2.友元类的使用 2.1什么是友元类 2.2 友元类的关系是单向的&#x…

Docker Network

1.简介 容器之间的通讯时通过网桥通讯的&#xff0c;跨主机通讯可以使用flannel进行通讯 那么为什么主机可以访问到虚拟机内部呢&#xff1f;因为VMware虚拟出一个虚拟的网卡&#xff0c;而这个虚拟网卡和主机在同一个局域网下 NAT是映射一个虚拟网卡&#xff0c;进行路由通信…

【Linux系统】—— 冯诺依曼体系结构与操作系统初理解

【Linux系统】—— 冯诺依曼体系结构与操作系统初理解 1 冯诺依曼体系结构1.1 基本概念理解1.2 CPU只和内存打交道1.3 为什么冯诺依曼是这种结构1.4 理解数据流动 2 操作系统2.1 什么是操作系统2.2 设计OS的目的2.3 操作系统小知识点2.4 如何理解"管理"2.5 系统调用和…

【行业解决方案篇十八】【DeepSeek航空航天:故障诊断专家系统 】

引言:为什么说这是“航天故障终结者”? 2025年春节刚过,航天宏图突然官宣"DeepSeek已在天权智能体上线",这个搭载在卫星和空间站上的神秘系统,号称能提前48小时预判99.97%的航天器故障。这不禁让人想起年初NASA禁用DeepSeek引发的轩然大波,更让人好奇:这套系…

计算机网络真题练习(高软29)

系列文章目录 计算机网络阶段练习 文章目录 系列文章目录前言一、真题练习总结 前言 计算机网络的阶段练习题&#xff0c;带解析答案。 一、真题练习 总结 就是高软笔记&#xff0c;大佬请略过&#xff01;