串口DMA方式发送&接收

USART 串口 DMA 发送和接收 串口DMA发送: 发送数据的流程: 前台程序中有数据要发送,则需要做如下几件事 1.      在数据发送缓冲区内放好要发送的数据,说明:此数据缓冲区的首地址必须要在DMA初始化的时候写入到DMA配置中去。 2.      将数据缓冲区内要发送的数据字节数赋值给发送DMA通道,(串口发送DMA和串口接收DAM不是同一个DMA通道) 3.      开启DMA,一旦开启,则DMA开始发送数 阅读详情

串口DMA方式收发

        笔者使用的是STM32F407VET6,共包含6路串口,页尾处程序已将全部串口的DMA收发配置完成,本文仅以串口1为例进行讲解。(查看代码可直接跳至第二节或页尾处下载)

1 STM32F4 DMA  简介

        DMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。
        STM32F4 最多有 2 个 DMA 控制器(DMA1 和 DMA2),共 16 个数据流(每个控制器 8 个),每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8个通道(或称请求)。每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。

它可以处理一下事务:

  • 外设到储存器的传输
  • 储存器到外设的传输
  • 储存器到储存器的传输

注意:DMA1 控制器 AHB 外设端口与 DMA2 控制器的情况不同,不连接到总线矩阵,因此,仅 DMA2 数据流能够执行存储器到
存储器的传输。

        其中,数据流的多通道选择,是通过 DMA_SxCR 寄存器控制的,如图1所示:

                                                                                   图1 通道选择

        上图可以看出,DMA_SxCR 控制数据流到底使用哪一个通道,每个数据流有 8 个通道可供选择,但每次只能选择其中一个通道进行 DMA 传输,DMA2 的各数据流通道映射表,如表 1 所示

                                                                             表1 DMA2数据流映射表

        上表就列出了 DMA2 所有可能的选择情况,来总共 64 种组合,比如本章我们要实现串口1的 DMA 发送,即USART1_TX,就必须选择 DMA2 的数据流 7,通道 4,来进行 DMA 传输。这里注意一下,有的外设(比如 USART1_RX)可能有多个通道可以选择,随意选择一个就可以。

重要寄存器简介

(1) DMA 中断状态寄存器

        该寄存器总共有 2 个:DMA_LISR 和 DMA_HISR,每个寄存器管理 4 数据流(总共 8 个),DMA_LISR 寄存器用于管理数据流 0~3,而 DMA_HISR 用于管理数据流 4~7。如果开启了 DMA_LISR 中这些位对应的中断,则在达到条件后就会跳到中断服务函数里面去,即使没开启,也可以通过查询这些位来获得当前 DMA 传输的状态。这里常用的是 TCIFx位,即数据流 x 的 DMA 传输完成与否标志。

注意:此寄存器为只读寄存器,所以在这些位被置位之后,只能通过【中断标志清除寄存器】来清除。

(2)DMA 中断标志清除寄存器

        该寄存器同样有 2 个:DMA_LIFCR 和 DMA_HIFCR,同样是每个寄存器控制 4 个数据流。该寄存器为只写寄存器,其各位就是用来清除 【中断状态寄存器】的对应位的,通过写 1 清除。

(3) DMA 数据流 x 配置寄存器(DMA_SxCR)

        该寄存器控制着 DMA 的很多相关信息,包括数据宽度、外设及存储器的宽度、优先级、增量模式、传输方向、中断允许、使能等都是通过该寄存器来设置的。所以 DMA_ SxCR 是 DMA 传输的核心控制寄存器。

(4)DMA 数据流 x 数据项数寄存器(DMA_SxNDTR)

        这个寄存器控制 DMA 数据流 x 的每次传输所要传输的数据量。其设置范围为 0~65535。并且该寄存器的值会随着传输的进行而减少,当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。所以可以通过这个寄存器的值来知道当前DMA 传输的进度。

注意:这里是数据项数目,而不是指的字节数。比如设置数据位宽为 16 位,那么传输一次(一个项)就是 2 个字节

