DMA技术在STM32中优化UART、SPI和I2C通信性能的研究与实现

**DMA(Direct Memory Access,直接存储器访问)技术可以在STM32微控制器上优化UART、SPI和I2C等通信性能。**DMA可以实现数据的高速传输,减轻CPU的负担,提高系统性能。在本篇文章中,我将探讨DMA技术在STM32中优化这些通信协议的研究和实现。

一、DMA工作原理

**DMA可以实现外设与存储器之间的直接数据传输,不需要CPU的干预。**DMA控制器位于片内,独立于CPU,可以直接访问片外存储器,以及与UART、SPI和I2C等外设进行数据交换。

DMA工作的基本原理如下:

  1. CPU配置DMA的控制寄存器,包括源地址、目的地址、传输长度和传输模式等。

  2. 当满足触发条件时,DMA控制器开始进行数据传输。

  3. DMA控制器从源地址读取数据,然后将数据传输到目的地址。

  4. 数据传输完成后,DMA控制器产生中断或通知CPU。

通过使用DMA技术,外设与存储器之间的数据传输可以在不干扰CPU的情况下进行,从而提高系统性能。

二、DMA在STM32中的应用

1. UART通信中的DMA
在UART通信中,使用DMA技术可以高效地完成数据的发送和接收操作。

复制代码
```c
#include "stm32f4xx.h"

void UART_DMA_Init() {
  // 使能UART时钟和DMA时钟
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
  
  // 配置UART和GPIO引脚
  
  // 配置UART的DMA模式和相关寄存器
  USART1->CR3 |= USART_CR3_DMAT | USART_CR3_DMAR; // 使能DMA发送和接收
  DMA2_Stream7->CR |= DMA_SxCR_DIR_0; // 设置DMA为内存到外设模式
  
  // 配置DMA传输相关寄存器和缓冲区
  DMA2_Stream7->PAR = (uint32_t)(&(USART1->DR)); // 外设地址为UART数据寄存器
  DMA2_Stream7->M0AR = (uint32_t)buffer; // 内存地址为数据缓冲区地址
  DMA2_Stream7->NDTR = sizeof(buffer); // 传输长度
  
  // 配置DMA传输模式、优先级等
  DMA2_Stream7->CR |= DMA_SxCR_MINC | DMA_SxCR_PINC; // 允许内存和外设地址自动增加
  DMA2_Stream7->CR |= DMA_SxCR_TCIE; // 使能传输完成中断
  
  // 使能DMA传输
  DMA2_Stream7->CR |= DMA_SxCR_EN;
}

void DMA2_Stream7_IRQHandler() {
  if (DMA2->HISR & DMA_HISR_TCIF7) {
    // 数据传输完成
    
    // 清除标志位
    DMA2->HIFCR |= DMA_HIFCR_CTCIF7;
  }
}

int main() {
  UART_DMA_Init();

  while (1) {
    // 向缓冲区写入数据
    // ...
    
    // 发起DMA传输
    DMA2_Stream7->CR |= DMA_SxCR_EN; // 手动启动DMA传输
  }
}
```

2. SPI通信中的DMA
在SPI通信中,DMA技术可以实现数据的高速传输、减少CPU的占用以及降低通信延迟。

复制代码
```c
#include "stm32f4xx.h"

void SPI_DMA_Init() {
  // 使能SPI时钟和DMA时钟
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
  
  // 配置SPI和GPIO引脚
  
  // 配置SPI的DMA模式和相关寄存器
  SPI1->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN; // 使能DMA发送和接收
  DMA2_Stream3->CR |= DMA_SxCR_DIR_0; // 设置DMA为内存到外设模式
  
  // 配置DMA传输相关寄存器和缓冲区
  DMA2_Stream3->PAR = (uint32_t)(&(SPI1->DR)); // 外设地址为SPI数据寄存器
  DMA2_Stream3->M0AR = (uint32_t)txBuffer; // 内存地址为发送数据缓冲区地址
  DMA2_Stream3->NDTR = sizeof(txBuffer); // 传输长度
  
  DMA2_Stream2->PAR = (uint32_t)(&(SPI1->DR)); // 外设地址为SPI数据寄存器
  DMA2_Stream2->M0AR = (uint32_t)rxBuffer; // 内存地址为接收数据缓冲区地址
  DMA2_Stream2->NDTR = sizeof(rxBuffer); // 传输长度
  
  // 配置DMA传输模式、优先级等
  DMA2_Stream3->CR |= DMA_SxCR_MINC; // 允许内存地址自动增加
  DMA2_Stream2->CR |= DMA_SxCR_MINC | DMA_SxCR_PL_1; // 允许内存地址自动增加,设置高优先级
  
  // 使能DMA传输
  DMA2_Stream3->CR |= DMA_SxCR_EN;
  DMA2_Stream2->CR |= DMA_SxCR_EN;
}

void DMA2_Stream3_IRQHandler() {
  if (DMA2->LISR & DMA_LISR_TCIF3) {
    // 数据传输完成
    
    // 清除标志位
    DMA2->LIFCR |= DMA_LIFCR_CTCIF3;
  }
}

void DMA2_Stream2_IRQHandler() {
  if (DMA2->LISR & DMA_LISR_TCIF2) {
    // 数据传输完成
    
    // 清除标志位
    DMA2->LIFCR |= DMA_LIFCR_CTCIF2;
  }
}

int main() {
  SPI_DMA_Init();

  while (1) {
    // 向发送缓冲区写入数据
    // ...
    
    // 发起SPI的DMA发送
    DMA2_Stream3->CR |= DMA_SxCR_EN; // 手动启动DMA发送
  }
}
```

