在线时间4746 小时
UID3441752
注册时间2017-11-21
NXP金币82795
TA的每日心情 | 开心 2025-7-11 08:53 |
---|
签到天数: 301 天 连续签到: 2 天 [LV.8]以坛为家I
管理员
  
- 积分
- 39227
- 最后登录
- 2025-7-18
|
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的信噪比目标。
硬件要求:
1. 连接 J-Link 调试器到 EVKB的 J62 接口。
2. 将耳机/扬声器接到 EVKB的 J88插口。
3. 将5V电源连接到EVKB的 J7插口。
4. 打开编译MQS工程,加载程序到开发板。
运行程序,就可以听到音乐声了。
需要在pinmux.c文件中配置的管脚:
- #include "fsl_common.h"
- #include "fsl_iomuxc.h"
- #include "pin_mux.h"
- /*FUNCTION**********************************************************************
- *
- * Function Name : BOARD_InitPins
- * Description : Configures pin routing and optionally pin electrical features.
- *
- *END**************************************************************************/
复制代码- void BOARD_InitPins(void) {
- CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_B0_00_MQS_RIGHT, /* GPIO_B0_00 is configured as MQS_RIGHT */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_B0_01_MQS_LEFT, /* GPIO_B0_01 is configured as MQS_LEFT */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
复制代码 music.h文件用于保存录制好的语音数据,
- #ifndef _MUSIC_H_
- #define _MUSIC_H_
- #define MUSIC_LEN sizeof(music)
- /*
- Channels: 2
- Sample width: 16-bit
- Sample rate: 16.0 kHz
- Frames number: 240000
- */
- AT_NONCACHEABLE_SECTION_ALIGN_INIT(uint8_t music[], 64) ={}
- #endif
复制代码- #include "board.h"
- #include "music.h"
- #include "pin_mux.h"
- #include "clock_config.h"
- #include "fsl_dmamux.h"
- #include "fsl_sai_edma.h"
- #include "fsl_iomuxc.h"
- #include "fsl_debug_console.h"
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* SAI instance and clock */
- #define DEMO_SAI SAI3
- /* Select Audio PLL (786.432 MHz) as sai1 clock source */
- #define DEMO_SAI_CLOCK_SOURCE_SELECT (2U)
- /* Clock pre divider for sai clock source */
- #define DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER (3U)
- /* Clock divider for sai clock source */
- #define DEMO_SAI_CLOCK_SOURCE_DIVIDER (4U)
- /* Get frequency of sai clock: SAI3_Clock = 786.432MHz /(3+1)/(4+1) = 39.321MHz */
- #define DEMO_SAI_CLK_FREQ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI_CLOCK_SOURCE_DIVIDER + 1U) / (DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER + 1U))
- /* DMA */
- #define DMAMUX0 DMAMUX
- #define EXAMPLE_DMA DMA0
- #define EXAMPLE_CHANNEL (0U)
- #define EXAMPLE_SAI_TX_SOURCE kDmaRequestMuxSai3Tx
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle) = {0};
- edma_handle_t dmaHandle = {0};
- static volatile bool isFinished = false;
- /*******************************************************************************
- * Code
- ******************************************************************************/
- /*
- * AUDIO PLL setting: Frequency = Fref * (DIV_SELECT + NUM / DENOM)
- * = 24 * (32 + 768/1000)
- * = 786.432 MHz
- */
- const clock_audio_pll_config_t audioPllConfig = {
- .loopDivider = 32, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
- .postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
- .numerator = 768, /* 30 bit numerator of fractional loop divider. */
- .denominator = 1000, /* 30 bit denominator of fractional loop divider */
- };
- static void callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
- {
- isFinished = true;
- }
- void configMQS(void)
- {
- CCM->CCGR0 = CCM->CCGR0 & (~CCM_CCGR0_CG2_MASK) | CCM_CCGR0_CG2(3);
- /* Enable MQS hmclk. */
- IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, true); /* Reset MQS. */
- IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, false); /* Release reset MQS. */
- IOMUXC_MQSEnable(IOMUXC_GPR, true); /* Enable MQS. */
- IOMUXC_MQSConfig(IOMUXC_GPR, kIOMUXC_MqsPwmOverSampleRate64, 0u);
- /* 78.6432MHz/64/(0+1) = 1.2288MHz,Higher frequency PWM involves less low frequency harmonic.*/
- }
- /*!
- * @brief Main function
- */
- int main(void)
- {
- sai_config_t config;
- sai_transfer_format_t format;
- sai_transfer_t xfer;
- edma_config_t dmaConfig = {0};
- BOARD_ConfigMPU();
- BOARD_InitPins();
- BOARD_BootClockRUN();
- CLOCK_InitAudioPll(&audioPllConfig);
- BOARD_InitDebugConsole();
- /*Clock setting for SAI. */
- CLOCK_SetMux(kCLOCK_Sai3Mux, DEMO_SAI_CLOCK_SOURCE_SELECT);
- CLOCK_SetDiv(kCLOCK_Sai3PreDiv, DEMO_SAI_CLOCK_SOURCE_PRE_DIVIDER);
- CLOCK_SetDiv(kCLOCK_Sai3Div, DEMO_SAI_CLOCK_SOURCE_DIVIDER);
- PRINTF("SAI MQS DAM example started.\n\r");
- /* Create EDMA handle */
- EDMA_GetDefaultConfig(&dmaConfig);
- EDMA_Init(EXAMPLE_DMA, &dmaConfig);
- EDMA_CreateHandle(&dmaHandle, EXAMPLE_DMA, EXAMPLE_CHANNEL);
- DMAMUX_Init(DMAMUX0);
- DMAMUX_SetSource(DMAMUX0, EXAMPLE_CHANNEL, EXAMPLE_SAI_TX_SOURCE);
- DMAMUX_EnableChannel(DMAMUX0, EXAMPLE_CHANNEL);
- /* Init SAI module */
- SAI_TxGetDefaultConfig(&config);
- SAI_TxInit(DEMO_SAI, &config);
- /* Configure the audio format */
- format.bitWidth = kSAI_WordWidth16bits;
- format.channel = 0U;
- format.sampleRate_Hz = kSAI_SampleRate16KHz;
- format.masterClockHz = DEMO_SAI_CLK_FREQ;
- format.protocol = config.protocol;
- format.stereo = kSAI_Stereo;
- format.isFrameSyncCompact = true;
- format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
- SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, callback, NULL, &dmaHandle);
- SAI_TransferTxSetFormatEDMA(DEMO_SAI, &txHandle, &format, DEMO_SAI_CLK_FREQ, format.masterClockHz);
- configMQS();
- /* xfer structure */
- xfer.data = (uint8_t *)(uint32_t)music;
- xfer.dataSize = MUSIC_LEN;
- while (1)
- {
- isFinished = false;
- SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &xfer);
- /* Wait until finished */
- while (isFinished != true)
- {
- }
- }
- }
复制代码
|
|