(5)DMA 数据流 x 的外设地址寄存器(DMA_SxPAR)

        该寄存器用来存储 STM32F4 外设的地址,比如使用串口 1,那么该寄存器必须写入 0x40011004(其实就是&USART1_DR)。

(6) DMA 数据流 x 的存储器地址寄存器

        由于 STM32F4 的 DMA 支持双缓存,所以存储器地址寄存器有两个:DMA_SxM0AR 和 DMA_SxM1AR,其中 DMA_SxM1AR 仅在双缓冲模式下,才有效。比如使用 USART1_TX_BUF[USART_LEN] 数组来做存储器,那么在DMA_SxM0AR 中写入 &USART1_TX_BUF 就可以了。

2 收发配置

2.1串口配置(使能DMA收发)

重点:使能串口1的接收、发送和串口1的DMA接收、发送并使能串口1的空闲中断

/*------------------------------------------------
* 函数名:void Init_USART1(u32 pclk2,u32 bound)
* 功  能:初始化IO 串口1
* 参  数:pclk2: PCLK2时钟频率(Mhz)
	      bound: 波特率 
* 返回值: 无
------------------------------------------------*/
void Init_USART1(u32 pclk2,u32 bound)
{  	 
	float temp;
	u16 mantissa;
	u16 fraction;	   
	temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV@OVER8=0
	mantissa=temp;				 //得到整数部分
	fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0 
        mantissa<<=4;
	mantissa+=fraction; 
	RCC->AHB1ENR|=1<<0;   	//使能PORTA口时钟  
	RCC->APB2ENR|=1<<4;  	//使能串口1时钟 
	GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出
 	GPIO_AF_Set(GPIOA,9,7);	//PA9,AF7
	GPIO_AF_Set(GPIOA,10,7);//PA10,AF7  	   
	//波特率设置
 	USART1->BRR=mantissa; 	//波特率设置	 
	USART1->CR1&=~(1<<15); 	//设置OVER8=0 
	
	USART1->CR1|=1<<3;  	//串口发送使能 
	USART1->CR3|=1<<7;      //使能串口1的DMA发送
	
#if EN_USART1_RX		  	//如果使能了接收	
	USART1->CR1|=1<<2;  	//串口接收使能
	USART1->CR3|=1<<6;      //使能串口1的DMA接收  
	USART1->CR1|=1<<4;    	//使能空闲中断	    	
	MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级 
#endif
	USART1->CR1|=1<<13;  	//串口使能
}

2.2两个变量

发送和接收的数据都将以如下两个变量为指定储存器。

#define USART_LEN  	50  	//定义最大接收字节数 50
u8 USART1_TX_BUF[USART_LEN];
u8 USART1_RX_BUF[USART_LEN];

2.3 DMA配置

(1)使能DMA2时钟,并等待数据流可配置 。

(2)设置外设地址

(3)设置储存器地址

(4)设置传输数据量

(5)设置数据流7的配置信息

(6)开启数据流7的传输完成中断

