使用PWM实现呼吸灯功能

CC表示的意思位捕获比较,CCR表示的是捕获比较寄存器

占空比等效于PWM模拟出来的电压的多少,占空比越大等效出的模拟电压越趋近于高电平,占空比越小等效出来的模拟电压越趋近于低电平,分辨率表示的是占空比变化的精细程度,按照实际项目的需求使用PWM波形可以在数字系统等效输出模拟量,可以实现LED控制亮度和控制电机的速度等操作

输出模式控制器是如何工作的

可以理解为:配置有效的电平就是设置高电平,配置无效的电平就是设置的低电平

舵机简介

电机驱动模块的硬件电路

接线图:PWM驱动呼吸灯

// 配置输出比较模块

//第一个参数的意思是选择定时器,第二个参数的意思是配置结构体

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct); // 给输出比较结构体赋值一个默认值

// 配置强制输出模式

void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

//配置CCR寄存器的预装功能

void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

// 配置快速使能

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

这个不是重点内容

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

// 单独设置输出比较的极性

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

// 单独修改使能输出参数

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

// 选择输出比较模式

void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

**// 单独更改CCR寄存器值的函数,比较重要**

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

PWM的C语言文件

使用PWM实现呼吸灯的效果

#include "stm32f10x.h"                  // Device header

void PWM_Init(void){
  // 开启时钟,这里TIM2是通用寄存器
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	// GPIO初始化代码
		/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
	// GPIO引脚重映射,表示重映射和引脚之间的关系
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	
	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	// 使用复用开漏推挽输出模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);						//将PA1和PA2引脚初始化为推挽输出
	
	
	
	// 选择时基单元的时钟,选择内部时钟的模式,定时器默认使用的是内部单元的时钟
	TIM_InternalClockConfig(TIM2);
	
	// 配置时基单元,初始化结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	// 将结构体成员都引用出来放置在这个位置
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;    // 配置参数是否分屏
	TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up; // 选择计数的模式选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 100 -1;               // 表示ARR自动重装器的值,这两个参数的取值都要在0-65535之间
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1;              // PSC预分频器的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;           // 重复计数器的值
	// 初始化结构体并将结构体的地址放置在init函数中
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
  // 初始化输出比较单元
	TIM_OCInitTypeDef TIM_OCInitStructure;
	// 给结构体赋初始值
	TIM_OCStructInit(&TIM_OCInitStructure);
  // 设置输出比较的模式
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  // 设置输出比较的极性,选择高极性
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	// 设置输出使能,输出状态
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable ;
	//设置CCR,设置ccr寄存器的值
	TIM_OCInitStructure.TIM_Pulse = 0;    // CCR
	
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);

	
	// 启动定时器
	TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare1(uint16_t Compare){
        TIM_SetCompare1(TIM2,Compare);
}

PWM头文件

#ifndef __PWM_H_
#define __PWM_H_
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
#endif

main主函数文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main(void)
{
  // 初始化oled
	OLED_Init();
	PWM_Init();
	while (1)
	{
		 for(i = 0; i<= 100; i++){
			     // 这个函数是设置CCR寄存器的值,不直接是占空比
					 PWM_SetCompare1(i);
			     Delay_ms(10);
		 }
	   for(i = 0; i<= 100; i++){
					 PWM_SetCompare1(100 - i);
			     Delay_ms(10);
		 }
	}
}

PWM驱动舵机旋转

PWM驱动直流电机旋转

  • 34
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 Keil 中实现呼吸灯功能,可以使用 PWM (脉冲宽度调制) 来控制 LED 的亮度。下面是一个示例代码,使用 PWM 实现呼吸灯: ```c #include <stdio.h> #include <stm32f10x.h> #define PWM_FREQUENCY 10000 // PWM 频率,单位为 Hz void setupPWM() { // 使能 GPIOB 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置 PB1 为 AFPP (复用推挽输出) 模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); // 使能 TIM3 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 配置 TIM3 为 PWM 模式,频率为 PWM_FREQUENCY TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Period = 1000 / PWM_FREQUENCY - 1; // 计数器自动重载值 TIM_InitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1; // 分频系数,时钟频率为 1 MHz TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_InitStruct); // 配置 TIM3_CH2 为 PWM 输出模式 TIM_OCInitTypeDef TIM_OC_InitStruct; TIM_OC_InitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC_InitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OC_InitStruct.TIM_Pulse = 0; // 初始占空比为 0% TIM_OC_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM3, &TIM_OC_InitStruct); // 启动 TIM3 TIM_Cmd(TIM3, ENABLE); } int main(void) { setupPWM(); while (1) { for (int i = 0; i < 1000; i++) { TIM_SetCompare2(TIM3, i); // 占空比从 0% 到 100% for (int j = 0; j < 100000; j++); // 延时 } for (int i = 1000; i > 0; i--) { TIM_SetCompare2(TIM3, i); // 占空比从 100% 到 0% for (int j = 0; j < 100000; j++); // 延时 } } } ``` 这段代码使用了 STM32F10x 的 TIM3_CH2 PWM 输出功能,通过改变 PWM 的占空比来控制 LED 的亮度。由于这里没有使用定时器,而是使用了简单的 for 循环来实现呼吸灯效果,所以程序的精度可能会受到影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值