812 views|1 replies

501

Posts

4

Resources
The OP
 

[Renesas Electronics 200MHz Cortex-M33 RA6E2 Evaluation Board] PWM Audio Playback [Copy link]

WeChat_20231023233924

Preface

Earlier we implemented PWM output, which can set the specified duty cycle and frequency. Based on this, we can implement PWM to play audio.

There are two ways to play audio with PWM

One is that PWM outputs different frequencies corresponding to different tones, similar to MIDI sound. This relatively low requirement for PWM update frequency, a tone does not change during a performance time.

The basic principle is as follows:

Frequency-corresponding pitch

Duty cycle-corresponding loudness

PWM output duration - corresponding playing duration

Another method is the PWM-DAC method, where different PWM output duty cycles represent different DAC output values, which requires a higher PWM update frequency.

We will now use the former to implement music playback.

Prepare

We need to first convert the music score into PWM frequency and duty cycle as well as the parameters of playing time.

Based on the international standard tone A-la-440HZ:

The frequency of do is 261.6HZ,

The frequency of re is 293.6HZ,

The frequency of mi is 329.6HZ,

The frequency of fa is 349.2HZ,

The frequency of sol is 392HZ,

The frequency of la is 440HZ,

The frequency of si is 493.8HZ.

Let’s take “Two Tigers” as an example

First look at the beat description in the upper left corner: 2/4 time, 1/4 note per beat, 2 beats per measure

76 beats per minute.

First define the following correspondence between scale and frequency

#define DO  523
#define RE  587
#define MI  659
#define FA  698
#define _SO 392
#define SO  784
#define LA  880
#define SI  987
#define NO  523
#define DUTY0  0

We can see that if the main frequency is 100MHz, the maximum 16-bit 65535 division frequency can only reach

1525HZ, so we need to reduce the main clock source frequency, we change it to 64 division

The corresponding functions below should also be modified

void pwm_set_frq_period(uint32_t duty, uint32_t frq)
{
	uint32_t period = (uint64_t)(100000000ul/64)/frq;
	duty = ((uint64_t)duty*period*2+100)/200;
	set_intensity(duty, period, TIMER_PIN);
}

Defining Takt Time

#define METERS  76ul             // 拍数76 1分钟76拍 每拍60/76秒 2/4  4分音符一拍 每小节2拍
#define NOTE_4  (60000ul/METERS)  // 先定一拍对应的音符 4分音符  x1000转化为单位mS
#define NOTE_8  (NOTE_4/2ul)     // 8分音符 一个下划线
#define NOTE_16  (NOTE_8/2ul)    // 16分音符 二个下划线

Define the scale table, corresponding frequency

const uint16_t beepfrep[] =
{
	DO,RE,MI,DO,
	DO,RE,MI,DO,
	MI,FA,SO,NO,
	MI,FA,SO,NO,
	SO,LA,SO,FA,MI,DO,
	SO,LA,SO,FA,MI,DO,
	DO,_SO,DO,NO,
	DO,_SO,DO,NO
};

Define the sound size table, corresponding to the duty cycle

const uint16_t beepduty[] =
{
	40,40,40,40,
	40,40,40,40,
	40,40,40,DUTY0,
	40,40,40,DUTY0,
	40,40,40,40,40,40,
	40,40,40,40,40,40,
	40,40,40,DUTY0,
	40,40,40,DUTY0,
};

Define the beat table, corresponding to the playing time of each scale

const uint32_t beeptime[]=

{
	NOTE_8,NOTE_8,NOTE_8,NOTE_8,
	NOTE_8,NOTE_8,NOTE_8,NOTE_8,
	NOTE_8,NOTE_8,NOTE_8,NOTE_8,
	NOTE_8,NOTE_8,NOTE_8,NOTE_8,
	NOTE_16,NOTE_16,NOTE_16,NOTE_16,NOTE_8,NOTE_8,
	NOTE_16,NOTE_16,NOTE_16,NOTE_16,NOTE_8,NOTE_8,
	NOTE_8,NOTE_8,NOTE_8,NOTE_16,
	NOTE_8,NOTE_8,NOTE_8,NOTE_16,
};

Implement delay function, unit: mS

void mdelay(uint32_t t)
{
	R_BSP_SoftwareDelay(t,BSP_DELAY_UNITS_MILLISECONDS);
}

Implementing the performance function

extern void pwm_set_frq_period(uint32_t duty, uint32_t frq);
void beep_play_music(const uint16_t* freq,const uint16_t* duty, const uint32_t* time, uint16_t len)
{
	uint16_t i = 0;
	for(i=0; i< len; i++)
	{
			pwm_set_frq_period(duty[i],freq[i]);
			mdelay(time[i]);
	}
}

test

Add test function

void pwm_audio_test(void)
{
	beep_play_music(beepfrep, beepduty, beeptime, sizeof(beepfrep)/sizeof(beepfrep[0]));
}

Add command line in shell_func.c

{ (const uint8_t*)"pwmaudio", PwmaudioFun, "pwmaudio"},

void pwm_audio_test(void);

void PwmaudioFun(unsigned char* param)

{

(void)param;

pwm_audio_test();

}

Add declaration in shell_func.h

void PwmaudioFun(unsigned char* param);

You can see the added commands are as follows

Connect the buzzer to test the effect, see the video

Summarize

  1. You can add more second scores to play different music.
  2. You can also change the above blocking delay to timed interrupt processing, so that non-blocking is more convenient to use.
This post is from Renesas Electronics MCUs

Latest reply

sharp  Details Published on 2023-11-2 16:58

3

Posts

0

Resources
2
 

sharp


This post is from Renesas Electronics MCUs
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list