当前位置: 首页 > news >正文

DMA直接存储器存取

参考视频:[8-1] DMA直接存储器存取_哔哩哔哩_bilibili

DMA简介

DMADirect Memory Access)直接存储器存取

DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源

12个独立可配置的通道:DMA1(7个通道),DMA2(5个通道)

每个通道都支持软件触发和特定的硬件触发

存储器到存储器的转运:一般使用软件触发

外设到存储器的数据转运:一般使用硬件触发

STM32F103C8T6 DMA资源:DMA1(7个通道)

存储器映像

  1. ROM是只读存储器,是一种非易失性、掉电不丢失的存储器。
  2. RAM是随机存储器,是一种易失性、掉电丢失的存储器。

DMA框图

Cortex-M3内核,包含了CPU和内核外设;其余的都可以看成存储器。

Flash是主闪存,SRAM是运行内存。各个外设可以看成是寄存器,也是一种SRAM存储器。

寄存器可以看成是一种特殊的存储器:

  • 一方面,CPU可以对寄存器进行读写。

  • 另一方面,寄存器的每一位背后,都连接了一根导线,这些导线可以用于控制外设电路的状态,比如置高低电平、导通和断开开关、切换数据选择器等等。

所以寄存器是连接软件和硬件的桥梁。软件读写寄存器,就当于在控制硬件的执行。

总线矩阵的左端,是主动单元,也就是拥有存储器的访问权;右端的是被动单元,它们的存储器只能被左边的主动单元读写。

DCode总线是专门访问Flash的,系统总线是访问其他东西的。

由于DMA要转运数据,DMA也必须要有访问的主动权。

DMA1、DMA2、以太网MAC都有一条DMA总线。

DMA1有七条通道,DMA2有五条通道,各个通道可以分别设置它们转运数据的源地址和目的地址。

仲裁器存在的原因:虽然有多个通道可以独立转运数据,但是最终DMA总线只有一条,所以所有的通道都只能分时复用这一条DMA总线,如果产生了冲突,那就会由仲裁器,根据通道的优先级来决定谁先用谁后用。

另外,在总线矩阵这里也有仲裁器,如果DMA和CPU都要访问同一个目标,那么DMA就会暂停CPU的访问,以防止冲突,不过总线仲裁器,仍然会保证CPU得到一半的总线带宽,保证CPU也会正常的工作。

AHB从设备,也就是DMA自身的寄存器。因为DMA作为一个外设,它自己也会有相应的配置寄存器。AHB从设备连接在了总线右边的AHB总线上。

所以DMA既是总线矩阵的主动单元,可以读写各种存储器,也是AHB总线上的被动单元。

DMA请求,也就是DMA触发,线路右边的触发源是各个外设,所以DMA请求就是DMA的硬件触发源,比如ADC转换完成,串口接收到数据。需要触发DMA转运数据的时候,就会通过这条线路,向DMA发出硬件触发信号,之后DMA就可以执行数据转运的工作了。

DMA基本结构

方向参数是用来控制从外设到存储器,还是从存储器到外设。另外还有一种转运方式,就是存储器到存储器。由于Flash是只读的,所以只能进行从SRAM到SRAM,或者Flash到SRAM。

外设存储器两个站点,都有三个参数:

起始地址:有外设端的起始地址,存储器端的起始地址。这两个参数决定了数据是从哪里来到哪里去的。

数据宽度:指定一次转运要按多大的数据宽度来进行,可以选择字节、半字和字。字节是8位,半字是16位,字是32位。

地址是否自增:指定一次转运完成后,下一次转运,是不是要把地址移动到下一个位置去。

传输计数器:这个是用来指定总共需要转运几次,是一个自减计数器。当减到0之后,之前自增的地址,也会恢复到起始地址的位置。

自动重装器:传输计数器减到0之后,是否要自动恢复到最初的值。不重装就是单次模式,重装就是循环模式。

触发,就是决定DMA需要在什么时机进行转运的。触发源有硬件触发和软件触发,具体选择哪个由M2M来决定。

