【STM32】DMA原理,配置步骤超详细,一文搞懂DMA

2023-05-16

目录

DMA(Direct Memory Access)简介

DMA传输方式

DMA功能框图

DMA请求映像

DMA1控制器

DMA2控制器

通道

仲裁器

DMA主要特性

DMA处理

DMA数据配置

从哪里来到哪里去

外设到存储器

存储器到外设

存储器到存储器

要传多少,单位是什么

什么时候传输完成

DMA配置部分

DMA初始化结构体详解

DMA_InitTypeDef初始化结构体

DMA存储器到存储器模式实验

编程要点

DMA宏定义及相关变量定义

DMA初始化配置

存储数据对比

存储器到存储器模式主函数


DMA(Direct Memory Access)简介

DMA(Direct Memory Access)——直接存储器访问,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用CPU,即在传输数据的时候,CPU可以干其他的事情,好像是多线程一样。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是SRAM或者是FLASH。DMA控制器包含了DMA1和DMA2,其中DMA1有7个通道,DMA2有5个通道,这里的通道可以理解为传输数据的一种管道。要注意的是DMA2只存在于大容量的单片机中(这里的大容量是指FLASH的大小,规定FLASH在256-512KB的视为大容量)。

DMA传输数据从一个地址空间复制到另一个地址空间,提供在外设和存储器或者存储器和存储器之间的高速数据传输。

我们知道CPU有转移数据,计算,控制程序转移等很多功能,系统运作的核心就是CPU,CPU无时无刻都在处理着大量的事务,但有些事却没有那么重要,比如说数据的复制和存储数据,如果我们把这部分CPU的资源拿出来,让CPU去处理其他的复杂事务,就能够更好的利用CPU的资源。

因此:转移数据(尤其是大量数据)是可以不需要CPU参与的,比如希望外设A的数据拷贝到外设B,只要给外设提供一条数据通道,直接让数据由A拷贝到B不经过CPU的处理。

å¨è¿éæå¥å¾çæè¿°

DMA就是基于以上思想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题,有了DMA使得CPU可以更加专注的实用的的操作——计算、控制等。

DMA定义:DMA用来提供在外设和存储器之间后者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速的移动,这就节省了CPU的资源来做其他操作。

DMA传输方式

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节(如R1,R2寄存器等),主要涉及三种情况的数据传输,但本质上是一样的,都是从内存中的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。三种情况的数据传输如下:

  • 外设到内存(例如:ADC)
  • 内存到外设(例如:串口发送)
  • 内存到内存(例如:直接给一变量赋值一个常量型变量的值)

PS:这里讲下,对于SRAM动态内存存储的主要是变量等数据,FLASH存储的主要是常量以及code(代码)。

DMA功能框图

DMA控制器独立于内核,属于一个单独的外设,结构比较简单,从编程的角度来看,我们只需要掌握功能框图中的三部分内容即可,具体见DMA框图;DMA控制器的框图。

DMA请求映像

如果外设想要通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA控制器接收到应答信号之后,就会启动DMA传输,直到传输完毕

DMA有DMA1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道,不同的DMA控制器的通道对应着不同的外设请求,这决定了我们在软件编程上面该怎么设置,具体见DMA请求映像表。

DMA1控制器

从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])

产生的7个请求、通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。参见下图的DMA1请求映像

外设的DMA请求,可以通过设置相应外省寄存器中的控制位,被独立的开启或关闭

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

DMA2控制器

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

PS: 其中ADC3、SDIO和TIM8的DMA请求只在大容量产品中存在,这个在具体项目时要注意。

通道

DMA具有12个独立可编程的通道,其中DMA1有7个通道,DMA2有5个通道,每个通道对应不同的外设的DMA请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

仲裁器