/*------------------------------------------------
* 函数名:void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr,u8 dir)
* 功  能:配置DMA
* 参  数:DMA_Streamx: DMA数据流(DMA1_Stream0~7/DMA2_Stream0~7)
	     chx: DMA通道选择(范围:0~7)
	     par: 外设地址
		 mar: 存储器地址
		 ndtr: 数据传输量
		 dir: 数据传输方向(DMA_DIR_PeripheralToMemory / DMA_DIR_MemoryToPeripheral / DMA_DIR_MemoryToMemory)
* 返回值: 无
------------------------------------------------*/
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr,u8 dir)
{ 
	DMA_TypeDef *DMAx;
	u8 streamx;
	if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
	{
		DMAx=DMA2;
		RCC->AHB1ENR|=1<<22;//DMA2时钟使能 
	}else 
	{
		DMAx=DMA1; 
 		RCC->AHB1ENR|=1<<21;//DMA1时钟使能 
	}
	while(DMA_Streamx->CR&0X01);//等待DMA可配置 
	streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18;		//得到stream通道号
 	if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16);	//清空之前该stream上的所有中断标志
	else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4);    //清空之前该stream上的所有中断标志
	else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16);//清空之前该stream上的所有中断标志
	else DMAx->LIFCR|=0X3D<<6*streamx;						//清空之前该stream上的所有中断标志
	
	DMA_Streamx->PAR=par;		//DMA外设地址
	DMA_Streamx->M0AR=mar;		//DMA存储器0地址
	DMA_Streamx->NDTR=ndtr;		//n个数据项
	DMA_Streamx->CR=0;			//先全部复位CR寄存器值 

	switch(dir)
	{
		case DMA_DIR_PeripheralToMemory: //外设到存储器模式
			DMA_Streamx->CR&=~(1<<6);
			DMA_Streamx->CR&=~(1<<7);
			break;
		case DMA_DIR_MemoryToPeripheral: 
			DMA_Streamx->CR|=1<<6;
			DMA_Streamx->CR&=~(1<<7);
			break;
		case DMA_DIR_MemoryToMemory: 
			DMA_Streamx->CR&=~(1<<6);
			DMA_Streamx->CR|=1<<7;
			break;
		default:break;
	}
	DMA_Streamx->CR|=0<<8;		//非循环模式(即使用普通模式)
	DMA_Streamx->CR|=0<<9;		//外设非增量模式
	DMA_Streamx->CR|=1<<10;		//存储器增量模式
	DMA_Streamx->CR|=0<<11;		//外设数据长度:8位
	DMA_Streamx->CR|=0<<13;		//存储器数据长度:8位
	DMA_Streamx->CR|=1<<16;		//中等优先级
	DMA_Streamx->CR|=0<<21;		//外设突发单次传输
	DMA_Streamx->CR|=0<<23;		//存储器突发单次传输
	DMA_Streamx->CR|=(u32)chx<<25;//通道选择
	//DMA_Streamx->FCR=0X21;	//FIFO控制寄存器

        DMA2_Stream7->CR|=1<<4;		//使能传输完成中断
        MY_NVIC_Init(2,1,DMA2_Stream7_IRQn,2);
}

2.4 设置MDA状态标志

注意:如果连续运行两个发送函数,如下,则可能在第一个还未发送完成时就会直接执行第二次发送。

myDMAprintf(USART1,"usart = %d\tch = %f\r\n",1,1.567);
myDMAprintf(USART1,"usart = %d\tch = %f\r\n",1,1.567);

其运行效果如图1所示,第一次仅发送了"us"即被第二次发送覆盖了。

运行效果
图1 运行效果

故需设置相应的标志位,对每次发送的状态进行标记,若正在进行传输,则等待,实现如下:

typedef enum 
{
	BUSY,
	IDLE
}DMA_Flag;

volatile DMA_Flag DMA2_Stream7_Flag = IDLE;		//USART1

2.5 DMA中断函数

        每次传输完成(串口发送完成)后,都会触发一次中断,此时只需在中断函数中清除相应标志位并对发送状态进行标记即可。

//对应USART1发送
void DMA2_Stream7_IRQHandler(void)
{
	if((DMA2->HISR&(1<<27)))
	{
		DMA2->HIFCR|=1<<27;
                DMA2_Stream7_Flag = IDLE;
	}
}

2.6 DMA初始化

        查询手册可知,串口1发送为DMA2的数据流7,通道4,并为内存到外设模式,而串口1接收为DMA2的数据流5,通道4,并为外设到内存模式。

注意:此处需提前开启一次DMA接收,否则第一次接收会产生错误数据。

//USART1发送 --- DMA2,数据流7,CH4---USART1_TXD 外设为串口1,存储器为USART1_TX_BUF,长度为:USART_LEN
MYDMA_Config(DMA2_Stream7,4,(u32)&USART1->DR,(u32)USART1_TX_BUF,USART_LEN,DMA_DIR_MemoryToPeripheral);
//USART1接收 --- DMA2,数据流5,CH4---USART1_RXD 外设为串口1,存储器为USART1_RX_BUF,长度为:USART_LEN
MYDMA_Config(DMA2_Stream5,4,(u32)&USART1->DR,(u32)USART1_RX_BUF,USART_LEN,DMA_DIR_PeripheralToMemory);
MYDMA_Enable(DMA2_Stream5,(u32)USART1_RX_BUF,USART_LEN);//开始一次DMA传输!

