历史上的今天
返回首页

历史上的今天

今天是:2025年01月29日(星期三)

2019年01月29日 | STM32基础设计(4)---DMA通信

2019-01-29 来源:eefocus

前面几篇文章介绍了STM32 F103C8的 GPIO口操作,串口的操作,中断的操作,今天这篇文章简单介绍STM32的DMA操作。


本文通过一个小的设计来进行讲解,将STM32内部存储的一个数组中的数据,通过DMA操作复制到第二个数组里,并用USART1串口将第二个数组中的数据输出到电脑端,进行检查,看是否复制成功。


首先总结全文,,使用STM32进行DMA操作的主要过程如下:


1,初始化GPIO


2,初始化串口


3,初始化DMA


4,编写主函数


下面介绍详细步骤:


(步骤1,2前几篇博客有详细讲,请读者翻阅。)


1,初始化GPIO

void IO_Init()

{

GPIO_InitTypeDef Uart_A; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

Uart_A.GPIO_Pin = GPIO_Pin_9;

Uart_A.GPIO_Speed = GPIO_Speed_50MHz;

Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA,&Uart_A);

Uart_A.GPIO_Pin = GPIO_Pin_10;

Uart_A.GPIO_Speed = GPIO_Speed_50MHz;

Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110

GPIO_Init(GPIOA,&Uart_A);

}

2,初始化USART1

void Usart1_Init()

{

USART_InitTypeDef Uart;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

Uart.USART_BaudRate = 115200;

Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

Uart.USART_Parity = USART_Parity_No;

Uart.USART_StopBits = USART_StopBits_1;

Uart.USART_WordLength = USART_WordLength_8b;

USART_Init(USART1,&Uart);

USART_Cmd(USART1,ENABLE);

USART_ClearFlag(USART1,USART_FLAG_TC); //page 540

}


3,初始化DMA

库函数中DMA的结构体如下:


typedef struct

{

  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

 

  uint32_t DMA_MemoryBaseAddr;     /*!< Specifies the memory base address for DMAy Channelx. */

 

  uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.

                                        This parameter can be a value of @ref DMA_data_transfer_direction */

 

  uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel. 

                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize

                                        or DMA_MemoryDataSize members depending in the transfer direction. */

 

  uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register is incremented or not.

                                        This parameter can be a value of @ref DMA_peripheral_incremented_mode */

 

  uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register is incremented or not.

                                        This parameter can be a value of @ref DMA_memory_incremented_mode */

 

  uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.

                                        This parameter can be a value of @ref DMA_peripheral_data_size */

 

  uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.

                                        This parameter can be a value of @ref DMA_memory_data_size */

 

  uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_circular_normal_mode.

                                        @note: The circular buffer mode cannot be used if the memory-to-memory

                                              data transfer is configured on the selected Channel */

 

  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_priority_level */

 

  uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.

                                        This parameter can be a value of @ref DMA_memory_to_memory */

}DMA_InitTypeDef;

DMA_DIR

这个是定义DMA的传输方向,DMA传输总共有三个方向,外设到内存,内存到外设,内存到内存(关于外设和内存可以这样简单理解,相当于一条路的两头)


库函数中有两个定义:


#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)

#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)

以DST结尾的那个,表示,以外设为目的地,以SRC结尾的那个,表示,以外设为起始点。


 uint32_t DMA_PeripheralBaseAddr;这个是用来定义外设地址的

uint32_t DMA_MemoryBaseAddr;这个是用来定义内存地址的

uint32_t DMA_BufferSize;这个是指DMA通道的DMA 缓存的大小,这是为了照顾,两边的速率不一致。

uint32_t DMA_PeripheralInc;这个是用来定义外设地址是否要自增

uint32_t DMA_MemoryInc; 这个是用来定义内存地址是否要自增

uint32_t DMA_PeripheralDataSize;用来制定外设的数据宽度

uint32_t DMA_MemoryDataSize;

这个是用来制定内存的数据宽度,当外设和存储器之间传数据时,两边的数据宽度应该设置为一样大小


uint32_t DMA_Mode; 

这个是用来指定DMA的工作模式,有一次传输和循环传输模式,两种。

uint32_t DMA_Priority;

这个是用来指定DMA的优先级,有非常高,高,中,低四种。


uint32_t DMA_M2M; 这个是用来设置是否进行 内存到内存传输

初始化函数如下:


void Dma_Init()

