PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

news2024/11/18 23:31:07

TD工程介绍

我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展,可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容,只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可,主要修我以为都是在FD工程进行修改即可。

FD工程介绍

这个工程我们主要演示了如何使用UART及UART中断,如何使用定时器中断,以及如何使用GPIO和GPIO中断。

FD工程导入

打开FD选择workspace为 demo_riscv\wkspace 就会自动导入该workspace下的所有项目。

由于你的FD的目录与我的FD目录不在同一个位置,会导致编译器工具链的找不着,我们需要在工程上右键选择Reset Project Toolchain

执行完这个操作就FD会重新修正工程的工具链配置。

FD工程源代码分析

头文件、宏定义及全局变量介绍

头文件

 

#include "core.h" // 核心头文件

//#define USE_MTIME // 不使用MTIME

#include "uart.h" // UART 头文件

#include "gpio.h" // GPIO 头文件

#include "anl_printf.h" // 打印库头文件

#include "interrupt.h" // 中断库头文件

#ifdef USE_MTIME

#include "mtime.h" // 如果使用 MTIME,则引入 MTIME 头文件

#else

#include "systick.h" // 否则引入 SysTick 头文件

#endif

  1. #include "core.h":这个头文件是系统的核心头文件,通常包含了与硬件相关的低级别配置和宏定义。它可能包含了处理器寄存器的定义、中断控制器配置等内容。

  2. #include "uart.h":这个头文件包含了 UART(通用异步收发传输)相关的函数声明和宏定义。

  3. #include "gpio.h":这个头文件包含了 GPIO(通用输入输出)相关的函数声明和宏定义。

  4. #include "anl_printf.h":这个头文件包含了打印函数的声明和定义。

  5. #include "interrupt.h":这个头文件包含了中断控制器相关的函数声明和宏定义。

  6. #ifdef USE_MTIME:这是一个条件编译指令,用于根据是否定义了 USE_MTIME 宏来选择性地包含不同的头文件内容。

  7. #include "mtime.h":如果定义了 USE_MTIME 宏,就会包含这个头文件。它可能包含了 MTIME(Machine Timer)相关的函数声明和宏定义,用于配置和操作处理器的计时器。

  8. #include "systick.h":如果没有定义 USE_MTIME 宏,就会包含这个头文件。它可能包含了 SysTick 定时器相关的函数声明和宏定义,用于配置和操作 SysTick 定时器。

  9. Systick 和 MTIME 定时器的区别主要是其资源占用和操作模式。 Systick 是一个自动重装的 30bit 定时器,用户需要使用 SetSystickCfg()函数启用定时器,并在定时器中断处理程序中使用 ClrSystickInt()函数清除掉挂起的定时器状态对于 MTIME 定时器而言,它的初始化和中断响应都是使用 SetMtimeCmp()函数将下一时钟节拍的计数值装入定时器比较值中。

全局变量sys_banner

static char sys_banner[] = {"- Anlogic eMCU buildtime [" __TIME__" " __DATE__ "] " "rev 1.0 \r\n"};

这行代码定义了一个静态字符数组 sys_banner,用于存储系统的横幅信息。该信息包含了编译时间和日期,以及版本号。

  • __TIME__:编译时的时间,格式为 HH:MM:SS。
  • __DATE__:编译时的日期,格式为 MMM DD YYYY(月份、日期、年份)。

这两个宏是编译器提供的预定义宏,在编译时会被替换为当前的编译时间和日期。在这里,它们被用于构建一个包含编译时间和日期的字符串。

宏定义

 

//THIS DEMO IS FOR SYSTICK SYSTEM

#define SYS_FREQ 80000000 // 系统频率

#define UART_BAUD 115200 // UART 波特率

#define GPIO_INTSRC 0x04 // GPIO 中断源

#define UART1_INTSRC 0x01 // UART1 中断源

#define TIM_TRIG_FREQ 1 // 定时器触发频率,每秒1次

