51单片机嵌入式开发:23,STC89C52R基于定时器实现PWM功能,并封装成周期占空比可调


STC89C52R基于定时器实现PWM功能,并封装成周期占空比可调

在这里插入图片描述
配套例程

目录

  1. 简介
  2. 基本原理
  3. PWM 信号的生成
  4. PWM 的应用
  5. PWM 的优缺点
  6. PWM 的实现
    • 硬件实现
    • 软件实现
  7. PWM 在不同平台上的应用
    • AVR/Arduino
    • STM32
    • ESP8266/ESP32
  8. 高级 PWM 技术
    • 频率调制
    • 占空比调制
  9. 示例代码
    • Arduino 实现 PWM
    • STM32 实现 PWM
  10. 常见问题及解决方案
  11. 结论

配套例程

1. 简介

PWM(Pulse Width Modulation,脉宽调制)是一种通过调节脉冲信号的宽度来控制电能传输的技术。PWM 在控制系统、电机驱动、通信等领域广泛应用。它通过调节占空比来实现对模拟量的数字控制。

2. 基本原理

PWM 信号是一种方波信号,其频率和占空比是两个主要参数:

  • 频率(Frequency):指单位时间内信号的重复次数,通常以赫兹(Hz)为单位。
  • 占空比(Duty Cycle):指信号在一个周期内为高电平的时间比例,通常以百分比表示。

例如,一个周期为 10ms 的 PWM 信号,如果高电平持续 2ms,则占空比为 20%。

3. PWM 信号的生成

PWM 信号的生成可以通过硬件和软件两种方式实现。

硬件生成

硬件 PWM 通常由定时器/计数器模块生成。定时器根据预设的频率和占空比自动生成 PWM 信号,具有精度高、响应快的优点。大多数微控制器(如 AVR、STM32 等)都内置了硬件 PWM 模块。

软件生成

软件 PWM 通过程序控制 I/O 引脚的高低电平来模拟 PWM 信号。虽然软件 PWM 实现简单,但由于受限于 CPU 处理速度,其精度和稳定性通常不如硬件 PWM。

4. PWM 的应用

PWM 技术广泛应用于以下领域:

电机控制

PWM 常用于直流电机的速度控制。通过调节 PWM 信号的占空比,可以改变电机的平均电压,从而控制电机的转速。

LED 调光

PWM 用于 LED 调光时,通过调节占空比,控制 LED 的亮度。高占空比的 PWM 信号使 LED 较亮,而低占空比的 PWM 信号使 LED 较暗。

电源管理

在开关电源中,PWM 用于控制功率开关的导通时间,从而调节输出电压和电流,实现稳压和稳流。

音频信号生成

PWM 可以用于生成音频信号,通过改变 PWM 信号的频率和占空比,可以生成不同频率和音色的声音。

5. PWM 的优缺点

优点

  • 高效性:PWM 控制电能传输效率高,能量损耗低。
  • 精度高:通过调节占空比,可以实现高精度的模拟量控制。
  • 响应快:PWM 信号变化快,适用于动态控制系统。

缺点

  • 噪声:高频 PWM 信号可能产生电磁干扰和噪声,需要进行滤波处理。
  • 复杂性:硬件 PWM 需要专用的定时器/计数器模块,软件 PWM 实现复杂度较高。

6. PWM 的实现

硬件实现

硬件 PWM 通常依赖于定时器/计数器模块。以下是硬件 PWM 实现的基本步骤:

  1. 配置定时器:设置定时器的模式、频率和初始值。
  2. 设置占空比:通过定时器的比较寄存器设置占空比。
  3. 启动定时器:使能定时器,开始生成 PWM 信号。

软件实现

软件 PWM 通过程序控制 I/O 引脚的高低电平来模拟 PWM 信号。以下是软件 PWM 实现的基本步骤:

  1. 初始化 I/O 引脚:将 I/O 引脚设置为输出模式。
  2. 生成 PWM 信号:在主循环中,根据设定的占空比和周期,控制 I/O 引脚的高低电平。

7. PWM 在不同平台上的应用

AVR/Arduino

Arduino 平台提供了方便的 PWM 控制函数 analogWrite(),可以轻松实现 PWM 信号输出。

int pwmPin = 9; // 使用数字引脚 9 作为 PWM 输出

void setup() {
  pinMode(pwmPin, OUTPUT); // 设置引脚模式为输出
}

void loop() {
  analogWrite(pwmPin, 128); // 设置占空比为 50%
  delay(1000); // 延时 1 秒
  analogWrite(pwmPin, 255); // 设置占空比为 100%
  delay(1000); // 延时 1 秒
}

STM32

STM32 微控制器通过定时器模块生成 PWM 信号。以下是使用 STM32CubeMX 和 HAL 库实现 PWM 的示例代码。

初始化定时器
  1. 打开 STM32CubeMX,配置定时器为 PWM 模式。
  2. 生成代码并初始化定时器。
/* 配置 PWM 定时器 */
void MX_TIM2_Init(void) {
  TIM_HandleTypeDef htim2;
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
    Error_Handler();
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 499; // 设置占空比为 50%
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
    Error_Handler();
  }

  HAL_TIM_MspPostInit(&htim2);
}
启动 PWM 信号
/* 启动 PWM 信号 */
void startPWM() {
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

ESP8266/ESP32

ESP8266 和 ESP32 平台提供了丰富的 PWM 控制功能,通过 analogWrite()ledcWrite() 函数实现 PWM 输出。

int pwmPin = 5; // 使用 GPIO 5 作为 PWM 输出

void setup() {
  pinMode(pwmPin, OUTPUT); // 设置引脚模式为输出
}

void loop() {
  analogWrite(pwmPin, 128); // 设置占空比为 50%
  delay(1000); // 延时 1 秒
  analogWrite(pwmPin, 255); // 设置占空比为 100%
  delay(1000); // 延时 1 秒
}

8. 高级 PWM 技术

频率调制

通过动态调整 PWM 信号的频率,可以实现频率调制(Frequency Modulation,FM)。频率调制常用于通信系统中,用于传输不同频率的信号。

占空比调制

通过动态调整 PWM 信号的占空比,可以实现占空比调制(Duty Cycle Modulation)。占空比调制常用于音频信号生成和调光应用中。

9. 示例代码

Arduino 实现 PWM

int pwmPin = 9; // 使用数字引脚 9 作为 PWM 输出

void setup() {
  pinMode(pwmPin, OUTPUT); // 设置引脚模式为输出
}

void loop() {
  for (int i = 0; i <= 255; i++) {
    analogWrite(pwmPin, i); // 动态调整占空比
    delay(10); // 延时 10 毫秒
  }
  for (int i = 255; i >= 0; i--) {
    analogWrite(pwmPin, i); // 动态调整占空比
    delay(10); // 延时 10 毫秒
  }
}

STM32 实现 PWM

/* 配置 PWM 定时器 */
void MX_TIM2_Init(void) {
  TIM_HandleTypeDef htim2;
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) {
    Error_Handler();
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 499; // 设置占空比为 50%
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) {
    Error_Handler();
  }

  HAL_TIM_MspPostInit(&htim2);
}

/* 启动 PWM 信号 */
void startPWM() {
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

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

  startPWM();

  while (1) {
    // 主循环
  }
}

STC89C52实现PWM

//main.c文件

#include "includes.h"



/******************************************************************/
/*                    微秒延时函数  //10us                         */
/******************************************************************/
void delay_us(unsigned int us)//delay us
{
	while(us--)
	{
	}
}

/******************************************************************/
/*                    微秒延时函数                                */
/******************************************************************/
void delay_ms(unsigned int Ms)//delay us
{
	while(Ms--)
	{
		delay_us(100);
	}
}



/*-----------------------------------------------
  名称:PWM 调光
  内容:1、学习目的:利用定时器产生PWM,了解原理和使用方法
        2、硬件要求:LED灯 定时器
        3、试验现象:LED灯由亮到灭,由灭到亮逐步变化,也就是调光现象
------------------------------------------------*/

sbit LED1= P3^7;
sbit LED = P1^2;      //定义LED灯,通过LED显示调光效果
unsigned char CYCLE;  //定义周期 该数字X基准定时时间 如果是10 则周期是10 x 0.1ms
unsigned char PWM_ON ;//定义高电平时间
/******************************************************************/
/*                    延时函数                                    */
/******************************************************************/
void delay(unsigned int cnt)
{
 while(--cnt);
}
/******************************************************************/
/*                    主函数                                      */
/******************************************************************/
void main()

{
bit Flag;

TMOD |=0x01;              //定时器设置 0.1ms in 12M crystal
TH0=(65536-100)/256; 
TL0=(65536-100)%256;      //定时0.1mS 
IE= 0x82;                 //打开中断
TR0=1;
CYCLE = 10;               // 时间可以调整 这个是10调整 8位PWM就是256步
while(!Flag)
  {
   delay(20000);          //延时时间,从一个亮度到下一个亮度的间隔时间,速度快就能看到连续效果
   PWM_ON++;              //这个使用较长延时,以便能看清楚变化过程
   if(PWM_ON == CYCLE)
     {                    //这个里可以添加其他程序 如到最亮时候控制设备
      Flag=1;
	  }
  }

 while(Flag)              //亮度递减 同上,是个相反的过程
  {
   delay(20000);
   PWM_ON--;
   if(PWM_ON == 0)
     {
      Flag=0;
	  }
  }
}
/******************************************************************/
/*                    定时器中断函数                              */
/******************************************************************/
void tim(void) interrupt 1 using 1
{
static unsigned char count; 
TH0=(65536-100)/256; 
TL0=(65536-100)%256;     //定时0.1mS 

if (count==PWM_ON)
    {
     LED = 1;            //灯灭 
    }
  count++;
if(count == CYCLE)
    {
    count=0;
	if(PWM_ON!=0)        //如果左右时间是0 保持原来状态
	   LED = 0;          //灯亮

    }

}

配套例程

10. 常见问题及解决方案

问题一:PWM 信号不稳定

解决方案:检查时钟源和定时器配置,确保定时器的频率和占空比设置正确。

问题二:电机驱动噪声大

解决方案:增加滤波电容,减少高频噪声;优化 PWM 频率,避免共振频率。

问题三:LED 调光不均匀

解决方案:调整 PWM 频率,使其高于人眼视觉的闪烁频率;使用线性比例调光算法。

11. 结论

PWM 是一种高效、灵活的控制技术,广泛应用于电机驱动、LED 调光、电源管理等领域。通过硬件和软件方法,可以在不同平台上实现 PWM 控制。理解和掌握 PWM 技术,对于电子工程师和嵌入式开发者来说,是非常重要的技能。希望本文对你理解和应用 PWM 技术有所帮助。

  • 42
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值