记录2——stm32f411CEU6的LED灯玩UART+DMA通信、外部中断EXIT、定时器中断


前言

本文简单介绍一下UART+DMA通信、外部中断EXIT、定时器中断的实现方法,水平有限,仅供参考。

一、UART+DMA

DMA概述

即直接访问寄存器。用在外设和存储器之间以及存储器与存储器之间进行高速数据传输,传输过程由DMA控制器执行,无需CPU参与,节省CPU资源

DMA传输四要素:

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

任务

实现LED每隔1s亮一次,且每次每隔1s都发送"abc" 在串口调试助手上显示;当电脑发送两个字母或数字时,单片机再将接收的内容发送回给电脑。

配置工程

1.引脚配置PC13如上一次方法一样
2.配置USART2
在这里插入图片描述
添加串口接收和发送的DMA数据流:
在这里插入图片描述
在这里插入图片描述
优先级配置很重要!!!
在这里插入图片描述

代码实现

/* USER CODE BEGIN 0 */
uint8_t temp1[]="abc";
uint8_t temp2[2];
//声明发送与接收的变量
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_Delay (1);//可以不用延迟,只是想要试验优先级
	if(huart==&huart2) HAL_UART_Transmit_DMA(&huart2,temp2,sizeof(temp2));
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_Delay (1);//可以不用延迟,只是想要试验优先级
	if(huart==&huart2) HAL_GPIO_TogglePin (GPIOC ,GPIO_PIN_13); 
}
 /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_DMA(&huart2,temp2,sizeof(temp2));
//开启DMA接收,temp2为数组,所以不需要&,若只为变量则需要&.由于之前开启了circle循环模式,所以只需要开启一遍即可
  /* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
  while (1)
  {
		HAL_UART_Transmit_DMA(&huart2,temp1,sizeof(temp1));//发送
		HAL_Delay (1000);//延迟一秒
    /* USER CODE END WHILE */

(注意写在while(1)里头!!!)
执行完发送后便开启对应的发送回调函数void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

(可以把单片机与调试器上对应的Tx、Rx用杜母线连接好,打开串口调试助手可以收发一些数据.注意:PA2连RX,PA3连TX。)

二、外部中断EXIT

通俗来说,中断就是当CPU在处理一件事是接到了另一件事发出的请求,CPU转去执行那一件事,完成之后又回来继续之前的事。

任务

实现按键控制LED亮灭,要求按键松开时触发中断

配置工程

配置PC13引脚与之前一样,按键控制的PA0为GPIO_EXTI0。选择的GPIO mode为上升沿进入外部中断,也就是松开按键时进入中断,不松KEY就不亮/灭;若选择为Falling edge trigger detection,则是一按键就亮/灭。
在这里插入图片描述

在这里插入图片描述
开启中断且设置优先级
在这里插入图片描述

代码实现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
函数定义如下图:
在这里插入图片描述

拓展

让LED灯按下按键时亮,松开时灭(按下时亮需要配置控制按键的PA0为下降沿触发)

/* USER CODE BEGIN 2 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
	{
		if(GPIO_Pin==GPIO_PIN_0 )
		{
			HAL_Delay (10);
			if(HAL_GPIO_ReadPin (GPIOA ,GPIO_PIN_0)==GPIO_PIN_RESET)//按键按下
			{
				HAL_GPIO_WritePin (GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);//LED亮
			}
		}
		if(GPIO_Pin==GPIO_PIN_0 )//需要再进行一次判断实现消抖,效果更好
		{
			HAL_Delay (10);
			if(HAL_GPIO_ReadPin (GPIOA ,GPIO_PIN_0)==GPIO_PIN_SET)//按键松开
			{
				HAL_GPIO_WritePin (GPIOC,GPIO_PIN_13,GPIO_PIN_SET);LED灭
			}
		}
	}

/* USER CODE END 2 */

(效果好像还不是很理想,会有松开时仍然亮着的情况)
此时Rising/Falling edge 就很好地派上了用场,反正只要按键有电平变化就进入中断,翻转LED电平(不过用TogglePin这个函数还是有一定的失误率,或许WritePin会更好)

/* USER CODE BEGIN 2 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin ==GPIO_PIN_0 )
	{
		HAL_Delay(10);
		HAL_GPIO_TogglePin (GPIOC,GPIO_PIN_13);
	}	
}

/* USER CODE END 2 */

三.定时器中断

任务1

实现用定时器控制LED灯每隔1s亮一次。

简单介绍

计算公式如图:
在这里插入图片描述

配置工程

1.配置LED引脚(PC13),同之前配置一样
2.开启TIM2
在这里插入图片描述

3.配置时钟树
在这里插入图片描述
4.计算且使能TIM2中断
由开头的计算公式可知:若想让LED灯每隔一秒闪一次,即周期为1s。由时钟树可知TIM2对应的TIM_CLK为100MHz,即1000000Hz,则配置PSC为100-1,ARR为1000000-1,此时计算得到的周期为1s.
在这里插入图片描述
在这里插入图片描述
5.优先级配置
优先级数字越大,优先级越高
在这里插入图片描述

代码实现

1.开启定时器中断

/* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim2);
  /* USER CODE END 2 */

2.定时器中断回调函数

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);//翻转电平
}
/* USER CODE END 0 */

版权声明:本文为CSDN博主「weixin_65489379」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_65489379/article/details/122783396

生成海报
点赞 0

weixin_65489379

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32F2————配置时钟延迟不准的问题

STM32F2配置时钟问题 笔者在本科毕业设计使用STM32F207芯片,但是在配置时钟时出现了问题。 问题 我按照F1写代码的延时函数放在F2竟然不准了 换个办法 使用Systick时钟也是不准,原因是笔者代

为什么重写printf函数没有用?

以前在网上找了无数方法去重写printf函数,但发现都没效果,今天偶然发现重写printf函数可以了,原因是以前没有勾选微库(Use MicroLlB)! 这里