这段代码是一些预定义的常量和注释,用于描述程序的一些基本参数和特性:

  1. // THIS DEMO IS FOR SYSTICK SYSTEM:这是一个注释,用于说明这段代码是针对 SysTick 系统设计的演示程序。

  2. #define SYS_FREQ 80000000:这是一个宏定义,表示系统的频率为 80MHz。这个频率用于配置定时器、UART 通信等时序相关的功能。

  3. #define UART_BAUD 115200:这是一个宏定义,表示 UART 的波特率为 115200。波特率是串行通信中表示数据传输速率的参数。

  4. #define GPIO_INTSRC 0x04:这是一个宏定义,表示 GPIO 中断源的值为 0x04。在某些系统中,GPIO 的中断可以被多个源触发,此处定义了其中一个源的标识值。

  5. #define UART1_INTSRC 0x01:这是一个宏定义,表示 UART1 中断源的值为 0x01。类似于上面的 GPIO 中断源,这里定义了 UART1 中断的标识值。

  6. #define TIM_TRIG_FREQ 1:这是一个宏定义,表示定时器的触发频率为每秒 1 次。这个参数用于配置定时器中断的触发频率,可以根据需要进行调整。

函数说明

main()函数

  • 先配置UART
 

// 配置 UART 参数

Uart_Config UART1_Cfg;

UART1_Cfg.BaudDivider=(SYS_FREQ/UART_BAUD);

UART1_Cfg.IntEnable=True;

UART1_Cfg.Event_ParityCheckFail=False;

UART1_Cfg.Event_RxFifoHalfFull=False;

UART1_Cfg.Event_TxFifoHalfEmpty=False;

UART1_Cfg.Event_RxBufFull=True;

UART1_Cfg.Event_TxBufEmpty=False;

UART1_Cfg.RxFifoEnable=False;

UART1_Cfg.TxFifoEnable=True;

UART1_Cfg.Parity=NONE;

UART1_Cfg.Stop=ONE;

uart_applyConfig(UART,&UART1_Cfg);

这段代码是配置 UART 参数的过程,具体的配置包括:

  • BaudDivider:波特率分频器,根据系统时钟频率 SYS_FREQ 和波特率 UART_BAUD 计算得出。
  • IntEnable:使能 UART 中断。
  • Event_ParityCheckFail:奇偶校验失败事件的处理,设置为 False 表示不处理。
  • Event_RxFifoHalfFull:接收 FIFO 缓冲区半满事件的处理,设置为 False 表示不处理。
  • Event_TxFifoHalfEmpty:发送 FIFO 缓冲区半空事件的处理,设置为 False 表示不处理。
  • Event_RxBufFull:接收缓冲区满事件的处理,设置为 True 表示处理。
  • Event_TxBufEmpty:发送缓冲区空事件的处理,设置为 False 表示不处理。
  • RxFifoEnable:使能接收 FIFO 缓冲区,设置为 False 表示不使用 FIFO 缓冲区。
  • TxFifoEnable:使能发送 FIFO 缓冲区,设置为 True 表示使用 FIFO 缓冲区。
  • Parity:奇偶校验类型,设置为 NONE 表示不使用奇偶校验。
  • Stop:停止位数,设置为 ONE 表示一个停止位。

最后,通过 uart_applyConfig 函数将以上配置应用到 UART 上。

  • 配置完后打印系统信息
 

// 打印系统信息

anl_printf("---------------------------------------------------------------- \r\n");

anl_printf("- SoftCore Demo : RISCV(Freq 80MHz. 32kB RAM. Full Feature) \r\n");

anl_printf("- Hardware Platform : EG4S20NG88 PotatoPie V4.0 \r\n");

anl_printf("- TD Ver. : TD 5.6.4(97693) \r\n");

anl_printf("- OS+Build+Debug : Windows, OpenOCD + Riscv-none-embed. \r\n");

anl_printf("- Test Case : UART Interrupt Demo \r\n");

anl_printf(sys_banner);

anl_printf("---------------------------------------------------------------- \r\n");

