Day1--FreeRTOS简介及多任务点灯、多任务传参、Mutex

2023-05-16

实时操作系统(Real Time Operating System,简称RTOS)

Arduino任务执行流程:单线程执行任务

 RTOS:可以同时执行所有Task,每个任务都有自己的循环

 操作系统排行:LINUX        WINDOWS        FREERTOS

ESP32架构:ESP32-IDF的底层运行的就是freestos

默认core1:编写程序        core2:蓝牙、wifi功能

任务优先级:

优先级高的任务先执行,比如中断

实时性要求比较高的任务用高优先级

实时性要求比较低的任务用低优先级,比如屏幕刷新,数据显示

多任务其实是CPU分时完成的,1ms执行一个任务,频率1Khz

freertos传递参数只能采用指针的方式,重点:结构体和指针

内存管理:任务到底需要多少内存?分配空间大小1024*N

任务优先级:

任务的绝对频率:vTaskDelayUntil

软件定时器Timer:一次性的,周期性的,非常有用

freertos提供的三种数据结构:队列单数据、流媒体缓存、消息缓存

多任务全局变量:对资源进行保护

二进制信号量:0和1

计数信号量:0~N

事件组等待:

事件组同步:

任务通知

多任务点灯

1GB(GigaByte)=1024MB

1MB(MegaByte)=1024KB

1KB(KiloByte)=1024B(字节)

1B(byte)字节=8Bit(binary digit)位

#include <Arduino.h>

void task1(void *pt)
{
  pinMode(23, OUTPUT);
  while (1)
  {
    digitalWrite(23, !digitalRead(23));
    vTaskDelay(500);
  }
}

void task2(void *pt)
{
  pinMode(21, OUTPUT);
  while (1)
  {
    digitalWrite(21, !digitalRead(21));
    vTaskDelay(700);
  }
}

void setup()
{
  // 参数1:task;  参数2:任务备注;  参数3:内存分配空间
  // 参数4:传递参数;  参数5:任务优先级; 参数6:对任务删除管理
  xTaskCreate(task1, "Blink 23", 1024, NULL, 1, NULL);
  xTaskCreate(task2, "Blink 21", 1024, NULL, 1, NULL);
}

void loop()
{
}

 通过空指针类型给task传递单个参数

#include <Arduino.h>

byte led1 = 21;
byte led2 = 22;
byte led3 = 23;

void task1(void *pt) // 接收的为空指针
{
  byte led_pin = *(byte *)pt; // 解耦
  pinMode(led_pin, OUTPUT);
  while (1)
  {
    digitalWrite(led_pin, !digitalRead(led_pin));
    vTaskDelay(500);
  }
}

void setup()
{
  // 参数1:task;  参数2:任务备注;  参数3:内存分配空间
  // 参数4:传递参数;  参数5:任务优先级; 参数6:对任务删除管理
  xTaskCreate(task1, "Blink 21", 1024, (void *)&led1, 1, NULL);
}

void loop()
{
}

给任务传递多个参数(重要)

通过空指针类型传递结构体

/*向任务中进行传多个参数*/
#include <Arduino.h>

typedef struct
{
  byte pin;
  int delayTime;
} LEDFLASH;
LEDFLASH led1, led2;

void ledFlash(void *pt)
{
  LEDFLASH *ptLedFlash = (LEDFLASH *)pt; // 数据解耦
  byte pin = ptLedFlash->pin;
  int delayTime = ptLedFlash->delayTime;

  pinMode(pin, OUTPUT);
  while (1)
  {
    digitalWrite(pin, !digitalRead(pin));
    vTaskDelay(delayTime);
  }
}

void setup()
{
  /*局部变量,结构体赋值一定要在setup里面,在外面会出错
  在外边,需要写成全局变量的形式*/
  led1.pin = 23;
  led1.delayTime = 1000;
  led2.pin = 21;
  led2.delayTime = 3000;

  xTaskCreate(ledFlash, "***", 1024, (void *)&led1, 1, NULL);
  xTaskCreate(ledFlash, "***", 1024, (void *)&led2, 1, NULL);
}
void loop() {}

