[Blue Bridge Cup single chip microcomputer learning record 11] PWM pulse width modulation signal (explained by little bee teacher)

The PWM pulse width signal is used to realize the independent key S7 control to control the brightness change of L1 indicator.

  1. The frequency of PWM pulse width signal is 100HZ
  2. L1 is off after the system is powered on
  3. There are four brightness modes when L1 is powered on, namely, complete off, 10% brightness, 50% brightness and 90% brightness
  4. Press the S7 key to cycle the four brightness modes of L1 indicator
#include "reg52.h"

sbit L1 = P0^0;
sbit S7 = P3^0;

void SelectHC573()/*74HC573 Latch*/
{
	P2 = (P2 & 0x1f) | 0x80;
}

//============Timing dependent function================
unsigned char count = 0;
unsigned char pwm_duty = 0;
void InitTimer0()
{
	TMOD = 0x01;
	TH0 = (65535 - 100) / 256;
	TL0 = (65535 - 100) % 256;
	
	ET0 = 1;
	EA = 1;
}


void ServiceTimer0() interrupt 1 /*Middle end service function of timer 0*/
{
	TH0 = (65535 - 100) / 256;
	TL0 = (65535 - 100) % 256; /*100 The interrupt is executed once in microseconds. The clock of the single chip microcomputer is 100us,100ms=100us, so it needs to be interrupted 100 times
	
	count++;
	if(count == pwm_duty)//Not lit under the specified pulse share
	{
		L1 = 1;
	}
	else if(count == 100)/*PWM The frequency is 100HZ, that is, one cycle is 10ms;100*100 microseconds = 10 milliseconds*/
	{
		L1 = 0;          //No light after 100 copies
		count = 0;
	}
}
//==========================================

//============Key related functions================
void Delay(unsigned int t)
{
	while(t--);
}

unsigned char stat = 0;
void ScanKeys()
{
	if(S7 == 0)
	{
		Delay(100);
		if(S7 == 0)
		{
			switch(stat)
			{
				case 0:
					L1 = 0;
				  TR0 = 1;
					pwm_duty = 10;
				  stat = 1;
				break;
				
				case 1:
					pwm_duty = 50;
					stat = 2;
				break;
				
				case 2:
					pwm_duty = 90;
				  stat = 3;
				break;
				
				case 3:
					L1 = 1;
				  TR0 = 0;
				  stat = 0;
				break;
			}
			while(S7 == 0);
		}
	}
}
//============================================

//==================Main function====================
void main()
{
	SelectHC573();
	L1 = 1;
	InitTimer0();
	while(1)
	{
		ScanKeys();
	}
}

It is better to generate PWM with timer 0 to avoid being interrupted by other timers

The following is from teacher bee's blog: https://blog.csdn.net/ohy3686/article/details/88372244  

On the comprehensive training platform of CT107D single chip microcomputer, PWM pulse width modulation signal is generated to control 8 LED lights to change breathing and flowing water. The specific functional requirements are as follows:

[1] when powered on and running, turn off the buzzer and relay, L4 and L5 will be on, and other LED lights will be off.

[2] after pressing the independent key S4 and releasing it, start to control the eight LED lights L1-L8 on the CT107D board to light up the breathing water every 1 second, that is: L1 slowly on - > L1 slowly off - > L2 slowly on - > L2 slowly off L8 slowly on - > L8 slowly off - > L1 slowly on - > L1 slowly off move in circles.

[3] after pressing the independent key S4 again and releasing it, control the LED light on the CT107D board to breathe water in reverse from the current light. That is: for example, the current flow is L2 slowly off - > L3 slowly on. After pressing the S4 key to release, L3 slowly off - > L2 slowly on - > L2 slowly off - > L1 slowly on - > L1 slowly off - > L8 slowly on - > L8 slowly off move in circles.

[4] each LED light will be on slowly for 0.5 seconds and off slowly for 0.5 seconds.

[5] when the independent key S4 is pressed, the current LED light pauses the water flow change and maintains the existing brightness. The brightness does not start to change until the key is released. After the current brightness change is completed, the direction of breathing and flowing water can be adjusted.

[6] when the independent key S7 is pressed, the current LED position and PWM signal duty cycle are displayed on the nixie tube. After releasing, the nixie tube goes out. The 1-digit nixie tube on the far left displays the position of LED light, and the 2-digit nixie tube on the far right displays the duty cycle of PWM signal. For example, when L6 light is currently on, the duty cycle of PWM signal is 30%. The left digit of nixie tube displays "6", the right digit of nixie tube displays "30", and the rest of nixie tubes go out.