这段代码使用 anl_printf 函数打印了一段系统信息。让我们来逐行解释:

  • anl_printf("---------------------------------------------------------------- \r\n");

    打印了一条分隔线,用于美观和区分信息的开头。

  • anl_printf("- SoftCore Demo : RISCV(Freq 80MHz. 32kB RAM. Full Feature) \r\n");

    打印了系统的软核演示信息,包括软核类型(RISCV)、频率(80MHz)、RAM 大小(32kB)和功能(全功能)。

  • anl_printf("- Hardware Platform : EG4S20NG88 PotatoPie V4.0 \r\n");

    打印了硬件平台信息,包括硬件平台型号(EG4S20NG88)和版本(PotatoPie V4.0)。

  • anl_printf("- TD Ver. : TD 5.6.4(97693) \r\n");

    打印了测试开发工具的版本信息,包括版本号(TD 5.6.4)和编译号(97693)。

  • anl_printf("- OS+Build+Debug : Windows, OpenOCD + Riscv-none-embed. \r\n");

    打印了操作系统、构建环境和调试工具的信息,包括操作系统类型(Windows)和使用的调试工具(OpenOCD + Riscv-none-embed)。

  • anl_printf("- Test Case : UART & GPIO Interrupt, SPI Master Demo \r\n");

    打印了测试用例的信息,包括测试的内容(UART & GPIO 中断、SPI 主控演示)。

  • anl_printf(sys_banner);

    打印了之前定义的 sys_banner 字符串,其中包含了编译时间和日期的信息。

  • anl_printf("---------------------------------------------------------------- \r\n");

    再次打印了一条分隔线,用于美观和区分信息的结尾。

 

SetSystickCfg((SYS_FREQ/TIM_TRIG_FREQ),True);

ClrSystickInt();

这两行代码用于配置和清除 SysTick 定时器的设置:

  1. SetSystickCfg((SYS_FREQ/TIM_TRIG_FREQ),True);

    • 这行代码调用了 SetSystickCfg 函数,用于设置 SysTick 定时器的配置。
    • 第一个参数 (SYS_FREQ/TIM_TRIG_FREQ) 表示每秒钟 SysTick 定时器的时钟周期数,它是系统频率 SYS_FREQ 除以定时器触发频率 TIM_TRIG_FREQ 的结果。
    • 第二个参数 True 表示启用 SysTick 定时器。
  2. ClrSystickInt();

    • 这行代码调用了 ClrSystickInt 函数,用于清除 SysTick 中断标志位。
    • 这样做是为了确保在进入主循环之前,任何可能触发的 SysTick 中断都被处理,以免影响程序的正常执行。
 

// 设置中断掩码

SetIntMask(UART1_INTSRC | GPIO_INTSRC);

uart_ClrEvent(UART,0xFF); //清除全部UART中断

ClrIntEvent(0xFFFFFFFF); // 清除所有中断

GPIO_A->OUTPUT_ENABLE=0x0000FFFF;

GPIO_A->GPIO_INTMASK=0xFFFFFFFF; // 允许所有 GPIO 发送中断

这段代码用于配置中断掩码和清除所有中断:

  1. SetIntMask(UART1_INTSRC | GPIO_INTSRC);

    • 这行代码调用了 SetIntMask 函数,用于设置中断掩码。通过将 UART1_INTSRC 和 GPIO_INTSRC 按位或运算,将 UART1 和 GPIO 的中断源加入到中断掩码中。
    • 这样做的目的是指定哪些中断将被允许触发。
  2. uart_ClrEvent(UART, 0xFF);

    • 这行代码调用了 uart_ClrEvent 函数,清除了 UART 的所有中断事件。
    • 第一个参数 UART 指定了要清除中断事件的 UART 模块。
    • 第二个参数 0xFF 表示清除所有类型的 UART 中断事件。
  3. ClrIntEvent(0xFFFFFFFF);

    • 这行代码调用了 ClrIntEvent 函数,清除了所有的中断事件。
    • 传递的参数 0xFFFFFFFF 表示清除所有中断事件。
  4. GPIO_A->OUTPUT_ENABLE = 0x0000FFFF;

    • 这行代码设置了 GPIO_A 模块的输出使能寄存器,使得 GPIO_A 的低 16 位引脚成为输出引脚。
  5. GPIO_A->GPIO_INTMASK = 0xFFFFFFFF;

    • 这行代码设置了 GPIO_A 模块的中断掩码寄存器,允许所有 GPIO_A 引脚产生中断。
 

