IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32基于PWM的呼吸灯的实现 -> 正文阅读

[嵌入式]STM32基于PWM的呼吸灯的实现

一、PWM

1、PWM基本介绍

PWM(Pulse Width Modulation)即脉冲宽度调制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术;它是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。PWM就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。

2、PWM工作原理

STM32的每个通用定时器都有独立的4个通道可以用来作为:输入捕获、输出比较、PWM输出、单脉冲模式输出等。\n\nSTM32的定时器除了TIM6和TIM7(基本定时器)之外,其他的定时器都可以产生PWM输出。其中,高级定时器TIM1、TIM8可以同时产生7路PWM输出。

PWM的工作模式:

  • PWM模式1(向上计数) :计数器从0计数加到自动重装载值(TIMx_ARR),然后重新从0开始计数,并且产生一个计数器溢出事件

  • PWM模式2(向下计数)
    :计数器从自动重装载值(TIMx_ARR)减到0,然后重新从重装载值(TIMx_ARR)开始递减,并且产生一个计数器溢出事件

请添加图片描述
上图为向上计数模式

  • 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。
  • 当CNT小于CCRx时,TIMx_CHx通道输出低电平;
  • 当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。

?PWM的一个周期

  • 定时器从0开始向上计数
  • 当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
  • t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
  • 当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数…循环此过程
    至此一个PWM周期完成

二、基于PWM的呼吸灯

1、创建CubeMX工程

新建工程,进行基本的配置。
在这里插入图片描述
选取需要的芯片,这里我选择STM32F103C8T6,然后点击Start。
在这里插入图片描述
打开外部时钟,选择RRC,在菜单栏中选择Crystal/Ceramic Resonator。
在这里插入图片描述
然后选择SYS,进行相应设置。
在这里插入图片描述
配置定时器3和4,如图选中TIM3,选择时钟源为Internal Clock,通道二选择PWMGeneration CH2。设置分频系数为71,计数周期为500。TIM4同样设置。
在这里插入图片描述然后进行时钟配置。

在这里插入图片描述
填写项目名和存储路径,勾选相应选项然后生成工程文件。
在这里插入图片描述
在这里插入图片描述

2、keil中修改

在keil中打开工程,修改main.c文件,定义两个变量存储占空比:
添加在main函数外。

uint16_t duty_num1 = 10;   //存储占空比
uint16_t duty_num2 = 10;

在main函数里面添加如下代码,开启TIM3、TIM4的通道2,输出PWM。

//开启TIM3和TIM4的通道2,输出PWM
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);  
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);

然后在while循环里添加如下代码:

	HAL_Delay(50);
		duty_num1 = duty_num1 + 10;
		duty_num2 = duty_num1 + 20;
		if(duty_num1 > 500)
		{
			duty_num1 = 0;
		}
		if(duty_num2 > 500)
		{
			duty_num2 = 0;
		}
		__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,duty_num1);
		__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_2,duty_num2);
  }

main.c文件里的全部代码如下:


#include "main.h"
#include "tim.h"
#include "gpio.h"


uint16_t duty_num1 = 10;   //存储占空比
uint16_t duty_num2 = 10;

void SystemClock_Config(void);
	
int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);  //开启TIM3和TIM4的通道2,输出PWM
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
		while (1)
  {
		HAL_Delay(50);
		duty_num1 = duty_num1 + 10;
		duty_num2 = duty_num1 + 10;
		if(duty_num1 > 500)
		{
			duty_num1 = 0;
		}
		if(duty_num2 > 500)
		{
			duty_num2 = 0;
		}
		__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,duty_num1);
		__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_2,duty_num2);
  }
  /* USER CODE END 3 */
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

3、效果展示

电路连接
LED灯的短脚分别接PA7、PB7,长脚接3.3。
请添加图片描述

修改完成后,进行保存、编译并烧录,可以看到结果如下:

呼吸灯

三、总结

这次实验完成了呼吸灯的效果,总体过程比较顺利,没有遇到什么难题,是一次有趣的实验过程。在实验过程中应注意一些小细节的配置,例如PWM的有效电平是可以自己设定的等等。

参考文章

http://www.mcublog.cn/stm32/2021_01/stm32cubemx-pwm-huxideng/

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:16:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 12:11:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码