给M2M位1时,DMA就会选择软件触发,软件触发是指以最快的速度,连续不断地触发DMA,争取早日把传输计数器清零,完成这一轮的转换(这里的软件触发和之前的ADC和外部中断的软件触发不太一样)。软件触发和循环模式不能同时用。软件触发一般是存储器到存储器的转运。

硬件触发源可以选择ADC、串口、定时器等等。硬件触发源的转运一般都是与外设有关的转运,这些转运需要一定的时机,比如ADC转换完成、串口收到数据、定时时间到等等,在硬件达到这些时机时,传一个信号过来,来触发DMA进行转运。

开关控制,DMA_Cmd函数,使能之后就可以进行DMA转运了。

DMA进行转运的几个条件:

1. 开关控制,DMA_Cmd必须使能。

2. 传输计数器必须大于0。

3. 触发源,必须有触发信号。

触发一次,转运一次,传输计数器自减一次,当传输计数器等于0,且没有自动重装时,这时无论是否触发,DMA都不会再进行DMA转运了。此时就需要DMA_Cmd,给DISABLE,关闭DMA,再为传输计数器写一个大于0的数,再DMA_Cmd,给ENABLE,开启DMA,DMA才能继续工作。注意一下,写传输计数器时,必须要先关闭DMA,再进行。

DMA1请求映像

DMA1的七个通道,每个通道都有一个数据选择器,可以选择硬件触发或者软件触发。EN是开关控制;M2M位是数据选择器的控制位,用于选择是硬件触发还是软件触发。

外设请求信号那里,每个通道的硬件触发源都是不同的,如果需要用ADC1来触发的话,就必须选择通道1,如果需要定时器2的更新事件来触发的话,就必须选择通道2。如果用软件触发,就可以任意选择通道了。

通道1,选择哪个硬件触发源是由对应的外设是否开启了DMA输出来决定的,比如要使用DMA1,那会有个库函数ADC_DMACmd,必须使用这个库函数开启ADC1的这一路输出,它才有效。如果都开启了,理论上3个硬件都可以触发。

之后七个通道进入仲裁器,进行优先级判断,最终产生内部的DMA1请求。

数据宽度与对齐

此部分是为了解决外设寄存器和存储器的数据宽度不一致问题。

当目标宽度比源端宽度大,就在目标数据前面多出来的空位补0。

当目标宽度比源端宽度小,把源端多出来的高位舍弃掉。

数据转运+DMA

首先是外设站点和存储器站点的起始地址、数据宽度、地址是否自增。

在这个例子里,外设地址显然应该填DataA数组的首地址。存储器地址给DataB数组的首地址。

数据宽度,两个数组的类型都是uint8_t,所以数据宽度都是按8位的字节传输。

由下图可以看出,两边地址都应该自增。

方向参数是外设站点转移到存储器站点。

显然要转运7次,所以传输计数器给7,自动重装暂时不需要。

这里选择软件触发,因为是存储器到存储器的转运,不需要等待硬件时机。

最后调用DMA_Cmd,给DMA使能。

ADC扫描模式+DMA

触发一次后,七个通道依次进行AD转换,然后转换结果都放到ADC_DR数据寄存器里面,在每个单独的通道转换完成后,进行一次DMA数据转运,并且目的地址进行自增。

所以DMA的配置:

外设地址写入ADC_DR这个寄存器的地址。存储器的地址,可以在SRAM中定义一个数组ADValue,然后把ADValue的地址当作存储器的地址。

数据宽度,因为ADC_DR和SRAM数组,都是uint16_t的数据,所以数据的宽度都是16位的半字传输。

地址是否自增:显然外设地址不自增,存储器地址自增。

传输方向是外设站点到存储器站点。

传输计数器,通道有7个,所以计数7次,计数器是否自动重装,可以看ADC的配置,如果ADC是单次扫描,那DMA的传输计数器可以不自动重装,转换一轮就停止,如果ADC是连续扫描,那么DMA就可以使用自动重装。在ADC启动下一轮的转换时,DMA也启动下一轮的转运。

触发选择:ADC_DR的值是在ADC单个通道转换完成后才会有效,所以DMA转运的时机,需要和ADC单个通道转换完成同步。所以DMA的触发要选择ADC的硬件触发。ADC扫描模式,在每个单独的通道转换完成后,没有任何标志位,也不会触发中断,但是它会产生DMA请求,去触发DMA转运。

