基于HAL库的STM32呼吸灯实验

发布者:花开堂前最新更新时间:2023-07-20 来源: elecfans关键字:HAL库  STM32  呼吸灯 手机看文章 扫描二维码
随时随地手机看文章

先决条件:装有编译和集成的开发环境,比如:Keil uVision5。

板子硬件要求:设计了LED在定时器的接口上

呼吸灯是一种常见的电子制作实验项目,其通过控制 LED 灯的亮度变化,实现了一种模拟人类呼吸的效果。 作为一种常见的数字调光技术,呼吸灯广泛应用于工业控制、智能家居等领域。 而在此过程中,使用微控制器如 STM32 ,则可以更加便捷、灵活地实现呼吸灯的控制。 因此,本文将介绍基于 STM32 的呼吸灯实验,通过代码编写、编译下载和调试运行,实现了一个简单的呼吸灯控制系统。

实验目的

本实验旨在通过 STM32 的呼吸灯实验,掌握 STM32 的编程方法和调试技巧,并深入理解呼吸灯的原理、调光技术和周期控制等知识点。 在本实验过程中,我们将涉及 STM32 的 GPIO 端口配置、定时器和 PWM 的使用、时钟配置和中断处理等技术

PWM介绍

PWM(Pulse Width Modulation)即脉冲宽度调制技术,是一种通过调节脉冲信号的占空比来实现模拟信号的调节的技术。 在PWM控制中,周期性的方波称为PWM波,其占空比是指高电平时间与周期的比值。 PWM波信号可以通过控制电路的输出电平来实现对外设的控制,如对LED的亮度、电机的转速等。 通常使用定时器模块来生成PWM波,定时器在每个周期内发出固定的时间间隔中断,根据设定的占空比,每个周期内的高电平时间和低电平时间不同,从而实现对PWM波的控制。

基础工程

使用STM32CubeMX配置stm32的基本配置。 基本的配置如下:开启swd调试,开启外部时钟,配置相应的定时器。

图片

  • 呼吸灯连接的硬件定时器配置

图片

  • 时钟界面选项卡:

图片

  • 工程选项卡:

图片

点击右上角的的生成代码:

图片

使用keil打开工程,编译工程,一切都是ok

图片

主要代码

其中我定时器配置了200hz的频率,肉眼观察明显一些,主函数中改变占空比。

/* TIM1 init function */

void MX_TIM1_Init(void)

{



  /* USER CODE BEGIN TIM1_Init 0 */



  /* USER CODE END TIM1_Init 0 */



  TIM_ClockConfigTypeDef sClockSourceConfig = {0};

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  TIM_OC_InitTypeDef sConfigOC = {0};

  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};



  /* USER CODE BEGIN TIM1_Init 1 */



  /* USER CODE END TIM1_Init 1 */

  htim1.Instance = TIM1;

  htim1.Init.Prescaler = 720-1;     // 分频720  100khz  10us计一数

  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim1.Init.Period = 500-1;        // 计数500次 500*10 = 5000us = 5ms = 200hz

  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim1.Init.RepetitionCounter = 0;

  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)

  {

    Error_Handler();

  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)

  {

    Error_Handler();

  }

  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)

  {

    Error_Handler();

  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)

  {

    Error_Handler();

  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 0;   

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)

  {

    Error_Handler();

  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;

  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

  sBreakDeadTimeConfig.DeadTime = 0;

  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)

  {

    Error_Handler();

  }

  /* USER CODE BEGIN TIM1_Init 2 */



  /* USER CODE END TIM1_Init 2 */

  HAL_TIM_MspPostInit(&htim1);



}

main函数


int main(void)

{

  /* USER CODE BEGIN 1 */

  //定义一个变量用来存储比较值

  uint16_t pulse = 0;

  //定义一个变量用来存储方向,0表示递增,1表示递减

  uint8_t dir = 0;

  /* USER CODE END 1 */



  /* MCU Configuration--------------------------------------------------------*/



  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();



  /* USER CODE BEGIN Init */



  /* USER CODE END Init */



  /* Configure the system clock */

  SystemClock_Config();



  /* USER CODE BEGIN SysInit */



  /* USER CODE END SysInit */



  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_USART1_UART_Init();

  MX_TIM2_Init();

  MX_TIM1_Init();

  /* USER CODE BEGIN 2 */



  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);

  /* USER CODE END 2 */



  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    /* USER CODE END WHILE */



    /* USER CODE BEGIN 3 */

   //根据方向判断是递增还是递减

  if (dir == 0)

  {

    //延时10毫秒

    HAL_Delay(10);

    //比较值加一

    pulse++;

    //设置比较值

    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, pulse);

    //如果比较值达到最大值499,就改变方向为递减

    if (pulse == 499)

    {

      dir = 1;

    }

  }

  else if (dir == 1)

  {

    //延时10毫秒

    HAL_Delay(10);

    //比较值减一

    pulse--;

    //设置比较值

    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, pulse);

    //如果比较值达到最小值0,就改变方向为递增

    if (pulse == 0)

    {

      dir = 0;

    }

  }

  }

  /* USER CODE END 3 */

}

