记录2——stm32f411CEU6的LED灯玩UART+DMA通信、外部中断EXIT、定时器中断(另含Proteus仿真)

编程入门 行业动态 更新时间:2024-10-07 04:25:34

记录2——stm32f411CEU6的LED灯玩UART+DMA通信、外部中断EXIT、<a href=https://www.elefans.com/category/jswz/34/1768257.html style=定时器中断(另含Proteus仿真)"/>

记录2——stm32f411CEU6的LED灯玩UART+DMA通信、外部中断EXIT、定时器中断(另含Proteus仿真)

文章目录

  • 前言
  • 一、UART+DMA
    • DMA概述
    • DMA传输四要素:
    • 任务
    • 配置工程
    • 代码实现
  • 二、外部中断EXIT
    • 任务
    • 配置工程
    • 代码实现
      • 拓展
  • 三.定时器中断
    • 任务1
    • 简单介绍
    • 配置工程
    • 代码实现
      • 1.开启定时器中断
      • 2.定时器中断回调函数
    • Proteus仿真


前言

本文简单介绍一下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,即100*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 */

Proteus仿真

  • 由于proteus的stm32类型有限,此处以f103c6为例,模拟仿真,相关配置参照前面的方法利用CubeMX+Keil+Proteus即可。

  • PA8为开启定时器2的引脚,PB1可由PA15(连接按键BUTTON)的外部中断进行开关控制。

  • 实现效果:
    D1、D2开始均亮;
    按下按键,D1灭,再按,亮
    D2每隔1s闪烁一次。

更多推荐

记录2——stm32f411CEU6的LED灯玩UART+DMA通信、外部中断EXIT、定时器中断(另含Proteus仿真)

本文发布于:2024-02-28 04:26:10,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768139.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:定时器   通信   UART   LED   Proteus

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!