08 STM32 DMA

DMA 协助CPU,完成数据转运工作。
两个程序: DMA数据转运,DMA+AD多通道
DMA数据转运,将使用DMA,进行存储器到存储器的数据转运,也就是把一个数组里面的数据,复制到另一个数组里。
定义一个数组DateA ,里面存放1、2、3、4;然后再定义一个数组DateB,里面存的4个0,作为数据转运的目的地,我们会写一个模块,叫MyDMA,把源数组和目的数组地址传进去,再传入转运数据长度4,就这执行主循环的流程。
第一步:自增,变化一下源数组DataA 的测试数据,
第二步:显示一下DataA和DataB,然后延时一秒,方便观看
第三步:调用一下MyDMA_Transfer函数,使用DMA进行数据转运。和使用for循环使用CPU一个个手动地转运数据,效果是一样的
接着最后,再显示一下DataA和DataB,看一下数据是不是从DataA转运到了DataB
DMA+AD多通道程序:
用ADC的扫描模式来实现多通道采集,然后使用DMA来进行数据转运,最终,AD转换数据就会直接自动地跑到我们定义的数组里面,然后用OLED显示一下就可以了。和上一节AD多通道的现象是一样的,就只是在STM32端,使用了扫描模式,并且加了DMA转运数据。
DMA这个外设,是可以直接访问STM32内部的存储器的,包括运行内存SRAM、程序存储器Flash和寄存器等等,DMA都有权利直接访问它们。所以DMA才能完成数据转运工作。
这里外设指的是外设的寄存器,一般是外设的数据寄存器DR Data Register ,比如ADC的数据寄存器,串口的数据寄存器等等,这里存储器指的就是运行内存SRAM和程序存储器Flash,是我们存储变量数组和程序代码的地方,在外设和存储器,或者存储器和存储器之间,进行数据转运,就可以使用DMA来完成,并且在转运的过程中,无须CPU的参与,节省了CPU的资源,CPU省下时间,就可以干一些其他的,更加专业的事情,搬运数据这种杂活,交给DMA就行了。
从一个地方移动到另一个地方,就需要占用一个通道,如果有多个通道进行转运,那它们之间可以各转各的,互不干扰,这就是DMA通道。
如果DMA进行的是存储器到存储器的数据转运,比如我们想把Flash里的一批数据,转运到SRAM里去,使用软件触发之后,DMA就会一股脑地把这批数据,以最快的速度,全部转运完成,这也是我们想要的结果。那如果DMA进行的是外设到存储器的数据转运,因为外设的数据是有一定时机的,所有这时我们需要用硬件触发,那就得ADC每个通道AD转换完成后,硬件触发一次DMA,之后DMA再转运。触发一次转运一次,这样的数据才是正确的,才是我们想要的效果。特定的硬件触发,意思是每隔DMA的通道,它的硬件触发源是不一样的,你要使用某个外设的硬件触发源,就得使用它连接的那个通道,而不能任意选择通道,

