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

If you want to play a song, you must use a passive buzzer, because the passive buzzer emits sound through the output frequency of PWM. When the PWM frequency is set to a certain value, the buzzer will emit the sound of do re mi Fa so La xi. This allows music to be played through the passive buzzer.

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 following code directly:

#ifndef __BUZZER_H
#define __BUZZER_H
#include "stm8s103f3p.h"

// Do re mi fa so La xi
#define BUZZER_LOW_DO_1         (262)  / / ARR value of 2045
#define BUZZER_LOW_RE_2         (294)  / / ARR value of 1820
#define BUZZER_LOW_MI_3         (330)  / / ARR value of 1620
#define BUZZER_LOW_FA_4         (349)  / / ARR value of 1525
#define BUZZER_LOW_SO_5         (392)  / / ARR value of 1355
#define BUZZER_LOW_LA_6         (440)  / / ARR value of 1205
#define BUZZER_LOW_XI_7         (494)  / / ARR value of 1078
/ / alto
#define BUZZER_MIDDLE_DO_1      (523)  / / ARR
#define BUZZER_MIDDLE_RE_2      (587)  / / ARR
#define BUZZER_MIDDLE_MI_3      (659)  / / ARR
#define BUZZER_MIDDLE_FA_4      (698)  / / ARR
#define BUZZER_MIDDLE_SO_5      (784)  / / ARR
#define BUZZER_MIDDLE_LA_6      (880)  / / ARR
#define BUZZER_MIDDLE_XI_7      (988)  / / ARR
/ / high
#define BUZZER_HIGH_DO_1        (1047)  / / ARR
#define BUZZER_HIGH_RE_2        (1175)  / / ARR
#define BUZZER_HIGH_MI_3        (1319)  / / ARR
#define BUZZER_HIGH_FA_4        (1397)  / / ARR
#define BUZZER_HIGH_SO_5        (1568)  / / ARR
#define BUZZER_HIGH_LA_6        (1760)  / / ARR
#define BUZZER_HIGH_XI_7        (1976)  / / ARR


typedef enum
{
	FREQ_2K,
	FREQ_2K3,
	FREQ_2K6,
	FREQ_2K9,
	FREQ_NO,
	FREQ_LOW_DO_1,
	FREQ_LOW_RE_2,
	FREQ_LOW_MI_3,
	FREQ_LOW_FA_4,
	FREQ_LOW_SO_5,
	FREQ_LOW_LA_6,
	FREQ_LOW_XI_7
} FREQ_Type; // Frequency type

typedef enum
{
	MONO = 0./ / mono
	POLY_ON = 1.// Start the chord
	POLY_OFF = 2  // Turn off the chord
} Tone_Type; // Sound type of the buzzer

typedef struct
{
	FREQ_Type Freq;	/ / frequency
	unsigned char OSCTime; // Duration of oscillation. The minimum unit is 10ms
	unsigned char PWRTime; // Power supply duration, the minimum unit is 10ms
} TONE_Def; // Tonal structures


void buzzer_gpio_init(void);
void BeepPwrOn(void);
void BeepPwrOff(void);
void BEEP_On(void);
void BEEP_Off(void);

void TIM1_Init(void);

void BuzzerStart(Tone_Type ToneType);
void BuzzerCtrl(void);
void BEEP_SetFreq(FREQ_Type Freq);

void MusicStart(void);

#endif /* __BUZZER_H */

Copy the code

First, the fixed frequency is defined in the header file using a macro definition. When using, the specified frequency is called directly through the macro definition.

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

_Bool Beep_Power  @PD_ODR:3;        //PD3 is used for buzzer power supply control
_Bool Beep_Pre  @PD_ODR:4;          //PD4 for frequency control

const TONE_Def Tone5[] =      // Two tigers (Two tigers two tigers run fast, run fast)
{
	{FREQ_LOW_DO_1, 25.25},/ / 1
	{FREQ_LOW_RE_2, 25.25},/ / 2
	{FREQ_LOW_MI_3, 25.25},/ / 3
	{FREQ_LOW_DO_1, 25.25},/ / 1
	{FREQ_LOW_DO_1, 25.25},/ / 1
	{FREQ_LOW_RE_2, 25.25},/ / 2
	{FREQ_LOW_MI_3, 25.25},/ / 3
	{FREQ_LOW_DO_1, 25.25},/ / 1
	{FREQ_LOW_RE_2, 25.25},/ / 2
	{FREQ_LOW_MI_3, 25.25},/ / 3
	{FREQ_LOW_FA_4, 50.25},//4 A slight pause
	{FREQ_LOW_RE_2, 25.25},/ / 2
	{FREQ_LOW_MI_3, 25.25},/ / 3
	{FREQ_LOW_FA_4, 100.25},//4
	{FREQ_NO, 0.0} / / stop
};

// do-re-mi-fa-so-la-ti
TONE_Def T1[] = {{FREQ_2K, 25.25},{FREQ_NO, 0.0}}; //do 1
TONE_Def T2[] = {{FREQ_2K3, 25.25},{FREQ_NO, 0.0}};//re 2
TONE_Def T3[] = {{FREQ_2K6, 25.25},{FREQ_NO, 0.0}};//mi 3
TONE_Def T4[] = {{FREQ_2K9, 25.25},{FREQ_NO, 0.0}};//fa 4

// 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;

// Control pin initialization
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
}

// Power control
void BeepPwrOn(void)
{
	Beep_Power=1;
}
void BeepPwrOff(void)
{
	Beep_Power=0;
}
// Frequency control
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;
}

void MusicStart(void)
{
	/* char i; for(i=1; i<5; i++) { if(i==1)pTone=T1; if(i==2)pTone=T2; if(i==3)pTone=T3; if(i==4)pTone=T4; BuzzerStatus = 1; while(BuzzerStatus! =3) { BuzzerCtrl(); delay_ms(15); }} * /
	pTone=Tone5;
	BuzzerStatus = 1;
	while(BuzzerStatus! =3)
	{
		BuzzerCtrl();
		delay_ms(15); }}// 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 							// The frequency is 0
		{
			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; }}// Initialize timer 1
void TIM1_Init(void)
{
	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 = 205/255;            // Set a fixed value
	TIM1_ARRL = 205%255;

	TIM1_CR1 |=0x01;                    // Enable the 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=255;      				//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;
	case FREQ_LOW_DO_1:
		prescal=2045;
		break;
	case FREQ_LOW_RE_2:
		prescal=1820;
		break;
	case FREQ_LOW_MI_3:
		prescal=1620;
		break;
	case FREQ_LOW_FA_4:
		prescal=1525;
		break;
	case FREQ_LOW_SO_5:
		prescal=1355;
		break;
	case FREQ_LOW_LA_6:
		prescal=1205;
		break;
	case FREQ_LOW_XI_7:
		prescal=1078;
		break;

	default:
		prescal=265;
	}
	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;            // Set a fixed value
	TIM1_ARRL = prescal%255;

	TIM1_CR1 |=0x01;                    // Enable the timer
}

Copy the code

SCM PD3 control buzzer power supply, PD4 output PWM waveform. By changing the timing of the timer to change the frequency of the output PWM, to make the code easier to write, only one bar of the two tigers’ song is played here.

You can play music by calling it directly from the main function.

#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
}

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

In the same way, you can code the music you want to play.