2.6 开启一次串口DMA传输

配置DMA数据流、内存地址及传输量。

void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx, u32 mar, u16 ndtr)
{
	DMA_Streamx->CR&=~(1<<0); 	//关闭DMA传输 
	while(DMA_Streamx->CR&0X1);	//确保DMA可以被设置  
	DMA_Streamx->M0AR=mar;		//DMA存储器地址
	DMA_Streamx->NDTR=ndtr;		//DMA传输数据量 
	DMA_Streamx->CR|=1<<0;		//开启DMA传输
}

2.7 格式化发送

该部分已封装为类似printf()的发送函数,大致为3个部分:

(1)格式化数据为字符串;

(2)判断发送状态,若“忙”,则等待。

(3)设置好储存器地址,使能发送并设置发送状态;

/*------------------------------------------------
* 函数名:Status myDMAprintf(USART_TypeDef *USARTx, const char *format, ...)
* 功  能:仿 printf 函数 
* 参  数:*USARTx: 串口号
	      *pString: 打印内容
	      ... : 变量
* 返回值: 状态
------------------------------------------------*/
Status myDMAprintf(USART_TypeDef *USARTx, const char *format, ...)
{
	va_list args; 	
	u16 len;
	
	if(format == NULL)
		return 1;
	va_start(args, format);
	
	if(USARTx == USART1)
	{
		len = vsnprintf((char *)USART1_TX_BUF, USART_LEN, format, args);
		while(DMA2_Stream7_Flag != IDLE);
		MYDMA_Enable(DMA2_Stream7,(u32)USART1_TX_BUF,len);
		DMA2_Stream7_Flag = BUSY;
	}
	else if(USARTx == USART2)
	{
		len = vsnprintf((char *)USART2_TX_BUF, USART_LEN, format, args);
		while(DMA1_Stream6_Flag != IDLE);
		MYDMA_Enable(DMA1_Stream6,(u32)USART2_TX_BUF,len);
		DMA1_Stream6_Flag = BUSY;
	}	
	else if(USARTx == USART3)
	{
		len = vsnprintf((char *)USART3_TX_BUF, USART_LEN, format, args);
		while(DMA1_Stream3_Flag != IDLE);
		MYDMA_Enable(DMA1_Stream3,(u32)USART3_TX_BUF,len);
		DMA1_Stream3_Flag = BUSY;
	}	
	else if(USARTx == UART4)
	{
		len = vsnprintf((char *)UART4_TX_BUF, USART_LEN, format, args);
		while(DMA1_Stream4_Flag != IDLE);
		MYDMA_Enable(DMA1_Stream4,(u32)UART4_TX_BUF,len);
		DMA1_Stream4_Flag = BUSY;
	}	
	else if(USARTx == UART5)
	{
		len = vsnprintf((char *)UART5_TX_BUF, USART_LEN, format, args);
		while(DMA1_Stream7_Flag != IDLE);
		MYDMA_Enable(DMA1_Stream7,(u32)UART5_TX_BUF,len);
		DMA1_Stream7_Flag = BUSY;
	}	
	else if(USARTx == USART6)
	{
		len = vsnprintf((char *)USART6_TX_BUF, USART_LEN, format, args);
		while(DMA2_Stream6_Flag != IDLE);
		MYDMA_Enable(DMA2_Stream6,(u32)USART6_TX_BUF,len);
		DMA2_Stream6_Flag = BUSY;
	}
	else
		return 2;
	
	va_end(args);
	
	return 0;
}

2.8串口DMA接收

        当串口进入空闲状态时即开启一次DMA接收,下次数据到来时DMA会自动搬运数据至指定的储存器(此处为USART1_TX_BUF),搬运完成后会再次触发空闲中断,此时清除空闲中断标志位、DMA传输完成标志位和传输错误标志位,并清除接收内存,开启下一次接收。