while (1)

{

GPIO_A->OUTPUT=i;

i=i+1;

Delay(5000000);

anl_printf("Hello Main!\r\n");

}

这个 while 循环是程序的主循环,它会不断地执行以下操作:

  1. GPIO_A->OUTPUT=i;

    • 将变量 i 的值写入 GPIO_A 模块的输出寄存器中,控制 GPIO_A 的输出状态。每次循环迭代,i 的值会递增。
    • 这个操作会改变 GPIO_A 引脚的输出状态,具体的改变依赖于 i 的值。
  2. i=i+1;

    • 递增变量 i 的值,用于改变 GPIO_A 输出状态的控制值。
  3. Delay(5000000);

    • 调用 Delay 函数,使程序停顿一段时间。在这里,函数的参数 5000000 表示延时的周期数,具体延时时长由系统时钟频率决定。
  4. anl_printf("Hello Main!\r\n");

    • 打印字符串 “Hello Main!\r\n” 到串行终端,向用户输出一条消息。

这样,循环将一直重复执行上述步骤,不断改变 GPIO_A 的输出状态,延时一段时间,然后打印一条消息,形成一个周期性的操作。

其它函数

 

void Delay(int cycle)

{

int i;

for (i=0;i<cycle;i++)

asm volatile(

"add x0, x0, x0"

);

}

这个Delay函数是一个简单的延时循环,它通过重复执行一个无操作的操作add x0, x0, x0来等待指定数量的周期。asm volatile语句用于将汇编语言直接嵌入到C代码中,提供一种执行可能无法直接用C表达的机器指令的方法。

它的功能说明:

  • for循环执行cycle次。
  • 在循环内部,它执行一个汇编指令,将寄存器x0的内容加到自身,并将结果存回x0
  • 由于这是一个无操作指令(它将一个值加到自身,实际上什么都没做),它实际上是一个消耗CPU周期的循环,没有执行任何有意义的计算。

这个函数可用于在时间敏感的应用程序中创建延时,例如控制某些操作的时序。然而,需要注意的是,延迟的持续时间取决于各种因素,包括处理器速度和优化设置,因此它可能不太精确,也不适用于不同平台。

 

// 定时器中断服务函数

void TimerISP()

{

#ifdef USE_MTIME

uint64_t mtime_calc;

mtime_calc=GetMTimeCnt()+(SYS_FREQ/TIM_TRIG_FREQ);

SetMTimeCmp(mtime_calc);

#else

ClrSystickInt();

#endif

GPIO_A->OUTPUT = ~(GPIO_A->OUTPUT);

anl_printf("Hello Tick!\r\n");

return;

}

这是定时器中断服务函数 TimerISP。根据编译时是否定义了 USE_MTIME 宏,函数会有不同的行为:

  1. 如果定义了 USE_MTIME

    • 函数首先声明了一个 uint64_t 类型的变量 mtime_calc,用于计算下一次定时器中断的触发时间。
    • 调用 GetMTimeCnt() 函数获取当前的 MTIME 计数值,即当前时间。
    • 根据系统频率 SYS_FREQ 和定时器触发频率 TIM_TRIG_FREQ 计算下一次定时器中断触发的时间点,并将结果存储在 mtime_calc 中。
    • 调用 SetMTimeCmp 函数设置 MTIME 比较寄存器,使得下一次定时器中断在计算得到的时间点触发。
    • 最后,将 GPIO_A 的输出取反,即翻转输出状态,并打印 “Hello Tick!\r\n” 消息。
  2. 如果未定义 USE_MTIME

    • 则调用 ClrSystickInt() 函数清除 SysTick 定时器中断标志。
    • 接着,将 GPIO_A 的输出取反,即翻转输出状态,并打印 “Hello Tick!\r\n” 消息。

无论哪种情况,这个函数都用于定时器中断服务,每当定时器中断触发时,GPIO_A 的输出状态都会取反,并输出一条消息。

 

// UART1 中断服务函数

void UART1_ISP()

{

char recv_value;

while(uart_GetEvent(UART,UartRxVld))

{

uart_write(UART,uart_read(UART));

}

uart_ClrEvent(UART,UartRxBufFull | UartRxBufHfFull);

ClrIntEvent(UART1_INTSRC);

}

这是 UART1 的中断服务函数 UART1_ISP。当 UART1 接收到数据时,该函数会执行以下操作:

  1. 声明一个 char 类型的变量 recv_value,用于存储接收到的数据。

  2. 使用 while 循环结构,调用 uart_GetEvent 函数检查 UART 接收缓冲区是否有数据可用(即接收到有效数据)。如果接收到数据,则进入循环体。

  3. 在循环体内,调用 uart_read 函数读取 UART 接收缓冲区中的数据,并立即将其通过 uart_write 函数写回 UART 发送缓冲区。这实现了一种称为回显(echo)的功能,即将接收到的数据原样发送回去。

  4. 循环继续,直到 UART 接收缓冲区中没有数据可用。

  5. 调用 uart_ClrEvent 函数清除 UART 接收缓冲区满和半满的标志位,以及清除 UART1 中断标志位。

总的来说,该函数实现了 UART1 接收数据并回显的功能,同时清除相关的中断标志位。

 

void GPIO_ISP()

{

anl_printf("Hello Click!\r\n");

ClrIntEvent(GPIO_INTSRC);

}

这是 GPIO 的中断服务函数 GPIO_ISP。当 GPIO 触发中断时,该函数会执行以下操作:

  1. 使用 anl_printf 函数打印字符串 “Hello Click!\r\n”,提示发生了 GPIO 中断。

  2. 调用 ClrIntEvent 函数清除 GPIO 中断源(即 GPIO_INTSRC 对应的中断标志位),以确认已处理完中断事件。

 

void ExternalISP()

{

uint32_t temp;

temp=GetIntEvent();

if(temp&UART1_INTSRC)

UART1_ISP();

if(temp&GPIO_INTSRC)

GPIO_ISP();

else

{

anl_printf("UNKNOWN INT SRC! SRC= 0x%x",temp);

while(1);

}

}

这是外部中断服务函数 ExternalISP。当发生外部中断时,该函数会执行以下操作:

  1. 声明一个 uint32_t 类型的变量 temp,用于存储当前发生的中断事件。

  2. 调用 GetIntEvent 函数获取当前的中断事件。

  3. 使用条件语句检查中断事件的类型:

    • 如果 temp 中包含 UART1_INTSRC 标志位,则执行 UART1 的中断服务函数 UART1_ISP
    • 如果 temp 中包含 GPIO_INTSRC 标志位,则执行 GPIO 的中断服务函数 GPIO_ISP
    • 如果 temp 中不包含以上任何一种中断源的标志位,则打印消息 “UNKNOWN INT SRC! SRC= 0x%x”,其中 %x 是 temp 的十六进制表示,表示未知的中断来源,并进入无限循环。

工程源码在这个路径:

实验结果:

在 《PotatoPie 4.0 实验教程(40) —— FPGA实现RISC-V工程创建和调试》教程里我们知道如何创建,编译下载和调试RISCV工程,我们这里先只编译FD工程,而不用FD进行下载。

在TD中我们需要修改TD Soc_Top.v文件中的TCM0_INITFILE为,并重新编译TD工程。

parameter TCM0_INITFILE="../../../../../wkspace/hello_world/Debug/hello_world.bin.mif";

然后打开看串口助手之类的工具,设置串口波特率为115200,8N1模式。

最后后用TD工具的JTAG下载功能下载到FPGA之中,在串口工具中我们将看到如下输出:

同时可以看到板上蓝灯一秒一闪烁。

如果你的FPGA中已下载过之前的RISCV软核位流,那么可以也可以直接在FD中点击这个进行代码运行,而不用重新编译和下载FPGA程序。

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

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

