当前位置:首页 > 单片机 > 单片机
[导读]一、DMA功能简介  首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量。在硬件系统中,主要由CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常要在内存和外设之间,外设和外设之间转移。例如:CPU

一、DMA功能简介

  首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量。在硬件系统中,主要由CPU(内核)、外设、内存(SRAM)、总线等结构组成,数据经常要在内存和外设之间,外设和外设之间转移。例如:CPU需要处理从外设采集回来的数据,CPU需要先将数据从ADC外设的寄存器读取到内存中(变量)去,然后进行运算处理,这是一般的解决方法。CPU的资源是非常宝贵的,我们可以设法把转移的工作交给其他部件来完成,CPU把更多的资源用于数据运算和中断响应上,如此DMA便登场了。DMA正是为CPU分担数据转移工作,因为DMA的存在,CPU才被解放出来,它可以在数据转移的同时进行数据运算,相应中断,大大提高了效率。

二、DMA的主要特性

  

三、DMA中断特性

四、DMA之串口通信

  我们实现一个简单的功能,在DMA中处理串口通信,把数据转移的工作交给DMA,DMA把数据从内存(数组)到外设(串口)的转移,在main函数中不断进行闪灯操作,这样我们可以看到DMA在工作的时候CPU也在工作。非常有必要复习一下DMA的对应关系,我们知道stm32总共有2个DMA控制器(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自一个或多个外设对存储器访问的请求,还有一个仲裁器来协调DMA请求的优先级(优先级分:很高、高、中等、低),这可不是随便对应的。

  

1、LED初始化程序如下:

1234567891011121314151617voidLED_GPIO_Config(void){/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;/*开启LED的外设时钟*/RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);/*选择要控制的GPIOB引脚*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;/*设置引脚模式为通用推挽输出*/GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;/*设置引脚速率为50MHz */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/*调用库函数,初始化GPIOB0*/GPIO_Init(GPIOB, &GPIO_InitStructure);/* 关闭所有led灯 */GPIO_SetBits(GPIOB, GPIO_Pin_14);}

  这个地方地方没什么要注意的,唯一要注意的就是输入输出模式,我们按需求这样配就好了。

2、串口初始化

123456789101112131415161718192021222324252627voidUSART3_Config(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* config USART3 clock */RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE);/* USART1 GPIO config *//* Configure USART1 Tx (PA.09) as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure USART1 Rx (PA.10) as input floating */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, &GPIO_InitStructure);/* USART1 mode config */USART_InitStructure.USART_BaudRate = 38400;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_Rx | USART_Mode_Tx;USART_Init(USART3, &USART_InitStructure);USART_Cmd(USART3, ENABLE);}

3、DMA初始化

123456789101112131415161718192021222324252627282930313233343536voidUSART3_DMA_Config(void){DMA_InitTypeDef DMA_InitStructure;/*开启DMA时钟*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//NVIC_Config(); //配置DMA中断//NVIC_Configuration();/*设置DMA源:串口数据寄存器地址*/DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;/*内存地址(要传输的变量的指针)*/DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;/*方向:从内存到外设*/DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;/*外设地址不增*/DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/*内存地址自增*/DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;/*外设数据单位*/DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/*内存数据单位 8bit*/DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;/*DMA模式:不断循环*/DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;/*优先级:中*/DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;/*禁止内存到内存的传输 */DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;/*配置DMA1的2通道*/DMA_Init(DMA1_Channel2, &DMA_InitStructure);//DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE); //配置DMA发送完成后产生中断/*使能DMA*/DMA_Cmd (DMA1_Channel2,ENABLE);}

在这里我们要注意以下几点:

(1)DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;这里对应USART数据寄存器地址,这个地址我们是这样定义的:#define USART3_DR_Base 0x40004804,这个值是怎么算出来的呢?我们可以查看stm32存储器映射表:

USART3的起始地址是0x40004800,我们查看stm32串口数据寄存器偏移地址为0x04

因此我们可以计算到USART3数据寄存器地址为0x40004804

(2)我们数据传输方向内存(变量)到外设(串口),所以DMA方向为内存到外设

(3)DMA传输模式有两种:DMA_Mode_Normal(普通模式),DMA只传输一次;DMA_Mode_Circular(循环模式),DMA循环传输,比如在AD采集时要配置成循环模式。

4、主函数

123456789101112131415161718192021222324252627intmain(void){/* USART1 config 115200 8-N-1 */USART3_Config();USART3_DMA_Config();LED_GPIO_Config();printf("rn usart3 DMA TX 测试 rn");{ ui

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

电磁铁是一种利用电流产生磁场的装置,具有快速响应、易于控制等特点,在工业自动化、电子设备、科学实验等领域有着广泛的应用。STM32是一款功能强大的微控制器,具有高性能、低功耗、易于编程等优点,是控制电磁铁的理想选择。本文...

关键字: 电磁铁 微控制器 STM32

边缘人工智能的实现涉及到三个基本 要素:安全性,连接性、自主性,而其中自主性是AI能力的体现,也是边缘AI有别于其他传统的物联网的关键。而通过ST Edge AI套件,就可以帮助各种不同类型的开发者实现覆盖全硬件平台的全...

关键字: 边缘人工智能 AI STM32

今天,小编将在这篇文章中为大家带来STM32单片机最小系统的有关报道,通过阅读这篇文章,大家可以对它具备清晰的认识,主要内容如下。

关键字: 单片机 单片机最小系统 STM32

上位机串口通信是指在上位机(通常是计算机或微控制器)与外部设备之间通过串行通信协议进行数据传输和通信的过程。在串口通信中,数据以位为单位按顺序传送,通常使用一个或两个物理线路(通常是两条线)来实现数据的发送和接收。

关键字: 上位机 串口通信

串口通信(Serial Communication)是一种常用的数据传输方式,它通过串行数据线逐位传输数据,具有成本低、简单易用、可靠性高等优点。在工业控制、通信设备、嵌入式系统等领域得到广泛应用。

关键字: 串口通信 嵌入式系统

串口通信是一种常见的通信方式,用于在不同设备之间传输数据。它通过串行数据线(通常是一对TXD和RXD线)在设备之间进行通信。串口通信具有简单、可靠、成本低等优点,因此在工业控制、嵌入式系统、数据采集等领域得到广泛应用。

关键字: 串口通信 串口编程

串口通信是一种常见的通信方式,主要应用于计算机和其他设备之间的数据传输。它的主要原理是利用串行数据传输的方式,将数据一位一位地按顺序传输,而不是同时传输所有的数据。下面我们来看看串口通信的主要原理以及如何提高其传输速度。

关键字: 串口通信 串口速度

串口通信是一种常见的通信方式,它通过串行方式传输数据。串口通信的原理相对简单,主要涉及到数据位的传输和接收。在串口通信中,数据按照一定的波特率(baud rate)逐位传输。通常,一个字节的数据由8位组成,所以传输一个字...

关键字: 串口通信 波特率

RS 232串口通信是一种常见的串行通信协议,广泛应用于计算机和其他设备之间的数据传输。它是由美国电子工业协会(EIA)制定的一种标准,规定了数据传输的物理层和部分数据链路层的规范。

关键字: RS 232 串口通信

虽然 USB 几乎完全取代那些旧电缆和连接器,但 UART 绝对不会成为过去。您会发现许多 DIY 电子项目都使用 UART。

关键字: UART 串口通信 USB
关闭
关闭