This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

At ordinary times in the use of single-chip microcomputer drive buzzer, most of the use of active buzzer, can only send out a sound, the sound is monotonous and harsh. When using the air conditioner, press the button on the air conditioner, the sound is the kind of tinkling bell, it sounds more pleasant, very nice to listen to. Can you realize this effect with your buzzer? Of course it can. The sound can be made by a passive buzzer and by spinning.

The driving principle diagram is as follows:To achieve the chord tone must be controlled through two IO ports, one of which controls the power supply of the buzzer, the other controls the frequency of oscillation.

The high level output at point A is preferred, and the triodes Q1 and Q2 are switched on to start charging capacitor C1. Then point B starts to output PWM wave, at which time the buzzer starts to sound and output sound of A certain frequency. Before the end of the music, point A outputs low level, at which time Q1 and Q2 are turned off, and the buzzer provides energy for the buzzer to sound by discharging capacitor C1. In this way, the sound of the buzzer will be smaller and smaller with the discharge of the capacitor, so as to achieve the effect of drag, and then set the frequency of the PWM output at different times. So the buzzer can achieve the effect of playing music.

The implementation code is as follows:

#include "buzzer.h"
#include "stm8s103f3p.h"

_Bool Beep_Power  @PD_ODR:3;        // Control power supply
_Bool Beep_Pre  @PD_ODR:4;          / / output PWM

// Frequency oscillation duration Power supply duration
TONE_Def Tone1[] = {{FREQ_2K6, 100.20},{FREQ_NO, 0.0}};/ / mono
TONE_Def Tone2[] = {{FREQ_2K3, 20.20},{FREQ_2K6, 20.20},{FREQ_2K9, 210.10},{FREQ_NO, 0.0}};// Start the chord
TONE_Def Tone3[] = {{FREQ_2K9, 20.20},{FREQ_2K6, 20.20},{FREQ_2K3, 210.10},{FREQ_NO, 0.0}};// Turn off the chord
 
TONE_Def  * pTone;
unsigned char BuzzerStatus =2;

void buzzer_gpio_init(void)
{
    PD_DDR|=(1<<3);					// The PD3 output controls the power supply of the buzzer
    PD_CR1|=(1<<3);					//PD3 push pull output
    PD_DDR|=(1<<4);					// The PD4 output controls the buzzer frequency
    PD_CR1|=(1<<4);					//PD4 push pull output
}

// For the buzzer power supply pin
void BeepPwrOn(void)
{
  Beep_Power=1;
}
void BeepPwrOff(void)
{
  Beep_Power=0;
}
////////////////////////

// For KAI off PWM
void BEEP_On(void)
{
  TIM1_CR1 |=(1<<0);        // Enable the timer
  Beep_Pre=1;               // The frequency control pin is open
}
void BEEP_Off(void)
{
   TIM1_CR1 &=~(1<<0);      // Disable the timer
  Beep_Pre=0;               // Close the frequency control pin
}
 
// Set the ringtone type to 0 1 2
void BuzzerStart(Tone_Type ToneType)
{
  switch (ToneType)
  {
	case MONO:          / / 0 single tone
	  pTone = Tone1;
	  break;
	case POLY_ON:       / / 1 boot
	  pTone = Tone2;
	  break;
	case POLY_OFF:      / / 2 to turn it off
	  pTone = Tone3;
	  break;
	default:
	  pTone = Tone1;    / / mono
	  break;
  }
  BuzzerStatus = 1;
}
 
// Sound control
void BuzzerCtrl(void)
{
  static TONE_Def Tone;     // Tone frequency oscillation time Power supply time
 
  switch (BuzzerStatus)     //
  {
	case 1:             // Call the tone array
	  Tone = *pTone;
	  if(Tone.Freq ! = FREQ_NO)// The frequency is not zero
	  {
		// First judge the power supply duration
		if(Tone.PWRTime ! =0)      // The power supply time is not 0
		{
		  Tone.PWRTime --;
		  BeepPwrOn();
		}
		else
		{
		  BuzzerStatus = 3;
		  break;
		}
		// Then judge the duration of the oscillation
		if(Tone.OSCTime ! =0)      // The oscillation time is not zero
		{
		  Tone.OSCTime--;
		  BEEP_SetFreq(Tone.Freq);  // Set the frequency
		  BEEP_On();
		}
		else
		{
		  BeepPwrOff();
		  BuzzerStatus = 3;
		  break;
		}
		// Start the countdown
		BuzzerStatus = 2;
	  }
	  else /* Tone.Freq == FREQ_NO */ // Is the terminator
	  {
		BuzzerStatus = 3;
	  }
	  break;
	case 2:             // Delay until the time is 0 to switch the next tone
	  if(Tone.PWRTime ! =0)
	  {
		Tone.PWRTime --;
	  }
	  else
	  {
		BeepPwrOff();
	  }
	  if(Tone.OSCTime ! =0)
	  {
		Tone.OSCTime --;
	  }
	  else
	  {
		BEEP_Off();
		pTone ++;   // Take the next tone
		BuzzerStatus = 1;
	  }
	  break;
	default:
	  break; }}// Timer 1 is used to initialize the test