[7] when the independent key S7 is pressed, the current LED light pauses the water flow change and maintains the existing brightness. The brightness does not start to change until the key is released.
 

#include "regx52.h"
#include "absacc.h"
 
sbit S7 = P3^0;
sbit S4 = P3^3;
 
unsigned char pwm = 0;    //Number of cycles      
unsigned char pwm_duty = 0;  //Duty cycle            
unsigned char times = 0;     //0.5s change   
unsigned char led_go = 0;    //LED pwm    
unsigned char stat_go = 0;     //LED flow status 
unsigned char stat = 0;         
unsigned char key_puse = 0;     //Key value record
 
unsigned char code SMG_duanma[18]=
		{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
		 0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
 
void DelaySMG(unsigned int t)
{
	while(t--);
}
 
void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{
	XBYTE[0xE000] = 0xff;
	XBYTE[0xC000] = 0x01 << pos;
	XBYTE[0xE000] = value;
}
 //Nixie tube data display
void Display_Info(unsigned char pos, unsigned char duty)
{
	DisplaySMG_Bit(0, SMG_duanma[pos]);
	DelaySMG(500);
 
	DelaySMG(500);
	DisplaySMG_Bit(6, SMG_duanma[duty / 10]);
	DelaySMG(500);
	DisplaySMG_Bit(7, SMG_duanma[duty % 10]);	
	DelaySMG(500);
	
	DisplaySMG_Bit(0, 0xff);
	DisplaySMG_Bit(6, 0xff);
	DisplaySMG_Bit(7, 0xff);
}
 
void Init_Timer0()
{
	TMOD = 0x01;
	TH0 = (65535 - 1000) / 256;			
	TL0 = (65535 - 1000) % 256;
	
	ET0 = 1;
	EA = 1;
	TR0 = 1;
}
 
void Service_Timer0() interrupt 1
{
	TH0 = (65535 - 1000) / 256;
	TL0 = (65535 - 1000) % 256;
	
	if(stat_go == 0)      		//Initially, only L4L5 is on				
      {
        XBYTE[0x8000] = 0xe7;						
        return;
      } 
	
        pwm++;                
  
      if(pwm <= pwm_duty)   
      {
	XBYTE[0x8000] = ~(0x01 << stat);
      }
      else if(pwm <= 10)
      {
        XBYTE[0x8000] = 0xff;
      }
      else
      {
        XBYTE[0x8000] = ~(0x01 << stat);
    
        pwm = 0;
        if(key_puse == 0)     
        {
          times++;
        }
      }
}
 
void LED_Control()
{
  if(times == 5)          
  {
    times = 0;
    if(led_go == 0)       
    {
//Increase the duty cycle
      pwm_duty = pwm_duty + 1;
      if(pwm_duty == 11)//Up to one cycle 10
      {
				pwm_duty = 10;
        led_go = 1;//State flip
      }
    }
    else if(led_go == 1)  
    {
//Reduce the duty cycle
      pwm_duty = pwm_duty - 1;
      if(pwm_duty == 255)//Reduced to the minimum
      {
		pwm_duty = 0;
        led_go = 0;//State flip
        
        if(stat_go == 1)  //From left to right    
        {
          stat++;
          if(stat == 8)
          {
            stat = 0;
          }
        }
        else if(stat_go == 2) //Right to left
        {
          stat--;
          if(stat == 255)
          {
            stat = 7;
          }
        }
      }
    }
  }
}
 
void Scan_Keys()
{
	if(S4 == 0)
	{
		DelaySMG(100);
		if(S4 == 0)
		{
			while(S4 == 0)
			{
				key_puse = 1;
			}
			key_puse = 0;
			
      stat_go++;            
      if(stat_go == 3)
      {
        stat_go = 1;
      }
		}
	}
	
	if(S7 == 0)
	{
		DelaySMG(100);
		if(S7 == 0)
		{
			while(S7 == 0)
			{
				key_puse = 1;
				Display_Info(stat + 1, pwm_duty * 10);
			}
			key_puse = 0;
		}
	}
}
 
void Init_System()
{
	XBYTE[0xA000] = 0xff;
	XBYTE[0xA000] = 0x00;
	XBYTE[0xE000] = 0xff;
	XBYTE[0xC000] = 0xff;
	
	Init_Timer0();
}
 
main()
{
	Init_System();
	while(1)
	{
		LED_Control();
		Scan_Keys();
	}
}

Keywords: Single-Chip Microcomputer

Added by cap2cap10 on Sat, 05 Feb 2022 03:20:34 +0200