查看: 4246|回复: 0

[分享] I.MXRT MQS 使用

[复制链接]
  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3868

    主题

    7472

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    39227
    最后登录
    2025-7-18
    发表于 2020-10-13 16:59:13 | 显示全部楼层 |阅读模式
    I.MXRT MQS 使用



    MQS (Medium quality sound)功能来实现语音输出,而不是 DAC方式。使用I.MXRT的MQS功能,在开发板I.MXRT1050-EVKB上测试。MQS来产生2通道的中等音质,类似PWM方式的声音,硬件上使用数字GPIO引脚,MQS_LEFT 和 MQS_RIGHT引脚。





    来自SAI3的44kHz或48kHz输入信号采用左对齐格式。MQS为低于10khz的信号提供不超过20db的信噪比目标。
    11.png

    12.png

    13.png

    14.png


    硬件要求:
    1.  连接 J-Link 调试器到 EVKB的 J62 接口。
    2.  将耳机/扬声器接到 EVKB的 J88插口。
    3.  将5V电源连接到EVKB的 J7插口。
    4.  打开编译MQS工程,加载程序到开发板。
    运行程序,就可以听到音乐声了。


    需要在pinmux.c文件中配置的管脚:
    1. #include "fsl_common.h"
    2. #include "fsl_iomuxc.h"
    3. #include "pin_mux.h"

    4. /*FUNCTION**********************************************************************
    5. *
    6. * Function Name : BOARD_InitPins
    7. * Description   : Configures pin routing and optionally pin electrical features.
    8. *
    9. *END**************************************************************************/
    复制代码
    1. void BOARD_InitPins(void) {
    2.   CLOCK_EnableClock(kCLOCK_Iomuxc);          /* iomuxc clock (iomuxc_clk_enable): 0x03u */

    3.   IOMUXC_SetPinMux(
    4.       IOMUXC_GPIO_AD_B0_12_LPUART1_TX,        /* GPIO_AD_B0_12 is configured as LPUART1_TX */
    5.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
    6.   IOMUXC_SetPinMux(
    7.       IOMUXC_GPIO_AD_B0_13_LPUART1_RX,        /* GPIO_AD_B0_13 is configured as LPUART1_RX */
    8.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
    9.   IOMUXC_SetPinMux(
    10.       IOMUXC_GPIO_B0_00_MQS_RIGHT,            /* GPIO_B0_00 is configured as MQS_RIGHT */
    11.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
    12.   IOMUXC_SetPinMux(
    13.       IOMUXC_GPIO_B0_01_MQS_LEFT,             /* GPIO_B0_01 is configured as MQS_LEFT */
    14.       0U);                                    /* Software Input On Field: Input Path is determined by functionality */
    复制代码
    music.h文件用于保存录制好的语音数据,
    1. #ifndef _MUSIC_H_
    2. #define _MUSIC_H_
    3. #define MUSIC_LEN sizeof(music)
    4. /*
    5.   Channels: 2
    6.   Sample width: 16-bit
    7.   Sample rate: 16.0 kHz
    8.   Frames number: 240000
    9. */
    10. AT_NONCACHEABLE_SECTION_ALIGN_INIT(uint8_t music[], 64) ={}
    11. #endif
    复制代码
    1. #include "board.h"
    2. #include "music.h"
    3. #include "pin_mux.h"
    4. #include "clock_config.h"

    5. #include "fsl_dmamux.h"
    6. #include "fsl_sai_edma.h"
    7. #include "fsl_iomuxc.h"
    8. #include "fsl_debug_console.h"
    9. /*******************************************************************************
    10. * Definitions
    11. ******************************************************************************/
    12. /* SAI instance and clock */
    13. #define DEMO_SAI SAI3

    14. /* Select Audio PLL (786.432 MHz) as sai1 clock source */
    15. #define DEMO_SAI_CLOCK_SOURCE_SELECT (2U)
    16. /* Clock pre divider for sai clock source */
    17. #define DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER (3U)
    18. /* Clock divider for sai clock source */
    19. #define DEMO_SAI_CLOCK_SOURCE_DIVIDER (4U)
    20. /* Get frequency of sai clock: SAI3_Clock = 786.432MHz /(3+1)/(4+1) = 39.321MHz */
    21. #define DEMO_SAI_CLK_FREQ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI_CLOCK_SOURCE_DIVIDER + 1U) / (DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER + 1U))

    22. /* DMA */
    23. #define DMAMUX0 DMAMUX
    24. #define EXAMPLE_DMA DMA0
    25. #define EXAMPLE_CHANNEL (0U)
    26. #define EXAMPLE_SAI_TX_SOURCE kDmaRequestMuxSai3Tx
    27. /*******************************************************************************
    28. * Prototypes
    29. ******************************************************************************/
    30. static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);

    31. /*******************************************************************************
    32. * Variables
    33. ******************************************************************************/
    34. AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle) = {0};
    35. edma_handle_t dmaHandle = {0};

    36. static volatile bool isFinished = false;

    37. /*******************************************************************************
    38. * Code
    39. ******************************************************************************/

    40. /*
    41. * AUDIO PLL setting: Frequency = Fref * (DIV_SELECT + NUM / DENOM)
    42. *                              = 24 * (32 + 768/1000)
    43. *                              = 786.432 MHz
    44. */
    45. const clock_audio_pll_config_t audioPllConfig = {
    46.     .loopDivider = 32,      /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
    47.     .postDivider = 1,       /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
    48.     .numerator = 768,       /* 30 bit numerator of fractional loop divider. */
    49.     .denominator = 1000,    /* 30 bit denominator of fractional loop divider */
    50. };

    51. static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
    52. {
    53.     isFinished = true;
    54. }

    55. void configMQS(void)
    56. {
    57.     CCM->CCGR0 = CCM->CCGR0 & (~CCM_CCGR0_CG2_MASK) | CCM_CCGR0_CG2(3);         
    58. /* Enable MQS hmclk. */
    59.     IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, true);                    /* Reset MQS. */
    60.     IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, false);                   /* Release reset MQS. */
    61.     IOMUXC_MQSEnable(IOMUXC_GPR, true);                                         /* Enable MQS. */
    62.     IOMUXC_MQSConfig(IOMUXC_GPR, kIOMUXC_MqsPwmOverSampleRate64, 0u);           
    63. /* 78.6432MHz/64/(0+1) = 1.2288MHz,Higher frequency PWM involves less low frequency harmonic.*/
    64. }

    65. /*!
    66. * @brief Main function
    67. */
    68. int main(void)
    69. {
    70.     sai_config_t config;
    71.     sai_transfer_format_t format;
    72.     sai_transfer_t xfer;
    73.     edma_config_t dmaConfig = {0};

    74.     BOARD_ConfigMPU();
    75.     BOARD_InitPins();
    76.     BOARD_BootClockRUN();
    77.     CLOCK_InitAudioPll(&audioPllConfig);
    78.     BOARD_InitDebugConsole();

    79.     /*Clock setting for SAI. */
    80.     CLOCK_SetMux(kCLOCK_Sai3Mux, DEMO_SAI_CLOCK_SOURCE_SELECT);
    81.     CLOCK_SetDiv(kCLOCK_Sai3PreDiv, DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER);
    82.     CLOCK_SetDiv(kCLOCK_Sai3Div, DEMO_SAI_CLOCK_SOURCE_DIVIDER);

    83.     PRINTF("SAI MQS DAM example started.\n\r");

    84.     /* Create EDMA handle */
    85.     EDMA_GetDefaultConfig(&dmaConfig);
    86.     EDMA_Init(EXAMPLE_DMA, &dmaConfig);
    87.     EDMA_CreateHandle(&dmaHandle, EXAMPLE_DMA, EXAMPLE_CHANNEL);

    88.     DMAMUX_Init(DMAMUX0);
    89.     DMAMUX_SetSource(DMAMUX0, EXAMPLE_CHANNEL, EXAMPLE_SAI_TX_SOURCE);
    90.     DMAMUX_EnableChannel(DMAMUX0, EXAMPLE_CHANNEL);

    91.     /* Init SAI module */
    92.     SAI_TxGetDefaultConfig(&config);
    93.     SAI_TxInit(DEMO_SAI, &config);

    94.     /* Configure the audio format */
    95.     format.bitWidth = kSAI_WordWidth16bits;
    96.     format.channel = 0U;
    97.     format.sampleRate_Hz = kSAI_SampleRate16KHz;
    98.     format.masterClockHz = DEMO_SAI_CLK_FREQ;
    99.     format.protocol = config.protocol;
    100.     format.stereo = kSAI_Stereo;
    101.     format.isFrameSyncCompact = true;
    102.     format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;

    103.     SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, callback, NULL, &dmaHandle);
    104.     SAI_TransferTxSetFormatEDMA(DEMO_SAI, &txHandle, &format, DEMO_SAI_CLK_FREQ, format.masterClockHz);

    105.     configMQS();

    106.     /*  xfer structure */
    107.     xfer.data = (uint8_t *)(uint32_t)music;
    108.     xfer.dataSize = MUSIC_LEN;

    109.     while (1)
    110.     {
    111.         isFinished = false;
    112.         SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer);
    113.         /* Wait until finished */
    114.         while (isFinished != true)
    115.         {
    116.         }
    117.     }
    118. }
    复制代码



    qiandao qiandao
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-19 14:26 , Processed in 0.153722 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表