DMA.h中的函数

// 恢复缺省配置
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);
// 初始化
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);
// 结构体初始化
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);
// 使能
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);
// 中断输出使能
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);
// DMA设置当前数据寄存器
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); 
// 给传输计数器写入数据,之后DMA获取当前数据寄存器
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
// 获取标志位状态
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);
// 清除标志位
void DMA_ClearFlag(uint32_t DMAy_FLAG);
// 获取中断状态
ITStatus DMA_GetITStatus(uint32_t DMAy_IT);
// 清除中断挂起位
void DMA_ClearITPendingBit(uint32_t DMAy_IT);

DMA数据转运

  1. RCC开启DMA的时钟
  2. 调用DMA_Init,初始化各个参数
  3. 进行开关控制,DMA_Cmd

接线图:

MyDMA.c

#include "stm32f10x.h"                  // Device headeruint16_t MyDMA_Size;void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{MyDMA_Size = Size;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);DMA_InitTypeDef DMA_InitStructure;// 外设站点DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;// 存储器DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 传输方向DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 缓存区大小,传输计数器DMA_InitStructure.DMA_BufferSize = Size;// 传输模式,是否使用自动重装DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 是否是存储器到存储器,选择硬件触发还是软件触发DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;// 优先级DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;DMA_Init(DMA1_Channel1, &DMA_InitStructure);DMA_Cmd(DMA1_Channel1, DISABLE);
}void MyDMA_Transfer(void)
{DMA_Cmd(DMA1_Channel1, DISABLE);DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);DMA_Cmd(DMA1_Channel1, ENABLE);while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);DMA_ClearFlag(DMA1_FLAG_TC1);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyDMA.h"uint8_t DataA[] = {0x01, 0x02, 0x03, 0x04};
uint8_t DataB[] = {0, 0, 0, 0};int main(void)
{OLED_Init();MyDMA_Init((uint32_t)DataA, (uint32_t)DataB, 4);OLED_ShowString(1, 1, "DataA");OLED_ShowString(3, 1, "DataB");OLED_ShowHexNum(1, 8, (uint32_t)DataA, 8);OLED_ShowHexNum(3, 8, (uint32_t)DataB, 8);while(1){DataA[0] ++;DataA[1] ++;DataA[2] ++;DataA[3] ++;OLED_ShowHexNum(2, 1, DataA[0], 2);OLED_ShowHexNum(2, 4, DataA[1], 2);OLED_ShowHexNum(2, 7, DataA[2], 2);OLED_ShowHexNum(2, 10, DataA[3], 2);OLED_ShowHexNum(4, 1, DataB[0], 2);OLED_ShowHexNum(4, 4, DataB[1], 2);OLED_ShowHexNum(4, 7, DataB[2], 2);OLED_ShowHexNum(4, 10, DataB[3], 2);Delay_ms(1000);MyDMA_Transfer();OLED_ShowHexNum(2, 1, DataA[0], 2);OLED_ShowHexNum(2, 4, DataA[1], 2);OLED_ShowHexNum(2, 7, DataA[2], 2);OLED_ShowHexNum(2, 10, DataA[3], 2);OLED_ShowHexNum(4, 1, DataB[0], 2);OLED_ShowHexNum(4, 4, DataB[1], 2);OLED_ShowHexNum(4, 7, DataB[2], 2);OLED_ShowHexNum(4, 10, DataB[3], 2);Delay_ms(1000);}
}

DMA+AD多通道

接线图:

AD.c

#include "stm32f10x.h"                  // Device headeruint16_t AD_Value[4];void AD_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  // 非连续转换模式ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  // 对齐方式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 触发方式ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;ADC_InitStructure.ADC_NbrOfChannel = 4;  // 通道数目ADC_InitStructure.ADC_ScanConvMode = DISABLE;  // 扫描转换模式ADC_Init(ADC1, &ADC_InitStructure);DMA_InitTypeDef DMA_InitStructure;// 外设站点DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 传输方向DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 缓存区大小,传输计数器DMA_InitStructure.DMA_BufferSize = 4;// 传输模式,是否使用自动重装DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 是否是存储器到存储器,选择硬件触发还是软件触发DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 优先级DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;DMA_Init(DMA1_Channel1, &DMA_InitStructure);DMA_Cmd(DMA1_Channel1, ENABLE);ADC_DMACmd(ADC1, ENABLE);ADC_Cmd(ADC1, ENABLE);// 调用复位校准ADC_ResetCalibration(ADC1);// 等待复位校准完成,该函数是返回复位校准的状态,所以要等待复位校准完成的话,要加一个while循环while (ADC_GetResetCalibrationStatus(ADC1) == SET) ;// 开始校准ADC_StartCalibration(ADC1);// 等待校准完成while (ADC_GetCalibrationStatus(ADC1) == SET);
}// 首先软件触发,然后等待转换完成,也就是等待EOC标志位置1,最后读取ADC数据寄存器
void AD_GetValue(void)
{DMA_Cmd(DMA1_Channel1, DISABLE);DMA_SetCurrDataCounter(DMA1_Channel1, 4);DMA_Cmd(DMA1_Channel1, ENABLE);ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);DMA_ClearFlag(DMA1_FLAG_TC1);
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1, 1, "AD0:");OLED_ShowString(2, 1, "AD1:");OLED_ShowString(3, 1, "AD2:");OLED_ShowString(4, 1, "AD3:");while(1){AD_GetValue();OLED_ShowNum(1, 5, AD_Value[0], 4);OLED_ShowNum(2, 5, AD_Value[1], 4);OLED_ShowNum(3, 5, AD_Value[2], 4);OLED_ShowNum(4, 5, AD_Value[3], 4);Delay_ms(100);}
}

相关文章:

DMA直接存储器存取

参考视频:[8-1] DMA直接存储器存取_哔哩哔哩_bilibili DMA简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源 12个独立可…...

java计算机毕设课设—坦克大战游戏

这是什么系统? 坦克大战游戏是一款以坦克为主题的射击游戏,旨在为玩家提供一个刺激、有趣的游戏体验。该游戏不仅拥有丰富的功能,还注重玩家的互动体验。此系统是使用Java语言实现坦克大战游戏程序,玩家通过连接访问进入游戏&…...

Vue入门-指令学习-v-on

v-on 作用:注册事件 添加监听 提供处理逻辑 语法: v-on:事件名"内联语句" v-on:事件名"methods中的函数名" 注意:" v-on:"可以替换为" " v-on:click"XXX" --> cli…...

Maven的生命周期与依赖作用域介绍

说明:本文介绍Maven的生命周期,以及在pom.xml文件中每个依赖(dependency标签内)scope标签的内容。 Maven生命周期 在IDEA项目中,右侧边栏,点Maven,可以看到以下生命周期。 其中, c…...

Django学习笔记四:urls配置详解

Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。URL配置是Django框架中非常重要的一部分,它定义了URL模式与视图函数之间的映射关系。以下是Django URL配置的详解: URL配置文件 通常,URL配置位于Django项…...

NIO的callback调用方式