相关文章

实时通讯技术 WebRTC 介绍

WebRTC WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音对话或视频对话的技术。 历史 2010年5月&#xff0c;Google以6820万美元收购VoIP软件开发商Global IP Solutions的GIPS引擎&#xff0c;并改为名为“WebRTC”。WebRTC使用…

C++ ─── 匿名对象+变量的创建顺序

目录 1. 匿名对象&#xff08;临时对象&#xff09; 2. 编译器的优化 3.变量的创建与销毁 1. 匿名对象&#xff08;临时对象&#xff09; 我们先来看有名对象的创建 Date d1; Date d2(2024,4,27);匿名对象的创建 Date(2024,56,1); 生成了一个匿名对象&#xff0c;执行完Da…

数据仓库是什么

写在前面 刚接触大数据的新手小白可能会对数据仓库这个词比较陌生&#xff0c;本文将介绍数据仓库的主要特征及OLTP&OLAP的区别&#xff0c;帮助读者更好理解数据仓库。 一、什么是数据仓库 数据仓库&#xff0c;简称数仓&#xff0c;是一个对数据进行加工&#xff0c;集…

信息系统项目管理师0073:网路集成(5信息系统工程—5.3系统集成—5.3.2网路集成)

点击查看专栏目录 文章目录 5.3.2网路集成5.3.2网路集成 计算机网络系统集成不仅涉及技术问题,而且涉及组织的管理问题,因而比较复杂,特别是大型网络系统更是如此。从技术角度讲,网络集成不仅涉及不同厂家的网络设备和管理软件,也会涉及异构和异质网络系统的互联问题。从管…

【算法学习】day1

文章目录 双指针算法移动零复写零 双指针算法 移动零 思路&#xff1a;通过定义两个下标作为双指针&#xff0c;cur从开始对整个数组进行遍历&#xff0c;而我们的dest代表的是非零元素的最后一个位置&#xff0c;cur位置为0的时候就cur&#xff0c;不为0元素的时候就交换dest…

STM32单片机C语言模块化编程实战:按键控制LED灯详解与示例

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 之前介绍了很多关于点灯的方法&#xff0c;比如…

设计模式学习笔记 - 项目实战一:设计实现一个支持各种算法的限流框架(实现)

概述 上篇文章&#xff0c;我们介绍了如何通过合理的设计&#xff0c;来实现框架的功能性需求的同时&#xff0c;满足易用、易扩展、灵活、低延迟、高容错等非功能性需求。在设计的过程中&#xff0c;我们也借鉴了之前讲过的一些开源项目的设计思想。比如 Spring 的低侵入松耦…

【ETAS CP AUTOSAR工具链】RTE层基本概念与开发流程

本篇文章续接上篇文章【ETAS CP AUTOSAR工具链】基本概念与开发流程&#xff0c;继续按上篇文章描述的ETAS CP工具链进行开发的基本框架&#xff0c;讲述了“RTE集成与配置”这部分的基本概念与开发流程。 RTE&#xff08;Runtime Environment&#xff09;处于应用层与基础软件…

Web前端开发 小实训(一) 成绩分类统计

用于学生web前端开发课程实训练习&#xff0c;掌握基本语法和数据类型 实训目的 使用分支语句&#xff0c;完成分数统计与等级对比,通过输入框输入分数&#xff0c;可以根据分数多少划分等级。 参考思路&#xff1a; 分析题目&#xff1a;根据输入分数进行等级划分。 操作过…

声光控路灯控制系统设计与仿真

目录 前言 一、设计任务 二、系统组成及工作原理 1、总体设计思路 2、电路各模块设计简介 &#xff08;1&#xff09;光控电路 &#xff08;2&#xff09;声控电路 (3) 逻辑控制电路 (4) 延时电路 三、系统中电源模块的设计 1、方案比较和确定 2、 设计思路 3、直流…

自定义View-旋转变色圆角三角形的绘制