void USART1_IRQHandler(void)
{
	u8 temp;
	u16 len;
	
	if(USART1->SR&(1<<4))//检测到线路空闲
	{
//软件序列清除IDLE标志位
		temp = USART1->SR;
		temp = USART1->DR;
		
		DMA2_Stream5->CR &=~(1<<0); //关闭DMA传输,准备重新配置
		DMA2->HIFCR|=1<<11;			//清除DMA2_Steam5传输完成标志
		DMA2->HIFCR|=1<<9;			//清除DMA2_Steam5传输错误标志
	
		len = USART_LEN - (uint16_t)(DMA2_Stream5->NDTR);
		myDMAprintf(USART1,"len = %d,data: %s",len,USART1_RX_BUF);
	}
	mymemset(USART1_RX_BUF,0,(u32)len);
	MYDMA_Enable(DMA2_Stream5,(u32)USART1_RX_BUF,USART_LEN);//开始一次DMA传输!
}

至此,串口1的发送和接收已全部配置完成,其他5个串口的配置类似。

程序链接

完整的6路串口DMA发送&接收程序:串口DMA发送&接收(v2.1)

参考文章

STM32—无需中断来实现使用DMA接收串口数据

串口1配合DMA接收不定长数据(空闲中断+DMA接收)

STM32 串口采用DMA方式收发

串口DMA接收数据基本思路 使用DMA半满中断实现双缓冲的DMA串口接收 阅读详情

相关推荐

MCU-串口收发使能DMA

对于发送,使用中断发送,不会阻塞线程,但需浪费大量中断资源,CPU频繁响应中断;当DMA传输数据完成,CPU介入开始拷贝DMA通道buf数据,如果此时串口继续有数据进来,DMA继续搬运数据到buf,就有可能将数据覆盖。第三步,buf后半部分数据搬运完成,触发“溢满中断”,CPU来拷贝buf后半部分数据。第一步,DMA将数据搬运完成buf的前一半时,产生“半满中断”,CPU来拷贝buf前半部分数据。对于发送,使用循环发送,可能阻塞线程,需要消耗大量CPU资源“搬运”数据,浪费CPU。

xiandang8023的博客 4210

stm32学习

波特率:每秒传送的位数 DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。 DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始...

sdkdslx的博客 1220

超详细!新手必看STM32-DMA配置与实验(串口使用DMA发送数据)

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

qq_1033275663的博客 2万+

串口DMA发送接收

DMA串口接收

qq_52362275的博客 5432

STM32串口DMA方式发送数据

文章目录一、DMA介绍1.概括2.DMA由来2.1程序传送方式2.2中断传送方式2.3DMA原理3.DMA具有的功能4.DMA传输方式5.DMA主要特征6.DMA处理7.DMA工作框图8.DMA工作传送过程二、串口DMA方式发送数据1.题目要求2.工程建立3.代码编写4.烧录测试五、参考 一、DMA介绍 1.概括 DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。 DMA传输将数据从一个地址空

cleveryoga的博客 1万+

串口DMA接收与发送不定长数据

项目中使用串口接收数据时需要单个字节进行中断接收,再判断字节放入缓冲区等待处理,这种方式一般情况无伤大雅,但在传输数据较多且CPU资源紧张时候,这种方式就显得力不从心,经过参考个人实现了一种使用串口DMA接收和发送不定长数据的方式,并且经过项目检验。因此作为笔记简单记录以下个人总结,方便日后参考

Yin_w的博客 3095

[转]一个严谨的STM32串口DMA发送&接收(1.5Mbps波特率)机制

文章目录 1 前言 2 串口有必要使用DMA吗 3 实现方式 4 STM32串口使用DMA 5 串口DMA接收 5.1 基本流程 5.2 相关配置 5.3 接收处理 5.3 .1 接收数据大小 5.3.2 接收数据偏移地址 5.4 应用读取串口数据方法 6 串口DMA发送 5.1 基本流程 5.2 相关配置 5.3 发送处理 6 串口设备 6.1 数据结构 6.2 对外接口 7 相关文章 8 完整源码 1 前言 直接存储器访问(Direct Memory Access)

xuanjianqiang的博客 3万+

STM32 串口DMA方式接收

STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M。最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USART1~USART5),支持DMA方式通信,DMA方式由于不需要CPU的参与,而是直接由DMA控制器完成串口数据的读写,因而可以很大程度的提高CPU的利用率。在使用STM32串口之前需要做一系列的初始

