ZHCAG09 November   2025 MSPM0G3507

 

  1.   1
  2. 说明
  3. 所需外设
  4. 兼容器件
  5. 设计步骤
  6. 设计注意事项
  7. 软件流程图
  8. 应用代码
  9. 其他资源
  10. E2E
  11. 10商标

应用代码

#include "ti_msp_dl_config.h"

/* musical notes frequencies in Hz - 6th octave */
#define NOTE_C  1047   // C6
#define NOTE_D  1175   // D6
#define NOTE_E  1319   // E6
#define NOTE_F  1397   // F6
#define NOTE_G  1568   // G6
#define NOTE_A  1760   // A6
#define NOTE_B  1976   // B6

/* sine wave lookup table for DAC output */
#define SINE_POINTS 64
const uint16_t gSineTable[] = {2048, 2248, 2447, 2642, 2831, 3013,
    3185, 3347, 3496, 3631, 3750, 3854, 3940, 4007, 4056, 4086, 4095, 4086,
    4056, 4007, 3940, 3854, 3750, 3631, 3496, 3347, 3185, 3013, 2831, 2642,
    2447, 2248, 2048, 1847, 1648, 1453, 1264, 1082, 910, 748, 599, 464, 345,
    241, 155, 88, 39, 9, 0, 9, 39, 88, 155, 241, 345, 464, 599, 748, 910, 1082,
    1264, 1453, 1648, 1847};

/* Variables for tone generation */
#define PHASE_FRAC_BITS 24
uint32_t gPhaseAccumulator = 0;
uint32_t gPhaseIncrement = 0;
/* 16.39kHz sample rate (61us timer period). May require some shifts depending on the piezo used */
uint32_t gSampleRate = 16393; 

/* Melody sequence: "BAG BAG GGGGAAAA BAG", "Hot crossed buns" */
/* 0u represents a rest, or a tone of "0" */
static const uint32_t gMelodyFreqs[] = {
    NOTE_B, 0u, NOTE_A, 0u, NOTE_G, 0u, 0u,
    NOTE_B, 0u, NOTE_A, 0u, NOTE_G, 0u, 0u,
    NOTE_G, 0u, NOTE_G, 0u, NOTE_G, 0u, NOTE_G, 0u,
    NOTE_A, 0u, NOTE_A, 0u, NOTE_A, 0u, NOTE_A, 0u,
    NOTE_B, 0u, NOTE_A, 0u, NOTE_G, 0u
};

/* durations in milliseconds for each entry above:
   full note -> 500ms, half note -> 250ms, short rest -> 80ms, phrase separator rest -> 250ms */
static const uint16_t gMelodyDurMs[] = {
    /* One phrase per line */
    500,  80, 500,  80, 500,  80, 250,
    500,  80, 500,  80, 500,  80, 250,
    250,  80, 250,  80, 250,  80, 250,  80,
    250,  80, 250,  80, 250,  80, 250,  80,
    500,  80, 500,  80, 500, 2000
};

/* defines for melody state machine*/
#define MELODY_LENGTH (sizeof(gMelodyFreqs)/sizeof(gMelodyFreqs[0]))
static uint16_t gCurrentMelodyIndex = 0;
static uint32_t gNoteSamplesRemaining = 0;

/* set the phase increment for a given frequency */
void setToneFrequency(uint32_t frequency) {
    if (frequency == 0) {
        gPhaseIncrement = 0;
        return;
    }
    /* compute increment with 24 fractional bits: inc = freq * SINE_POINTS * 2^PHASE_FRAC_BITS / sampleRate */
    /* allows for smooth frequency shifting */
    uint64_t inc = (uint64_t)frequency * (uint64_t)SINE_POINTS * ((uint64_t)1 << PHASE_FRAC_BITS);
    inc /= gSampleRate;
    gPhaseIncrement = (uint32_t)inc;
}

/* play each note from the melody based on index (updated by isr) */
static void startMelodyNote(uint16_t idx)
{
    if (idx >= MELODY_LENGTH) {
        idx = 0;
    }

    gCurrentMelodyIndex = idx;
    uint32_t freq = gMelodyFreqs[idx];
    setToneFrequency(freq);

    /* compute note duration */
    uint32_t durMs = gMelodyDurMs[idx];
    gNoteSamplesRemaining = (durMs * gSampleRate) / 1000u;

    /* if duration is zero, click note for one sample*/
    if (gNoteSamplesRemaining == 0) {
        gNoteSamplesRemaining = 1;
    }
}

int main(void)
{
    SYSCFG_DL_init();
    /* Start the first note of the melody */
    startMelodyNote(0);
    /* Start timer to trigger DAC */
    DL_TimerG_startCounter(TIMER_0_INST);
    /* Enable DAC interrupt to update output */
    NVIC_EnableIRQ(DAC12_INT_IRQN);


    /* Calling WFI after calling DL_SYSCTL_enableSleepOnExit will result in
     * only ISR code to be executed. This is done to showcase the device's
     * low power consumption when sleeping.
     */
    DL_SYSCTL_enableSleepOnExit();
    while (1) {
        __WFI();
    }
}

void DAC12_IRQHandler(void)
{
    switch (DL_DAC12_getPendingInterrupt(DAC0)) {
        case DL_DAC12_IIDX_FIFO_1_2_EMPTY:
            {
                /* code for rest */
                if (gPhaseIncrement == 0) {
                    DL_DAC12_output12(DAC0, 2048);
                } else { /*code for tone, walk through phase table */
                    uint32_t tableIndex = (gPhaseAccumulator >> PHASE_FRAC_BITS) & (SINE_POINTS - 1);
                    DL_DAC12_output12(DAC0, gSineTable[tableIndex]);
                    gPhaseAccumulator += gPhaseIncrement;
                }

                /* state machine forward */
                if (gNoteSamplesRemaining > 0) {
                    gNoteSamplesRemaining--;
                }

                if (gNoteSamplesRemaining == 0) {
                    /* move to next note, wrap around */
                    uint16_t next = gCurrentMelodyIndex + 1;

                    /* causes song to loop*/
                    if (next >= MELODY_LENGTH) {
                        next = 0;
                    }
                    startMelodyNote(next);
                }
            }
            break;
        /* unused */
        case DL_DAC12_IIDX_FIFO_3_4_EMPTY:
        case DL_DAC12_IIDX_NO_INT:
        case DL_DAC12_IIDX_MODULE_READY:
        case DL_DAC12_IIDX_FIFO_FULL:
        case DL_DAC12_IIDX_FIFO_1_4_EMPTY:
        case DL_DAC12_IIDX_FIFO_EMPTY:
        case DL_DAC12_IIDX_FIFO_UNDERRUN:
        case DL_DAC12_IIDX_DMA_DONE:
            break;
    }
}