可以通过void *pt空指针的方式传递单个参数,可以通过void *struct传递多个参数 

通过结构体传址的方式进行数据传输

任务共享全局变量(重要)

任务1:对商品的数量进行计算

任务2:显示商品的数量

重点:写操作只能有一个,读操作可以有多个

/*任务之间通过全局变量进行数据传递*/
#include <Arduino.h>

/*养成良好习惯,被多进程和中断调用的变量使用 volatile修饰符*/
/*ESP32是32位的,一定要定义为uint32_t,因为同一个变量占用CPU同一个通道
*/
volatile u_int32_t inventory = 100; // 总库存
volatile u_int32_t retailCount = 0; // 线下销售量

/*任务1:库存数量变化计算*/
void retailTask(void *pt)
{
  while (1)
  {
    /*以下实现了带有随机延迟的库存减1
    等效为 inventory--; retailCount++;*/
    u_int32_t inv = inventory;
    for (byte i; i < random(10, 100); i++)
    {
      vTaskDelay(i);
    }
    if (inventory > 0)
    {
      inventory = inv - 1;
      retailCount++;
    }
  };
  vTaskDelay(10);
}

/*任务2:显示库存和线下销售量*/
void showTask(void *pt)
{
  while (1)
  {
    printf("Inventory : %d\n", inventory);
    printf("   Retail :%d\n", retailCount);
    if (inventory == 0)
    {
      printf("\n------sales summary-------\n");
      printf("totail sales: %d\n\n", retailCount);
    }
    vTaskDelay(1000);
  }
}

void setup()
{
  Serial.begin(115200);
  xTaskCreate(retailTask, "库存数量变化", 1024 * 4, NULL, 1, NULL);
  xTaskCreate(showTask, "数量显示", 1024 * 4, NULL, 1, NULL);
}
void loop() {}

使用相互排斥 Mutex 来解决竞争冒险Race Condition(重要)

注意:在对全局变量数据进行访问时,使用Mutex,不能在程序一开始就获取钥匙,在if里对共享资源计算完就立刻释放钥匙,不要把释放钥匙语句放到任务最后

在上面一个示例中,数据计算时容易出现竞争冒险的问题,采用Mutex对数据进行保护,解决多个任务同时对共享资源访问造成的问题

Mutex互斥锁,先把共享资源放进保险柜里(只有一把钥匙),任务(例如task1)先申请钥匙,再对共享资源进行访问,Task2如果想要访问共享资源,需要等到task1归还钥匙

使用步骤:

  1. 创建一把锁, create
  2. 在指定时间内获取钥匙, take
  3. 归还钥匙,give

  语法:

  SemaphoreHandle_t xHandler; 创建Handler

  xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler

  xSemaphoreGive(xHandler); 释放

  xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

  理解方法:

  MUTEX的工作原理可以想象成

  共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问

/*
  程序: Tasks之间数据传递
        有多任务同时写入,或者数据大小超过cpu内存通道时,或者对共享资源的访问时候,需要有防范机制
        使用MUTEX对数据对Cirtical Section的内容进行保护
        可以想象成MUTEX就是一把锁

  公众号:孤独的二进制

  语法:
  SemaphoreHandle_t xHandler; 创建Handler
  xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler
  xSemaphoreGive(xHandler); 释放
  xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

  理解方法:
  MUTEX的工作原理可以想象成
  共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问
*/

// 养成良好习惯,被多进程和中断调用的变量使用 volatile 修饰符
volatile uint32_t inventory = 100; //总库存
volatile uint32_t retailCount = 0; //线下销售量
volatile uint32_t onlineCount = 0; //线上销售量

SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handler

TickType_t timeOut = 1000; //用于获取信号量的Timeout 1000 ticks


