您的位置 首页 嵌入式

STM32 DMA 串口透传

一直没有好好的捣鼓过DMA,在调BLE项目的时候,遇到了DMA串口传输的问题,伤心流涕甚长时间!!!DMA网上的解释一大堆,简单总结一下:DMA…

一向没有好好的捣鼓过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_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);//USART1_TXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);//USART1_RXGPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);}void DMA_Configuration(void){DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输DMA_DeInit(DMA1_Channel5);DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(USART1->DR));DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                              //外设作源头//外设是作为数据传输的意图地仍是来历DMA_InitStructure.DMA_BufferSize = 5;                                           //DMA缓存的巨细 单位在下边设定DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外设地址寄存器不递加DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                         //内存地址递加DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;         //外设字节为单位DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;             //内存字节为单位DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                 //作业在循环缓存形式DMA_InitStructure.DMA_Priority = DMA_Priority_High;                             //4优先级之一的(高优先) VeryHigh/High/Medium/LowDMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                    //非内存到内存DMA_Init(DMA1_Channel5, &DMA_InitStructure);                                    //依据DMA_InitStruct中指定的参数初始化DMA的通道1寄存器DMA_ITConfig(DMA1_Channel5, DMA_IT_HT, ENABLE);                                 //DMA5半传输完结中止USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                                    //使能USART1的接纳DMA恳求DMA_Cmd(DMA1_Channel5, ENABLE);          DMA_ClearFlag(DMA1_FLAG_TC5); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority =  0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}void DMA_Configuration2(void){DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输DMA_DeInit(DMA1_Channel4);DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(USART1->DR));DMA_InitStructure.DMA_MemoryBaseAddr = (u32)TxBuffer;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST ;                             //外设作源头//外设是作为数据传输的意图地仍是来历DMA_InitStructure.DMA_BufferSize = NbrOfDataToTransfer;                         //DMA缓存的巨细 单位在下边设定DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外设地址寄存器不递加DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                         //内存地址递加DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;         //外设字节为单位DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;             //内存字节为单位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;                                  //作业在循环缓存形式DMA_InitStructure.DMA_Priority = DMA_Priority_High;                             //4优先级之一的(高优先) VeryHigh/High/Medium/LowDMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                    //内存到非内存DMA_Init(DMA1_Channel4, &DMA_InitStructure);                                    //依据DMA_InitStruct中指定的参数初始化DMA的通道1寄存器DMA_ITConfig(DMA1_Channel4, DMA_IT_TC , ENABLE);                                //DMA4传输完结中止USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);                                    //使能USART1的发送DMA恳求DMA_Cmd(DMA1_Channel4, ENABLE);          DMA_ClearFlag(DMA1_FLAG_TC4); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority =  1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}/* 名    称:int main(void)* 功    能:主函数* 进口参数:无* 出口参数:无* 说    明:* 调用办法:无 / int main(void){int i,j;RCC_Configuration();   				//体系时钟装备//TIM3_Configuration();NVIC_Configuration();			LED_Config();	USART1_Configration();DMA_Configuration();	//DMA_Configuration2();//LED操控装备// printf("Start DMA transmission!\r\n");//LED1_ON ;for(i=0;i<1000000;i++);// for(j=0;j<20;j++);	DMA_Configuration2();while (1){}}/* 名    称:void RCC_Configuration(void)* 功    能:体系时钟装备为72MHZ* 进口参数:无* 出口参数:无* 说    明:* 调用办法:无 / void RCC_Configuration(void){   SystemInit();}void DMA1_Channel5_IRQHandler(void){u8 end;int i;	  printf("Start DMA transmission!\r\n");/ 全传输完结*///   if(DMA_GetITStatus(DMA1_IT_TC5))//    {  //  end = DMA_GetCurrDataCounter(DMA1_Channel5);//  DMA_ClearITPendingBit(DMA1_IT_GL5);///* 清中止源//  DMA_ClearFlag(DMA1_FLAG_TC5);   // //       printf("AA%dAA:", end);//       printf("%s\r\n", SendBuff);//	  for(i=0;i<100000;i++); //   }/// 半传输完结*/if(DMA_GetITStatus(DMA1_FLAG_HT5)){  end = DMA_GetCurrDataCounter(DMA1_Channel5);DMA_ClearITPendingBit(DMA1_IT_GL5);///* 清中止源DMA_ClearFlag(DMA1_IT_TC5);   printf("AA%dAA:", end);printf("%s\r\n", SendBuff);for(i=0;i<100000;i++); }//}void DMA1_Channel4_IRQHandler(void){if(DMA_GetITStatus(DMA1_IT_TC4)==SET){DMA_ClearFlag(DMA1_IT_TC4);//TCIE,TE,RE			printf("AAAA!");}}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/264864.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部