运算器、控制器、存储器、输入设备和输出设备
其中运算器和控制器一般会合在一起叫做CPU,计算机核心关键部分就是CPU和存储器
存储器两个重要的知识点:内容和地址。
这个表是STM32中所有类型的存储器,和它们被安排的地址,STM32的数据手册里,也有存储器映像的图,一个意思。
外设到存储器实质上也是存储器到存储器之间的数据转运。
ROM第一块:程序存储器Flash 主闪存 也就是我们下载程序的位置 运行程序,一般也是从主闪存里面开始运行的。这一块存储器,STM32给它分配的地址是0x0800 0000 起始地址,也就是第一个字节的地址是0800这个,起始地址,也就是第一个字节的地址是0800这个,然后剩余字节的地址依次增长,每个字节都分配一个独一无二的地址,就像给每个住户编门牌号一样,程序才能精准地访问这个存储器,最终终止地址是多少呢,取决于它的容量。
如果在软件里看到,某个数据的地址是0800开头的,可以确定它属于主闪存的数据。
系统存储器和选项字节,两块存储器掉电不丢失,也是ROM的一种,实际上它们的存储介质也是Flash,只不过我们一般讲的Flash指的是主闪存Flash,而不指这两块区域,可以看出这两块区域位置是在ROM区的最后面。
系统存储器的用途:BootLoader程序是芯片出厂自动写入的,一般也不允许我们修改,
选项字节位置是在ROM区的最后面,下载程序可以不刷新选项字节的内容,存的主要是Flash的读保护,写保护,还有看门狗等等的配置。
运行内存SRAM 存放 我们在程序中定义 变量、数组、结构体的地方,类比电脑的话,运行内存就是内存条
外设寄存器 也就是我们初始化各个外设,最终所读写的东西。它的存储介质其实也是SRAM,只不过习惯把运行内存叫SRAM,外设寄存器直接叫寄存器
内核外设就是NVIC和SysTick,因为内核外设和其他外设不是一个厂家设计的,所以它们的地址也是被分开了。
在STM32中,所有的存储器都被安排到了0-8个F这个地址范围内,因为CPU是32位的,所以寻址范围就是32位的范围,最大可以支持4GB容量的存储器,而STM32中的存储器都是KB级别的,所以这个4GB的寻址空间,会有大量的地址是空的,算一下地址使用率还不到1%。
它这里写的是别名到Flash或者系统存储器,取决于Boot引脚,所以这里需要我们想要执行的程序,映射到0地址来。如果映射在Flash区,就是从Flash执行,如果映射再系统存储器区,就是从系统存储器运行BootLoader,如果映射到SRAM,就是从SRAM启动,怎么选择,由BOOT0和BOOT1两个引脚来决定。
具体的每个外设,又有它们自己的起始地址,比如TIM2的地址是4000 0000 又可以具体细分到每个寄存器的地址、寄存器里每个字节的地址。

左上角是M3的内核,里面包含了CPU和内核外设等等,剩下的所有东西,都可以把它看成是存储器,所以总共就CPU和存储器两个东西。
Flash是主闪存区,SRAM是运行内存,各个外设,都可以看成是寄存器,也是一种SRAM寄存器,一方面,CPU可以对寄存器进行读写,就像读写运行内存一样,另一方面,寄存器的每一位背后,都连接了一根导线,用于控制外设电路的状态,比如置引脚的高低电平,导通和断开开关,切换数据选择器。所以,寄存器是连接软件和硬件的桥梁。软件读写寄存器,就相当于控制硬件的执行。
既然外设是寄存器,寄存器就是存储器,那使用DMA进行数据转运,就都可以归结为一类问题了,就是从某个地址取内容,再放到另一个地址去。
为了高效有条理地访问存储器,设计了一个总线矩阵,总线矩阵的左端是主动段元,也就是拥有存储器的访问权,右边这些是被动单元,它们的存储器只能被左边的主动单元读写,主动单元这里,内核有DCode和系统总线,可以访问右边的存储器,其中DCode总线是专门访问Flash的,系统总线是访问其他东西的。另外,由于DMA要转运数据,所以DMA也要有访问的主动权,那主动单元除了内核CPU剩下的就是DMA总线了。这里DMA1有一条DMA总线,DMA2也有一条DMA总线,还有以太网外设自己私有的DMA,这个可以先不用管,在DMA1和DMA2里面,可以看到DAM1有7个通道,DMA2有5个通道,各个通道可以分别设置它们转运数据的源地址和目的地址,这样它们就可以各自独立地工作了。
下面的仲裁器是因为,虽然多个通道可以独立转运数据,但是DMA总线只有一条,所以所有的通道都只能分时复用这一条DMA总线,如果产生了冲突,那就会由仲裁器,根据通道的优先级,来决定谁先用,谁后用。另外总线矩阵里也有个仲裁器,如果DMA和CPU都要访问同一个目标,那么DMA就会暂停VPU的访问,以防止冲突,不过总线仲裁器,仍然会保证CPU得到一半的总线带宽,使CPU正常的工作,这就是仲裁器的作用。
DAM作为一个外设,也会有相应的配置寄存器,这里连接在总线右边的AHB总线上,所以DMA即便是总线矩阵的主动单元,可以读写各种存储器,也是AHB总线上的被动单元,CPU通过这一条线路,就可以对DMA进行配置了。
DMA请求就是DAM的硬件触发源,比如ADC转换完成,串口接收到数据,需要触发DMA转运数据的时候,会通过这条线路,向DMA发出硬件触发信号,之后DMA就可以执行数据转运的工作了,这就是DMA请求的作用。
Flash如果通过总线直接访问,无论是CPU还是DMA,都是只读的,不能写入,我们可以配置Flash接口控制器,对Flash进行写入,这个流程就比较复杂了,要先对Flash按页进行擦除,再写入数据,这是另一个课题。暂不讨论。
SRAM可以任意读写
外设寄存器得看手册说明是只读的还是只写的,还是读写的