void retailTask(void *pvParam) {
  while (1) {

    // 在timeout的时间内如果能够获取就继续
    // 通俗一些:获取钥匙
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      //被MUTEX保护的内容叫做 Critical Section


      //以下实现了带有随机延迟的 inventory减1;
      //等效为 inventory--; retailCount++;
      uint32_t inv = inventory;
      for (int i; i < random(10, 100); i++) vTaskDelay(pdMS_TO_TICKS(i));
      if (inventory > 0) {
        inventory = inv - 1;
        retailCount++;

        //释放钥匙
        xSemaphoreGive(xMutexInventory);
      } else {
        //无法获取钥匙
      }


    };

    vTaskDelay(100); //老板要求慢一些,客户升级后,可以再加快速度
  }
}

void onlineTask(void *pvParam) {
  while (1) {

    // 在timeout的时间内如果能够获取二进制信号量就继续
    // 通俗一些:获取钥匙
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      //被MUTEX保护的内容叫做 Critical Section
      //以下实现了带有随机延迟的 inventory减1;
      //等效为 inventory--; retailCount++;
      uint32_t inv = inventory;
      for (int i; i < random(10, 100); i++) vTaskDelay(pdMS_TO_TICKS(i));
      if (inventory > 0) {
        inventory = inv - 1;
        onlineCount++;

        //释放钥匙
        xSemaphoreGive(xMutexInventory);
      } else {
        //无法获取钥匙
      }
    };

    vTaskDelay(100); //老板要求慢一些,客户升级后,可以再加快速度
  }
}