void TIM1_Init(void)
{
	TIM1_CR1 = 0x00;  // Up counting direction, interrupt counting non-stop
	TIM1_IER = 0x01;  // Allow update interrupts
	TIM1_PSCRH = 0x00;  // Perform 16 frequency division =16M/(15+1)=1M CNTR count once for 1/1m =1us
	TIM1_PSCRL = 0x0e;

	TIM1_ARRH = 265/255;	//250us 
	TIM1_ARRL = 265%255;
    
	TIM1_CR1 |=0x01;    // Start timer
}

// Timer 1 interrupt function
// The frequency of one cycle is 2K
@far @interrupt void TIM1_OVER_Int(void)
{
	TIM1_SR1 = 0x00;
	Beep_Pre=~Beep_Pre;
}
// Change the buzzer frequency
void BEEP_SetFreq(FREQ_Type Freq)
{
	unsigned char prescal=0;	
	switch(Freq)
	{
		case FREQ_2K :prescal=265;      //2K 265
                    break;
		case FREQ_2K3:prescal=230;      / / 2.3 K of 230
                    break;
		case FREQ_2K6:prescal=205;      / / 2.6 K of 205
                    break;
		case FREQ_2K9:prescal=182;      / / 2.9 K of 182
                    break;
		default:      prescal=265;
                    break;
	}
	TIM1_CR1|=(1<<7);       // Automatic preloading is allowed
	TIM1_IER = 0x01;        // Allow update interrupts
	TIM1_PSCRH = 0x00;      // Perform 3 frequency division =16M/(15+1)=1M CNTR count once 1/1m =1us
	TIM1_PSCRL = 0x0e;
	TIM1_ARRH = prescal/255;	    //1000ms
	TIM1_ARRL = prescal%255;
    
	TIM1_CR1 |=0x01;        // Enable the timer
	
}

Copy the code

PD3 pin of SCM controls the power switch, and PD4 pin outputs PWM wave. PWM frequency is realized by the timer. In the timer, the PD4 pin is reversed. Changing the timing time of the timer will change the PD4 pin turnover time, thus changing the PWM output frequency.

Next, call the buzzer directly in the main function to output the chord tones.

#include "stm8s103f3p.h"
#include "delay.h"
#include "buzzer.h"

extern unsigned char BuzzerStatus;
void CLK_Init(void)
{
	CLK_SWR=0xe1; 				//HSI 16MHz CPU clock frequency of the primary clock source
	CLK_CKDIVR=0x00;			// The CPU clock is 0 and the system clock is 0
}

void test(void)
{
	char i=0;
	for(i=0; i<10; i++)
	{
		delay_ms(500);
		BuzzerStart(0);   / / ChanShengYin
		while(BuzzerStatus! =3)
		{
			BuzzerCtrl();
			delay_ms(5); }}for(i=0; i<10; i++)
	{
		delay_ms(500);
		BuzzerStart(1);   // Start the chord
		while(BuzzerStatus! =3)
		{
			BuzzerCtrl();
			delay_ms(5); }}for(i=0; i<10; i++)
	{
		delay_ms(500);
		BuzzerStart(2);   // Turn off the chord
		while(BuzzerStatus! =3)
		{
			BuzzerCtrl();
			delay_ms(5);
		}
	}
}

main()
{
	unsigned char key;
	CLK_Init();
	_asm("sim");            // Disable interrupt
	delay_init(16);
	buzzer_gpio_init();
	_asm("rim");            // Enable interrupt
	while (1) { test(); }}Copy the code

In the main function, a call test is performed for the three chords, each of which is called 10 times in a loop. If the FREQUENCY of the PWM output is output according to the beat of the song, then music can be played through the passive buzzer.