实验现象


能在我的硬件上实现呼吸灯的效果。


关键字:HAL库  STM32  呼吸灯 引用地址:基于HAL库的STM32呼吸灯实验

上一篇:基于STM32+FPGA的数据采集系统的设计与实现
下一篇:基于STM32cubemx的电磁智能车

推荐阅读最新更新时间:2024-11-16 20:59

STM32如何确定执行哪个中断函数
如下面所示: NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //NRF24L01 中断响应 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); 则对应的中断函数就是 STM3210x_
[单片机]
STM32调用C库自带函数
在MDK5的安装路径中:D:MDK5ARMARMCCinclude,可以看到很多C库头文件,在程序中只要包含了相应的头文件,编译器就会自动把相应的代码编译链接进去。 下面介绍在STM32可能会用到的函数: include math.h include stdio.h 主要就是printf函数在串口上的应用: 以正点原子的程序模版为例: 在usart.c中定义了把printf和串口一输出相关联的函数: 如果你注释掉这段话,但程序上使用了 printf,虽然软件编译不会报错,但是硬件上 STM32 是无法启动的,这段代码最好不要去修改。 若要映射到其他串口,只要把上诉的USART1改为USARTX或UARTX(X表示
[单片机]
STM32 FreeRTOS 串口队列接收
要使用队列,必须首先建立队列,建立队列后,在任务中检测队列中是否有数据,若有数据,则进行处理。 xQueueHandle xQueueRx; static void vOnCommunicationTask(void *pvParameters) { portCHAR cChar; xQueueRx = xQueueCreate(20, sizeof(u8));/*创建一个深度为20的队列*/ while(1) { if(xQueueReceive(xQueueRx, &cChar, 10/portTICK_RATE_MS)==pdTRUE) /*队列中有数据*/ { printf(
[单片机]
实现STM32的串口数据发送和printf函数重定向
在调试电机驱动程序的时候,是不能随便利用中断来进行一些寄存器或数据的查看的,不然你在运行的时候突然来一下,如果占空比大的话那可能直接就把MOS管给烧了,所以我们很多情况下只能使用USART(串口)来进行程序的调试和数据的监控了。 对于STM32来说,由于很多内容都是有库来实现的,那就省了很多时间,直接看个例子就可以写了,大致有4步步骤: 1 1、RCC始终初始化,对端口和USARTX使能时钟 2 2、初始化端口功能,RX设置为输入悬空,TX设置为复用功能的推挽输出,注意GPIO_SPEED要设置下,我没设置弄了半天都没输出 3 3、设置USARTX寄存器,波特率、数据位、校验位、停止位等 4 4、看需要是否开中断,我这里
[单片机]
基于TFTP协议实现STM32的IAP
0引言 随着嵌入式技术以及32位嵌入式微处理器的发展,嵌入式系统的应用日益广泛,嵌入式产品与人们的生产、生活结合得越来越紧密。然而,嵌入式系统的设计不可能一步到位,尤其是嵌入式软件,需要不断修改和完善。当程序出错或用户需求变更时,传统的方法是安排技术人员到现场或将设备回收对控制器芯片重新编程。这种方式费时费力,效率低下[1]。采用IAP(In-Application Programming)技术则可以免除拆卸设备、烧录MCU(Microcontroller Unit)等繁琐的过程。IAP即“在应用中编程”,是指产品发布后在运行过程中通过预留的通信接口(如USART、I2C、CAN、USB、以太网接口等)对微控制器MCU中的软件进行
[单片机]
基于TFTP协议实现<font color='red'>STM32</font>的IAP
一步步写STM32 OS【二】环境搭建
一、安装IAR for ARM6.5 二、新建工程 1、选择处理器:STM32F407VG,暂不使用FPU 2、必要的路径配置和宏定义 3、使用SWO重定向IO输出 4、使用ST-LINK仿真器 5、下载配置 6、设置CPU频率,防止SWO输出乱码 三、代码调试 四、工程下载 stepbystep_stm32_os_template.rar
[单片机]
一步步写<font color='red'>STM32</font> OS【二】环境搭建
STM32入门之旅(第四天)-------位带操作、中断
一、位带操作 1.意义 回想以前写51代码 P0 = 0x10; //将P0端口设置为0x10 P1_0=1; //将P1端口1号引脚设置为高电平 a = P2_2; //获取P2端口2号引脚的电平 根据上述的方法,我们可以发现快速定位修改某个引脚的电平还有获取引脚的状态 GPIO_SetBits、GPIO_ResetBits操作IO口的性能没有达到极致,因为这些函数都需要进行现场保护和现场恢复的动作,比较耗时间,没有进行一步到位,使用位带操作则没有上述的烦恼,简单快速! //位带操作,实现51类似的GPIO控制功能 //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr
[单片机]
STM32跑马灯实验——库函数版本
1.编写led.h文件 #ifndef __LED_H #define __LED_H //如果标识符__LED_H没有被定义,则定义标识符__LED_H, void LED_Init(void); #endif 3,编写led.c文件 #include led.h #include stm32f4xx.h void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); GPIO_InitStructure.GP
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved