嵌入式开发系列----入门保姆级必看博客

嵌入式开发是指为特定的硬件平台编写软件的过程,通常涉及硬件资源有限、实时性要求高的应用。嵌入式系统广泛应用于消费电子、工业自动化、汽车、医疗设备等领域。本文将介绍嵌入式开发的基础内容,包括硬件和软件的构成、开发工具链、常用的编程语言以及嵌入式开发中的一些核心概念。

一.嵌入式开发必备基础知识

1. 嵌入式系统的组成

嵌入式系统通常由以下几个部分组成:

硬件平台:包括微处理器(如ARM、MIPS、x86等)、传感器、执行器、输入输出设备(如LCD、按键、LED等)。
操作系统:嵌入式系统可以使用实时操作系统(RTOS)或裸机(bare-metal)开发。RTOS如FreeRTOS、uC/OS-II等,裸机编程通常指直接与硬件打交道,没有操作系统的介入。
软件:包括驱动程序、应用程序、系统软件等。驱动程序负责硬件与软件的通信,应用程序则实现系统功能。

2. 嵌入式开发工具链

嵌入式开发通常需要一系列的开发工具:

集成开发环境(IDE):常用的IDE有Keil、IAR Embedded Workbench、Eclipse等,它们提供了代码编辑、编译、调试等功能。
编译器:常见的嵌入式编译器有GCC、ARM Compiler等,能够将源代码编译成适合嵌入式平台的机器代码。
调试器:如JTAG调试器、ST-Link、OCD等,用于调试程序的执行,帮助开发者查看寄存器、内存等信息,实时诊断问题。
仿真器:帮助开发者在没有实际硬件的情况下测试代码。

3. 嵌入式编程语言

嵌入式开发中,最常用的编程语言是:

C语言:几乎所有嵌入式开发都使用C语言,因为它能够直接操作硬件,提供较高的执行效率,并且占用内存较少。嵌入式开发中,C语言常用于编写驱动、操作系统和应用层代码。
汇编语言:对于需要极高性能和硬件控制的任务,汇编语言有时用于优化代码,直接操作硬件寄存器。
C++:在一些复杂的嵌入式系统中,C++用于面向对象编程,尤其是在处理较为复杂的算法时。

4. 嵌入式开发中的实时性要求

实时性是嵌入式系统中至关重要的概念,特别是在处理信号采集、控制系统时。根据实时性要求,嵌入式系统可以分为:

硬实时系统:对时间要求非常严格,任务必须在规定的时间内完成,否则将导致系统失败。例如,航空航天、医疗设备等。
软实时系统:虽然有时间限制,但如果超时不会导致系统完全失败,系统仍然能正常工作。例如,视频播放、音频处理等。

5. 基本的嵌入式开发流程

嵌入式开发流程一般包括以下步骤:

需求分析:明确系统的功能需求、硬件需求、性能要求等。
硬件选择:选择适合的微控制器(MCU)或微处理器(MPU),并了解其硬件资源(如GPIO、UART、SPI、I2C等外设)。
软件设计:根据需求设计嵌入式软件架构,包括驱动、RTOS配置、应用层逻辑等。
编程与调试:在开发环境中编写代码,进行调试和测试,确保软件的正确性和性能。
测试与验证:在目标硬件上进行系统测试,验证软件和硬件的协同工作。

6. 简单的嵌入式代码示例

下面我们将通过一个简单的LED闪烁的例子,展示嵌入式编程的基本内容。我们使用C语言在STM32微控制器上编写代码,来控制一个LED灯每秒闪烁一次。

硬件连接:
STM32开发板
连接到板上的LED(一般连接到某个GPIO口)

软件代码:

#include "stm32f4xx.h"// 初始化GPIO
void GPIO_Init(void)
{// 打开GPIO时钟RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;  // 开启GPIOD时钟// 配置GPIO模式为输出GPIOG->MODER &= ~(0x3 << (13 * 2));  // 清除GPIO口13的模式GPIOG->MODER |= (0x1 << (13 * 2));   // 设置GPIO口13为输出模式
}// 延时函数
void Delay(uint32_t delay)
{while (delay--) {__NOP();  // 空操作,消耗时间}
}// 主函数
int main(void)
{// 初始化GPIOGPIO_Init();// 主循环while (1) {// 点亮LEDGPIOG->ODR |= (1 << 13);  // 设置GPIO口13为高电平,LED亮Delay(1000000);            // 延时// 熄灭LEDGPIOG->ODR &= ~(1 << 13);  // 设置GPIO口13为低电平,LED灭Delay(1000000);            // 延时}
}

代码解析:
GPIO初始化:使用GPIO_Init函数初始化GPIO端口,将端口13配置为输出模式。STM32的GPIO寄存器通过MODER配置端口的工作模式。
延时函数:Delay函数通过循环实现一个简单的延时,模拟延时1秒钟。
主循环:在main函数的主循环中,我们交替控制LED的亮灭状态,利用ODR寄存器设置GPIO口的输出值。

7.更复杂的嵌入式开发代码示例

我们将通过一个稍微复杂的示例来展示如何编写嵌入式代码,控制多个外设,并结合中断来实现更高效的系统响应。

目标
控制一个LED闪烁,频率为1Hz。
使用定时器中断(Timer Interrupt)来控制LED闪烁。
硬件需求
STM32F4开发板
LED:连接到GPIO口
定时器:使用系统定时器定时产生中断
系统架构
使用STM32的定时器产生中断。
每次定时器中断发生时,改变LED的状态(开/关)。
代码实现
1. 初始化GPIO口
我们首先需要初始化GPIO口,以便控制LED的开关。假设LED连接到GPIO端口的第13引脚(常见于STM32F4开发板的内置LED)。

#include "stm32f4xx.h"// 初始化GPIO口
void GPIO_Init(void)
{// 开启GPIOG时钟RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;  // 开启GPIOG的时钟// 设置GPIOG13为输出模式GPIOG->MODER &= ~(0x3 << (13 * 2));  // 清除原有的设置GPIOG->MODER |= (0x1 << (13 * 2));   // 设置为输出模式
}

2. 初始化定时器
为了产生定时器中断,我们需要配置STM32的定时器。定时器将根据我们设置的预分频值和自动重载值(ARR)来产生中断。

// 定时器初始化
void Timer_Init(void)
{// 开启定时器6时钟RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;   // 开启TIM6时钟// 配置定时器6的时钟频率TIM6->PSC = 16000 - 1;  // 设置预分频值,1秒产生一次中断TIM6->ARR = 1000 - 1;   // 设置自动重载值,定时器每1秒产生一次中断// 使能定时器中断TIM6->DIER |= TIM_DIER_UIE;   // 使能更新中断// 启动定时器TIM6->CR1 |= TIM_CR1_CEN;     // 启动定时器
}

 3. 中断处理程序
当定时器溢出时,它会产生一个中断,触发中断服务程序。我们需要在中断服务程序中实现LED的状态切换。

// 中断服务程序
void TIM6_DAC_IRQHandler(void)
{if (TIM6->SR & TIM_SR_UIF) {  // 检查更新中断标志TIM6->SR &= ~TIM_SR_UIF;  // 清除中断标志// 切换LED状态GPIOG->ODR ^= (1 << 13);  // 切换GPIO13的输出状态(开关LED)}
}

4. 主函数
主函数中,初始化GPIO和定时器,并开启全局中断。

int main(void)
{// 初始化GPIO和定时器GPIO_Init();Timer_Init();// 配置NVIC,使能定时器6的中断NVIC_EnableIRQ(TIM6_DAC_IRQn);  // 启用定时器6的中断请求// 使能全局中断__enable_irq();  // 开启全局中断// 主循环(空循环,所有工作由中断处理)while (1) {// 这里不需要做任何事情,LED控制完全由定时器中断处理}
}

5. 总结与扩展
GPIO控制:我们通过寄存器直接控制GPIO端口,设置为输出模式,通过ODR寄存器控制LED的开关。
定时器中断:定时器用于产生精确的中断,并在中断服务程序中处理LED状态的切换。定时器配置涉及到预分频器和自动重载值。
中断服务程序:通过TIM6_DAC_IRQHandler来处理定时器中断,每当定时器溢出时切换LED状态。
6. 代码扩展
外部中断:如果你希望使用按钮等外部设备控制LED状态,可以设置GPIO外部中断。 

// 初始化外部中断
void EXTI_Init(void)
{// 使能GPIO端口时钟RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;// 配置PA0为输入模式GPIOA->MODER &= ~(0x3 << 0);  // 清除PA0的模式GPIOA->PUPDR |= (0x1 << 0);   // 设置为上拉输入模式// 配置外部中断SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PA;  // 设置PA0为外部中断0的来源EXTI->IMR |= EXTI_IMR_MR0;  // 使能外部中断0EXTI->RTSR |= EXTI_RTSR_TR0;  // 配置为上升沿触发// 使能中断控制器NVIC_EnableIRQ(EXTI0_IRQn);  // 启用外部中断0的中断请求
}// 外部中断0的中断处理函数
void EXTI0_IRQHandler(void)
{if (EXTI->PR & EXTI_PR_PR0) {  // 检查是否为外部中断0EXTI->PR |= EXTI_PR_PR0;  // 清除中断标志// 切换LED状态GPIOG->ODR ^= (1 << 13);  // 切换GPIO13的输出状态}
}

二.常见的嵌入式C语言知识

在嵌入式开发中,C语言是最常用的编程语言之一,因为它能够直接操作硬件、实现高效的底层控制,并且与许多嵌入式系统平台兼容。嵌入式C开发通常需要具备一些特殊的知识和技能,尤其是在资源受限的环境中。下面,我将介绍一些常见的嵌入式C语言知识,并夹杂一些代码示例,帮助你理解如何在嵌入式系统中应用这些知识。

1. 指针和内存操作
在嵌入式开发中,直接操作硬件寄存器和内存地址是常见的任务。指针用于存储地址,并可以直接访问存储在特定内存位置的数据。例如,嵌入式系统中的外设控制寄存器通常是通过指针直接访问的。

示例代码:访问硬件寄存器
假设我们要控制一个LED的GPIO引脚,使用指针操作硬件寄存器。

#define LED_GPIO_BASE 0x40020000  // 假设GPIOA的基地址
#define GPIO_MODER_OFFSET 0x00    // GPIO模式寄存器的偏移
#define GPIO_ODR_OFFSET  0x14    // GPIO输出数据寄存器的偏移volatile uint32_t *gpio_moder = (volatile uint32_t *)(LED_GPIO_BASE + GPIO_MODER_OFFSET);
volatile uint32_t *gpio_odr   = (volatile uint32_t *)(LED_GPIO_BASE + GPIO_ODR_OFFSET);void LED_Init(void) {// 设置PA5为输出模式*gpio_moder &= ~(0x3 << (5 * 2));  // 清除原有设置*gpio_moder |= (0x1 << (5 * 2));   // 设置为输出模式
}void LED_Toggle(void) {*gpio_odr ^= (1 << 5);  // 切换PA5的状态
}

在这个例子中,我们使用了指针来访问GPIO寄存器。volatile关键字确保编译器不会优化掉对这些寄存器的访问,因为它们是硬件相关的,可能会在程序运行时发生变化。

2. 中断和中断服务程序(ISR)
嵌入式系统中,中断是一个重要的概念,它允许CPU在处理完当前任务后,响应外部事件。中断服务程序(ISR)是响应中断事件时执行的代码。

示例代码:定时器中断
在一个简单的定时器中断示例中,我们使用定时器中断来每隔一段时间切换LED的状态。

#include "stm32f4xx.h"// 定时器6中断服务程序
void TIM6_DAC_IRQHandler(void) {if (TIM6->SR & TIM_SR_UIF) {  // 检查定时器更新中断标志TIM6->SR &= ~TIM_SR_UIF;  // 清除中断标志// 切换LED状态GPIOG->ODR ^= (1 << 13);  // 切换GPIO13(LED)}
}void Timer_Init(void) {// 启用定时器6时钟RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;// 配置定时器6TIM6->PSC = 16000 - 1;  // 设置预分频器,定时器溢出时间为1秒TIM6->ARR = 1000 - 1;   // 自动重载值,设定溢出周期为1秒// 启用定时器中断TIM6->DIER |= TIM_DIER_UIE;// 启动定时器TIM6->CR1 |= TIM_CR1_CEN;// 启用定时器中断向量NVIC_EnableIRQ(TIM6_DAC_IRQn);
}int main(void) {// 初始化GPIO和定时器GPIO_Init();Timer_Init();// 启用全局中断__enable_irq();// 无限循环,所有工作通过中断完成while (1) {// 主循环中不做任何事情}
}

在中断服务程序中,我们通过TIM6_DAC_IRQHandler函数来响应定时器中断,切换LED的状态。TIM6定时器被配置为每1秒触发一次中断。

3. 位操作(Bit Manipulation)
在嵌入式开发中,我们经常需要进行位操作,以直接操作寄存器或者控制某些硬件外设的状态。C语言提供了很多位操作的工具,如移位、与、或、非等操作。

示例代码:位操作控制GPIO
假设我们要设置一个GPIO端口的某一位为输出(如设置GPIO引脚5为输出)。

#define GPIOA_MODER  ((volatile uint32_t *) 0x40020000) // GPIOA模式寄存器地址
#define GPIOA_ODR    ((volatile uint32_t *) 0x40020014) // GPIOA输出数据寄存器地址void GPIOA_SetPin5Output(void) {// 设置GPIOA引脚5为输出模式*GPIOA_MODER &= ~(0x3 << (5 * 2));   // 清除原设置*GPIOA_MODER |= (0x1 << (5 * 2));    // 设置为输出模式
}void GPIOA_SetPin5High(void) {*GPIOA_ODR |= (1 << 5);  // 设置PA5为高电平
}void GPIOA_SetPin5Low(void) {*GPIOA_ODR &= ~(1 << 5);  // 设置PA5为低电平
}

4. 定时器和延时
嵌入式开发中常用定时器进行精确延时。虽然使用外部时钟和定时器来产生延时更加精准,但也有一些简单的基于循环的延时方式,适用于资源受限的场合。

示例代码:基于定时器的延时
在一些简单的系统中,如果不使用操作系统,可以使用定时器进行延时。

void delay_ms(uint32_t ms) {// 假设系统时钟是168MHz,我们配置一个定时器进行延时TIM2->PSC = 16799;     // 设置预分频器,168MHz / 16800 = 10kHzTIM2->ARR = 999;        // 设置定时器重载值,10kHz * 1000 = 1秒TIM2->CNT = 0;          // 清除计数器TIM2->CR1 |= TIM_CR1_CEN;  // 启动定时器for (uint32_t i = 0; i < ms; i++) {while (!(TIM2->SR & TIM_SR_UIF));  // 等待定时器溢出TIM2->SR &= ~TIM_SR_UIF;          // 清除溢出标志}TIM2->CR1 &= ~TIM_CR1_CEN;  // 关闭定时器
}

5. 优化与资源管理
在嵌入式开发中,硬件资源通常非常有限(如内存和处理能力)。因此,需要对代码进行优化,减少内存占用和CPU使用,确保程序高效运行。

示例代码:优化内存使用
一个常见的优化技巧是避免使用递归和过多的堆栈空间,而是通过循环和静态分配来实现。

#define BUFFER_SIZE 128
uint8_t buffer[BUFFER_SIZE]; // 静态内存分配,避免动态内存分配void process_data(void) {for (int i = 0; i < BUFFER_SIZE; i++) {buffer[i] = i * 2;  // 填充数据}
}

 三.完整的嵌入式开发项目

下面是一个简单的嵌入式项目代码示例,使用了STM32系列微控制器来控制一个LED灯,通过定时器中断每隔1秒切换LED的状态。该示例包含了GPIO初始化、定时器配置、和中断服务程序(ISR)的使用。

项目需求:
配置一个GPIO引脚(如PA5)控制一个LED灯的开关。
使用定时器(比如TIM6)每隔1秒切换一次LED状态。
使用中断服务程序(ISR)响应定时器中断,并切换LED状态。
使用的硬件:
STM32F4系列开发板
连接至PA5引脚的LED(如STM32F4的板载LED)
项目结构:
main.c:主要代码文件,包含初始化、主循环和定时器中断服务程序。
startup.s:启动文件,通常由STM32的HAL库自动生成或手动编写。
main.c 完整代码:

#include "stm32f4xx.h"// LED控制引脚PA5
#define LED_PIN     5
#define GPIOA_BASE  0x40020000  // GPIOA基地址
#define GPIOA_MODER 0x00        // GPIOA模式寄存器偏移
#define GPIOA_ODR   0x14        // GPIOA输出数据寄存器偏移// 定时器6中断服务程序
void TIM6_DAC_IRQHandler(void) {if (TIM6->SR & TIM_SR_UIF) {  // 检查定时器更新中断标志TIM6->SR &= ~TIM_SR_UIF;  // 清除中断标志// 切换PA5的状态(LED)GPIOA->ODR ^= (1 << LED_PIN);  // 切换LED的状态}
}// GPIO初始化,配置PA5为输出
void GPIO_Init(void) {// 启用GPIOA时钟RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;// 设置PA5为输出模式GPIOA->MODER &= ~(0x3 << (LED_PIN * 2));  // 清除原有设置GPIOA->MODER |= (0x1 << (LED_PIN * 2));   // 设置为输出模式(00: 输入, 01: 输出, 10: 复用, 11: 模式)
}// 定时器6初始化,每秒中断一次
void Timer_Init(void) {// 启用定时器6时钟RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;// 设置定时器预分频器,假设系统时钟为168MHz,定时器6的频率为1kHzTIM6->PSC = 16799;  // 168MHz / 16800 = 10kHzTIM6->ARR = 999;     // 设置重载值,定时器溢出周期为1秒// 启用定时器中断TIM6->DIER |= TIM_DIER_UIE;// 启动定时器TIM6->CR1 |= TIM_CR1_CEN;// 启用定时器中断向量NVIC_EnableIRQ(TIM6_DAC_IRQn);
}int main(void) {// 初始化GPIO和定时器GPIO_Init();Timer_Init();// 启用全局中断__enable_irq();// 无限循环,主循环中不做任何事情,所有工作由中断完成while (1) {// 主循环为空,因为LED的切换工作完全交给中断处理}
}

代码解析:
GPIO初始化:

GPIO_Init() 函数负责配置PA5为输出模式。我们首先启用GPIOA时钟,然后通过MODER寄存器设置PA5为输出模式。
定时器初始化:

Timer_Init() 函数负责配置定时器6(TIM6)。在此示例中,定时器6的时钟源为APB1总线时钟,假设系统时钟为168 MHz。通过设置PSC(预分频器)和ARR(自动重载值),我们配置定时器的周期为1秒(溢出周期为1000ms)。
启用定时器中断,当定时器溢出时,会触发TIM6_DAC_IRQHandler()中断服务程序。
定时器中断服务程序(ISR):

在TIM6_DAC_IRQHandler()函数中,我们首先检查是否发生了定时器溢出中断。如果是,清除中断标志,并切换LED的状态(通过GPIOA->ODR寄存器操作PA5的输出状态)。
主循环:

主循环实际上不做任何工作,所有LED切换的任务都由定时器中断来处理。由于中断处理程序会定期切换LED状态,因此主循环为空。
全局中断启用:

__enable_irq() 函数启用全局中断,使定时器中断能够触发并执行。
项目构建:
启动文件和链接器脚本:

在STM32开发中,通常会使用标准的启动文件(startup_stm32f4xx.s)来配置中断向量表和复位启动流程。链接器脚本(如STM32F4.x.ld)会指定内存布局,确保代码和数据存储在正确的位置。
编译工具链:

该项目需要使用ARM工具链(如gcc-arm-none-eabi)进行编译。你可以通过STM32CubeIDE或Keil等IDE进行项目的编译和烧录。
硬件配置:

确保LED正确连接到PA5引脚,并且相应的电阻已经正确配置。你可以使用开发板的板载LED,或者通过外接LED与适当的电阻连接。
运行效果:
每1秒钟,定时器会产生一次中断,触发TIM6_DAC_IRQHandler()函数,切换PA5的状态,从而使连接到PA5的LED闪烁。

 四.总结

嵌入式开发是将计算机技术嵌入到硬件设备中的一种开发模式,广泛应用于消费电子、汽车、工业控制、医疗设备、智能家居等领域。它不仅涉及到传统的软件开发,还包括对硬件平台的深入理解。嵌入式系统通常具有资源受限(如内存、存储、处理能力、功耗等)的特点,因此开发者需要在高效利用硬件资源的基础上,确保系统的稳定性、实时性和可靠性。嵌入式开发涉及多个层次,从硬件设计到驱动开发,再到上层应用的实现,需要开发者掌握微处理器架构、数字电路、操作系统(RTOS或裸机编程)、设备驱动、通信协议、调试工具等多方面的知识。

在实际开发过程中,开发者需要与硬件工程师紧密合作,理解硬件电路设计、信号处理等,以确保软件能够有效控制硬件工作。同时,嵌入式开发中常常需要处理外部设备的接口与通信问题,如GPIO、UART、SPI、I2C等通信协议的实现,这要求开发者能够灵活运用中断、DMA、定时器等硬件特性。在系统软件方面,嵌入式开发通常涉及到底层固件(如启动引导程序)、驱动程序和应用层代码的编写,尤其是在实时性要求较高的场合,还需要设计高效的任务调度和资源管理机制。

调试和优化是嵌入式开发中的关键环节,由于嵌入式设备大多没有显示器或操作界面,开发者需要借助串口调试、JTAG、逻辑分析仪、示波器等工具进行硬件级调试,进行代码的性能分析和优化。此外,功耗管理也是嵌入式系统中的一个重要课题,如何在保证系统性能的前提下降低功耗,延长电池使用寿命,是开发者在设计嵌入式系统时必须考虑的因素。

总的来说,嵌入式开发是一个跨学科的领域,既需要硬件知识,也需要扎实的软件编程能力,开发者要不断学习新技术、理解硬件与软件的紧密配合,才能在复杂的嵌入式系统中成功实现创新应用。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络(4)

同轴电缆 由一根空心的外圆柱导体和一根位于中心轴线的内导线组成&#xff0c;内导线和圆柱 导体及外界之间用绝缘材料隔开&#xff0c;按直径的不同&#xff0c;同轴电缆分为粗缆和细缆 两种 与双绞线相比&#xff0c;同轴电缆的抗干扰能力强&#xff0c;屏蔽性好&#xff0c;…

Cesium基础-(Entity)-(label )

里边包含Vue、React框架代码详细步骤、以及代码详细解释 Label 在 Cesium 中表示一个可以在三维地球上显示的文本标签。它通常用于在特定位置显示信息,比如地名、地标名称或其他注释。Label 可以自定义样式、颜色、大小,并能根据距离视角动态调整显示效果。 以下是 Label 的…

云计算虚拟化-自用服务器购买指南

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 首先强调&#xff1a;这个不是必需品&#xff0c;请各位根据自己的情况来。技术的进步这些只能算锦上添花&#xff0c;重要的…

基于gewe制作第一个微信聊天机器人

现在我们制作一个微信智能聊天机器人。发送文字它可以回复一段话&#xff0c;或一张图片&#xff0c;是不是有点小酷&#xff01; 当然&#xff0c;这种智能回复的算法和数据库我们自己肯定是没有的&#xff0c;所以我们借助于gewe框架的开放API接口来完成我们的功能。 请求参…

C++模板进阶

C教学总目录 C模板进阶 1、模板初阶的补充2、非类型模板参数3、模板的特化3.1、函数模板特化3.2、类模板特化3.2.1、全特化3.2.2、偏特化3.2.3、类模板特化的应用 4、模板的分离编译 1、模板初阶的补充 现在假设我们有一个vector对象&#xff0c;我们要遍历输出vector对象中的…

Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本v9版

Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本 Shell脚本源码地址&#xff1a; Gitee&#xff1a;https://gitee.com/raymond9/shell Github&#xff1a;https://github.com/raymond999999/shell脚本可以去上面的Gitee或Github代码仓库拉取。 支持的功能和系统&am…

Iotop使用

文章目录 Iotop依赖及编译1:内核配置2: 环境配置3.依赖库ncurses3.1 Ncurses的编译配置 4. Iotop的编译及修改5.测试效果如下&#xff1a; Iotop依赖及编译 源码路径&#xff1a;https://github.com/Tomas-M/iotop#how-to-build-from-source (GitHub - Tomas-M/iotop: A top u…

CVPR力推!预训练+医学图像这么玩,审稿人都得为你让条路!

最近发现Nature、CVPR、NeurIPS等顶会顶刊上&#xff0c;涌现了不少预训练医学图像的文章&#xff0c;不仅效果拔群&#xff0c;思路也很有启发性。 像是Nature上的REFERS&#xff0c;便颠覆了传统方法&#xff0c;使标注数据量直降90&#xff05;&#xff01;此外还有CVPR24上…

Spark 共享变量:广播变量与累加器解析

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

基于Matlab 疲劳驾驶检测

Matlab 疲劳驾驶检测 课题介绍 该课题为基于眼部和嘴部的疲劳驾驶检测。带有一个人机交互界面GUI&#xff0c;通过输入视频&#xff0c;分帧&#xff0c;定位眼睛和嘴巴&#xff0c;通过眼睛和嘴巴的张合度&#xff0c;来判别是否疲劳。 二、操作步骤 第一步&#xff1a;最…

强化学习不愧“顶会收割机”!2大创新思路带你上大分,毕业不用愁!

强化学习之父Richard Sutton悄悄搞了个大的&#xff0c;提出了一个简单思路&#xff1a;奖励聚中。这思路简单效果却不简单&#xff0c;等于是给几乎所有的强化学习算法上了一个增强buff&#xff0c;所以这篇论文已经入选了首届强化学习会议&#xff08;RLC 2024&#xff09;&a…

个人记录。改错huggingface,离线使用

huggingface_hub.utils._errors.LocalEntryNotFoundError: Connection error, and we cannot find the requested files in the disk cache. Please try again or make sure your Internet connection is on. 下载 true改false

【计算机网络】网络框架

一、网络协议和分层 1.理解协议 什么是协议&#xff1f;实际上就是约定。如果用计算机语言进行表达&#xff0c;那就是计算机协议。 2.理解分层 分层是软件设计方面的优势&#xff08;低耦合&#xff09;&#xff1b;每一层都要解决特定的问题 二、网络传输基本流程 1.预备…

C++练习 字符串反转

从界面上输入一个C风格的字符串&#xff0c;如果输入的是"abc"&#xff0c;反转后"cba"。 要求&#xff1a; 1&#xff09;反转的结果存放在另一字符串中。 2&#xff09;原地反转&#xff0c;不借助其它的字符串。 #include <iostream> using n…

Postman常见问题及解决方法

软件测试资料领取&#xff1a;[内部资源] 想拿年薪40W的软件测试人员&#xff0c;这份资料必须领取~ 软件测试面试刷题工具&#xff1a;软件测试面试刷题【800道面试题答案免费刷】 1、网络连接问题 如果Postman无法发送请求或接收响应&#xff0c;可以尝试以下操作&#xf…

LED和QLED的区别

文章目录 1. 基础背光技术2. 量子点技术的引入3. 色彩表现4. 亮度和对比度5. 能效6. 寿命7. 价格总结 LED和 QLED都是基于液晶显示&#xff08;LCD&#xff09;技术的电视类型&#xff0c;但它们在显示技术、色彩表现和亮度方面有一些关键区别。以下是两者的详细区别&#xff…

光流法(Optical Flow)

一、简介 光流法&#xff08;Optical Flow&#xff09;是一种用于检测图像序列中像素运动的计算机视觉技术。其基于以下假设&#xff1a; 1.亮度恒定性假设&#xff1a;物体在运动过程中&#xff0c;其像素值在不同帧中保持不变。 2.空间和时间上的连续性&#xff1a;相邻像素之…

400. 第 N 位数字

目录 题目解法 题目 给你一个整数 n &#xff0c;请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …] 中找出并返回第 n 位上的数字。 解法 class Solution { public:int findNthDigit(int n) {int low 1, high 9;while (low < high) {int mid (high - lo…

FlinkPipelineComposer 详解

FlinkPipelineComposer 详解 原文 背景 在flink-cdc 3.0中引入了pipeline机制&#xff0c;提供了除Datastream api/flink sql以外的一种方式定义flink 任务 通过提供一个yaml文件&#xff0c;描述source sink transform等主要信息 由FlinkPipelineComposer解析&#xff0c…

10款音频剪辑推荐!!你的剪辑好帮手!!

在如今的数据化浪潮中&#xff0c;工作已经采用了线上线下相结合。我的工作就需要借助一些剪辑工具&#xff0c;来实现我对音频工具的剪辑。我初次接触到音频剪辑也是因为工作需求&#xff0c;从起初我只是一个音频剪辑的小白&#xff0c;这些工具的协助。吸引着我。对于这些工…