你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32基础设计---DMA通信

[复制链接]
STMCU小助手 发布时间:2023-1-5 20:55
本文通过一个小的设计来进行讲解,将STM32内部存储的一个数组中的数据,通过DMA操作复制到第二个数组里,并用USART1串口将第二个数组中的数据输出到电脑端,进行检查,看是否复制成功。

首先总结全文,,使用STM32进行DMA操作的主要过程如下:
1,初始化GPIO
2,初始化串口
3,初始化DMA
4,编写主函数

下面介绍详细步骤:

1,初始化GPIO
  1. void IO_Init()
  2. {
  3.         GPIO_InitTypeDef Uart_A; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  4.         Uart_A.GPIO_Pin = GPIO_Pin_9;
  5.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
  6.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
  7.         GPIO_Init(GPIOA,&Uart_A);
  8.        
  9.         Uart_A.GPIO_Pin = GPIO_Pin_10;
  10.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
  11.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
  12.         GPIO_Init(GPIOA,&Uart_A);
  13.        
  14. }
复制代码

2,初始化USART1

  1. void Usart1_Init()
  2. {
  3.         USART_InitTypeDef Uart;
  4.        
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
  6.         Uart.USART_BaudRate = 115200;
  7.         Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  8.         Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  9.         Uart.USART_Parity = USART_Parity_No;
  10.         Uart.USART_StopBits = USART_StopBits_1;
  11.         Uart.USART_WordLength = USART_WordLength_8b;
  12.         USART_Init(USART1,&Uart);
  13.        
  14.         USART_Cmd(USART1,ENABLE);
  15.         USART_ClearFlag(USART1,USART_FLAG_TC); //page 540
  16. }
复制代码


3,初始化DMA
库函数中DMA的结构体如下:
  1. typedef struct
  2. {
  3.   uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

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

  5.   uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.
  6.                                         This parameter can be a value of @ref DMA_data_transfer_direction */

  7.   uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel.
  8.                                         The data unit is equal to the configuration set in DMA_PeripheralDataSize
  9.                                         or DMA_MemoryDataSize members depending in the transfer direction. */

  10.   uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register is incremented or not.
  11.                                         This parameter can be a value of @ref DMA_peripheral_incremented_mode */

  12.   uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register is incremented or not.
  13.                                         This parameter can be a value of @ref DMA_memory_incremented_mode */

  14.   uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.
  15.                                         This parameter can be a value of @ref DMA_peripheral_data_size */

  16.   uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.
  17.                                         This parameter can be a value of @ref DMA_memory_data_size */

  18.   uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Channelx.
  19.                                         This parameter can be a value of @ref DMA_circular_normal_mode.
  20.                                         @note: The circular buffer mode cannot be used if the memory-to-memory
  21.                                               data transfer is configured on the selected Channel */

  22.   uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.
  23.                                         This parameter can be a value of @ref DMA_priority_level */

  24.   uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.
  25.                                         This parameter can be a value of @ref DMA_memory_to_memory */
  26. }DMA_InitTypeDef;
复制代码
  1. DMA_DIR
复制代码

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

库函数中有两个定义:
  1. #define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)
  2. #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; 这个是用来设置是否进行 内存到内存传输

初始化函数如下:
  1. void Dma_Init()
  2. {
  3.         DMA_InitTypeDef dma;
  4.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//老规矩,先开心脏
  5.         dma.DMA_MemoryBaseAddr = (u32)zimu;内存地址
  6.         dma.DMA_PeripheralBaseAddr = (u32)zimu_1;外设地址
  7.         dma.DMA_DIR = DMA_DIR_PeripheralDST;外设为目的地,即zimu_1数组为目的地
  8.        
  9.         dma.DMA_BufferSize = 26;缓冲区大小
  10.         dma.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;数据宽度
  11.         dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;同上
  12.        
  13.         dma.DMA_MemoryInc = DMA_MemoryInc_Enabl;内存地址自增
  14.         dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;外设地址自增
  15.        
  16.         dma.DMA_Mode = DMA_Mode_Normal;单次模式
  17.         dma.DMA_Priority = DMA_Priority_High;优先级为高
  18.         dma.DMA_M2M = DMA_M2M_Enable;设置为内存到内存传输
  19.        
  20.         DMA_Init(DMA1_Channel6,&dma);寄存器初始化
  21.         DMA_Cmd(DMA1_Channel6,ENABLE);DMA使能
  22. }
