使用HAL库实验中断开关点灯及串口通信

一、实验题目要求

学习sm32中断原理和编程方法。使用stm32tubemx和HAL库完成以下练习:
1.用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

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

二、中断介绍

1.什么是中断

中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。

中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。
中断分为同步中断和异步中断。

  • 同步中断——同步中断是当指令执行时由 控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断
  • 异步中断——异步中断是由其他硬件设备依照 CPU 时钟信号随机产生的
    -通常我们所说的中断指的是异步中断,我们将同步中断称为异常。(异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的)。
    应用程序不必关心中断的发生与处理
    中断服务程序不必关心应用程序的执行状态
    中断是“上层应用”与“底层代码”的“分割边界”
    在这里插入图片描述
    中断处理:CPU响应中断,转入中断处理程序,系统开始处理中断。
    中断响应:CPU收到中断请求后转向相应的事件处理程序。

开中断后,系统就可以响应其他的中断了,关中断后,系统不响应其他的中断除非优先级高的中断。

中断屏蔽:在中断请求产生后,系统用软件方式有选择地封锁部分中断而允许其余部分中断仍能得到响应。

2.中断的类型及优先级

1.中断的类型

  • 硬中断:通过处理器中断信号线产生的中断
  • 软中断:通过非法指令或特殊指令触发的中断

2.中断优先级

  • 多个中断同时出现时,处理器先响应高优先级的中断
  • 低优先级中断的ISR执行时,可以被高优先级中断再次打断
  • ISR比App Code拥有更高的执行优先级
    在这里插入图片描述

三、CubeMX中断方式点灯

1、实验题目分析

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

这里我选用的核心板为STM32F103C8T6最小核心板
设置PA1端接开关,PB5接LED

对于按键电路,设置上拉式按键

  • 按键按下,引脚PA1读到低电平
  • 按键释放,引脚PA1读到高电平
    LED灯的触发方式
  • 按键按下瞬间,形成下降沿
  • 按键释放瞬间,形成上升沿
    因此这里设置上升沿触发,即松开按键时灯亮,因为题目要求为开关接高高电平亮灯。

2、CubeMX工程设置

新建项目选择STM3210c8t6.

  • 外设设置
    设置指示灯LED引脚pb3,设置引脚模式为输出模式GPIO_Output
    设置按键引脚PA2,设置引脚为外部中断功能,PA2与外部中断线EXIT1连接GPIO_EXIT1
    在这里插入图片描述
    对于LED对应的PB3管脚,默认设置即可,名字设为LED

在这里插入图片描述
对于开关对应管脚PA2,设置其触发方式为上升沿触发
在这里插入图片描述

  • 使能对应的外部中断线,点击Enabled
    在这里插入图片描述
  • 配置中断优先级
    在这里插入图片描述
  • 时钟设置
    在这里插入图片描述
    之后生成工程文件即可

3、代码撰写

在Keil文件中的gpio.c文件可以找到中断服务函数

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)

当捕获到上升沿,触发中断,就会进入到这个函数里面

然后就会执行HAL_GPIO_EXTI_Callback(GPIO_Pin)函数,此函数为回调函数,我们打开可以发现前面有个weak。
那么我们在main.c文件中找个地方重新写一下。
位置在main函数下方。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if( GPIO_Pin == A1_EXTI_Pin)//判断外部中断源
	{
		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);//翻转LED状态
	}
}


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

将代码烧录到C8T6核心板中

在这里插入图片描述

4、电路连接

GPIO默认是3.3V高电平,当按下按键,GPIO变为低电平,此过程是下降沿。松开按键,GPIO又变为高电平,此过程为上升沿。因为设置的是上升沿中断,也就是松开按键的时候,灯会变化。

GND ———G
3v3————3v3
RXD————PA9
TXD————PA10
LED长脚——3V3
LED短脚——PB3
PA2——3V3——亮灯
PA2——GND——熄灯

成果演示
请添加图片描述

四、中断方式串口通信

1、实验要求

采用串口中断方式重做口通信作业,分别实现:1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。

2、工程设置

  • 设置RCC
    在这里插入图片描述
  • 设置串口

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

  • 时钟设置
    在这里插入图片描述
    之后导出Keil文件并打开。

3、代码撰写

  • 在main函数前定义全局变量
char tips[]="go stm32!";//开始信号
char c;//指令 s:停止  t:开始
char message[]="hello Windows!\r\n";//输出信息
char stop[]="stop stm32!";
char tips1[]="go stm32!\r\n";
char *tt="go stm32!";
int flag=0;//标志 0:停止发送 1.开始发送

  • 在main函数中设置接收中断
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

函数功能

功能:串口中断接收,以中断方式接收指定长度数据。
大致过程是,设置数据存放位置,接收数据长度,然后使能串口接收中断。
接收到数据时,会触发串口中断。
再然后,串口中断函数处理,直到接收到指定长度数据
而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)
参数
UART_HandleTypeDef *huart UATR的别名
huart1 *pData 接收到的数据存放地址
Size 接收的字节数
本次实验设置接收中断

HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  //接收字符中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&tips, strlen(tips));  //接收字符串中断

main函数中的while循环里面添加传输代码

if(flag==1){
			//发送信息
			HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF); 
			
			//延时
			HAL_Delay(1000);
		}

在main函数下面重写中断处理函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	//当输入的指令为0时,发送提示并改变flag
	if(c=='s'){
		flag=0;
	}
	
	//当输入的指令为1时,发送提示并改变flag
	else if(c=='t'){
		flag=1;
	}
	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
}

接收字符串时的中断处理函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	
	//当输入的指令为1时,发送提示并改变flag
	if(strcmp(tips,tt)==0){
		flag=1;
		HAL_UART_Transmit(&huart1, (uint8_t *)&g, strlen(g),0xFFFF);
	}
	//当输入的指令为0时,发送提示并改变flag
	else{
		flag=0;
		HAL_UART_Transmit(&huart1, (uint8_t *)&sp, strlen(sp),0xFFFF); 
	}
	
	//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&tips, strlen(tips));  
}

4、效果演示

在这里插入图片描述

五、串口DMA连续向上位机连续发送数据

1、DMA基本介绍

DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,

CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?

因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理。
请添加图片描述
DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。

1、DMA定义

DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

2、DMA传输方式

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

  • 外设到内存
  • 内存到外设
  • 内存到内存
  • 外设到外设

3、DMA传输参数

我们知道,数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个

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

4、DMA的主要特征

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

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

2、实验要求

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

3、工程设置

  • RCC设置
    在这里插入图片描述
  • 串口设置
    在这里插入图片描述
  • 中断设置
    在这里插入图片描述
  • DMA设置
    在这里插入图片描述
  • 在System view下选择DMA
    在这里插入图片描述
  • 时钟设置
    在这里插入图片描述
    之后导出Keil工程文件即可。

4、代码

在main.c文件添加代码

uint8_t Senbuff[] = "Hello world!";  //定义数据发送数组
 HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
  HAL_Delay(1000);

5、串口发送数据

请添加图片描述

六、总结

经历了特别多的失败希望,好在在帮助下成功完成了实验。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值