当发生多个通道请求时,就意味着有先后响应处理的顺序问题,这就是由仲裁器来管理的。仲裁器管理DMA通道请求分为两个阶段。第一阶段属于软件阶段,可以在DMA_CCRx寄存器中设置,有4个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的DMA通道请求优先级一样的话,则它们优先级取决于通道编号,编号越低,优先级越高。比如通道0高于通道1,在大容量产品中DMA1控制器拥有高于DMA2控制器的优先级。

DMA主要特性

  • 12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道
  • 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能由软件来配置。
  • 在同一个DMA模块上,多个请求间的优先级可以通过软件编程设置(共有四级:非常高、高、中和低),优先权设置相等时由硬件决定(请求0优于请求1,依此类推)
  • 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
  • 支持循环的缓冲器管理
  • 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这三个事件标志逻辑或成为一个单独的中断请求。
  • 存储器和存储器之间的传输
  • 外设和存储器、存储器和外设之间的传输
  • 内存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标
  • 可编程的数据传输数目:最大为65535

DMA处理

在发生一个事件之后,外设向DMA控制器发送一个请求信号,DMA控制器根据通道的优先级处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果有更多的请求时,外设可以启动下一个周期。

总之,每次DMA传送由3个操作组成:

  • 从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址时DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储单元。
  • 存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
  • 执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

DMA数据配置

使用DMA,最核心的就是配置要传输的数据,包括数据从哪里来,要到哪里去,传输的数据的单位是什么,要传多少数据,是一次传输还是循环传输(即传输方式)

从哪里来到哪里去

我们知道DMA传输数据的方向有3个:从外设到存储器,从存储器到外设,从存储器到存储器。具体的方向DMA_CCR位DIR配置:0代表从外设到存储器,1表示从存储器到外设。这里面涉及到的外设地址由DMA_CPAR配置,存储器地址由DMA_CMAR配置。

外设到存储器

当我们使用从外设到存储器传输时,以ADC采集为例。DMA外设寄存器的地址对应的就是ADC数据寄存器的地址,DMA存储器的地址就是我们自定义变量(用来接收存储AD采集的数据)的地址。方向我们设置外设为源地址。

存储器到外设

当我们使用从存储器到外设传输时,以串口向电脑发送数据为例。DMA外设寄存器的地址对应就是串口数据寄存器地址,DMA存储器的地址是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置为外设为目标地址

存储器到存储器

当我们使用从存储器到存储器传输时,以内部FLASH向内部SRAM复制数据为例。DMA外设寄存器的地址对应的就是内部FLASH(我们这里把内部FLASH当作一个外设来看)的地址,DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部FLASH的数据)的地址。方向我们设置外设(即内部FLASH)为源地址。跟上面两个不一样的是,这里需要把DMA_CRR位14:MEM2MEM:存储器到存储器模式配置为1,启动M2M模式。

要传多少,单位是什么

当我们配置好数据要从哪里来到哪里去之后,我们还需要知道我们要传输的数据是多少,数据的单位是什么。

以串口向电脑发送数据为例,我们可以一次性给电脑发送很多数据,具体多少由DMA_CNDTR

配置,这是一个32位的寄存器,一次最多能传输65535个数据。

要想传输正确,源和目标地址存储的数据宽度还必须一致,串口数据寄存器是8位的,所以我们定义的要发送的数据也必须是8位的。外设的数据宽度由DMA_CCRx的PSIZE[1:0]配置,可以是8/16/32位,存储器的数据宽度由DMA_CCRx的MSIZE[1:0]配置,可以是8/16/32位。

在DMA控制器的控制下,数据想要有条不紊的从一个地方搬移到另一个地方,还必须正确设置两边数据指针的增量模式。外设的地址指针由DMA_CCRx的PINC配置,存储器的地址指针由MINC配置。以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定。

什么时候传输完成

数据什么时候传输完成,我们可以通过查询标志位后者通过中断的方式来鉴别。每个DMA通道在DMA传输过半、传输完成、传输出错时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。有关各标志位的详细描述可参考相应手册的寄存器部分。