firehood的专栏 1万+

STM32使用DMA接收串口数据

目录 01、概述 02、DMA接收 03、中断 04、代码 01、概述 在之前的文章里《STM32串口详解》和《STM32 DMA详解》文章中,详细讲解了STM32的串口和DMA外设,本篇文章将不在细述串口和DMA的知识。 在串口讲解的文章中,示例代码采用中断方式接收和发送数据,中断的好处在于可以及时响应,快速接收到数据,但缺点也很明显,那就是频繁中断,接收1000个字节需要中断1000次,频繁中断就意味着会打断其他代码的执行,对一些应用场景是不允许的。这个时候,使用DMA+串口的组合就可以很

人生一路,点滴记录 2万+

一个严谨的STM32串口DMA发送&接收(1.5Mbps波特率)机制

本文描述串口DMA收/发机制设计,及STM32串口DMA收/发实现。

只要思想不滑坡,想法总比问题多。 5万+

SAP软件外币评估系统配置与操作

文章摘要:本文详细介绍了SAP系统中外币评估的流程、策略及系统操作。外币评估是期末关账的重要环节,主要针对外币未清项目及资产/负债进行汇率重估,生成评估差异过账以反映真实财务状况。文中阐述了三种评估策略(不评估、增量评估、期末评估冲回)及适用场景,并提供了SAP系统外币评估的具体操作步骤(FAGL_FCV/FAGL_FC_VAL事务码)。同时,讲解了货币资金科目和未清项管理科目的评估差异处理方式,以及相关的系统配置(OB59、OBA1等)。文章还区分了已实现和未实现汇兑损益的会计处理,为企业外币业务管理提供

weixin_40672823的博客 1963

STM32 USART串口DMA 接收和发送的源码详解!

硬件平台:STM32F103ZET6;开发环境:KEIL 4;先说说应用通讯模式,串口终端的工作方式和迪文屏差不多,终端被动接受MCU发的指令,终端会偶尔主动发送一些数据给MCU(像迪文屏的触摸信息上传)。串口DMA发送:发送数据的流程:前台程序中有数据要发送,则需要做如下几件事1.在数据发送缓冲区内放好要发送的数据,说明:此数据缓冲区的首地址必须要在DMA初始化的时候写入到DMA配......

魏波 2万+

从选型到调试:MCU外部晶振电路设计的实战避坑指南

本文详细解析了MCU外部晶振电路设计的关键要点,从选型到调试提供全面指南。重点探讨了晶振频率选择、负载电容计算、PCB布局优化等核心问题,并分享常见故障排查技巧与EMC设计经验,帮助工程师规避设计陷阱,提升嵌入式系统时钟稳定性。

weixin_30872577的博客 280

STM32 串口USART DMA方式发送接收数据

`DMA`,直接内存存取,类似用它的双手释放`CPU`的灵魂,所以,本文通过`USART3`进行串口收发,接受使用DMA的方式,无需`CPU`进行干预,当接受完成之后,数据可以直接从内存的缓冲区读取,从而减少了`CPU`的压力。 具体的代码实现如下: - `usart_driver.h` 封装了接口,数据接收回调函数类型,基本数据结构等; - `usart_driver.c` 函数原型实现,中断服务函数实现等;

一名热爱技术的工程师的博客。分享技术干货,记录美好生活。永远相信美好的事情即将发生。 2万+

树莓派CM4 PCIe扩展方案与ASM1184e芯片应用

PCIe(Peripheral Component Interconnect Express)是计算机硬件中重要的高速串行总线标准,广泛应用于存储、网络等设备连接。其核心原理是通过差分信号实现高带宽传输,PCIe Gen2 x1的理论带宽可达5Gbps。在嵌入式开发中,PCIe扩展技术能有效解决单板计算机接口不足的问题,特别适合树莓派等微型平台。ASMedia ASM1184e作为PCIe交换芯片,可将单个接口扩展为多个,支持热插拔且免驱动,极大提升了工程灵活性。通过PCIe交换机方案,开发者能在树莓派CM