3. I2C通信中的DMA
在I2C通信中,DMA技术可以实现数据的高速传输、减少CPU的占用以及提高通信的稳定性。

复制代码
```c
#include "stm32f4xx.h"

void I2C_DMA_Init() {
  // 使能I2C时钟和DMA时钟
  RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
  
  // 配置I2C和GPIO引脚
  
  // 配置I2C的DMA模式和相关寄存器
  I2C1->CR2 |= I2C_CR2_DMAEN; // 使能DMA
  DMA1_Stream6->CR |= DMA_SxCR_DIR_1; // 设置DMA为外设到内存模式
  
  // 配置DMA传输相关寄存器和缓冲区
  DMA1_Stream6->PAR = (uint32_t)(&(I2C1->DR)); // 外设地址为I2C数据寄存器
  DMA1_Stream6->M0AR = (uint32_t)rxBuffer; // 内存地址为接收数据缓冲区地址
  DMA1_Stream6->NDTR = sizeof(rxBuffer); // 传输长度
  
  // 配置DMA传输模式、优先级等
  DMA1_Stream6->CR |= DMA_SxCR_MINC | DMA_SxCR_PL_1; // 允许内存地址自动增加,设置高优先级
  
  // 使能DMA传输
  DMA1_Stream6->CR |= DMA_SxCR_EN;
}

void DMA1_Stream6_IRQHandler() {
  if (DMA1->HISR & DMA_HISR_TCIF6) {
    // 数据传输完成
    
    // 清除标志位
    DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
  }
}

int main() {
  I2C_DMA_Init();

  while (1) {
    // 向I2C发送数据
    // ...
    
    // 发起I2C的DMA发送
    DMA1_Stream6->CR |= DMA_SxCR_EN; // 手动启动DMA发送
  }
}
```

**三、总结
DMA技术在STM32上的应用可以显著提高UART、SPI和I2C等通信协议的性能和效率,减轻CPU的负担,提高系统的稳定性。**通过上述代码示例,可以实现UART、SPI和I2C的DMA传输。在实际应用中,需要根据具体需求和外设功能进行配置,以实现最佳的性能和稳定性。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

相关推荐
雅斯驰26 分钟前
AES-128加密+滚动码认证:ATA5702W如何防御中继攻击与信号重放
运维·单片机·嵌入式硬件·物联网·自动化
iCxhust1 小时前
微机原理课程设计大综合---计数器
汇编·单片机·嵌入式硬件·课程设计·微机原理
搁浅小泽3 小时前
PCBA焊点的检测方法
单片机·嵌入式硬件·可靠性工程师
朴人4 小时前
【stm32无感FOC理论与实践:滑模观测器】【01 观测反电动势】
stm32·foc·永磁同步电机·无刷电机·pmsm·无感
Deitymoon4 小时前
STM32——PWM控制舵机
stm32·单片机·嵌入式硬件
菜鸟的日志5 小时前
【嵌入系统】嵌入式学习笔记(一)
windows·笔记·嵌入式硬件·学习·ubuntu·操作系统
电子科技圈6 小时前
四大“门派”围攻边缘及端侧AI SoC市场“光明顶”
人工智能·嵌入式硬件·mcu·物联网·网络安全·音视频·语音识别
CHINA红旗下6 小时前
串口的使用
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑7 小时前
嵌入式测试学习第2天:欧姆定律 + 功率计算 + 电路单位换算
单片机·嵌入式硬件
BT-BOX7 小时前
Multisim 14.3 安装与汉化指南(附下载链接)
嵌入式硬件·物联网