一、项目要求
Funpack是硬禾学堂联合Digi-Key发起,为期一年的“玩成功就能得奖”活动。
活动参与者可从以下任务中任选其一完成:
任务一:
读取SD卡(SD卡自备)中的音频文件,使用板卡上的3.5mm音频接口播放音乐。
任务二:
读取SD卡中预先存入的图像,显示在屏幕上(OLED或LCD)。
任务三:
实现USB-UART Hub,自己设计通信方式,实现USB到多路UART的收发。
任务四:
移植Micropython,并实现串口通信和控制IO口。
我选择的是任务三,实现一个USB转双路串口的hub,实现双路串口收发传送功能。
二、使用平台介绍
LPC55S6x是一款基于ARM Cortex-M33的嵌入式应用微控制器。这些设备包括一个手臂Cortex-M33协处理器,鬼马小精灵加密/ FFT引擎,PowerQuad硬件加速器DSP功能,320 KB的片上存储器,640 KB的芯片上的flash,王子为动态闪光加密/解密模块,高速和全速USB主机和设备接口crystal-less全速运行,SD/MMC/SDIO接口,5个通用定时器,一个SCTimer/PWM,一个RTC/告警定时器,一个24位多速率定时器(MRT),一个窗口看门狗定时器(WWDT), 9个灵活的串行通信外围设备(可以配置为USART, SPI,高速SPI, I2C,或I2S接口),可编程逻辑单元(PLU),一个16位1.0 Msamples/sec ADC,能够同时进行转换。ARM Cortex-M33提供了一个安全基础,通过TrustZone技术提供隔离来保护有价值的IP和数据。利用综合数字信号处理(DSP)指令简化了数字信号控制系统的设计和软件开发。为了支持安全需求,LPC55S6x还提供了对安全引导、HASH、AES、RSA、UUID、DICE、动态加密和解密、调试身份验证和TBSA遵从性的支持。
LPC55S6x LPCXpresso™ series ARM® Cortex®-M33 MCU 32-位 评估板
集成了LPC55S69外围电路,LPC_Link调试器,RGB_LED,SD_CARD,USB接口,SD卡接口,音频芯片,ISP
三、项目实现过程介绍
项目基于MCUXpresso中的例程 dev_composite_cdc_vcom_cdc_vcom_bm 修改得到,首先使用MCUXpresso Config Tools创建一个例程。
打开对应的串口0,串口2
串口初始化
通过SDK包中例程的基础上将需要的COM初始化成串口,并开启响应中断模式.
配置时钟
主时钟由外部晶振提供,通过内部如下时钟树,进行分频,PLL送到CPU内部使用
四、软件代码
USB驱动部分
void USB_DeviceCdcVcomTask(void)
{
usb_status_t error = kStatus_USB_Error;
volatile usb_cdc_vcom_struct_t *vcomInstance;
for (uint8_t i = 0; i < USB_DEVICE_CONFIG_CDC_ACM; i++)
{
vcomInstance = &g_deviceComposite->cdcVcom[i];
if ((1 == vcomInstance->attach) && (1 == vcomInstance->startTransactions))
{
/* User Code */
/* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
if ((0 != vcomInstance->recvSize) && (USB_CANCELLED_TRANSFER_LENGTH != vcomInstance->recvSize))
{
int32_t i;
/* Copy Buffer to Send Buff */
for (i = 0; i < vcomInstance->recvSize; i++)
{
vcomInstance->currSendBuf[vcomInstance->sendSize++] = vcomInstance->currRecvBuf[i];
}
vcomInstance->recvSize = 0;
}
if (vcomInstance->sendSize)
{
uint32_t size = vcomInstance->sendSize;
vcomInstance->sendSize = 0;
error = USB_DeviceCdcAcmSend(vcomInstance->cdcAcmHandle, vcomInstance->bulkInEndpoint,
NULL, 0);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
if(i == 0)
{
USART_WriteBlocking(FLEXCOMM0_PERIPHERAL,vcomInstance->currSendBuf,size);
}
else
{
USART_WriteBlocking(FLEXCOMM2_PERIPHERAL,vcomInstance->currSendBuf,size);
}
while(0)
{
}
}
}
}
}
外设串口0初始化部分(串口1类似)
void FLEXCOMM0_FLEXCOMM_IRQHANDLER(void) {
/* Place your code here */
uint8_t data;
volatile usb_cdc_vcom_struct_t *vcomInstance1;
vcomInstance1 = &g_deviceComposite->cdcVcom[0];
/* If new data arrived. */
if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(FLEXCOMM0_PERIPHERAL))
{
data = USART_ReadByte(FLEXCOMM0_PERIPHERAL);
(void)USB_DeviceCdcAcmSend(g_deviceComposite->cdcVcom[0].cdcAcmHandle, vcomInstance1->bulkInEndpoint, &data, 1);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
五、实际效果展示
板卡插入两根USB_MICRO数据线,用来达成双串口的硬件条件,连接到电脑上两个USB接口,值得一提的是需要安装双CDC驱动.(驱动在NXP的SDK包中)
烧录程序之后,就可以在硬件管理器中看到三个串口COM,就可以实现其中两个串口进行收发通信.
六、总结
总结 之前使用NXP芯片时,因为网上资料较为匮乏,导致使用起来比较困难,上手较慢,并且调试时间较长,BUG较多,通过这一次活动让我认识到进一步的NXP,通过NXP_CONFIG系列开发软件,可以通过图形化手段进行代码直接生成,这样轻松就可以实现对外设硬件定义,以及相关IO初始化,非常便捷,高效,并且不会存在写错的可能性,完成了最基础也是最繁琐,最重复的工作,直接编写自己所需要的逻辑代码部分即可,这点让我们非常受用,时代在进步,感谢硬禾学堂提供的本次学习机会.