基于LPC55S69-EVK的音频播放器 - Funpack11项目分享一

电子森林 2021-11-08 22:04

Funpack11期于10月31日截止后,到现在已审核完毕,相信审核通过的小伙伴都已经收到祝贺邮件了,那就静等返款吧。


本期的任务也是很有用意思,四选一,难度中等。这款来自NXP的强大的LPC55S69-EVK在群友们和各种开源资料的帮助下被大家玩的非常深入,轻松完成这期的几个任务。


下面就来看看vic网友如何使用本期板卡实现音频播放器的吧。以下项目已开源在电子森林:https://www.eetree.cn/project/detail/626,大家感兴趣的可以来一起学习。




1. 实现功能说明
本次使用LCP55S69-EVK开发板显示的功能是,任务一:读取SD卡中的音频文件,使用板卡上的3.5mm音频接口播放音乐。
 
2. 功能代码展示
2.1. 主函数
在主函数中主要是对需要用到的外设进行初始化,例如:USART、I2C、I2S、Codec等,最后创两个任务分别用于完成SD卡管理以及通过USART0提供shell接口。
int main(void){    int ret;
/* set BOD VBAT level to 1.65V */ POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false); CLOCK_EnableClock(kCLOCK_InputMux); CLOCK_EnableClock(kCLOCK_Iocon); CLOCK_EnableClock(kCLOCK_Gpio0); CLOCK_EnableClock(kCLOCK_Gpio1);
/* USART0 clock */ CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
/* I2C clock */ CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4);
PMC->PDRUNCFGCLR0 |= PMC_PDRUNCFG0_PDEN_XTAL32M_MASK; /*!< Ensure XTAL16M is on */ PMC->PDRUNCFGCLR0 |= PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK; /*!< Ensure XTAL16M is on */ SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK; /*!< Ensure CLK_IN is on */ ANACTRL->XO32M_CTRL |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK;
/*!< Switch PLL0 clock source selector to XTAL16M */ CLOCK_AttachClk(kEXT_CLK_to_PLL0);
const pll_setup_t pll0Setup = { .pllctrl = SYSCON_PLL0CTRL_CLKEN_MASK | SYSCON_PLL0CTRL_SELI(2U) | SYSCON_PLL0CTRL_SELP(31U), .pllndec = SYSCON_PLL0NDEC_NDIV(125U), .pllpdec = SYSCON_PLL0PDEC_PDIV(8U), .pllsscg = {0x0U, (SYSCON_PLL0SSCG1_MDIV_EXT(3072U) | SYSCON_PLL0SSCG1_SEL_EXT_MASK)}, .pllRate = 24576000U, .flags = PLL_SETUPFLAG_WAITLOCK}; /*!< Configure PLL to the desired values */ CLOCK_SetPLL0Freq(&pll0Setup);
CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 0U, true); CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 1U, false);
/* I2S clocks */ CLOCK_AttachClk(kPLL0_DIV_to_FLEXCOMM6); CLOCK_AttachClk(kPLL0_DIV_to_FLEXCOMM7);
/* Attach PLL clock to MCLK for I2S, no divider */ CLOCK_AttachClk(kPLL0_to_MCLK); SYSCON->MCLKDIV = SYSCON_MCLKDIV_DIV(0U); SYSCON->MCLKIO = 1U;
/* reset FLEXCOMM for I2C */ RESET_PeripheralReset(kFC4_RST_SHIFT_RSTn);
/* reset FLEXCOMM for DMA0 */ RESET_PeripheralReset(kDMA0_RST_SHIFT_RSTn);
/* reset FLEXCOMM for I2S */ RESET_PeripheralReset(kFC6_RST_SHIFT_RSTn); RESET_PeripheralReset(kFC7_RST_SHIFT_RSTn);
/* reset NVIC for FLEXCOMM6 and FLEXCOMM7 */ NVIC_ClearPendingIRQ(FLEXCOMM6_IRQn); NVIC_ClearPendingIRQ(FLEXCOMM7_IRQn);
/* Enable interrupts for I2S */ EnableIRQ(FLEXCOMM6_IRQn); EnableIRQ(FLEXCOMM7_IRQn);
/* Initialize the rest */ BOARD_InitPins(); BOARD_BootClockPLL1_150M(); BOARD_InitDebugConsole(); BOARD_InitSysctrl();
PRINTF("\r\n"); PRINTF("**********************************\r\n"); PRINTF("Maestro audio solutions demo start\r\n"); PRINTF("**********************************\r\n"); PRINTF("\r\n");
ret = BOARD_CODEC_Init(); if (ret) { PRINTF("CODEC_Init failed\r\n"); return -1; }
if (xTaskCreate(APP_SDCARD_Task, "SDCard Task", SDCARD_TASK_STACK_SIZE, &app, configMAX_PRIORITIES - 4, NULL) != pdPASS) { PRINTF("\r\nFailed to create application task\r\n"); while (1) ; }
/* Set shell command task priority = 1 */ if (xTaskCreate(APP_Shell_Task, "Shell Task", SHELL_TASK_STACK_SIZE, &app, configMAX_PRIORITIES - 5, &app.shell_task_handle) != pdPASS) { PRINTF("\r\nFailed to create application task\r\n"); while (1) ; }
/* Run RTOS */ vTaskStartScheduler();
/* Should not reach this statement */ return 0;}

2.2. SD卡管理任务
SD卡任务的代码如下所示,其主要的作用是:SD在插入时会触发中断,最终触发到当前任务,用于完成SD卡的挂载操作。
void APP_SDCARD_Task(void *param){    const TCHAR driverNumberBuffer[3U] = {SDDISK + '0', ':', '/'};    FRESULT error;    app_handle_t *app = (app_handle_t *)param;
app->sdcardSem = xSemaphoreCreateBinary();
BOARD_SD_Config(&g_sd, APP_SDCARD_DetectCallBack, BOARD_SDMMC_SD_HOST_IRQ_PRIORITY, app);
PRINTF("[APP_SDCARD_Task] start\r\n");
/* SD host init function */ if (SD_HostInit(&g_sd) != kStatus_Success) { PRINTF("[APP_SDCARD_Task] SD host init failed.\r\n"); vTaskSuspend(NULL); }
/* Small delay for SD card detection logic to process */ vTaskDelay(100 / portTICK_PERIOD_MS);
while (1) { /* Block waiting for SDcard detect interrupt */ xSemaphoreTake(app->sdcardSem, portMAX_DELAY);
if (app->sdcardInserted != app->sdcardInsertedPrev) { app->sdcardInsertedPrev = app->sdcardInserted;
SD_SetCardPower(&g_sd, false);
if (app->sdcardInserted) { /* power on the card */ SD_SetCardPower(&g_sd, true); if (f_mount(&app->fileSystem, driverNumberBuffer, 0U)) { PRINTF("[APP_SDCARD_Task] Mount volume failed.\r\n"); continue; }
#if (FF_FS_RPATH >= 2U) error = f_chdrive((char const *)&driverNumberBuffer[0U]); if (error) { PRINTF("[APP_SDCARD_Task] Change drive failed.\r\n"); continue; }#endif
PRINTF("[APP_SDCARD_Task] SD card drive mounted\r\n");
xSemaphoreGive(app->sdcardSem); } } }}

2.3. shell任务
shell任务的主要目的通过USART0(与Link2的虚拟串口链接),为用户提供一个可以控制播放器的操作接口,主要处理函数如下所示:
uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,                                      BaseType_t xClearCountOnExit,                                      TickType_t xTicksToWait )    {        uint32_t ulReturn;
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
taskENTER_CRITICAL(); { /* Only block if the notification count is not already non-zero. */ if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) { /* Mark this task as waiting for a notification. */ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 ) { prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE ); traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
/* All ports are written to allow a yield in a critical * section (some will yield immediately, others wait until the * critical section exits) - but it is not something that * application code should ever do. */ portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } taskEXIT_CRITICAL();
taskENTER_CRITICAL(); { traceTASK_NOTIFY_TAKE( uxIndexToWait ); ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
if( ulReturn != 0UL ) { if( xClearCountOnExit != pdFALSE ) { pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; } else { pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; } } else { mtCOVERAGE_TEST_MARKER(); }
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL();
return ulReturn; }

2.4. codec初始化
codec使用的是板载的wm8904,初始化代码如下所示。
int BOARD_CODEC_Init(void){    CODEC_Init(&codecHandle, &boardCodecConfig);
/* Invert the DAC data in order to output signal with correct polarity - set DACL_DATINV and DACR_DATINV = 1 */ WM8904_WriteRegister((wm8904_handle_t *)codecHandle.codecDevHandle, WM8904_AUDIO_IF_0, 0x1850);
/* Initial volume kept low for hearing safety. */ CODEC_SetVolume(&codecHandle, kCODEC_PlayChannelHeadphoneLeft | kCODEC_PlayChannelHeadphoneRight, 75);
return 0;}

3. 功能配置
功能配置使用的NXP提供的MCUXpresso Config Tools,各个配置项如下所示。

3.1. 管脚配置
主要是对用到的USART、I2C、SDIF等外设管脚进行初始化。

