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

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.mzph.cn/pingmian/4333.shtml

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

相关文章

【mysql】mysql命令使用大全,你想要的都在这里

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

go设计模式之工厂方法模式

工厂方法模式 什么是工厂方法模式 工厂方法模式是一种创建型设计模式&#xff0c;它定义了一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。工厂方法使一个类的实例化推迟到其子类。 这个接口就是工厂接口&#xff0c;子类就是具体工厂类&#xff0c;而需要创…

《QT实用小工具·四十三》历史编辑器(支持历史搜索 关键字匹配)

1、概述 源码放在文章末尾 该项目实现了在输入框中输入部分信息能全部展现之前的历史输入信息&#xff0c;支持历史搜索和关键词匹配&#xff0c;项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #include "historymodel.h" #include <QM…

实时通讯技术 WebRTC 介绍

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

大语言模型Ollama

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Ollama简介 Ollama是一个开源的大语言模型平台&#xff0c;它允许用户在本地环境中运行、创建和共享大型语言模型。Ollama提供了丰富的功能和特性&#xff0c;使得用户可以…

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务&#xff08;Spring MVC Springboot&#xff09;同时允许跨域 Tomcat 配置允许跨域Web 项目配置允许跨域Tomcat 同时允许静态文件和 Web 服务跨域 偶尔遇到一个 Tomcat 部署项目跨域问题&#xff0c;因为已经处理过…

mysql-sql-练习题-1

文章目录 环境注释建表 5张建库学生表课程表教师表分数表总表 语法书写顺序in学过/没学过完全相同 环境 Windows cmd&#xff08;普通用户/管理员&#xff09; mysql -uroot -pmysql版本&#xff0c;模式&#xff08;可自定义&#xff09; select version(),global.sql_mode…

在PR中使用 obs 和 vokoscreen 录制的视频遇到的问题

1. obs 录制的视频 在 Adobe Premiere Pro CS6 中只有音频没有视频 2. vokoscreen 录制的视频&#xff0c;没有声音 这是是和视频录制的编码有关系&#xff0c;也和显卡驱动关系 首先 obs 点击 文件 ---> 设置 录制的视频都是可以正常播放的&#xff0c;在PR不行。更…

用NuGet安装 Oracle ODP.NET

oracle官网原文&#xff1a;Using NuGet to Install and Configure Oracle Data Provider for .NET Using NuGet to Install and Configure Oracle Data Provider for .NET In this section, you will install ODP.NET NuGet packages from nuget.org. Select View > Solut…

【网站项目】图书推荐系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

C++高级特性:C/C++内存结构模型(十一)

1、内存结构 C/C语言一只被认为是一种底层语言&#xff0c;与其他语言不一样&#xff0c;对内存结构理解是C/C程序员从入门到入土的开端。 其他编程语言对内存管理是透明的&#xff0c;程序员无序关心可以认为是一个黑盒&#xff1b;而C/C不一样理解好内存结构有利于编写健壮性…

使用C++实现尾插式循环链表结构

在编码中避免不了使用链表&#xff0c;特别是循环链表&#xff0c;很多同学使用时为了省事直接使用C STL库中的链表实现&#xff0c;这样当然很简单也不容易出错&#xff0c;但同时也不可避免的带来了一些问题&#xff1a; 是半个黑盒&#xff0c;虽然能看源码&#xff0c;但是…

【禅道客户案例】同方智慧能源数智化转型新实践 禅道助力前行

同方智慧能源是同方股份有限公司的骨干企业。依托中核集团、清华大学的科技优势&#xff0c;坚持技术和资源双核驱动&#xff0c;基于30多年行业积淀&#xff0c;面向建筑、交通、工业、北方供热、数据中心等主要用能场景提供设计咨询、产品技术、投资建设、运营服务&#xff0…

DELL PowerEdge服务器通过iDRAC升级BIOS遇到的问题

本文对PowerEdge 12G系统&#xff0c;也就是iDRAC 7版本升级BIOS中遇到的几个问题做个总结&#xff0c;对于其他版本理论上应该也是适用的。如果还遇到其他问题&#xff0c;可以添加VX&#xff0c;VX号为 StorageExpert 进行进一步的分析探讨。 第一个问题&#xff0c;成功下载…

Android 11 裁剪系统显示区域(适配异形屏)

概述 在显示技术中&#xff0c;"OverScan"&#xff08;超扫描&#xff09;是一种调整显示图像边界的技术。通常情况下&#xff0c;OverScan 会在显示屏的边缘周围裁剪一小部分图像。这种裁剪是为了确保显示内容在屏幕上的完整可见性&#xff0c;尤其是在老式电视或投…

ZABAPGIT问题,导入github上的程序包时报 DBSQL_DUPLICATE_KEY_ERROR

跟踪程序发现在94050行 INSERT seocompotx FROM TABLE it_descriptions 报的错 刚开始&#xff0c;不想着改动他&#xff0c;把seocompotx 表的数据做下指定清楚&#xff0c;但是5次清楚后&#xff0c;果断注释掉 改成 MODIFY seocompotx FROM TABLE it_descriptions。 在用…

航片水体空洞修补

水体空洞情况如下图所示&#xff1a; 水体空洞修补结果如下图所示&#xff1a; 操作视频教程&#xff1a; MCM智拼图软件V8.5-漏洞空洞修补-水体修补_哔哩哔哩_bilibili

鸿蒙OpenHarmony【小型系统 编译】(基于Hi3516开发板)

编译 OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式&#xff0c;build.sh脚本编译方式请参考[使用build.sh脚本编译源码]。 使用build.sh脚本编译源码 进入源码根目录&#xff0c;执行如下命令进行版本编译。 ./build.sh --product-name name --ccache 说明&…

基于数据挖掘的斗鱼直播数据可视化分析系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 随着网络直播平台的兴起&#xff0c;斗鱼直播作为其中的佼佼者&#xff0c;吸引了大量用户和观众。为了更好地理解和分析斗鱼直播中的数据&#xff0c;本项目介绍了一个基于数据挖掘的斗鱼直播数据…

【AI导师写作】毕业论文答辩PPT生成

无论是大专、本科或者硕博&#xff0c;撰写毕业论文、开题报告、文献综述、任务书、课程论文、调研报告等都是必不可少的一件事。而这些任务重往往都需要我们花费大量的时间和精力&#xff0c;而“AI导师写作”在这一方面无疑提供了高效和便捷。可毕业季的论文答辩也是每个学者…