在这个图里面,外设寄存器和Flash、SRAM是数据转运的两大站点,STM32手册里,所说的存储器,一般是特指Flash和SRAM,不包含外设寄存器,外设寄存器就会直接称为外设。转运方向有一个方向的参数,可以进行控制,另外还可以从存储器到存储器。由于Flash是只读的,所以DMA不可以进行SRAM到Flash,或者Flash到Flash的转运操作。
既然要进行数据转运,那肯定要指定从哪里转到哪里,具体怎么转了,所以外设和存储器两个站都有3个参数,第一个是起始地址,有外设端的起始地址,和存储器端的起始地址,这两个参数决定了数据是从哪里来,到哪里去的。
第二个是数据宽度,指定一次要转运要按多大的数据宽度来进行,它可以选择字节Byte,半字HalfWord和字Word,字节8位,半字16位,字是32位。
第三个参数,地址是否自增,参数的作用,指定一次转运完成之后,下一次转运是不是要把地址移动到下一个位置去,这相当于指针,p++,这个意思。比如ADC的扫描模式,用DMA进行数据转运,外设地址是ADC_DR寄存器,寄存器这边显然地址不用自增的,如果自增,那下一次转运就跑到别的寄存器那里去了。存储器这边地址就需要自增,每转运一个数据后,就往后挪个坑,要不然下次转运会覆盖掉。
传输计数器就是用来指定,总共需要转运几次。这是一个自减计数器,比如给它写5,那DMA就只能进行5次数据转运,每转运一次,计数器的数就会减1,当传输计数器减到0之后,DMA就不会再进行数据转运了,之前自增的地址,也会恢复到起始地址的位置,以方便DMA开始新一轮的转运。
自动重装器的作用是传输计数器减到0之后,是否要自动恢复到最初的值,比如传输计数器给5,如果不使用自动重装器,那转运5次之后,DMA就结束了,如果使用自动重装器,那就转运5次,计数器减到0后,就会立即重装到初始值5。决定转运的模式,如果不重装,就是正常的单次模式,如果重装就是循环模式。比如想转运一个数组,一般就是单次模式,转运一轮就结束了。如果是ADC扫描模式+连续转换,那为了配合ADC,DMA也要使用循环模式,所以这个循环模式和ADC的连续模式差不多,都是指定一轮工作结束后,是不是立即开始下一轮工作。
DMA触发控制,触发就是决定DMA需要在什么时候进行转运的,具体触发源选择由M2M这个参数决定Memory to Memory,to和2的英文同音,存储器到存储器的意思。
软件触发并不是调用某个函数触发一次,而是以最快的速度,连续不断地触发DMA,争取早日把传输计数器清零,完成这一轮的转换。所以这里的软件触发和之前外部中断和ADC的软件触发可能不太一样,可以把它理解为连续触发,那这个软件触发和循环模式,不能同时用,因为软件触发是想把传输计数器清零,循环模式是清零后自动重装,如果同时用的话,DMA就停不下来了。软件触发一般适用于存储器到存储器的转运。
硬件触发源可以选择ADC、串口、定时器等等,使用硬件触发的转运,一般都是与外设有关的转运,这些转运需要一定的时机,比如ADC转换完成、串口接收数据、定时时间到等等。
开关控制DMA_Cmd函数,当给DMA使能后,DMA准备就绪,就可以进行转运了。DMA转运的几个条件:
1.开关控制,DMA_Cmd必须使能
2.传输计数器必须大于0
3.触发源必须有触发信号
触发一次,转运一次,传输计数器自减一次,当传输计数器等于0,且没有自动重装时,这是无论是否触发,DAM都不会再进行转运了,此时就需要DMA_Cmd,给DISABLE,关闭DMA,再为传输计数器写一个大于0的数,再DMA_Cmd,给ENABLE,开启DMA,DMA才能继续工作。(不能在DMA开启时,写传输计数器,这是手册里的规定)
DMA请求:


这张图表示的是DMA的触发部分,DMA1的请求映像,7个通道。
每个通道都有一个数据选择器,可以选择硬件触发或软件触发,这个图不太好理解,因为一般数据选择器的侧边是输入选择控制位,图示的意思难道是EN给1,是硬件触发,EN给0是软件触发吗?显然不对,而且左边写的是软件触发,MEM2MEM位,难道M2M是软件触发吗,也不太好理解。所以看上面的PPT图才好理解。正确理解:EN位是开关控制,是决定这个数据选择器要不要工作,M2M选择1时软件触发。
可以看到每个通道的硬件触发源都是不同的,如果需要ADC1来触发的话,那就必须选择通道1,如果需要定时器2的更新事件来触发的话,那就必须选择通道2,剩下的同理,每个通道的硬件触发源都不同。
所以如果想使用某个硬件触发源的话,就必须使用它所在的通道,这就是硬件触发的注意事项。而如果使用软件触发的话,那通道就可以任意选择了,因为每个通道的软件触发都是一样的
优先级的判断类似中断的优先级。此处默认优先级是通道号越小,优先级越高

如果数据宽度一样,那就是正常的一个个转运,如果宽度不一样,那是怎么处理呢?
由表可知:如果目标的数据宽度比源端数据宽度大,那就在目标数据前面多出来的空位补0,否则就是把多出来的高位舍弃掉

这里的转运是一种复制转运,转运完成后DataA的数据并不会消失,

左边是ADC扫描模式的执行流程,有7个通道,触发一次之后,7个通道依次进行AD转换,然后转换结果都放到ADC_DR数据寄存器里面,我们要做的就是在每个单独的通道转换完成后,进行一个DMA数据转运,并且目的地址进行自增,这样数据就不会被覆盖了。
ADC扫描模式,在每个单独的通道转换完成后,没有任何标志位,也不会触发中断,所以程序不太好判断,某一个通道转换完成的时机是什么时候,但是根据UP的研究实战,虽然单个通道转换完成后,不产生任何的标志位和中断,但是应该会产生DMA请求,去触发DMA转运。这部分内容手册里没有详细描述。单个通道的DMA请求肯定是有的,不然实验就做不成了。
一般来说,DMA最常见的用途就是配合ADC的扫描模式,因为ADC扫描模式会有个数据覆盖的特征,或者可以说这个数据覆盖的问题是ADC固有的缺陷,这个缺陷使ADC和DMA成为了最常见的伙伴,ADC对DMA的需求是非常强烈的。像其他一些外设,使用DMA可以提高效率,是锦上添花的操作,但是不使用也可以,顶多是损失一些性能,但是这个ADC的扫描模式,如果不使用DMA,功能都会受到很大的限制。
代码编写:
查找表,字库数据可以把它们定义为常量,这样节省SRAM的空间,定义在Flash里面。地址由编译器确定,不同的程序,地址可能不一样,是不固定的,
外设寄存器的地址:地址是固定的,在程序里可以用结构体,很方便地访问寄存器。
如果想算某个寄存器的地址,就可以查手册计算一下,首先查这个寄存器所在外设的起始地址,然后再在外设的寄存器总表里,查一下偏移,起始地址+偏移,就是这个寄存器的实际地址,
如何知道ADC1->DR寄存器地址。在ADC1右键跳转到定义,
#define ADC1 ((ADC_TypeDef*)ADC1_BASE)
左边是一个强制类型转换,把ADC1_BASE转换为了ADC_TypeDef类型的指针,右边ADC1_BASE是ADC1的基地址,就是起始地址
ADC1的基地址就是APB2外设基地址+0x2400,APB2外设基地址就是外设基地址+0x10000,外设基地址就是0x4000 0000。基地址+偏移地址就是寄存器的实际地址,使用了非常巧妙的方法来实现这个偏移,那就是使用结构体,依次定义了各种寄存器,结构体成员的顺序和寄存器实际存放顺序是一一对应的。这就是STM32中,使用结构体来访问寄存器的流程
ADC1->DR 中ADC1是结构体指针,指向的是ADC1外设的起始地址,访问结构体成员,相当于加了一个地址偏移,起始地址+偏移,就是指定的寄存器,这里因为ADC1是一个结构体指针,所以要用->,也就是箭头这个符号来取成员。
步骤:
1.RCC开启DMA时钟,
2.直接调用DMA_Init,初始化各个参数,包括外设和存储器站点的起始地址、数据宽度、地址是否自增、方向、传输计数器、是否需要自动重装、选择触发源,还有通道优先级,开关控制,给指定的通道使能