3.2. 时钟配置
时钟配置如下所示,只配置了基本的时钟以及使用到的外设时钟。

4. 功能展示
4.1. 连线方式
需要链接的是:
- 使用Micro USB链接电脑和开发板的调试串口(主要进行程序下载以及SHELL交互)
- 使用3.5MM的接口链接开发板和扬声器(右边的是音频输出)

5. 心得体会
这是第一次使用NXP的MCU进行开发,工具做的很完善,例程支持也很完善。芯片的外设资源也很丰富。总之就是很强大,之后可以借助于这个芯片做很多有意思的东西。

总体而言,透过Funpack第十一期的活动收益良多。感谢硬禾提供这么好的活动!

END


硬禾学堂

硬禾团队一直致力于给电子工程师和相关专业的同学,带来规范的核心技能课程,帮助大家在学习和工作的各个阶段,都能有效地提升自己的职业能力。

硬禾学堂

我们一起在电子领域探索前进

关注硬禾公众号,随时直达课堂


点击阅读原文查看更多

电子森林 讲述电子工程师需要掌握的重要技能: PCB设计、FPGA应用、模拟信号链路、电源管理等等;不断刷新的行业新技术 - 树莓派、ESP32、Arduino等开源系统;随时代演进的热点应用 - 物联网、无人驾驶、人工智能....
评论
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-14 20:56 62浏览
  • 在现代软件开发领域,效率和可靠性是企业在竞争中取胜的关键。本文将深入探讨 ANA Systems 如何通过引入业界领先的 CI/CD 平台——CircleCI,克服传统开发流程的瓶颈,实现开发运营效率的全面提升。同时,本文还将详细解析 CircleCI 的核心优势,包括其强大的自动化功能、广泛的工具整合能力,以及为企业量身定制的支持服务,揭示其如何助力 ANA Systems 在「新一代国内旅客项目」中脱颖而出。这一案例将为企业优化开发流程、提升竞争力提供重要的实践参考。ANA Systems
    艾体宝IT 2024-12-16 16:44 55浏览
  • 在现代生活中,我们经常会遇到需要检测电线是否带电的情况。这时,一款好用的数显测电笔就显得尤为重要了。今天,我想跟大家分享一下DELIXI数显测电笔的使用方法,通过一个故事来讲述它如何帮助我们解决生活中的小麻烦。 在一个阳光明媚的周末,小明决定对他家的电路进行一次全面的检查。他知道,虽然自己不是专业的电工,但有了DELIXI数显测电笔的帮助,他也能轻松应对。 小明拿出了DELIXI数显测电笔,这款测电笔设计得非常人性化,操作起来也很简单。他首先注意到了测电笔上的两个按键:DIRECT(A键)和
    丙丁先生 2024-12-16 12:58 44浏览
  • 家用国产固态继电器(SSR)已成为各行各业的基石,性能可靠、设计紧凑、效率高。这些先进的开关设备取代了传统的机电继电器,具有静音运行、使用寿命更长、可靠性更高等诸多优点。家用SSR专为从工业自动化到家用电器等各种应用而设计,展示了本地制造商的独创性和竞争力。国产固态继电器特点和优势家用SSR采用半导体技术制造,与传统继电器相比,具有很强的耐磨性。主要特点包括:静音无振动运行:SSR使用半导体元件进行开关,消除了机械噪音。响应时间快:是工业控制系统中高速开关的理想选择。耐用性:没有移动部件,即使在
    克里雅半导体科技 2024-12-13 16:49 45浏览
  •        霍尔传感器是一种基于霍尔效应的传感器。霍尔效应指的是当通过一个导体的电流受到外部磁场的影响时,导体内部将会产生一种电场,使得在导体两端的电势差发生变化,这种电势差变化称为霍尔电势差。利用这种现象,可以设计出一种可以测量磁场强度和方向的传感器,即霍尔传感器。  霍尔传感器分为线型霍尔传感器和开关型霍尔传感器两种。  (一)开关型霍尔传感器由稳压器、霍尔元件、差分放大器,斯密特触发器和输出级组成,它输出数字量。开关型霍尔传感器还有一种特
    锦正茂科技 2024-12-14 10:58 61浏览
  • 全球领先的光学解决方案供应商艾迈斯欧司朗(瑞士证券交易所股票代码:AMS)于10月23日在深圳益田威斯汀酒店举办了艾迈斯欧司朗中国发展中心(以下简称,CDC)圆桌论坛。本次论坛以“智能化时代,以多元应用场景和技术 助力中国市场加速发展”为核心议题,探讨在人工智能驱动的市场趋势下,CDC如何助力中国伙伴把握时代机遇,推动大中华地区业务稳健增长,展示了艾迈斯欧司朗对中国市场的信心。立足中国 贴近本土客户需求在全球经济增速放缓和国际形势复杂多变的背景下,中国市场依然保持了稳定的增长势态,并释放出强大的
    艾迈斯欧司朗 2024-12-16 18:00 50浏览
  • 概述 Cyclone 10 GX器件的ALM结构与Cyclone V类似,所以在Cyclone 10 GX器件上实现TDC功能理论上是可以完全参考甚至移植自Cyclone V系列的成功案例。但是,现实却是更多的问题出现当在Cyclone 10 GX使用和Cyclone V同样策略实现TDC的时候。 本文主要记录在Cyclone 10 GX器件上实现TDC时的探索,并为后续TDC设计、测试等展开前期研究。Cyclone 10 GX ALM结构 如图1所示,Cyclone 10 GX器件的ALM结构
    coyoo 2024-12-14 17:15 61浏览
  • 一、引言在数字化时代,芯片作为现代科技的核心,其制造过程却常被视作神秘的黑箱。菊地正典的《大话芯片制造》为我们揭开了这层神秘的面纱,以通俗易懂的方式,全面系统地介绍了芯片制造的各个环节。作为一名电子信息技术专业的教育工作者,我深感这本书不仅为学生提供了宝贵的知识资源,也让我对芯片制造及其在现代社会中的作用有了更深刻的理解。二、生活中的芯片印记芯片的影响渗透到我们日常生活的每一个角落。从智能手机的闹钟唤醒,到交通卡的便捷支付,再到智能家居的智能化功能,芯片以其强大的运算和处理能力,为我们的现代生活
    月光 2024-12-16 11:52 50浏览
  • 霍尔传感器的原理        霍尔传感器是一种固体的传感器,其输出电压与磁场强度成比例。顾名思 义,这种器件是依赖于霍尔效应原理工作的。霍尔效应原理是在导体通电 和加有磁场的情况下,在导体的横向 上会产生电压。电子(在实践中多数载流子最常被使 用)在外部电场的驱动下会产生“漂移”,当暴露于磁场中时,这些运动 的带电粒子会受到一个垂直于电场和 磁场的力的作用。这个力会让导体的边缘充电,一边为正,一边为负。边
    锦正茂科技 2024-12-14 11:41 50浏览
  • 擎天柱,这个名字听起来就像是从科幻电影里走出来的英雄。但今天,我们要聊的不是那个变形金刚,而是一款同样令人兴奋的实验板——Ai8051U-LQFP48 转 89C52-DIP40 核心功能实验板。这款实验板就像是电子世界的“擎天柱”,它拥有强大的力量和无限的潜力,等待着我们去发掘和探索。 想象一下,你手中握着的不是一块普通的电路板,而是一张通往未来科技世界的门票。Ai8051U芯片,这颗强大的心脏,内置了硬件浮点运算单元(TFPU@120MHz),让你的计算速度飞起来,就像给机器人装上了翅膀。
    丙丁先生 2024-12-16 13:02 43浏览
  • 串口调试助手软件:XCOM 也是一款专为嵌入式开发和硬件调试设计的强大工具,如正点原子串口调试助手 XCOM V2.6。这款软件支持多种串口参数配置,满足不同开发需求,广泛应用于嵌入式系统开发、硬件调试以及电子爱好者的项目开发中。XCOM在嵌入式开发和硬件调试中的作用主要体现在以下几个方面: 1. 串口通信测试:XCOM作为一款强大的串口调试工具,允许用户通过计算机的串口进行数据的发送与接收,从而实现对串口通信的测试。这对于验证硬件设备的通信协议、确保数据传输的正确性至关重要。 2. 数据发
    丙丁先生 2024-12-15 11:56 63浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-13 23:20 58浏览
  • 光耦合器是一种重要的电子元件,其在电子信号隔离和传输中的作用不可替代。自20世纪60年代首次被研发以来,光耦合器经历了从基础隔离器件到高性能元件的不断演化,在现代电子设备中占据了重要地位。本文将深入探讨光耦合器的发展历程、技术特点以及在当今科技领域中的广泛应用。光耦合器的诞生背景光耦合器的诞生源于20世纪60年代,为了解决电子信号在不同电路之间传输时的隔离问题,科学家们设计了一种基于光信号传递的全新器件。光耦合器通过发光二极管(LED)将电信号转化为光信号,再由光敏器件接收并重新转换为电信号,从
    腾恩科技-彭工 2024-12-13 16:18 42浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