本文字数&#xff1a;3151字 预计阅读时间&#xff1a;20分钟 在现代设计中&#xff0c;动效图在APP的UI界面中所起到的作用无疑是显著的。相比于静态的界面&#xff0c;动效更符合人类的自然认知体系&#xff0c;它有效地降低了用户的认知负载&#xff0c;UI动效俨然已经成为了…

利用ENVI SPEAR工具和WV-2卫星影像数据量测水深

ENVI的SPEAR工具集&#xff08;(Spectral Processing Exploitation and Analysis Resource)&#xff09;是将很多的遥感图像处理过程集成为流程化的操作方式&#xff0c;使得遥感图像处理知识相对薄弱的非专业人员也能利用流程化的工具进行图像处理&#xff0c;图像处理速度也有…

自动驾驶框架 UniAD环境部署

感谢大佬们的开源工作 UniAD-github地址-YYDS更多bev算法部署参考如果您觉得本帖对您有帮助&#xff0c;感谢您一键三连支持一波^_^ 统一自动驾驶框架 (UniAD) &#xff0c;第一个将全栈驾驶任务整合到一个深度神经网络中的框架&#xff0c;并可以发挥每个子任务以及各个模块的…

[每周一更]-(第94期):认识英伟达显卡

英伟达显卡&#xff1a;引领图形计算的领先者&#xff0c;显卡也常称为GPU&#xff08;图形处理器 Graphics processing unit&#xff09;&#xff0c;是一种专门在个人电脑、工作站、游戏机和一些移动设备&#xff08;如平板电脑、智能手机等&#xff09;上执行绘图运算工作的…

【STM32+HAL】三轴按键PS2摇杆

一、准备工作&#xff1a; 有关CUBEMX的初始化配置&#xff0c;参见我的另一篇blog&#xff1a;【STM32HAL】CUBEMX初始化配置 有关定时器触发ADC模式配置&#xff0c;详见【STM32HAL】ADC采集波形实现 二、所用工具&#xff1a; 1、芯片&#xff1a; STM32F407VET6 2、CUBE…

大数据面试题 —— Spark数据倾斜及其解决方案

目录 1 调优概述2 数据倾斜发生时的现象3 数据倾斜发生的原理4 如何定位导致数据倾斜的代码4.1 某个 task 执行特别慢的情况4.2 某个 task 莫名其妙内存溢出的情况5 查看导致数据倾斜的 key 的数据分布情况6 数据倾斜的解决方案6.1 使用 Hive ETL 预处理数据6.2 过滤少数导致倾…

Ubuntu中的 Everything 搜索软件 ==> fsearch

本文所使用的 Ubuntu 系统版本是 Ubuntu 22.04 ! 在 Windows 中&#xff0c;我经常使用 Everything 来进行文件搜索&#xff0c;搜索效率比 Windows 自带的高出千百倍。 那么在 Ubuntu 系统中&#xff0c;有没有类似的软件呢&#xff1f;那必须有&#xff0c;它就是 FSearch 。…

JavaScript-Web API基本认知-什么是DOM和BOM

基本认知 var、let、const选用Web API作用和分类什么是DOM什么是DOM树DOM对象&#xff08;重要&#xff09;什么是BOM var、let、const选用 var or let or const &#xff1f; 首先var 先排除&#xff0c;老派写法&#xff0c;问题很多&#xff0c;可以淘汰掉… let or const …

Docker 的数据管理 与 Docker 镜像的创建

目录 一、Docker 的数据管理 1.1.数据卷 1.2.数据卷容器 1.3.容器互联&#xff08;使用centos镜像&#xff09; 二、Docker 镜像的创建 2.1.基于现有镜像创建 2.2.基于本地模板创建 2.3.基于Dockerfile创建 2.3.1联合文件系统&#xff08;UnionFs&#xff09; 2.3.2…

多线程模型浅谈

优质博文&#xff1a;IT-BLOG-CN 笔者近期在维护的项目中发现了一些比较随机的问题&#xff0c;时有时无的&#xff0c;排查之后发现是使用多线程导致的&#xff0c;恍然之下研究了下多线程的底层模型相关知识&#xff0c;现不大家简要分享下。 一个程序进程可包含多个线程&am…