weixin_42602368的博客 423

【ISP图像处理】Demosaic去马赛克技术演进与边缘优化策略

本文深入解析了ISP图像处理中的Demosaic(去马赛克)技术。从Bayer阵列原理出发,梳理了从双线性插值、Hamilton-Adams边缘导向算法到利用通道相关性与自相似性的技术演进历程,并重点探讨了针对边缘与纹理伪影的优化策略,为工程实践中的算法选型与硬件协同设计提供了专业指导。

weixin_29091445的博客 389

GD32 DMA串口接收发送

最近,工作上需要将mlx90640的数据通过串口传出去,而数据比较大,发送得比较慢,就想着看能不能用DMA来发送看速度会不会快点。

Fengziwen1的博客 1万+

Power domain 划分该如何下手

假如PD1比PD3更always on的话,我们只需要插入普通buffer即可,因为PD3 on,PD1也肯定是ON,PD1 off,PD3肯定时off,PD1能cover PD3的电源情况,因此使用普通buffer也可,但是处于省电角度,我们还是使用AO buffer;在我们做多power domain时,在切分power domain时,需要谨慎,稍有不慎,就会出现congestion以及timing问题,那问题来了,我们在切分power domain时有什么考究么,今天小编就和大家一起讨论讨论。

芯冰乐 207

STM32DMA+串口完成中断 接收和发送

最近在使用STM32F103单片机进行串口接收处理不定长数据测试时有两个需求。1、需要接收不定长的数据。2、提高串口响应速度。 一直看过很多贴子关于串口+DMA+完成中断的用法,但是没有找到合适的。参考了很多资料自己整理一份程序代码,供大家参考。 软件链接:https://download.youkuaiyun.com/download/shaozp529/11573556 软件设计思路: 接收函数串...

shaozp529的博客 1万+

【DeepSeek R1构建本地RAG知识库】数据结构化清洗-知识图谱制作、使用、dify集成

本文探讨了在构建本地RAG(Retrieval-Augmented Generation)系统时,如何通过引入知识图谱来增强系统的知识理解能力。传统的向量数据库和嵌入模型虽然能处理语义匹配,但无法有效捕捉知识间的关联性。知识图谱通过“实体-关系-属性”的结构化表示,能够更好地支持推理、推荐和多跳问答等高级功能。文章详细介绍了知识图谱的基本概念、制作思路,以及如何使用Neo4j图数据库进行知识图谱的构建和查询。通过实例展示了从PDF文件解析到知识图谱入库的全过程,强调了知识图谱在提升RAG系统性能中的重要作用

少说,多做 567

【FPGA教程案例59】深度学习案例6——基于FPGA的CNN卷积神经网络之整体实现

在课程,我们对的基本原理有了初步认识。在上一个课程,我们完成了CNN的Relu激活层、pool池化层、卷积层以及图像输入层的实现,如下图所示:在本课程中,我们将上述四个模块结合起来,构建一个简单的CNN卷积神经网络。...

FPGA/MATLAB学习教程/源码/项目合作开发 2637

STM32HAL库---串口DMA发送接收详解

该文章包含了DMA串口的配置过程以及流程说明,会以较为深入的方式讲解

随心 6110

记录Rancher集群中coredns问题导致的服务DNS解析超时

coredns问题处理

1360

HC32F460 串口 DMA 发送 接收

DMA_TX 流程图

红红火火恍恍惚惚 6979

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex&trade;-M4F 内核的信息,请参见《Cortex&trade;-M4F 技术参考手册》。

STM32 LL库 串口DMA发送接收配置教程

STM32 LL库 DMA串口收发

qq_40932099的博客 8255

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = &quot;R. B. Palm&quot;, title = &quot;Prediction as a candidate for learning deep hierarchical models of data&quot;, year = &quot;2012&quot;,}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er&lt;0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free &quot;Bitdeli Badge&quot;)

STM32 使用DMA进行串口发送和接收

DMA+USART Rx

qq18285的博客 6875

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: C语言指针实例
下一篇: 推导反向传播中的dZ=A - y
且听风吟0618
博客等级 码龄11年 150粉丝 25原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值