1.消费者 public class CallbackClient {public static void main(String[] args) {try {SocketChannel socketChannel SocketChannel.open();socketChannel.connect(new InetSocketAddress("127.0.0.1", 8000));ByteBuffer writeBuffer ByteBuffer.allocate(32);…...

百度文心智能体平台开发萌猫科研加油喵

百度文心智能体平台开发萌猫科研加油喵 在科研的道路上,研究生们常常面临着巨大的压力和挑战。为了给这个充满挑战的群体带来一些鼓励和温暖,我借助百度文心智能体平台开发了一个独特的智能体 《萌猫科研加油喵》。 一、百度文心智能体平台介绍 百度文…...

Hive数仓操作(十六)

DML(数据操作语言)指的是用于操作数据的 SQL 语言部分,主要包括对数据的插入、更新、删除等操作。Hive 的 DML语句主要包括 INSERT、UPDATE 和 DELETE 。以下是一些重要的 Hive DML 语句及其解析。 Hive的DML语句 一、 插入操作INSERT 一般…...

第十二届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)(第一套)

一.题目分析 (1).题目 (2).题目分析 1.串口功能分析 a.串口接收车辆出入信息:通过查询车库的车判断车辆是进入/出去 b.串口输出计费信息:输出编号,时长和费用 c.计算停车时长是难点&#x…...

MongoDB入门:安装及环境变量配置

一、安装MonggoDB Windows系统安装MongoDB 1、下载MongoDB安装包 访问MongoDB官方网站,选择与Windows系统相匹配的MongoDB Community Server版本进行下载。 Download MongoDB Community Server | MongoDB 2、安装MongoDB 双击下载好的安装包文件,根…...

利用 notepad++ 初步净化 HaE Linkfinder 规则所提取的内容(仅留下接口行)

去掉接口的带参部分 \?.*去掉文件行 .*\.(docx|doc|xlsx|xls|txt|xml|html|pdf|ppt|pptx|odt|ods|odp|rtf|md|epub|css|scss|less|sass|styl|png|jpg|jpeg|gif|svg|ico|bmp|tiff|webp|heic|dds|raw|vue|js|ts|mp4|avi|mov|wmv|mkv|flv|webm|mp3|wav|aac|flac|ogg|m4a).*(\r\…...

RCE(remote command/code execute)远程命令注入

远程命令注入RCE RCE(remote command/code execute,远程命令执行)漏洞,一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口,比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上。一般会给…...

​一篇关于密码学的概念性文章

文章目录 1. 引言2. 加密学基本概念3. 加密算法的类型3.1 对称密钥加密(SKC)3.2 公钥密码学3.3 哈希函数3.4. 为什么需要三种加密技术?3.5 密钥长度的重要性4. 信任模型4.1 PGP信任网络4.2 Kerberos4.3 公钥证书和证书颁发机构4.4 总结5. 密码算法的实际应用5.1 密码保护5.2…...

什么是汽车中的SDK?

无论是在家里使用预制菜包做一顿大厨级别的晚餐,还是使用IKEA套组装配出时尚的北欧风桌子,我们都熟悉这样一种概念:比起完全从零开始,使用工具包可以帮助我们更快、更高效地完成一件事。 在速度至关重要的商业软件领域&#xff0…...

利用CRITIC客观权重赋权法进行数值评分计算——算法过程

1、概述 ‌CRITIC客观评价法是一种基于指标的对比强度和指标之间的冲突性来确定指标客观权数的方法。‌ 该方法适用于判断数据稳定性,并且适合分析指标或因素之间有着一定的关联的数据‌。 CRITIC方法的基本原理包括两个主要概念:对比强度和指标之间的…...

一个月学会Java 第4天 运算符和数据转换

Day4 运算符和数据转换 今天来讲运算符,每个运算符的作用和现象,首先我们先复习一下数据类型, day2讲过基本数据类型有八种,int、short、long、byte、char、boolean、float、double,分别为四个整型、一个字符型、一个布…...

Stream流的终结方法(一)

1.Stream流的终结方法 2.forEach 对于forEach方法,用来遍历stream流中的所有数据 package com.njau.d10_my_stream;import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.function.Consumer; import java.util…...

GO网络编程(二):客户端与服务端通信【重要】

本节是新知识,偏应用,需要反复练习才能掌握。 目录 1.C/S通信示意图2.服务端通信3.客户端通信4.通信测试5.进阶练习:客户端之间通信 1.C/S通信示意图 客户端与服务端通信的模式也称作C/S模式,流程图如下 其中P是协程调度器。可…...

快速熟悉Nginx

一、Nginx是什么? ‌Nginx是一款高性能、轻量级的Web服务器和反向代理服务器。‌ ‌特点‌:Nginx采用事件驱动的异步非阻塞处理框架,内存占用少,并发能力强,资源消耗低。‌功能‌:Nginx主要用作静态文件服…...

VikParuchuri/marker 学习简单总结

核心代码 VikParuchuri/marker 的核心是使用https://github.com/VikParuchuri/surya的 pdf 模型,注意不仅仅是ocr,在marker的代码里面有标注ocr 是option的。强制OCR 要设置:OCR_ALL_PAGES=true核心代码就是convert.py def convert_single_pdf(fname: str,model_lst: List,…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制&#xff0…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...