复制代码

4,编写主函数
  1. int main()
  2. {
  3.         void printf_string(char* a);
  4.         IO_Init();GPIO初始化
  5.         Usart1_Init();USART1初始化
  6.         Dma_Init();DMA初始化
  7.         while(DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET){}//等待DMA操作完成,在参考手册的149页可以仔细看这个寄存器
  8.        
  9.         while(1){
  10.             if(USART_GetFlagStatus(USART1,USART_FLAG_TXE))判断是否能用串口输出
  11.                 {
  12.                     printf_string(zimu_1);输出zimu_1数组
  13.                     delay(3000);延时
  14.                 }
  15.         }
  16. }
  17. void printf_string(char* a)
  18. {
  19.         while(*a != '\0')直到数组末尾
  20.         {
  21.                 USART1->DR = *a;赋值给USART的数据寄存器
  22.                 while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));等待发送成功
  23.                 a++;地址加一
  24.         }
  25. }
复制代码


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


亲测,可运行。详细代码如下:
  1. #include<stm32f10x.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4.        
  5. 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'};
  6. char zimu_1[32]={'.'};
  7. void delay(uint n)
  8. {
  9.         int i,j;
  10.         for(i=0;i<n;i++)
  11.         for(j=0;j<8500;j++);
  12. }

  13. void IO_Init()
  14. {
  15.         GPIO_InitTypeDef Uart_A;
  16.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  17.        
  18.         Uart_A.GPIO_Pin = GPIO_Pin_9;
  19.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
  20.         Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
  21.         GPIO_Init(GPIOA,&Uart_A);
  22.        
  23.         Uart_A.GPIO_Pin = GPIO_Pin_10;
  24.         Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
  25.         Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
  26.         GPIO_Init(GPIOA,&Uart_A);
  27.        
  28. }
  29. void Usart1_Init()
  30. {
  31.         USART_InitTypeDef Uart;
  32.        
  33.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
  34.         Uart.USART_BaudRate = 115200;
  35.         Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  36.         Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  37.         Uart.USART_Parity = USART_Parity_No;
  38.         Uart.USART_StopBits = USART_StopBits_1;
  39.         Uart.USART_WordLength = USART_WordLength_8b;
  40.         USART_Init(USART1,&Uart);
  41.        
  42.         USART_Cmd(USART1,ENABLE);
  43.         USART_ClearFlag(USART1,USART_FLAG_TC); //page 540
  44. }

  45. void Dma_Init()
  46. {
  47.         DMA_InitTypeDef dma;
  48.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  49.         dma.DMA_MemoryBaseAddr = (u32)zimu;
  50.         dma.DMA_PeripheralBaseAddr = (u32)zimu_1;
  51.         dma.DMA_DIR = DMA_DIR_PeripheralDST;
  52.        
  53.         dma.DMA_BufferSize = 26;
  54.         dma.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
  55.         dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  56.        
  57.         dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
  58.         dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
  59.        
  60.         dma.DMA_Mode = DMA_Mode_Normal;
  61.         dma.DMA_Priority = DMA_Priority_High;
  62.         dma.DMA_M2M = DMA_M2M_Enable;
  63.        
  64.         DMA_Init(DMA1_Channel6,&dma);
  65.         DMA_Cmd(DMA1_Channel6,ENABLE);
  66. }
  67. int main()
  68. {
  69.         void printf_string(char* a);
  70.         IO_Init();
  71.         Usart1_Init();
  72.         Dma_Init();
  73.        
  74.         GPIOC->BSRR = GPIO_Pin_13;
  75.        
  76.         while(DMA_GetFlagStatus(DMA1_FLAG_TC6) == RESET){}
  77.        
  78.         while(1){
  79.         if(USART_GetFlagStatus(USART1,USART_FLAG_TXE))
  80.         {
  81.                 printf_string(zimu_1);
  82.                 delay(3000);
  83.         }
  84.         }
  85. }
  86. void printf_string(char* a)
  87. {
  88.         //USART1->CR1 &= ~USART_CR1_TXEIE;
  89.         USART1->CR1 |= USART_CR1_TXEIE;
  90.         while(*a != '\0')
  91.         {
  92.                 USART1->DR = *a;
  93.                 while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));
  94.                 a++;
  95.         }
  96. }
复制代码

————————————————
版权声明:家安


收藏 评论0 发布时间:2023-1-5 20:55

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版