传输完成还分为两种模式,是一次传输还是循环传输,一次传输很好理解,即使传输一次之后就停止,要想再传输的话,必须关闭DMA使能之后在重新配置后才能继续传输。循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输,不断地重复。具体的由DMA_CRRx寄存器的CIRC循环模式位控制。

DMA配置部分

DMA初始化结构体详解

标准库函数对每个外设都建立了一个初始化结构体xxx_InitTypeDef(xxx位外设名称),结构体成员用于设置外设工作参数,并由标准库函数xxx_Init()调用这些设定参数进入设置外设相应的寄存器,达到配置外设的工作环境的目的。

PS:以上的就是固件库编程的总体思路,并不只是这一个实验,固件库编程的“套路”都是这样的。

DMA_InitTypeDef初始化结构体

typedef struct
{
  uint32_t DMA_PeripheralBaseAddr; //外设地址

  uint32_t DMA_MemoryBaseAddr;     //存储器地址

  uint32_t DMA_DIR;                //传输方向

  uint32_t DMA_BufferSize;         /传输数目

  uint32_t DMA_PeripheralInc;      //外设地址增量模式

  uint32_t DMA_MemoryInc;          //存储器地址增量模式

  uint32_t DMA_PeripheralDataSize; //外设数据宽度

  uint32_t DMA_MemoryDataSize;     //存储器数据宽度

  uint32_t DMA_Mode;               //模式选择

  uint32_t DMA_Priority;           //通道优先级

  uint32_t DMA_M2M;                //存储器到存储器模式

}DMA_InitTypeDef;

DMA存储器到存储器模式实验

编程要点

  1. 使能DMA时钟(凡是外设,第一步永远是开时钟)
  2. 配置DMA数据参数
  3. 使能DMA,进行传输
  4. 等待传输完成,并对源数据和目标地址数据进行比较

DMA宏定义及相关变量定义

#define BUFFER_SIZE			32        //定义传输的数据数量
#define DMA_MTM_CLK 		RCC_AHBPeriph_DMA1    //定义DAM的外设时钟
#define DMA_MTM_CHANNEL		DMA1_Channel5         //定义DAM的通道


void DMA_MTM_Config(void);                        //DMA初始化函数声明
uint8_t Buffercmp(const uint32_t* pBuffer,         
                  uint32_t* pBuffer1, uint16_t BufferLength);    //比较数据函数声明

DMA初始化配置