void showTask(void *pvParam) {
  while (1) {

    printf("Inventory : %d\n", inventory);
    printf("  Retail : %d, Online : %d\n", retailCount, onlineCount);


    if (inventory == 0 ) {
      uint32_t totalSales = retailCount + onlineCount;
      printf("-----SALES SUMMARY-----\n");
      printf("  Total Sales:  %d\n", totalSales);
      printf("  OverSales:  %d\n", 100 - totalSales);
    }
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  xMutexInventory = xSemaphoreCreateMutex(); //创建MUTEX

  if (xMutexInventory == NULL) {
    printf("No Enough Ram, Unable to Create Semaphore.");
  } else {
    xTaskCreate(onlineTask,
                "Online Channel",
                1024 * 4,
                NULL,
                1,
                NULL);
    xTaskCreate(retailTask,
                "Retail Channel",
                1024 * 4,
                NULL,
                1,
                NULL);
    xTaskCreate(showTask,
                "Display Inventory",
                1024 * 4,
                NULL,
                1,
                NULL);
  }

}

void loop() {
}

 MUTEX实例

使用MPU6050传感器时,可以创建一个结构体存储7个数据(芯片温度、3轴角速度、3轴角度)

MPU6050的数据写进结构体中,然后屏幕进行读取

两个任务,一个读,一个写,一定要用MUTEX进行数据保护

原因:不管是读操作还是写操作,它都是一个独立的task,这样用freertos运行多任务就会出现某个任务因为分配的时间到了,对数据的处理被迫中断,然后另一个任务又开始对数据进行操作,而这时的数据很可能只有一半是操作完成,另一半还未完成的状态,这样的数据状态会产生很大的运算错误,非常危险。所以一个参数只要有两个或以上task要对其进行操作,就必须上钥匙

/*
   程序:  MPU6050 & MUTEX
   公众号:孤独的二进制
*/
#include <Arduino.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

Adafruit_MPU6050 mpu;
Adafruit_Sensor *mpu_temp, *mpu_accel, *mpu_gyro;

typedef struct
{
  float temp;
  float accX;
  float accY;
  float accZ;
  float gyroX;
  float gyroY;
  float gyroZ;
} MPU6050;

MPU6050 mpu6050;

SemaphoreHandle_t xMutexMPU6050 = NULL; //创建信号量Handler
TickType_t timeOut = 1000;              //用于获取信号量的Timeout 1000 ticks

void mpu6050Task(void *pvParam)
{

  mpu.begin();

  mpu_temp = mpu.getTemperatureSensor();
  mpu_temp->printSensorDetails();

  mpu_accel = mpu.getAccelerometerSensor();
  mpu_accel->printSensorDetails();

  mpu_gyro = mpu.getGyroSensor();
  mpu_gyro->printSensorDetails();

  sensors_event_t accel;
  sensors_event_t gyro;
  sensors_event_t temp;

  while (1)
  {

    if (xSemaphoreTake(xMutexMPU6050, timeOut) == pdPASS)
    {

      //获取MPU数据
      mpu_temp->getEvent(&temp);
      mpu_accel->getEvent(&accel);
      mpu_gyro->getEvent(&gyro);

      mpu6050.temp = temp.temperature;
      mpu6050.accX = accel.acceleration.x;
      mpu6050.accY = accel.acceleration.y;
      mpu6050.accZ = accel.acceleration.z;
      mpu6050.gyroX = gyro.gyro.x;
      mpu6050.gyroY = gyro.gyro.y;
      mpu6050.gyroZ = gyro.gyro.z;

      xSemaphoreGive(xMutexMPU6050); //释放钥匙
    }
    else
    {
      // Unable to obtain MUTEX
    }

    vTaskDelay(500);
  }
}

void lcdTask(void *ptParam)
{ // LCD任务主体

  lcd.init();
  lcd.backlight();

  //定义是 2004 LCD
  byte lcdLine = 4;
  byte lcdChar = 20;

  //创建一个二维的的数组
  //注意长度是 lcdChar+1 最后还有一个位置要给换行符
  char line0[lcdChar + 1], line1[lcdChar + 1], line2[lcdChar + 1], line3[lcdChar + 1];
  char *line[] = {
      line0,
      line1,
      line2,
      line3,
  };

  while (1)
  {

    if (xSemaphoreTake(xMutexMPU6050, timeOut) == pdPASS)
    {

      // 组合数据
      sprintf(line0, "     MPU6050 %d", xTaskGetTickCount() / 100);
      sprintf(line1, " Temperature  %.2f", mpu6050.temp);
      sprintf(line2, " ACC  %.2f %.2f %.2f", mpu6050.accX, mpu6050.accY, mpu6050.accZ);
      sprintf(line3, " GYRO %.2f %.2f %.2f", mpu6050.gyroX, mpu6050.gyroY, mpu6050.gyroZ);

      xSemaphoreGive(xMutexMPU6050); //释放钥匙
    }
    else
    {
      // Unable to obtain MUTEX
    }

    // 显示数据
    for (int i = 0; i < 4; i++)
    {
      lcd.setCursor(0, i);
      lcd.print(line[i]);
    }

    vTaskDelay(1000);
  }
}

void setup()
{
  Serial.begin(115200);

  xMutexMPU6050 = xSemaphoreCreateMutex(); //创建MUTEX

  xTaskCreate(mpu6050Task, "MPU6050", 1024 * 8, NULL, 1, NULL);
  vTaskDelay(1000); //让MPU6050提前先运行一秒获取第一笔数据
  xTaskCreate(lcdTask, "lcd", 1024 * 8, NULL, 1, NULL);
}

void loop() {}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Day1--FreeRTOS简介及多任务点灯、多任务传参、Mutex 的相关文章

  • 注册中心Nacos

    注册中心 nacosNacos注册中心与配置中心nocos优点与缺点启动docker镜像测试linux windows下单机启动应用启动个报错nacos如何修改用户名密码 nacos Nacos注册中心与配置中心 nacos官方文档 Nac
  • git常见问题

    git常见错误 1 在git pull时遇到fatal refusing to merge unrelated histories错误 意思是 xff1a 拒绝合并不相关的分支 表示要合并的本地分支和远程分支是相互独立而不是相关联的 我的情
  • PID 控制器

    本文参考 xff1a 从不懂到会用 xff01 PID从理论到实践 哔哩哔哩 bilibili 目录 1 PID控制器入门 1 1 PID控制器的引入 1 2 PID控制器适用系统 1 3 PID控制器宏观意义 2 PID控制器的必备知识
  • Linux - 第11节 - 网络入门

    目录 1 计算机网络背景 1 1 网络发展 1 2 认识 34 协议 34 2 网络协议初识 2 1 协议分层 2 2 OSI七层模型 2 3 TCP IP五层 xff08 或四层 xff09 模型 3 网络传输基本流程 3 1 同局域网的
  • 【经典问题:汉诺塔】C语言编写程序实现汉诺塔问题——函数递归

    汉诺塔 xff08 Tower of Hanoi xff09 xff0c 又称河内塔 xff0c 是一个源于印度古老传说的益智玩具 大梵天创造世界的时候做了三根金刚石柱子 xff0c 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘 大梵
  • 1.语音增强技术概述

    一 语音增强发展历史 1987年 xff1a Lim和Oppenheim发表语音增强的维纳滤波方法 xff1b 1987年 xff1a Boll发表谱减法 xff1b 1980年 xff1a Maulay和Malpass提出软判决噪声一直方
  • PCB软件对比分析(AD、Pads、Allegro)

    文章目录 前言一 国内的EDA软件市场二 Altium三 Mentor四 Candence总结 前言 今天来说一说国内用的最多的三款PCB软件对比 一 国内的EDA软件市场 国内的EDA软件几乎被三家瓜分 1 Altium 2 Canden
  • (二)立创EDA之新建工程,原理图,PCB

    文章目录 前言一 界面介绍二 工程广场介绍三 新建工程3 1 修改图纸属性 四 基本的操作介绍4 1 添加器件4 2 连接导线4 3 添加插针4 4 查看封装4 5 修改封装 五 原理图转PCB5 1设置PCB高亮显示元器件5 2 布局传递
  • stm32mp157 wm8960音频驱动调试笔记

    这次调试wm8960音频驱动遇到了好多的坑 xff0c 研究好几天终于调试好了 驱动调试步骤 驱动能不能成功加载是调试的第一大步骤 xff0c 也是最关键的步骤之一 1 查看硬件原理图 2 打开对应的设备树 xff08 stm32mp157
  • ROS发布者(Publisher)和订阅者(Subscriber)的python编程实现(讲解超级详细)

    有时候想想 xff0c 国内有些资源确实比较稀缺 xff0c 但是我们一样不会落后 xff01 学习python和ROS这么久了 xff0c 一直很少去实战 xff0c 另外看到基于python编程的ROS话题通信教程实在是稀缺了 xff0
  • C#工控上位机——框架

    C 工控上位机 第一部分 xff1a UI模块 先点击一下Panel xff0c 在点击一下屏幕 先选中Panel xff0c 在进行属性设置 图标连接 嵌入式窗体 设置按键的事件 using
  • docker镜像启动es/kibana

    下载镜像elasticsearch docker search elasticsearch docker pull elasticsearch 启动镜像 docker run name my elasticsearch p 9200 920
  • 虚拟串口的使用

    虚拟串口的使用
  • 修改闭包内使用的外部变量

    修改闭包内使用的外部变量的错误示例 定义一个外部函数 def func out num1 定义一个内部函数 def func inner num2 这里本意想要修改外部num1的值 xff0c 实际上是在内部函数定义了一个局部变量num1
  • 嵌入式软件面试题

    CSDN的小伙伴们 xff0c 我是林君 今天给小伙伴们分享一些嵌入式软件开发工程师的校招面试题 企业校招对基础考察较多 其次 xff0c 在校参加的相关比赛 xff0c 项目经历 我在生病前 xff0c 面试了一周 xff0c 收到八九个
  • 嵌入式软件工程师技术等级

    1 初级 xff1a 8051或其他单片机 xff0c UCOS xff0c I C xff0c SPI xff0c UART 汇编和C语言能力一般 xff0c 系统集成能力弱 2 中级 xff1a 在初级的基础上 xff0c ARM MI
  • FreeRTOS之动态方法任务创建和删除实验

    一 实验设计 start task xff1a 用来创建其他两个任务 task1 task 当此任务运行5次就调用vTaskDelete 删除任务task2 task task2 task 此任务为普通的应用任务 一 宏定义 任务优先级 d
  • 人工智能研究主要有哪三大学派,其特点是什么?

    人工智能研究主要有哪三大学派 xff0c 其特点是什么 xff1f xff08 1 xff09 符号主义 xff1a 又称为功能模拟学派 xff0c 主要观点认为智能活动的基础是物理符号系统 xff0c 思维过程是符号模式的处理过程 其特点
  • FreeRTOS入门

    目录 一 任务要求二 FreeRTOS移植1 简介2 参考教程3 多任务程序管理实现4 执行结果 三 总结 一 任务要求 在STM32下完成一个基于FreeRTOS的多任务程序 xff0c 执行3个周期性task xff0c 具体任务不限
  • 2021年全国大学生电子设计大赛F题——智能送药小车,全方位解决方案+程序代码(详细注释)山东赛区国奖

    目录 1 赛题及硬件方案分析 xff1a 2 用到的主要器件清单 xff1a 3 各部分思路及代码实现 1 小车舵机 马达驱动 2 蓝牙通信 3 单片机与OpenMV的串口通信 4 单片机与OpenMV的通信协议 5 单片机main文件中的

随机推荐

  • C++学习小记之代码重用问题(1)

    C 43 43 Primer Plus第六版第14章程序清单14 2给的示例代码中有以下两段代码 xff1a double amp Student operator int i return scores i double Student
  • 出现“ ‘xxx‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。”的一个解决方法

    XXX 不是内部或外部命令 xff0c 也不是可运行的程序或批处理文件 前提是已经安装成功某一个插件 有时候 xff0c 我们想用cmd xff08 以管理员身份运行 xff09 执行命令的时候 xff0c 总会出现 XXX 不是内部或外部
  • RK算法分析

    这一节介绍一下由Rabin和Karp提出的RK算法 1 xff0c RK算法的基本思想 HASH xff01 如果两个字符串hash后的值不相同 xff0c 则它们肯定不相同 xff1b 如果它们hash后的值相同 xff0c 它们不一定相
  • Xilinx ZYNQ FreeRTOS+Tracealyzer(移植)

    PL端配置 使用ZYNQ IP Core 打开串口 网口等所需接口 新手注意 xff1a 需要生成bit文件后 xff0c 并输出相应硬件平台 xff0c 网上教程很多 xff0c 请参考其它教程 PS端配置 1 创建任务 xff0c 注意
  • Openmv学习day2——AprilTag

    仅作为个人学习 xff0c 原文地址 xff1a 链接 link AprilTag的简介 AprilTag是一个视觉基准系统 xff0c 可用于各种任务 xff0c 包括AR xff0c 机器人和相机校准 这个tag可以直接用打印机打印出来
  • JS进行简单的表单验证(附详细代码)

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 一 JS表单验证是什么 xff1f 一 JS表单验证需求分析 xff1f 三 表单验证所需事件设置from表单及其文本框 xff
  • FreeRTOS学习(三)FreeRTOS任务基础知识

    FreeRTOS任务基础知识 1 FreeRTOS任务特性2 FreeRTOS的任务状态3 任务优先级4 任务调度方式5 任务控制块6 任务堆栈 1 FreeRTOS任务特性 特性1 xff1a 任务数量没有限制 xff0c 想要创建多少个
  • 如何写串口通信

    1 初始化串口 void USART INIT void GPIO InitTypeDef GPIO InitStructure 使能USART1 RCC APB2PeriphClockCmd RCC APB2Periph USART1 E
  • 树莓派WiFi连接问题及网页打开问题的解决

    树莓派WiFi连接问题及网页打开问题的解决 一 问题描述 前一段时间在网上买了一个树莓派 4b计划做一个人脸识别的智能锁 xff0c 前一段时间整赶上期末考试 xff0c 挤时间做了做人脸识别以及人体红外感知模块 xff0c 大致能简单实现
  • windows双系统如何删除ubuntu系统并重装

    电脑装有windows和Ubuntu双系统 xff0c 当需要重装Ubuntu时 xff0c 需要先卸载掉已经安装的Ubuntu系统 博主电脑安装的是Windows10和Ubuntu20 04LTS 现在需要卸载Ubuntu20 04 xf
  • 全网最全的MCU面试经(基于STM32F103)

    免责声明 提示 xff1a 写本文章的缘由 xff1a 本人在秋招时复习STM32有关的知识点 xff0c 便顺势记录下来 本文章的知识均属于各大论坛的大佬回答 xff0c 其中也有我的一些补充 xff0c 本文主要以自己对STM32的理解
  • Quartus II和Modelsim初学踩坑笔记

    Quartus II和Modelsim初学踩坑笔记 1 软件安装 网上有关软件安装的教程已经足够多了 xff0c 这里不再赘述 xff0c 但我要提醒的一点是 xff0c 不要把软件和之后创建的项目工程放在中文路径下面 本文使用的软件环境是
  • HDLBits刷题记录--Modules:Hierarchy

    HDLBits刷题记录 Modules Hierarchy Module 电路图 xff1a 代码 xff1a module top module span class token punctuation span input a span
  • C++中SORT函数使用方法

    一 sort函数 1 sort函数包含在头文件为 include lt algorithm gt 的c 43 43 标准库中 xff0c 调用标准库里的排序方法可以实现对数据的排序 xff0c 但是sort函数是如何实现的 xff0c 我们
  • Window下LaTex+VS Code的配置

    目录 前言 一 软件下载二 软件安装1 TexLive安装2 VS Code及插件安装 三 配置 VS Code四 简单测试一下五 进阶操作及可能遇到的问题1 前向搜索和反向搜索2 编译带参考文献的 tex文件 前言 考虑本文受众有新手小白
  • 与 vmx86 驱动程序的版本不匹配解决方法

    一个新手可能遇到的问题 第一次安装完VMware后 xff0c 启动时可能会遇到问题 xff1a 与 vmx86 驱动程序的版本不匹配 预期为xxx 实际为 xxx 驱动程序 vmx86 sys的版本不正确 如下图 xff1a 解决方法 x
  • 汽车电子系统知识积累

    文章目录 前言一 汽车电子系统的分类1 电子控制汽车电子控制系统2 电子控制车载汽车电子系统 二 分类及详述1 动力2 底盘3 车身4 娱乐 总结 前言 汽车电子系统是以汽车电子技术为基础的汽车结构 一 汽车电子系统的分类 按照电子系统对汽
  • Jetson Xavier NX 学习(一),安装sd卡镜像

    Jetson Xavier NX 学习 xff08 一 xff09 xff0c 安装sd卡镜像 说明个人说明了解JetPack SDK下载镜像将图像写入microSD卡启动查看设置 说明 Jetson Xavier NX可为运行现代AI工作
  • 服务器ssh远程连接失败

    服务器远程ssh连接失败解决方案 查看ssh服务状态 systemctl status sshd service 正常应该是下图情况 xff1a xff08 running xff09 绿色即为正常状态 在这里插入图片描述 如果正常查看后面
  • Day1--FreeRTOS简介及多任务点灯、多任务传参、Mutex

    实时操作系统 xff08 Real Time Operating System xff0c 简称RTOS xff09 Arduino任务执行流程 xff1a 单线程执行任务 RTOS xff1a 可以同时执行所有Task xff0c 每个任