Principle and Practice of PWM Output of MCU

1. What is PWM?

  PWM (Pulse Width Modulation) pulse width modulation , which modulates the width of a series of pulses, equivalent to the required waveform (including shape and amplitude), and digitally encodes the analog signal level.   In layman's terms , it is to control how long the high level and how long the low level (high level: 5/3.3V, low level: 0V) in a cycle. Adjust the change of signal, energy, etc. by adjusting the change of high and low level time. The picture shows the PWM waveform with a period of 4 milliseconds and a duty cycle of 0.25
View source image
  
The picture shows the PWM waveform with a period of 4 milliseconds
  

  • Two important concepts, frequency and duty cycle

  Frequency: refers to the number of times the signal goes from high level to low level and back to high level per second , which is the reciprocal of a PWM wave cycle . Figure above frequency = 1 / (0.003 + 0.001) = 250 HZ
  duty cycle: refers to sustained high level for longer than a period of time . In the above figure, the duty ratio=1/(1+3)=25%, so the equivalent voltage of the output can be controlled by controlling the duty ratio.
  So for a square wave, the frequency and duty cycle determine a wave.

2. How can a PWM wave be generated?

  Method 1 : Use the internal modules of the chip to output PWM signals, except for TIM6 and 7 for STM32 timers. Other timers can be used to generate PWM output. The advanced timers TIM1 and TIM8 can generate up to 7 PWM outputs at the same time. The general-purpose timer can also generate up to 4 PWM outputs at the same time, so that STM32 can generate up to 30 PWM outputs at the same time! but! ! ! The same timer TIM can only generate PWM waves of one frequency, and you can only change the duty cycle. See the STM32 data manual for specific routines !
  Method 2 : Use the IO port to change the high and low levels to output the PWM signal. For example, in the above figure, first set the level to 1, maintain 1ms, then pull the level low, maintain 3ms, and then set the level high, and so on. A PWM wave with a period of 4 milliseconds and a duty ratio of 25% can be generated. The specific method is to add a timer to the IO port and use the timer interrupt to switch between high and low levels in time. Look at the 51 MCU code part behind.

  • Timer

  If you want to use 51 single-chip microcomputer to generate a PWM, according to the above method 2, you should first know what a timer is? How does the timer work?

  Timer : It is the same thing as the counter, because it can both time and count. The essence of the timer is to accumulate from the machine frequency to a 16-bit register, and trigger an interrupt when the accumulation overflows. In order to generate a time interval we want. For example, 1s, so we need to set an initial value in this register so that it can be accumulated on this initial value to produce a multiple of 1s. This way we get a stable time interval.
  This register is divided into TH (high eight bits) and TL (low eight bits). So we need to divide the calculated initial value into two parts into TH and TL.

  Process
  First, we know the clock cycle of the single-chip microcomputer's crystal oscillator, clock cycle*12=machine cycle. Each machine cycle +1 in the register, until it fills up and overflows to generate an interrupt.

  For example,
  if the external clock frequency of the single-chip microcomputer is 12MHz, the clock cycle is 1/12μs, and the machine cycle is 1μs , that is, register +1 per 1μs. It takes up to (2^16)-1=65535μs for a 16-bit register to overflow. Overflow also requires one machine cycle, so a total of 65536μs. But this value is too awkward and has nothing to do with the 1s we want. We'd better let it remember 50,000μs to generate an interrupt, so its initial value is set to 65536-50000=15536. But we also need to put this value in the upper eight digits and the lower eight digits, so we need to convert this decimal number into a 4-digit hexadecimal number and assign the values ​​separately. Decimal calculation method: TH = 15536/256; TL = 15536%256; The calculation of decimal system is not discussed in detail here. In this case, an interrupt will be generated every 50ms. We only need to use the program to judge the interruption 20 times and record 1s.
   

Three, the application of PWM

1. Output analog voltage ( control the brightness of LED, the speed of DC motor, the tone of buzzer, etc. ) by the level of voltage.
  PWM digitally encodes the level of analog signal, the computer can only output 0 or 5V digital The voltage value cannot output an analog voltage, and if we want to obtain an analog voltage value (a voltage value between 0-5V), we need to use a high-resolution counter to change the duty cycle of the square wave to compare an analog signal Level is encoded. The voltage is clamped to the analog load in a repetitive pulse sequence of connection (1) or disconnection (0). Connection means DC power supply output, and disconnection means DC power supply disconnection. By controlling the connection and disconnection time, as long as the bandwidth is sufficient, any analog voltage not greater than the maximum voltage value can be output.

  Output voltage = (on time/pulse time) * maximum voltage value

PWM output equivalent voltage
   PWM output equivalent voltage