恢复缺省配置
初始化
结构体初始化
使能
中断输出使能
DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); DMA设置当前数据寄存器 这个函数是给传输数据寄存器写数据的,
DMA_GetCurrDataCounter DMA获取当前数据寄存器,这个函数返回传输计数器的值,
获取标志位状态
清除标志位
获取中断状态
清除中断挂起位
除了中间两个函数,其他的都是经典函数
键盘上的Alt键,然后按鼠标左键进行框选,就可以以方框的形式框选,如果不按Alt,就是一行一行连续运行的框选。
可以看到此时硬件外设,已经实现了相互配合,和高度的自动化,各种操作都是硬件自己完成的,极大地减轻了软件负担,软件什么都不需要做,也不需要任何中断,可以再加一个外设,用ADC单次扫描,再用定时器去定时触发,这样就是定时器触发ADC,ADC触发DMA,整个过程完全自动,不需要程序手动进行操作。这就是STM32中,硬件自动化的一大特色。各种外设相互连接,互相交织,不再是传统的一个CPU单独控制多个独立的外设,而是外设之间相互合作形成一个网状结构,这样在完成某些简单且繁琐的工作的时候,就不需要CPU来统一调度了,可以直接通过外设之间的相互配合,自动完成这些繁琐的工作,大大提高外设的性能
相关文章:
08 STM32 DMA
DMA 协助CPU,完成数据转运工作。 两个程序: DMA数据转运,DMAAD多通道 DMA数据转运,将使用DMA,进行存储器到存储器的数据转运,也就是把一个数组里面的数据,复制到另一个数组里。 定义一个数组D…...
LLM之基于llama-index部署本地embedding与GLM-4模型并初步搭建RAG(其他大模型也可,附上ollma方式运行)
前言 日常没空,留着以后写 llama-index简介 官网:https://docs.llamaindex.ai/en/stable/ 简介也没空,以后再写 注:先说明,随着官方的变动,代码也可能变动,大家运行不起来,可以进…...
Python 异步爬虫:高效数据抓取的现代武器
标题:“Python 异步爬虫:高效数据抓取的现代武器” 在当今信息爆炸的时代,网络爬虫已成为数据采集的重要工具。然而,传统的同步爬虫在处理大规模数据时往往效率低下。本文将深入探讨如何使用 Python 实现异步爬虫,以提…...
【数据结构算法经典题目刨析(c语言)】使用数组实现循环队列(图文详解)
💓 博客主页:C-SDN花园GGbond ⏩ 文章专栏:数据结构经典题目刨析(c语言) 目录 一.题目描述 二.解题思路 1.循环队列的结构定义 2.队列初始化 3.判空 4.判满 5.入队列 6.出队列 7.取队首元素 8.取队尾元素 三.完整代码实…...
PTA L1-005 考试座位号
L1-005 考试座位号(15分) 每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生…...
软件测试3333
禅道? 学习正则表达式 目标: 能说出软件测试缺陷判定标准 能说出项目中缺陷的管理系统 能使用Excel对于缺陷进行管理 能使用工具管理缺陷 一、用例执行 说明:用例执行不通过,执行结果与用例的期望结果不一致(含义&…...
JJJ:结构体定义中常加的后缀:attribute ((packed))
__attribute__ ((packed)): 的作用就是告诉编译器取消结构体在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系,跟编译器有关 在GCC下:struct my{ char ch; int a;} sizeof(int)4…...
【HTML】DOCTYPE作用
<!DOCTYPE html> DOCTYPE是document type(文档类型)的缩写。是HTML5中一种标准通用标记语言的文档类型声明,告诉浏览器文档的类型,便于解析文档。不同渲染模式会影响浏览器对CSS代码甚至JS脚本的解析。它必须声明在第一行。…...
STM32学习记录-04-EXTI外部中断
1 中断系统 (1)中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续…...
Android Studio 动态表格显示效果
最终效果 一、先定义明细的样式 table_row.xml <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_h…...
Python 全栈系列264 使用kafka进行并发处理
说明 暂时考虑的场景是单条数据处理特别复杂和耗时的场景。 场景如下: 要对一篇文档进行实体处理,然后再对实体进行匹配。在这个过程当中,涉及到了好几部分服务: 1 实体识别服务2 数据库查询服务3 es查询服务 整个处理包成了服…...
【安全靶场】-DC-7
❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 一、收集信息 1.查看主机是否存活 nmap -T4 -sP 192.168.216.149 2.主动扫描 看开放了哪些端口和功能 n…...
0065__windows开发要看的经典书籍
windows开发要看的经典书籍_window编程书籍推荐-CSDN博客...
第133天:内网安全-横向移动域控提权NetLogonADCSPACKDC永恒之蓝
案例一:横向移动-系统漏洞-CVE-2017-0146 这个漏洞就是大家熟悉的ms17-010,这里主要学习cs发送到msf,并且msf正向连接后续 原因是cs只能支持漏洞检测,而msf上有很多exp可以利用 注意msf不能使用4.5版本的有bug 这里还是反弹权…...
【IoTDB 线上小课 06】列式写入=时序数据写入性能“利器”?
【IoTDB 视频小课】更新来啦!今天已经是第六期了~ 关于 IoTDB,关于物联网,关于时序数据库,关于开源... 一个问题重点,3-5 分钟,我们讲给你听: 列式写入到底是? 上一期我们详细了解了…...
【机器学习】小样本学习的实战技巧:如何在数据稀缺中取得突破
我的主页:2的n次方_ 在机器学习领域,充足的标注数据通常是构建高性能模型的基础。然而,在许多实际应用中,数据稀缺的问题普遍存在,如医疗影像分析、药物研发、少见语言处理等领域。小样本学习(Few-Shot Le…...
2024.08.14 校招 实习 内推 面经
地/球🌍 : neituijunsir 交* 流*裙 ,内推/实习/校招汇总表格 1、校招 | 理想汽车2025“理想”技术沙龙开启报名 校招 | 理想汽车2025“理想”技术沙龙开启报名 2、校招 | 紫光国芯2025校园招聘正式启动 校招 | 紫光国芯2025校园招聘正式…...
国产双通道集成电机一体化应用的电机驱动芯片-SS6951A
电机驱动芯片 - SS6951A为电机一体化应用提供一种双通道集成电机驱动方案。SS6951A有两路H桥驱动,每个H桥可提供较大峰值电流4.0A,可驱动两个刷式直流电机,或者一个双极步进电机,或者螺线管或者其它感性负载。双极步进电机可以以整…...
32 - II. 从上到下打印二叉树 II
comments: true difficulty: 简单 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9832%20-%20II.%20%E4%BB%8E%E4%B8%8A%E5%88%B0%E4%B8%8B%E6%89%93%E5%8D%B0%E4%BA%8C%E5%8F%89%E6%A0%91%20II/README.md 面试题 32 - II. 从上到下打…...
總結熱力學_3
參考: 陈曦<<热力学讲义>>http://ithatron.phys.tsinghua.edu.cn/downloads/thermodynamics.pdf 4 热力学量的测量 4.3 主温度计 常用的气体温度计有等体积气体温度计、声学气体温度计和介电常数气体温度计。很多气体在水的三相点附近都接近理想气体。但真正的理…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
DriveGPT4: Interpretable End-to-end Autonomous Driving via Large Language Model
一、研究背景与创新点 (一)现有方法的局限性 当前智驾系统面临两大核心挑战:一是长尾问题,即系统在遇到新场景时可能失效,例如突发交通状况或非常规道路环境;二是可解释性问题,传统方法无法解释智驾系统的决策过程,用户难以理解车辆行为的依据。传统语言模型(如 BERT…...
Ubuntu 可执行程序自启动方法
使用 autostart(适用于桌面环境) 适用于 GNOME/KDE 桌面环境(如 Ubuntu 图形界面) 1. 创建 .desktop 文件 sudo vi ~/.config/autostart/my_laser.desktop[Desktop Entry] TypeApplication NameMy Laser Program Execbash -c &…...