void DMA_MTM_Config(void)
{
	/*定义DMA初始化结构体*/
	DMA_InitTypeDef DMA_InitStruct;
	/*打开DMA外设时钟,DMA挂载在AHB总线时钟上*/
	RCC_AHBPeriphClockCmd(DMA_MTM_CLK, ENABLE);
	/*设置外设基地址,即源地址*/
	DMA_InitStruct.DMA_PeripheralBaseAddr =	(uint32_t) aSRC_Const_Buffer;
	/*设置目标存储器地址,即目标地址*/
	DMA_InitStruct.DMA_MemoryBaseAddr	  =	(uint32_t) aDST_Buffer;
	/*配置传输方向,这里为止解决的是从哪里来,到哪里去*/
	DMA_InitStruct.DMA_DIR 				  =	DMA_DIR_PeripheralSRC;
	/*设置要传输的数量*/
	DMA_InitStruct.DMA_BufferSize		  =	BUFFER_SIZE;
	/*设置外设的字宽*/
	DMA_InitStruct.DMA_PeripheralDataSize =	DMA_PeripheralDataSize_Word;
	/*设置外设地址增量*/
	DMA_InitStruct.DMA_PeripheralInc	  =	DMA_PeripheralInc_Enable;
	/*设置存储器地址增量*/
	DMA_InitStruct.DMA_MemoryInc		  =	DMA_MemoryInc_Enable;
	/*设置存储器的宽度*/
	DMA_InitStruct.DMA_MemoryDataSize	  =	DMA_MemoryDataSize_Word;
	/*设置传输模式是一次性传输,还是循环传输*/
	DMA_InitStruct.DMA_Mode				  =	DMA_Mode_Normal;
	/*设置优先级*/
	DMA_InitStruct.DMA_Priority			  =	DMA_Priority_High;
	/*开启存储器到存储器传输*/
	DMA_InitStruct.DMA_M2M				  =	DMA_M2M_Enable;
	/*DMA初始化*/
	DMA_Init(DMA_MTM_CHANNEL, &DMA_InitStruct);
	/*打开DMA通道*/
	DMA_Cmd(DMA_MTM_CHANNEL,  ENABLE);


存储数据对比

**
  * 判断指定长度的两个数据源是否完全相等,
  * 如果完全相等返回1,只要其中一对数据不相等返回0
  */
uint8_t Buffercmp(const uint32_t* pBuffer, 
                  uint32_t* pBuffer1, uint16_t BufferLength)
{
  /* 数据长度递减 */
  while(BufferLength--)
  {
    /* 判断两个数据源是否对应相等 */
    if(*pBuffer != *pBuffer1)
    {
      /* 对应数据源不相等马上退出函数,并返回0 */
      return 0;
    }
    /* 递增两个数据源的地址指针 */
    pBuffer++;
    pBuffer1++;
  }
  /* 完成判断并且对应数据相对 */
  return 1;  
}

存储器到存储器模式主函数

extern const uint32_t aSRC_Const_Buffer[BUFFER_SIZE];
extern uint32_t aDST_Buffer[BUFFER_SIZE];

void delay(uint32_t count)
{
	for(;count!=0;count--);

}
int main(void)
{
	
	uint8_t status=0;
	LED_GPIO_Config();
	LED_YELLOW;
	delay(0xFFFFFF);
	DMA_MTM_Config();
	
	while(DMA_GetFlagStatus(DMA1_FLAG_TC5) == RESET);
	
	status =  Buffercmp(aSRC_Const_Buffer, 
                   aDST_Buffer, BUFFER_SIZE);
	
	if(status == 1)
	{
		LED_GREEN;
	}
	else
	{
		LED_RED;
	}
	while(1)
	{
	
	}
}

这里最后在说明一点,关于存储器到外设的比如串口发送数据的例子和这个是大同小异的,主要就是DMA的配置,有关具体的可以看我资源里面的关于DMA实验的资料。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32】DMA原理,配置步骤超详细,一文搞懂DMA 的相关文章

  • 134-基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真+源程序...

    资料编号 134 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 ds1302时钟 DHT11温湿度 电机 蜂鸣器 制作一个基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真 2 通过DH
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • arm64 上的 Linux:从 mmapped 相干 DMA 缓冲区发送数据时,sendto 导致“未处理的故障:对齐故障 (0x96000021)”

    我正在构建一个基于配备arm64 CPU的UltraScale FPGA的数据采集系统 数据通过DMA传输到RAM 驱动程序中的 DMA 缓冲区保留如下 virt buf i dma zalloc coherent pdev gt dev
  • 匹配 STM32F0 和 zlib 中的 CRC32

    我正在研究运行 Linux 的计算机和 STM32F0 之间的通信链路 我想对我的数据包使用某种错误检测 并且由于 STM32F0 有 CRC32 硬件 并且我在 Linux 上有带有 CRC32 的 zlib 所以我认为在我的项目中使用
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • 毕业设计 江科大STM32的智能温室控制蓝牙声光报警APP系统设计

    基于STM32的智能温室控制蓝牙声光报警APP系统设计 1 项目简介 1 1 系统构成 1 2 系统功能 2 部分电路设计 2 1 stm32f103c8t6单片机最小系统电路设计 2 2 LCD1602液晶显示电路设计 2 2 风
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 最终启动顺序错误 - STM32L476 的 Eclipse System Workbench 调试

    我正在尝试调试和运行 STM32L476 的简单汇编代码 我已经设置了 Eclipse Oxygen 在 Eclipse 中安装了最新版本的 System Workbench 插件并安装了 ST Link 驱动程序 IDE 成功构建了程序
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • STM32 暂停调试器时冻结外设

    当到达断点或用户暂停代码执行时 调试器可以停止 Cortex 中代码的执行 但是 当皮质停止在暂停状态下执行代码时 调试器是否会冻结其他外设 例如 DMA UART 和定时器 您只能保留时间 r 取决于外围设备 我在进入主函数时调用以下代码
  • DMA 与中断驱动的 I/O

    我不太清楚 DMA 和中断 I O 之间的区别 当前正在阅读操作系统概念 第 7 版 具体来说 我不确定在这两种情况下何时会发生中断 以及在这两种情况下 CPU 在什么时候可以自由地执行其他工作 我一直在读但不一定能调和的东西 中断驱动 通
  • Freertos低功耗管理

    空闲任务中的低功耗Tickless处理 在整个系统运行得过程中 其中大部分时间都是在执行空闲任务的 空闲任务之所以执行 因为在系统中的其他任务处于阻塞或者被挂起时才会执行 因此可以将空闲任务的执行时间转换成低功耗模式 在其他任务解除阻塞而准
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • 库函数点亮Led

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • 为什么在 Linux 中使用 kmalloc 和 GFP_DMA 时会得到高地址?

    我正在 Linux 中为 DMA 设备编写设备驱动程序 在Linux 设备驱动程序 第 15 章 http lwn net images pdf LDD3 ch15 pdf 它说 对于有这种限制的设备 应该分配内存 通过将 GFP DMA
  • STM32 上的位置无关代码 - 指针

    我已成功在 STM32 上构建并运行位置无关的代码 向量表和 GOT 已修补 一切正常 但我对这样的代码有问题 double myAdd double x return x 0 1 double ptrmyAdd double myAdd
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015

随机推荐

  • 【统计计算】课程总结笔记

    传统的主成分分析法 xff08 PCA xff09 缺陷在于 xff1a 对于 小样本问题 xff08 样本维数d远大于样本个数N xff09 xff0c 样本协方差矩阵规模 d d 太大了 xff0c 在后续求特征值问题中计算量较大 于是
  • ros --- 双目相机内参与外参标定

    ros 双目相机内参与外参标定 小觅相机直接获取参数手动重新标定1 双目相机内外参标定生成标定板录制 stereo calibra bag标定标定结果标定验证 2 双目 43 imu外参标定录制 stereo 43 imu calibra
  • RT-Thread之入门跑代码

    本文将讲述如何在window10中利用tensorflow跑代码 xff0c 并且编译成bin文件 xff0c 最后在k210中运行 一 在window上安装tensorflow框架 xff08 python3 7 xff09 1 安装An
  • keil5的基本使用

    项目文件后缀 硬件下载 1 编译 2 下载 软件仿真 一 基本知识 1 选择软件仿真选项 2 编译 3 启动软件仿真 4 运行代码 二 软件仿真的具体使用 1 我们想运行到 哪一步就在那一步添加断点 xff08 在左边的空白处左键点一下就可
  • pytorch之池化层

    实际图像里 xff0c 我们感兴趣的物体不会总出现在固定位置 xff1a 即使我们连续拍摄同一个物体也极有可能出现像素位置上的偏移 这会导致同一个边缘对应的输出可能出现在卷积输出 Y中的不同位置 xff0c 进而对后面的模式识别造成不便 在
  • 串口通信协议

    通信协议的基本概念 用于定义通信过程及细节规则的协议称为通信协议 xff0c 通信系统之间为了完成通信所必须遵循的规则和约定 xff08 数据包格式 字段的内容 字段的含义 发送的时间 接收的时间等细节 xff09 个人理解 xff1a 就
  • gazebo的安装

    安装ros 1 1设置软件源 xff1a 清华源或者阿里都可 sudo sh c 39 etc lsb release amp amp echo 34 deb Index of ros ubuntu 清华大学开源软件镜像站 Tsinghua
  • 驱动开发基础

    1 Hello驱动 我们应用程序使用open函数的时候 xff0c 会调用内核的sys open函数 xff0c 然后接下来 1 然后打开普通文件的话会使用文件系统操作硬件 xff0c 2 要是打开驱动文件 xff0c 会使用驱动程序对应的
  • ARM架构与编程 · 基于IMX6ULL

    一 嵌入式系统硬件介绍 cpu 43 RAM xff08 内存 xff09 43 FALSH 集成 xff08 flash存储设备 xff09 61 MCU 单片机 AP MPU 进化之后可以外接内存和存储设备 跑复杂的操作系统 xff0c
  • 嵌入式常用算法

    1 冒泡排序 1 两两之间对比 xff0c 要是顺序排 xff0c 一轮过后最大的就是最后一个 2 下一轮参加排序的数比上一轮少一个 include lt iostream gt using namespace std void paixu
  • 实习面试的总结

    2023 4 3 阿凡达机器人 驱动开发实习生 1 怎么注册一个字符设备 注销 1 注册一个设备号 2 设备号加载进内核 3 创建类 4 创建设备 注销 1 从内核中删除 2 删除设备 3 删除类 2 怎么将新加入的网络设备加入到内核中去
  • 字符设备结构体与probe函数

    1 设备结构体 设备结构体 struct ap3216c dev dev t devid 设备号 主设备号 43 次设备号 struct cdev cdev cdev 字符设备对象 xff0c 字符设备驱动的一种结构体类型 struct c
  • SLAM --- VIO 基于 EKF 开源

    1 VIO based on EKF 已知一致性的Visual Inertial EKF SLAM 实现添加链接描述
  • 暗夜精灵7 linux

    Ubuntu18 04 安装nvidia显卡驱动 distro non free 小乌坞的博客 CSDN博客 注意在关闭显示界面的时候需要输入密码 xff0c 不然会一直卡着 在验证是否屏蔽驱动的时候 xff0c 要先重启一下 cuda L
  • linux应用编程

    项目内容 开发板内部使用c语言调用硬件驱动实现各种测试功能 xff0c 保存测试结果 外部程序通过socket接口使用tcp协议与开发板通信进行信息传输 xff0c 最后使用python GUI构造一个界面按照测试顺序逐步显示出各个模块的测
  • NUC10快乐装机

    NUC10装机 由于为了RoboMaster比赛 xff0c 身为全队唯一一个视觉队员兼队长的我 xff0c 经过疫情期间的再三斟酌 xff0c 最后决定工控机选择为nuc10 为什么选择nuc10 作为第一年参赛的新队伍 xff0c 视觉
  • 什么是PID?讲个故事,通俗易懂

    什么是PID xff1f PID xff0c 就是 比例 xff08 proportional xff09 积分 xff08 integral xff09 微分 xff08 derivative xff09 xff0c 是一种很常见的控制算
  • C语言对寄存器的封装

    目录 1 封装总线和外设基地址 2 封装寄存器列表 3 修改寄存器的位操作的方法 把变量的某位清零 把变量的某几个连续位清零 对变量的某几位进行赋值 对变量的某位取反 1 封装总线和外设基地址 在编程上为了方便理解和记忆 xff0c 我们把
  • STM32——串口通信及实验

    目录 1 按照数据传送的方向 xff0c 分为 xff1a 2 按照通信方式 xff0c 分为 xff1a STM32串口通信基础 串口通信过程 UART xff08 USART xff09 框图 串口通信实验 编程要点 代码分析 通信接口
  • 【STM32】DMA原理,配置步骤超详细,一文搞懂DMA

    目录 DMA xff08 Direct Memory Access xff09 简介 DMA传输方式 DMA功能框图 DMA请求映像 DMA1控制器 DMA2控制器 通道 仲裁器 DMA主要特性 DMA处理 DMA数据配置 从哪里来到哪里去