STM32中断与DMA通信编程

一、学习任务

  1. 用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

  2. 采用串口中断方式重做上周的串口通信作业。

  3. STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。

二、采用中断模式编程控制LED

2.1中断概述

1.数据传输方式
数据传输方式
2.中断概念
中断中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
在这里插入图片描述
3.中断的作用
中断使计算机系统具备应对突发事件的能力,使CPU在运行过程中对外部事件发出的中断请求及时地进行处理,处理完成后又立即返回断点,继续进行CPU原来的工作。
在这里插入图片描述
4.中断优先级
处理器根据不同中断的重要程序设置不同的优先等级。不同优先级中断的处理原则是:高级中断可以打断低级中断;低级中断不能打断高级中断。在某一时刻有几个中断源同时发出中断请求时,处理器只响应其中优先权最高的中断源。当处理机正在运行某个中断服务程序期间出现另一个中断源的请求时,如果后者的优先权低于前者,处理机不予理睬,反之,处理机立即响应后者,进入所谓的“嵌套中断”。
在这里插入图片描述5.中断向量
中断标识码(中断类型号):由硬件(通常是中断控制器)产生,以标识不同的中断源。
中断向量:中断服务程序的入口地址。在某些计算机中,中断向量的位置存放一条跳转到中断服务程序入口地址的跳转指令。
中断向量地址:存储中断向量的存储单元地址。
在这里插入图片描述
6.HAL库的外部中断处理流程
在这里插入图片描述

2.2STM32微控制器中断系统

1.中断通道
中断:由内核外部产生的,一般由硬件引起,比如外设中断和外部中断等。
异常:通常是内核自身产生的,大多是软件引起的,比如除法出错异常、预取值失败等。
在这里插入图片描述
2.
2.1中断优先级

在这里插入图片描述
2.2优先级分组
在这里插入图片描述
3.GPIO引脚的外部中断
触发方式:上升沿触发、下降沿触发、双边沿触发
在这里插入图片描述

2.3工程创建

基础设置及操作参考:https://blog.csdn.net/qq_46475595/article/details/120983297

1.选择芯片STM32F 103C8
在这里插入图片描述
配置系统调试接口 SYS,选择 Serial Wire
在这里插入图片描述
配置外设 RCC ,选择 HSE (外部高速时钟)为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)
在这里插入图片描述
2.设置LED引脚为PA1的输出模式 GPIO_Output,按键引脚为PB15的外部中断模式GPIO_EXTI1
在这里插入图片描述
PA1命名为LED1,PB1命名为EXTI1
在这里插入图片描述
开关对应PB1管脚,GPIO mode处设置为上升沿触发
在这里插入图片描述
使能外部中断线,点击Enabled
在这里插入图片描述
配置中断优先级,因为此处只有一个中断,因此它的优先级为0,为最高,如果有多个中断则可设为0,1,2,3。
在这里插入图片描述
设置时钟
在这里插入图片描述
设置项目名称和路径,修改Toolchain/IDE为MDK-ARM
在这里插入图片描述
自动生成程序。

2.4编写程序

1.添加代码
打开上述工程,点击main.c,添加代码。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 
{ 
	if( GPIO_Pin == EXTI1_Pin ) 
		{
			HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); 
		}
}

在这里插入图片描述
编译
在这里插入图片描述

2.5烧录

选择生成的hex文件并进行烧录(这里我烧录成功)
在这里插入图片描述
在这里插入图片描述
这里有明显接触不良,为接地原因

改良如下:
在这里插入图片描述

三、串口中断实现串口通信

3.1串口中断

特点:
① 发送数据时,将一字节数据放入数据寄存器DR;接收数据时,将DR的内容存放到用户存储区;
② 中断方式不必等待数据的传输过程,只需要在每字节数据收发完成后,由中断标志位触发中断,在中断服务程序中放入新的一字节数据或者读取接收到的一字节数据;
③ 在传输数据量较大,且通信波特率较高(大于38400)时,如果采用中断方式,每收发一个字节的数据,CPU都会被打断,造成CPU无法处理其他事务。因此在批量数据传输,通信波特率较高时,建议采用DMA方式。
函数介绍:
串口中断方式发送函数
在这里插入图片描述
串口中断方式接收函数
在这里插入图片描述
串口中断通用处理函数
在这里插入图片描述
串口发送中断回调函数
在这里插入图片描述
串口接受中断回调函数
在这里插入图片描述
串口中断使能函数
在这里插入图片描述
串口中断标志查询函数
在这里插入图片描述
空闲中断标志清除函数
在这里插入图片描述

3.2创建工程

1.选择芯片
在这里插入图片描述
设置时钟RCC,点击HSE,选择Crystal/Ceramic Resonator
在这里插入图片描述
设置USART1,点击Mode,选择Asynchronous
设置中断,在NVIC Settings中点击Enabled
在这里插入图片描述点击Clock Configuration选择HSE和PLLCLK,修改HCLK值
在这里插入图片描述
设置项目名称和路径,修改Application Structure为Basic,Toolchain/IDE为MDK-ARM,生成项目
在这里插入图片描述
创建成功并打开工程
在这里插入图片描述

3.3代码编写

stm32f1xx_hal.c文件添加头文件

#include <stdio.h>
extern UART_HandleTypeDef huart1;   //声明串口

在这里插入图片描述
重写fget和fput函数

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

在这里插入图片描述
在主函数main.c文件的while循环中添加发送数据

printf("hello windows!\r\n");
HAL_Delay(1000);

在这里插入图片描述
添加定义,接收串口数据

#include "stdio.h"
#include <string.h>
 
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数

在这里插入图片描述
在主函数main.c文件中添加开启接收中断的语句

HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

在这里插入图片描述
添加中断回调函数

/* USER CODE BEGIN 4 */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(RxBuffer,0x00,sizeof(RxBuffer));
		HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
        
	}
	else
	{
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	
		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
            while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

在这里插入图片描述
编译结果
在这里插入图片描述

3.4仿真

烧录成功!!!
在这里插入图片描述
野火调试:
在这里插入图片描述

四、串口DMA接收发数据

4.1DMA

DMA定义:
DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
DMA传输方式:
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。

四种情况的数据传输:
① 外设到内存
② 内存到外设
③ 内存到内存
④ 外设到外设

在这里插入图片描述
DMA数据传输方式
在这里插入图片描述
串口DMA方式发送函数:
在这里插入图片描述
串口DMA方式接收函数:
在这里插入图片描述
接口函数
在这里插入图片描述

4.2创建工程

点击 File->New Pioject或ACCEE TO MCU SELECTOR,创建新工程
选择 STM32F103C8 芯片,点击 Start Project 进入工程
设置时钟RCC,点击HSE,选择Crystal/Ceramic Resonator
设置USART1,点击Mode,选择Asynchronous,在NVIC Settings中点击Enabled(中断)
如上述步骤创建工程。

在USART1中,点击DMA Settings的Add,添加USART_RX 和USART_TX,传输速率设置为中速Medium,模式设置为Normal,右侧选择Memory;在最右侧的System view中选择DMA,点击Add,添加MEMTOMEM。
在这里插入图片描述
设置时钟源,点击Clock Configuration选择HSE和PLLCLK。
在这里插入图片描述
设置项目文件,修改Application Structure为Basic,Toolchain/IDE为MDK-ARM。
在这里插入图片描述
在这里插入图片描述

4.3编写代码

1.添加代码
main.c文件的主函数main

uint8_t Senbuff[] = "Goodbye\r\n";  //定义数据发送数组

主函数main的while循环

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

在这里插入图片描述
编译结果
在这里插入图片描述

4.4仿真

烧录
BOOT0置1,BOOT1置0,打开mcuisp,选择文件路径,开始烧录
在这里插入图片描述
野火调试:
在这里插入图片描述

五、总结

通过此次实验,我掌握了中断的基本概念和作用,了解了HAL库的中断处理流程,学会了DMA方式的串口通信,DMA可以直接访问存储器,而直接绕过CPU,为CPU减负。

六、参考资料

第九章__串口通信(new).pdf
第六章__通用输入输出接口(二)(new).pdf
第七章__中断系统(new).pdf
https://blog.csdn.net/as480133937/article/details/104827639/
https://www.cnblogs.com/breezy-ye/articles/12157442.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值