{

DMA_InitTypeDef dma;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//老规矩,先开心脏

dma.DMA_MemoryBaseAddr = (u32)zimu;内存地址

dma.DMA_PeripheralBaseAddr = (u32)zimu_1;外设地址

dma.DMA_DIR = DMA_DIR_PeripheralDST;外设为目的地,即zimu_1数组为目的地

dma.DMA_BufferSize = 26;缓冲区大小

dma.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;数据宽度

dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;同上

dma.DMA_MemoryInc = DMA_MemoryInc_Enabl;内存地址自增

dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;外设地址自增

dma.DMA_Mode = DMA_Mode_Normal;单次模式

dma.DMA_Priority = DMA_Priority_High;优先级为高

dma.DMA_M2M = DMA_M2M_Enable;设置为内存到内存传输

DMA_Init(DMA1_Channel6,&dma);寄存器初始化

DMA_Cmd(DMA1_Channel6,ENABLE);DMA使能

}


4,编写主函数

int main()

{

void printf_string(char* a);

IO_Init();GPIO初始化

Usart1_Init();USART1初始化

Dma_Init();DMA初始化

while(DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET){}//等待DMA操作完成,在参考手册的149页可以仔细看这个寄存器

while(1){

    if(USART_GetFlagStatus(USART1,USART_FLAG_TXE))判断是否能用串口输出

        {

    printf_string(zimu_1);输出zimu_1数组

    delay(3000);延时

        }

}

}

void printf_string(char* a)

{

while(*a != '\0')直到数组末尾

{

USART1->DR = *a;赋值给USART的数据寄存器

while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));等待发送成功

a++;地址加一

}

}

本文到此结束,因博主水平有限,如有错误,敬请指出,不胜感激!


亲测,可运行。详细代码如下:


#include

#define uint unsigned int

#define uchar unsigned char

char zimu[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

char zimu_1[32]={'.'};

void delay(uint n)

{

int i,j;

for(i=0;i

for(j=0;j<8500;j++);

}

 

void IO_Init()

{

GPIO_InitTypeDef Uart_A;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

Uart_A.GPIO_Pin = GPIO_Pin_9;

Uart_A.GPIO_Speed = GPIO_Speed_50MHz;

Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA,&Uart_A);

Uart_A.GPIO_Pin = GPIO_Pin_10;

Uart_A.GPIO_Speed = GPIO_Speed_50MHz;

Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110

GPIO_Init(GPIOA,&Uart_A);

}

void Usart1_Init()

{

USART_InitTypeDef Uart;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

Uart.USART_BaudRate = 115200;

Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

Uart.USART_Parity = USART_Parity_No;

Uart.USART_StopBits = USART_StopBits_1;

Uart.USART_WordLength = USART_WordLength_8b;

USART_Init(USART1,&Uart);

USART_Cmd(USART1,ENABLE);

USART_ClearFlag(USART1,USART_FLAG_TC); //page 540

}

 

void Dma_Init()

{

DMA_InitTypeDef dma;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

dma.DMA_MemoryBaseAddr = (u32)zimu;

dma.DMA_PeripheralBaseAddr = (u32)zimu_1;

dma.DMA_DIR = DMA_DIR_PeripheralDST;

dma.DMA_BufferSize = 26;

dma.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;

dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

dma.DMA_MemoryInc = DMA_MemoryInc_Enable;

dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;

dma.DMA_Mode = DMA_Mode_Normal;

dma.DMA_Priority = DMA_Priority_High;

dma.DMA_M2M = DMA_M2M_Enable;

DMA_Init(DMA1_Channel6,&dma);

DMA_Cmd(DMA1_Channel6,ENABLE);

}

int main()

{

void printf_string(char* a);

IO_Init();

Usart1_Init();

Dma_Init();

GPIOC->BSRR = GPIO_Pin_13;

while(DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET){}

while(1){

if(USART_GetFlagStatus(USART1,USART_FLAG_TXE))

{

printf_string(zimu_1);

delay(3000);

}

}

}

void printf_string(char* a)

{

//USART1->CR1 &= ~USART_CR1_TXEIE;

USART1->CR1 |= USART_CR1_TXEIE;

while(*a != '\0')

{

USART1->DR = *a;

while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));

a++;

}

}


推荐阅读

史海拾趣

Aplus Flash Technology Inc公司的发展小趣事

随着全球环保意识的提高,电子行业对环保的要求也越来越高。Aplus Flash Technology Inc公司积极响应环保号召,将环保理念融入产品设计和生产过程中。公司研发出了一款低能耗、环保型的闪存芯片,不仅降低了产品的能耗和碳排放,还提高了产品的可回收利用率。这一创新举措得到了消费者的广泛认可和支持,也为公司在市场上树立了良好的环保形象。