2. In
  the process of controlling a stepper motor to do a project, a stepper motor is often used when precise control of displacement is involved.
  For a four-wire bipolar stepping motor, the electric pulse signal is converted into an angular displacement motor to control the rotation of the rotor. Used as an actuator in automatic control devices. Each time a pulse signal is input, the stepping motor takes one step forward, so it is also called a pulse motor. ! ! ! Note here that if you directly control the single-chip microcomputer, it is pulse control, that is, a pulse signal comes in and the stepper motor rotates by a step angle (usually 0.9°). So the way to control the speed of a stepper motor is to control the  frequency  (duty cycle is generally 50%) but! ! ! Now the step angle can be subdivided by connecting the stepper motor drive board. For example, if it is subdivided into 2, a pulse stepper motor will rotate half a pulse (0.45°)


Four, 51 microcontroller routines

  Here, 51 is used to realize the function of the breathing light . The same principle can also control the DC motor; the stepper motor controls the speed by controlling the frequency, and the buzzer controls the tone by controlling the frequency.

Wiring: Connect P1.0 to any LDE light!

Write picture description here
There are two implementation methods: no timer (delay), timer
delay, and timer use. The difference is that the delay is the addition and subtraction of variables in the delay function. During the delay, the microcontroller can only execute delay. In the case of a function
                                              timer, the TH and TL registers are continuously accumulated until the interrupt handler is executed once when it overflows, during which the microcontroller can also execute other programs!


1. No timer (just use delay)

/***
*源代码来来自于 https://www.bilibili.com/read/cv4779664
*pwm LED呼吸灯
*现象:亮-灭-亮 循环
*LED接口:P1.0
*思路:改变延时时间实现亮度不一从而实现呼吸的效果
******/
#include <reg52.h> //引用头文件

sbit led=P1^0;     //LED接口

bit ledsign=0;     //定义一个标志位ledsign==0 

void delay(int);   //声明延时函数
   
void main()
{
  int i=0;         //i:延时控制变量
  while(1)         
  {
   if(ledsign==0)   //如果b=0(初始0)(灯由亮到灭)
		 {   
				led=1;         //灭
				delay(i);      //i秒后(i从小到大)
				led=0;         //亮
				delay(1000-i); //延时1000(可自行定义)-i秒后
				i+=2;          //增加i(开灯的时间)
        if(i>=1000) 
        {	
            ledsign=1;     //i到最大值(>1000)改变标志位下一阶段(灯由灭到亮)
        }
   }
   else if(ledsign==1)         //判断是否进入到下一阶段(灯由灭到亮)
   {       
      led=1;    //灭
      delay(i);   //i秒后(i在上一阶段已到最大值(>1000))
      led=0;    //亮
      delay(1000-i);//延时1000(随手定义)-i秒后
      i-=2;     //减少i(开灯的时间)
      if(i<=0) 
      {
        ledsign=0;//判断是否回到上一阶段
      }
   }
   
  }
}

void delay(int a)      //定义延时函数
{
  int i;
  for(i=0;i<a;i++);
}

 2. Use timer

#include<reg52.h>
/*************************

**************************/

sbit LED = P1^0;

unsigned char PWM_COUNT;  	 //计数
unsigned int  HUXI_COUNT;    //占空比更新时间
unsigned char PWM_VLAUE;     //占空比比对值
bit direc_flag;             //占空比更新方向

void timer0_init(void);
	
void main()
{
    HUXI_COUNT = 0;
    PWM_COUNT = 0;
    PWM_VLAUE = 5;
    direc_flag = 0;
    LED = 1;            //默认LED熄灭   
    timer0_init();      //定时器0初始化
    while(1);
}

void timer0_init()
{
    TMOD=0x02;          		//  工作于模式2(M1=1,M0=0)
    TH0=0x38;               //定时器溢出值设置,每隔200us发起一次中断。12M晶振
    TL0=0X38;
    ET0=1;                  //开定时器0中断
    EA=1;                       //开总中断
    PWM_COUNT =0;
	  TR0=1;                  //定时器0开始计时
}

void time0() interrupt 1
{   
    PWM_COUNT++;
    HUXI_COUNT++;
    if(PWM_COUNT == PWM_VLAUE)      //判断是否到了点亮LED的时候
        LED = 0;                    //点亮LED
    if(PWM_COUNT == 10)             //当前周期结束
    {
        LED = 1;                    //熄灭LED
        PWM_COUNT = 0;              //重新计时
    }

    if((HUXI_COUNT == 600) && (direc_flag == 0))
    {                               //占空比增加10%
        HUXI_COUNT = 0;
        PWM_VLAUE++;
        if(PWM_VLAUE == 9)          //占空比更改方向
            direc_flag = 1; 
    }

    if((HUXI_COUNT == 600) && (direc_flag == 1))
    {                               //占空比减少10%
        HUXI_COUNT = 0;
        PWM_VLAUE--;
        if(PWM_VLAUE == 1)          //占空比更改方向
            direc_flag = 0; 
    }   
}

 

Guess you like

Origin blog.csdn.net/qq_27148893/article/details/110194229