Use Hongmeng OS to put a song "Two Tigers" on the buzzer

This article describes how to use the PWM interface of the Harmony OS IoT hardware subsystem to drive the buzzer to play music on the HiSpark Wi-Fi IoT kit.

Use PWM to output square wave

Square wave frequency of PWM output

Through the PwmStartinterface notes, we can know that the freq parameter is the frequency division multiple, and the square wave frequency actually output by the PWM is equal to the PWM clock source frequency divided by the frequency division multiple, that is

f = Fcs / freq

Among them, Fcs is the PWM clock source frequency;

Duty cycle of PWM output square wave

The duty cycle of the output square wave can be controlled through PwmStartthe dutyparameters of the interface. The duty cycle refers to the ratio of the high level time of the PWM output square wave waveform to the entire square wave cycle. The specific duty cycle value is the ratio of duty and freq, for example If you want to output a square wave signal with a duty cycle of 50%, the value of duty should be freq/2;

Note-frequency correspondence

Reference: https://liam.page/2018/04/09/pitch-interval-and-harmonic/
Note-frequency correspondence

The lowest frequency that the development board can output

Through the previous formula, we know:

  1. The frequency of the square wave output by the PWM is inversely proportional to freq, the larger the freq, the smaller the frequency of the output square wave;
  2. freq is the unsinged shorttype, the maximum value is 65535;
    therefore, the minimum value of the output frequency depends on the clock source, the default clock source of PWM is 160M:
    unsigned int HalPwmInit(HalWifiIotPwmPort port)
    {
    if (hi_pwm_set_clock(PWM_CLK_160M) != HI_ERR_SUCCESS) {
        return (unsigned int)HAL_WIFI_IOT_FAILURE;
    }
    return hi_pwm_init((hi_pwm_port)port);
    }

We hi_pwm_set_clockcan modify the clock source by directly calling the interface:

/**
 * @ingroup iot_pwm
 *
 * Enumerates the PWM clock sources.CNcomment:PWM时钟源枚举。CNend
 */
typedef enum {
    PWM_CLK_160M, /**< 160M APB clock.CNcomment:160M 工作时钟 CNend */
    PWM_CLK_XTAL, /**< 24M/40M crystal clock.CNcomment:24M或40M 晶体时钟 CNend */
    PWM_CLK_MAX   /**< Maximum value, which cannot be used.CNcomment:最大值,不可使用CNend */
} hi_pwm_clk_source;

hi_u32 hi_pwm_set_clock(hi_pwm_clk_source clk_type);

Through the comments, we know hi_pwm_set_clock(PWM_CLK_XTAL);that the clock source can be set to the crystal clock, the crystal clock may be 24M or 40M;
then the question is-how much is the crystal clock?

What is the crystal clock frequency?

We can calculate the crystal clock frequency through experiments, the specific steps are as follows:

  1. Using the hi_pwm_set_clock(PWM_CLK_XTAL);set clock source is a crystal clock;
  2. Use PwmStart(WIFI_IOT_PWM_PORT_PWM0, 20*1000, 40*1000);output square wave signal;
  3. Using an oscilloscope to measure the frequency of the square wave;
    by actual measurement, assessment was 1000Hz square wave, and therefore, the clock frequency 1000 * 40 * 1000is 40 MHz;

The lowest frequency of square wave that can be output

Therefore, the lowest frequency of the square wave is 40M / 65535, which is:

>>> 40 * 1000 * 1000 / 65535
610.3608758678569

Comparing the frequency table above, we can know that all notes above E♭ can be output;

Prepare the score

In order to make the code simpler, I chose the score of "Two Tigers" as the material, and quickly found the numbered score:
Two tigers notation

Notation description

For students who lack music foundation, some of the symbols on the notation may not be clear what they mean. Here is a brief explanation:

  1. The 1=C in the upper left corner means the mode (you don’t need to care about it), 1 is the roll name, C is the note name, 1=C is the forward tone (the normal correspondence: 1-C, 2-D, 3-E, 4 -F, 5-G, 6-A, 7-B);
  2. The 4/4 in the upper left corner is four or four beats, which means that the quarter note is one beat, and there are four beats per measure;
  3. The vertical line on the score below is each bar separator, corresponding to 4/4;
  4. "Run fast" The horizontal line behind 5 above indicates one beat delay;
  5. In the sentence "Always without eyes", the dot after 5 means half a beat, one underline means half the time, and two underlines mean one quarter of the time;

Write code

With the above knowledge, we can write code, the key part of the code is as follows:

static volatile int g_buttonPressed = 0;
static const uint16_t g_tuneFreqs[] = {
    0, // 40M Hz 对应的分频系数:
    38223, // 1 1046.5
    34052, // 2 1174.7
    30338, // 3 1318.5
    28635, // 4 1396.9
    25511, // 5 1568
    22728, // 6 1760
    20249, // 7 1975.5
    51021 // 5_ 783.99 // 第一个八度的 5
};

// 曲谱音符
static const uint8_t g_scoreNotes[] = {
    // 《两只老虎》简谱:http://www.jianpu.cn/pu/33/33945.htm
    1, 2, 3, 1,        1, 2, 3, 1,        3, 4, 5,  3, 4, 5,
    5, 6, 5, 4, 3, 1,  5, 6, 5, 4, 3, 1,  1, 8, 1,  1, 8, 1, // 最后两个 5 应该是低八度的,链接图片中的曲谱不对,声音到最后听起来不太对劲
};

// 曲谱时值,根据简谱记谱方法转写,4/4拍中下面划一条线是半拍,划两条线是四分之一拍,点是顺延半拍
static const uint8_t g_scoreDurations[] = {
    4, 4, 4, 4,        4, 4, 4, 4,        4, 4, 8,  4, 4, 8,
    3, 1, 3, 1, 4, 4,  3, 1, 3, 1, 4, 4,  4, 4, 8,  4, 4, 8,
};

static void *BeeperMusicTask(const char *arg)
{
    (void)arg;

    printf("BeeperMusicTask start!\r\n");

    hi_pwm_set_clock(PWM_CLK_XTAL); // 设置时钟源为晶体时钟(40MHz,默认时钟源160MHz)

    for (size_t i = 0; i < sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]); i++) {
        uint32_t tune = g_scoreNotes[i]; // 音符
        uint16_t freqDivisor = g_tuneFreqs[tune];
        uint32_t tuneInterval = g_scoreDurations[i] * (125*1000); // 音符时间
        printf("%d %d %d %d\r\n", tune, (40*1000*1000) / freqDivisor, freqDivisor, tuneInterval);
        PwmStart(WIFI_IOT_PWM_PORT_PWM0, freqDivisor/2, freqDivisor);
        usleep(tuneInterval);
        PwmStop(WIFI_IOT_PWM_PORT_PWM0);
    }

    return NULL;
}

Among them, the last two 5s of the score are errors of the score, which should be the lower octave 5, that is, there should be a dot below the 5; I modified the code to make the whole song sound more natural;

Complete code: https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/02_device_control/beeper_music_demo.c

Guess you like

Origin blog.51cto.com/xusiwei/2545519