微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32 DMA 串口透传

STM32 DMA 串口透传

时间:11-19 来源:互联网 点击:
一直没有好好的捣鼓过DMA,在调BLE项目的时候,遇到了DMA串口传输的问题,伤心流涕甚长时间!!!

DMA 网上的解释一大堆,简单总结一下:

DMA处理过程全部是由硬件来实现的,速度很快!

DMA在专门的DMA控制下,实现高速外设与主存储期之间自动成批量的数据交换。

通常有两种交换方式:1独占总线方式 2周期挪用方式

DMA传送过程

DMA预处理

DMA数据传送

DMA结束处理将总线控制权交换给CPU

DMA内部寄存器

地址寄存器:存放DMA传输是储存单元地址

字节寄存器:存放DMA传输字节数

控制寄存器:存放CPU设定的DMA传输方式

状态寄存器:存放DMAC当前的状态

DMA外设地址:基地址+偏移地址

两种方法设定地址:

#defineUSART1_DR_Base 0x40013804

#defineUSART1_DR_Base (&(USART1->DR)) 觉得还是第二种方法比较直接

DMA两种中断触发方式:

DMA_IT_TC1传输完成中断:每次更新发生在计数>=设定值

DMA_IT_HT1传输过半中断:每次更新发生在计数>(设定值/2)

DMA_IT_GL1全局中断:(实验了几次和过半中断传输情况一致)

编程的时候根据DMA请求映像来判断通道号,然后找到目的地址和原地址基本上就算完事儿了。当然得分清是传输是外设和内存,内存和外设,内存和内存三种情况,会有 (DMA_InitTypeDef 结构体).DMA_M2M 进行设置。

下面是DMA串口收发简单例子,并没有用到FIFO精确收发,有时间再好好写写~

DMA_Configuration()是DMA5通道 串口1接收通道配置函数

DMA_Configuration2()是DMA4通道 串口1发送通道配置函数

对于发送 可以每当发送的时候 都执行DMA_Configuration2(),进行发送操作

对于接收 理应采用FIFO,对于接收数组进行处理,这里只是简单的接收,没有进一步处理

/* Includes ------------------------------------------------------------------*/#include "stm32f10x.h"#include "stm32f10x_tim.h" #include "stm32f10x_rcc.h"#include "stm32f10x_map.h"	#include "stm32f10x_it.h"	  #include "misc.h" #include "bsp_timer.h"#include "stm32f10x_usart.h"#include "stm32f10x_dma.h"#include "stdio.h"#define SENDBUFF_SIZE   10vu8 SendBuff[SENDBUFF_SIZE]={0};vu8 TxBuffer[] = "hello xiao lei !!! ";vu8 NbrOfDataToTransfer = sizeof(TxBuffer)-1;GPIO_InitTypeDef GPIO_InitStructure;#define LED1_ON GPIO_SetBits(GPIOB, GPIO_Pin_5);  #define LED1_OFF GPIO_ResetBits(GPIOB, GPIO_Pin_5); #define LED2_ON GPIO_SetBits(GPIOD, GPIO_Pin_6);  #define LED2_OFF GPIO_ResetBits(GPIOD, GPIO_Pin_6); #define LED3_ON GPIO_SetBits(GPIOD, GPIO_Pin_3);  #define LED3_OFF GPIO_ResetBits(GPIOD, GPIO_Pin_3);  void RCC_Configuration(void);void LED_Config(void);void Delay(__IO uint32_t nCount);int fputc(int ch, FILE *f){USART_SendData(USART1, (u8) ch);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}return ch;}/* 名    称:void LED_Config(void)* 功    能:LED 控制初始化函数* 入口参数:无* 出口参数:无* 说    明:* 调用方法:无 / void LED_Config(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				     //LED1  V6	   //将V6,V7,V8 配置为通用推挽输出  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;			 //口线翻转速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);					 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_3;		 //LED2, LED3	 V7 V8GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 			      //LCD背光控制GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_ResetBits(GPIOD, GPIO_Pin_13);			              //LCD背光关闭	}void USART1_Configration(){USART_InitTypeDef USART_InitStructure;  GPIO_InitTypeDef GPIO_InitStr            

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top