当前位置: 首页 > 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,…...

【AI知识点】词嵌入(Word Embedding)

词嵌入(Word Embedding)是自然语言处理(NLP)中的一种技术,用于将词语或短语映射为具有固定维度的实数向量。这些向量(嵌入向量)能够捕捉词语之间的语义相似性,即将语义相近的词映射到…...

Python从入门到高手5.1节-Python简单数据类型

目录 5.1.1 理解数据类型 5.1.2 Python中的数据类型 5.1.3 Python简单数据类型 5.1.4 特殊的空类型 5.1.5 Python变量的类型 5.1.6 广州又开始变热 5.1.1 理解数据类型 数据类型是根据数据本身的性质和特征来对数据进行分类,例如奇数与偶数就是一种数据类型。…...

Hbase要点简记

Hbase要点简记 Hbase1、底层架构2、表逻辑结构 Hbase HBase是一个分布式的、列式的、实时查询的、非关系型数据库,可以处理PB级别的数据,吞吐量可以到的百万查询/每秒。主要应用于接口等实时数据应用需求,针对具体需求,设计高效率…...

RabbitMQ的各类工作模式介绍

简单模式 P: ⽣产者, 也就是要发送消息的程序 C: 消费者,消息的接收者 Queue: 消息队列, 图中⻩⾊背景部分. 类似⼀个邮箱, 可以缓存消息; ⽣产者向其中投递消息, 消费者从其中取出消息.特点: ⼀个⽣产者P,⼀个消费者C, 消息只能被消费⼀次. 也称为点对点(Point-to-…...

李宏毅深度学习-图神经网络GNN

图卷积的开源代码网站DGL 好用的还是 GAT, GIN(指出最好的卷积 就是 hi 邻居特征(而且只能用 sum)) Introduction GNN 可以理解为是由 Graph(图) Nerual Networks 组合而成的,图结构应该都在数据结构与…...

Redis篇(缓存机制 - 分布式缓存)(持续更新迭代)

目录 一、单点 Redis 的问题 1. 数据丢失问题 2. 并发能力问题 3. 故障恢复问题 4. 存储能力问题 5. 四种问题的解决方案 二、Redis持久化(两种方案) 1. RDB持久化 1.1. 简介 1.2. 执行时机 save命令 bgsave命令 停机时 触发RDB条件 1.3. …...

python交互式命令时如何清除

在交互模式中使用Python,如果要清屏,可以import os,通过os.system()来调用系统命令clear或者cls来实现清屏。 [python] view plain copy print? >>> import os >>> os.system(clear) 但是此时shell中的状态是:…...

Token,Cookie,Session,JWT详解

这四个技术虽然在功能上有所不同,但在web应用中常常一起使用,已实现用户身份验证,授权和会话管理。 Token:指的是用于身份验证,授权成信息交换的令牌,可以有不同的实现方式,例如JWT。 Cookie&…...

opencv-rust 系列: 1, 安装及运行自带示例和测试程序

opencv-rust 系列: 1, 安装及运行自带示例和测试程序 运行环境: ubuntu ; rust 已安装; 对rust的掌握为三脚猫程度一. opencv-rust安装:二. 运行自带examples和tests 运行环境: ubuntu ; rust 已安装; 对rust的掌握为三脚猫程度 一. opencv-rust安装: 安装软件: sudo apt in…...

Linux系统编程(一):Linux平台上静态库和动态库的制作与使用

本篇文章我们通过 gcc 或g编译器手动制作Linux 平台上的静态库和动态库。由于涉及的内容较多,所以后面分多次来完成本篇文章。做任何事情都是一样的,我们不可能一次性把处在舒适区的事情做好。 本讲主要内容如下: 库的基本概念Linux 平台上…...