STM32中断与串口DMA通信

一、中断与DMA通信原理

1. 中断

中断是由内核外部产生的,一般由硬件引起,比如外设中断和外部中断等。

1.1 中断全过程

中断发生:当CPU在处理某一事件A时,发生了另一个事件B,请求CPU迅速去处理;
中断处理:CPU暂停当前的工作,转去处理事件B;
中断返回:当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继续处理事件A;
以上整个过程称之为中断。
在这里插入图片描述

1.2 中断通道

微控制器片内集成了很多外设,对于单个外设而言,它通常具备若干个可以引起中断的中断源,而该外设的所有中断源只能通过指定的中断通道向内核申请中断。由于中断源数量较多,而中断通道有限,会出现多个中断源共享一个中断通道的情况。

1.3 外部中断

EXTI(External interrupt/event controller) ,外部中断/事件控制器,管理了控制器的 20 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。

  • 外部中断控制器结构框图
    在这里插入图片描述
  • GPIO引脚在这里插入图片描述
    在这里插入图片描述

1.4 中断的作用

  1. 速度匹配:可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾;
  2. 分时操作:CPU可以分时为多个外部设备服务,提高计算机的利用率;
  3. 实时响应:CPU能够及时处理应用系统的随机事件,增强系统的实时性;
  4. 可靠性高:CPU可以处理设备故障及掉电等突发事件,提高系统可靠性;

2. DMA通信原理

2.1 DMA基本定义

  • DMA,全称Direct Memory Access,即直接存储器访问。
  • DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设与存储器之间以及存储器与存储器之间进行高速数据传输。
  • DMA传输过程的初始化和启动由CPU完成传输过程由DMA控制器执行,无需CPU参与,从而节省CPU资源,提高利用率。

2.2 DMA传输方式

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。

  • 四种情况的数据传输如下:
    a) 外设到内存
    b) 内存到外设
    c) 内存到内存
    d) 外设到外设

2.3 DMA传输的四个要素

  1. 传输源 :DMA数据传输的来源
  2. 传输目标:DMA数据传输的目的
  3. 传输数量:DMA传输数据的数量
  4. 触发信号:启动一次DMA数据传输的动作

当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式,当到达传输终点时会重新启动DMA传输。  
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。

2.4 DMA的主要特征

每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发,这些功能通过软件来配置。

  • 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推);
  • 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;
  • 支持循环的缓冲器管理;
  • 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
  • 存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;
    闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;
  • 可编程的数据传输数目:最大为65535。

2.5 DMA数据传输方式

  1. 普通模式
    传输结束后(即要传输数据的数量达到零),将不再产生DMA操作。若开始新的DMA传输,需在关闭DMA通道情况下,重新启动DMA传输。
  2. 循环模式
    可用于处理环形缓冲区和连续数据流(例如ADC扫描模式)。当激活循环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值进行加载, 并继续响应DMA请求。

2.6 STM32的DMA控制器特点

  1. STM32F411微控制器具备两个DMA控制器:DMA1和DMA2,每个控制器有8个数据流,每个数据流可以映射到8个通道(或请求);
  2. 每一个DMA控制器用于管理一个或多个外设的存储器访问请求,并通过总线仲裁器来协调各个DMA请求的优先级;
  3. 数据流(stream)是用于连接传输源和传输目标的数据通路,每个数据流可以配置为4. 不同的传输源和传输目标,这些传输源和传输目标称为通道(Channel);
  4. 具备16字节的FIFO。使能FIFO功能后,源数据先送入FIFO,达到FIFO的触发阈值后,再传送到目标地址。
    在这里插入图片描述

关于更多DMA通信原理的了解,可参考博客:
【STM32】 DMA原理,步骤超细详解,一文看懂DMA

二、使用中断控制LED灯点亮熄灭

本例使用的是外部中断控制一个LED灯的变化。

1. 新建工程

打开STM32CubeMX程序,点击File下的New Project新建一个工程;
在这里插入图片描述
Part Number处选择芯片,根据自己需求所选,这里以STM32F103C8为例,然后点击中间出现的一列芯片的信息,再点击Start Project
在这里插入图片描述

2. 基本配置

2.1 配置调试接口

点击System Core,进入SYS,在Debug处选择Serial Wire(SWD串行调试接口);
在这里插入图片描述

2.2 配置时钟

进入RCC,将HSE设置为Crystal/Ceramic Resonator
在这里插入图片描述
切换到Clock Configuration界面,勾选PLLCLK
在这里插入图片描述

3. 外设配置

3.1 配置输出寄存器

切换回Pinout & Configuration界面,进入GPIO,点击相应的引脚,如PA4,选择GPIO_Output
在这里插入图片描述

3.2 配置外部中断

接着初始化一个GPIO端口模拟按键,如PB10,右击选择GPIO_EXTI10模式;
在这里插入图片描述
在中间的GPIO Mode and Configuration界面中点击PA4,配置如下图所示:
请添加图片描述
配置PB10
请添加图片描述

3.3 配置中断优先级

切换到NVIC Mode and Configuration界面,勾选图示位置,使能外部中断,并配置优先级(本例一个管脚,默认为0);
请添加图片描述

4. 工程配置

切换到Project Manager界面,在Project下,配置工程名及路径,选择所需的编译器及对应版本;
请添加图片描述
进入Code Generator界面,在Generated files处勾选生成初始化.c/.h文件,最后点击GENERATE CODE生成代码。
请添加图片描述
最后点击Open Project可直接进入工程。
请添加图片描述

