STM32 DMA学习笔记

1. 实验环境:

开发板:野火指南者(STM32F103VE)

STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0

IDE:KEIL5(代码编写很不方便,只在编译的时候用到)

代码编写工具:Source Insight 4.0(跟读代码、编写代码的最佳工具)

使用到的串口:USART1

传送方向:内存--->外设

硬件原理图:

实验效果:

2. 新建user_usart.h、user_usart.c、user_dma.h、user_dma.c、main.c 5个文件并从STM32官方库的例子中将stm32f10x_it.c、stm32f10x_it.h、stm32f10x_conf.h拷贝到自己的工程目录下。

3. 在user_usart.h中添加如下代码

1 #ifndef __USER_USART_H
2 #define __USER_USART_H
3 #include "stm32f10x.h"
4 
5 void User_USART_GPIO_Config(void);
6 void User_USART_Config(void);
7 
8 
9 #endif
user_usart.h

4. 在user_usart.c中添加如下代码

 1 #include "user_usart.h"
 2 
 3 
 4 
 5 void User_USART_Config(void)
 6 {
 7     USART_InitTypeDef USART_Config;
 8 
 9     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
10 
11     USART_Config.USART_BaudRate = 115200;
12     USART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
13     USART_Config.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
14     USART_Config.USART_Parity = USART_Parity_No;
15     USART_Config.USART_StopBits = USART_StopBits_1;
16     USART_Config.USART_WordLength = USART_WordLength_8b;
17 
18     USART_Init(USART1, &USART_Config);
19 
20     USART_Cmd(USART1, ENABLE);
21 
22 
23 }
24 
25 
26 void User_USART_GPIO_Config(void)
27 {
28     GPIO_InitTypeDef USART_GPIO_TX,USART_GPIO_RX;
29 
30     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
31 
32     USART_GPIO_TX.GPIO_Mode = GPIO_Mode_AF_PP;
33     USART_GPIO_TX.GPIO_Pin = GPIO_Pin_9;
34     USART_GPIO_TX.GPIO_Speed = GPIO_Speed_50MHz;
35 
36     GPIO_Init(GPIOA, &USART_GPIO_TX);
37 
38     USART_GPIO_RX.GPIO_Mode = GPIO_Mode_IN_FLOATING;
39     USART_GPIO_RX.GPIO_Pin = GPIO_Pin_10;
40 
41     GPIO_Init(GPIOA, &USART_GPIO_RX);
42 
43 
44     
45 
46 }
user_usart.c

5. 在user_dma.h中添加如下代码

 1 #ifndef __USER_DMA_H
 2 #define __USER_DMA_H
 3 
 4 #include "stm32f10x.h"
 5 
 6 
 7 #define USART_DATA_ADRESS    (USART1_BASE + 0x04)
 8 
 9 extern char str[];
10 
11 
12 
13 void User_DMA_Config(void);
14 
15 
16 
17 #endif
user_dma.h

6. 在user_dma.c中添加如下代码

 1 #include "user_dma.h"
 2 
 3 char str[] = "aahhhhhhhhhh";
 4 
 5 
 6 void User_DMA_Config(void)
 7 {
 8     DMA_InitTypeDef m_DMA;
 9 
10     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
11 
12     m_DMA.DMA_BufferSize = sizeof(str);        //此处大小一定要和发送的字符串大小一致,否则多余的部分出现乱码,因为值是未知的
13     m_DMA.DMA_DIR = DMA_DIR_PeripheralDST;
14     m_DMA.DMA_M2M = DMA_M2M_Disable;
15     m_DMA.DMA_MemoryBaseAddr = (uint32_t)str;
16     m_DMA.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
17     m_DMA.DMA_MemoryInc = DMA_MemoryInc_Enable;
18     m_DMA.DMA_Mode = DMA_Mode_Circular;
19     m_DMA.DMA_PeripheralBaseAddr = USART_DATA_ADRESS;
20     m_DMA.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
21     m_DMA.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
22     m_DMA.DMA_Priority = DMA_Priority_Medium;
23 
24     /*
25     串口工具接收来自开发板发送的数据,结合硬件实际物理连接,
26     此处为USART1_TX,即DMA1_Channel
27     */
28     DMA_Init(DMA1_Channel4, &m_DMA);
29 
30 
31     //使能实际与之对应的DMA通道,
32     DMA_Cmd(DMA1_Channel4, ENABLE);
33 
34 
35 }
user_dma.c

7. 在main.c中添加如下代码

 1 #include "stm32f10x.h"
 2 #include "user_dma.h"
 3 #include "user_usart.h"
 4 
 5 extern char str[];
 6 
 7 
 8 int main(void)
 9 {
10 
11     
12     User_DMA_Config();
13     User_USART_GPIO_Config();
14     User_USART_Config();
15 
16     //使能USART的DMA模式,这里操作的寄存器是USART的CR3第7bit,此bit置一为打开
17     USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
18 
19 
20     while(1)
21     {
22 
23     }
24 
25 
26     return 0;
27 }
main.c

实现步骤总结:

1、设置USART硬件中实际使用到的GPIO口,这里为GPIOA的PIN9、PIN10,具体设置如下

  1.1、使能GPIO时钟,使用RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)库函数

  1.2、初始化GPIO_InitTypeDef结构体成员,若为输入则不需要初始化GPIO_Speed成员

  1.3、将GPIO_InitTypeDef结构体的值写入到对应GPIO寄存器中,使用GPIO_Init(GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_InitStruct)库函数

2、设置USART对应的寄存器

  2.1、使能USART时钟,使用RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)库函数,若不是USART1则需要使用RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)库函数,因为USART1挂载在APB2总线上,USART2~USART5挂载在APB1总线上。

  2.2、初始化USART_InitTypeDef结构体成员。一般为8N1,即数据长度为8bit、无校验位、1个停止位

  2.3、将USART_InitTypeDef结构体的值写入到对应的USART寄存器中,使用USART_Init(USART_TypeDef * USARTx, USART_InitTypeDef * USART_InitStruct)库函数

  2.4、打开对应的中断寄存器来响应中断,即中断到来时可进入对应的中断服务程序,若不需要中断,则不用设置,跳过此不走。本实验使用了数据接收中断,使用USART_ITConfig(USART_TypeDef * USARTx, uint16_t USART_IT, FunctionalState NewState)库函数设置

  2.5、使能串口USART1,使其进行工作,使用USART_Cmd(USART_TypeDef * USARTx, FunctionalState NewState)库函数

3、定义要传输的数据

4、设置DMA对应的寄存器

  4.1、使能DMA时钟,使用RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)库函数

  4.2、初始化DMA_InitTypeDef结构体成员

  4.3、将DMA_InitTypeDef结构体的值写入DMA对应的寄存器中,使用DMA_Init(DMA_Channel_TypeDef * DMAy_Channelx, DMA_InitTypeDef * DMA_InitStruct)库函数

  4.4、使能串口DMA,使其进行工作,使用DMA_Cmd(DMA_Channel_TypeDef * DMAy_Channelx, FunctionalState NewState)库函数

5. 使能USART的DMA模式,使用USART_DMACmd(USART_TypeDef * USARTx, uint16_t USART_DMAReq, FunctionalState NewState)库函数

实验代码:

链接:https://pan.baidu.com/s/19QRoJf6HSdOejX_YIXFc6A
提取码:3xd0

猜你喜欢

转载自www.cnblogs.com/QSHL/p/10589176.html