AdaptivEnergy公司的发展小趣事

近年来,电子行业面临着原材料价格上涨、贸易壁垒增多等挑战。Aplus Flash Technology Inc公司也受到了这些因素的影响,生产成本上升,市场竞争压力加大。为了应对这些挑战,公司及时调整了发展战略,加大了对技术研发的投入,提高了生产效率和质量。同时,公司还积极开拓国际市场,通过参加国际电子展会、建立海外销售网络等方式,拓展海外市场份额。这些举措使公司在面对市场挑战时保持了稳健的发展态势。

长运通(CYT)公司的发展小趣事

作为一家高新技术企业,长运通深知技术创新的重要性。公司投入大量资源用于研发,不断推出具有竞争力的新产品。例如,在电源管理IC领域,长运通成功研发出多款高性能、低功耗的产品,满足了客户对于高效、稳定电源管理的需求。在LED光源方面,公司也取得了多项技术突破,推出了多款高效、环保的LED照明产品。这些技术突破和创新不仅提升了公司的市场竞争力,也为公司赢得了更多的客户信任。

Fullywell Semiconductor Co Ltd公司的发展小趣事

随着市场的不断扩大,Fullywell意识到需要进一步提升产能以满足客户需求。于是,公司在2010年启动了大规模的产能扩张计划,投资建设了一座现代化的晶圆制造厂。同时,公司也加大了对国际市场的开拓力度,与多家国际知名电子企业建立了战略合作关系。这些举措不仅显著提升了Fullywell的产能和产品质量,也使其在国际市场上的知名度大幅提升,进一步巩固了其在行业内的地位。

GE Industrial Solutions公司的发展小趣事
由于光耦的CTR随温度变化而变化,可能导致输出信号的非线性失真。解决方法包括选择温度稳定性好的光耦,或在电路中加入温度补偿电路。
Barry Industries Inc公司的发展小趣事

Barry Industries Inc深知品质是企业生存和发展的关键。因此,公司始终将品质管理放在首位,从原材料采购到生产流程控制,再到产品出厂检验,每一个环节都严格把控品质。同时,公司还注重品牌建设,通过提升产品形象和服务水平,逐渐树立了良好的品牌形象。

问答坊 | AI 解惑

一个可替代传统人机的方案,你不心动吗?

液晶终端+单片机系统=人机界面(HMI)        北京迪文科技有限公司  生产的TFT真彩液晶终端,配上一个小型单片机系统就可实现传统计人机界面的功能。液晶终端实现界面显示及触摸反馈功能,单片机系统进行与PLC的 ...…

查看全部问答>

Linux命令行大全中文版(CHM格式)

Linux命令行大全中文版(CHM格式)…

查看全部问答>

跨导OTA仿真问题

谁用ADS做过mos管OTA仿真? 教教我…

查看全部问答>

步进电机的控制(C语言)

大家好 请问怎样用并口控制两相混合式步进电机的正反转。在网上看了都是用单片来控制的,请问不用单片机直接用两相混合式步进电机细分驱动器可以控制吗? 还有就是写这种程序一般用的是keil软件吗? 小弟初学很多不懂,希望大家帮帮忙。 谢谢…

查看全部问答>

如何察看NIDS_PACKET的内容

看见网上经常有介绍NIDS_PACKET是就贴出这样的内容: Packet length : 590 005dba36:00 00 5a 42 40 86 00 10 7b 3b 90 f5 08 00 45 00 005dba46:02 40 d3 2a 40 00 7f 06 08 24 85 fc 09 70 85 fc 005dba56:09 01 04 72 00 14 02 00 d5 35 9b ...…

查看全部问答>

CListViewCtrl

请指教:   我想用一个位图来做 CListViewCtrl控件的背景,怎么实现?…

查看全部问答>

新手求助如何搭建VS 2005开发wince的环境!在线等!!!!!

  本人初次做Win ce的开发,IDE用的是VS 2005,所建项目类型是在智能设备中的Windows ce 5.0模板用的是设备应用程序,但是在调试时在弹出的“选择应用程序的部部署位置”时我选 了Windows CE Device时出现了\"连接到设备失败。  &nbs ...…

查看全部问答>

华为公司2007年社会招聘

华为内部推荐 招聘对象:        04,05年本科及硕士,06年硕士生,07年的应届生不招, 学校要求省重点大学及以上,通信、电子、计算机、经济类、管理类等相关专业毕业。 招聘的是正式“华为员工”,待遇一般不低于07年的 ...…

查看全部问答>