5. 编写中断函数

打开工程,可以在stm32f1xx_it.c文件中,找到已配置好的中断处理函数:
请添加图片描述
接下来要将中断处理函数放到void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 函数中,这是用户自定义的一个函数,代码如下:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  switch(GPIO_Pin)
  {
    case GPIO_PIN_10: 
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);	//LED为自定义的引脚名
		}
		break;
    default: break;		
  }
}

加入main.c函数如下:
请添加图片描述
添加代码后,点击左上角的按钮进行编译,生成相应的.hex文件;
请添加图片描述

6. 程序烧录

打开mcuisp软件进行程序烧录:
选择刚刚生成的.hex文件,点击开始编程进行烧录;
在这里插入图片描述
结果显示烧录成功;
在这里插入图片描述

7. 运行效果

由于使用c8t6最小系统板,板上没有多余的按键,所以使用杜邦线代替。
本例使用杜邦线将PB10引出,PB10每从高电平到低电平,LED灯翻转一下。
在这里插入图片描述

三、使用串口中断方式发送“Hello windows!”

在上篇博客 基于MDK5实现STM32串口通信 中,用while循环连续发送“Hello windows!”,但是这样程序执行效率低,本例我们使用串口的方式来发送数据。

1. 中断配置

关于新建工程、基本配置、工程配置及相关GPIO 都与前例相同,不同之处在于中断配置,这里不再赘述。

进行USART1的中断配置:
Pinout & Configuration 界面进入Connnectivity,选择USART1,Mode选择Asynchronous(异步模式),并在下面的NVIC Settings,勾选中断;
请添加图片描述

2. 编写中断函数

使用MDK5打开刚刚创建的工程,这里需要使用一个数组来保存我们需要发送的数据:

uint8_t temp[]="Hello windows!\n";

还需要一个回调函数 HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) :

uint8_t i;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(i<=50)
	{
		HAL_UART_Transmit_IT(&huart1, temp, sizeof(temp));
		i++;   //每调用一次,i++,当调用超过50次时,不再发送数据
	}	
}

我们在回调函数中发送再次发送相同的数据,在合适的条件下结束发送;

在这里插入图片描述

在main函数中调用

HAL_UART_Transmit_IT(&huart1, temp, sizeof(temp));

将数组中的内容发送出去,发送完成后,自动调用发送完成回调函数;

请添加图片描述
最后点击左上角的按钮进行调试编译,生成相应的.hex文件。
在这里插入图片描述

3. 程序烧录

使用mcuisp软件,选择刚刚生成的.hex文件,点击开始编程进行烧录。
在这里插入图片描述

4. 运行效果

打开野火串口调试助手程序:
在这里插入图片描述
可以看到上位机接收了832个字节就不再接收了,实验成功。

四、使用串口DMA方式发送“Hello windows!”

1. 基本配置

新建工程基本过程同上,进入到基本配置:
Pinout & Configuration 界面点击System Core,勾选SYS,在Debug处选择Serial Wire
请添加图片描述
进入RCC,将HSE设置为Crystal/Ceramic Resonator
请添加图片描述
接着点击Connnectivity,选择USART1Mode处选择Asynchronous,此时在下面就可以看到配置好的一些基础参数:
波特率为115200 Bits/s;传输数据长度为8 Bit;无奇偶检验;停止位为1;
请添加图片描述
点击NVIC Settings ,勾选Enabled使能接收中断;
请添加图片描述

2. DMA配置

在同一界面下进入DMA setting,点击Add添加通道;
请添加图片描述
添加USART_TXUSART_RX,并且配置如下:
请添加图片描述
切换到Clock Configuration界面,勾选HSEPLLCLK,设置APB1分频器/ 2
请添加图片描述
至此工程配置基本完成,创建工程便如上所示操作即可。

3. 编写代码

打开刚刚创建的工程,在mian.c文件中定义一个数组来保存我们需要发送的数据:

uint8_t Senbuff[] = "Hello windows!\n";  //定义一个数组,将想要发送的数据放到数组中去

请添加图片描述
在main函数的while循环语句中加入以下代码:

HAL_UART_Transmit_DMA(&huart1,Senbuff, sizeof(Senbuff));
HAL_Delay(1000);

请添加图片描述
添加代码后,点击左上角的按钮进行编译,生成相应的.hex文件;
请添加图片描述

4. 程序烧录

使用mcuisp软件,选择刚刚生成的.hex文件,点击开始编程进行烧录;
在这里插入图片描述

5. 运行效果

打开野火串口调试助手程序:
在这里插入图片描述

上位机持续接收“Hello windows!”,即实验成功。

五、总结

在本次实验中,使用串口中断方式点亮LED灯,并且分别使用串口中断与DMA方式向上机位发送“Hello windows!”,再次体会到用Cube直接提供初始化代码的便捷性。在学习了理论基础后,再进行实验操作,使对STM32中断和串口DMA传输背后的原理也有了更深的理解。在实际操作过程中,有时会出现LED灯持续亮的问题,经过测试他人的板子,排除了代码错误的可能性,故猜测应该是我们的面包板有接触不良的问题。

六、参考资料

  1. 【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)
  2. STM32中断与DMA通信编程
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值