1、硬件介绍
这次Funpack11活动的板子是来自恩智浦的LPC55S69-EVK,这块板子基于全球首款ARM cortex-33内核的微控制器LPC55S69,主打高性能和低功耗。LPC55系列有分为S系列和非S系列,S系列的MCU在高性能外又具有极高的安全性,支持对flash进行加密以及对用户的image进行签名认证。
下图是该EVK板的主要外设接口
2、功能介绍
这次活动的四个任务中我选择了第三个任务:实现USB-UART Hub,自己设计通信方式,实现USB到多路UART的收发。因为恩智浦的工程师们在SDK中已经实现了用USB虚拟CDC设备的功能,我们只要基于该程例进行简单的修改就可以实现任务三。
我们从欢迎 | MCUXpresso SDK构建工具 (nxp.com)上选择LPC55S69-EVK板后全选所有SDK,然后下载解压到本地。打开MCUXpresso配置工具并选择SDK解压后的路径,选择dev_composite_cdc_vcom_cdc_vcom_bm这个例程,生成对应例程。
在生成例程时会弹出该窗口,需要打开外设对应的按钮后方可对外设进行控制
在时钟页面分别打开flexcomm0和flexcomm2的时钟,在外设页启用相关外设并把两个串口设置成中断模式。
这里使用到flexcomm0和flexcomm2用到的引脚如下表所示:
TX | RX | |
flexcomm0 | P0_30 | P0_29 |
flexcomm2 | P0_27 | P1_24 |
由于板载的调试器虚拟串口和flexcomm0相连,而flexcomm0在板上还留有排针,所以我将排针上flexcomm0的RX、TX与flexcomm2的TX、RX相连,如下图所示
3、主要代码介绍
串口中断处理(通过USB将串口接收到的数据发送到电脑)
flexcomm0
/* FLEXCOMM0_IRQn interrupt handler */
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
}
flexcomm2
/* FLEXCOMM2_IRQn interrupt handler */
void FLEXCOMM2_FLEXCOMM_IRQHANDLER(void)
{
/* Place your code here */
uint8_t data;
volatile usb_cdc_vcom_struct_t *vcomInstance1;
vcomInstance1 = &g_deviceComposite->cdcVcom[1];
/* If new data arrived. */
if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(FLEXCOMM2_PERIPHERAL))
{
data = USART_ReadByte(FLEXCOMM2_PERIPHERAL);
(void)USB_DeviceCdcAcmSend(g_deviceComposite->cdcVcom[1].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接收数据处理(将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);
}
}
}
}
4、实现效果演示
5、心得体会
以前在上学时都是学习stm32,对恩智浦芯片的了解不是很多,这次活动中的lpc55s69-EVK让我第一次接触到了恩智浦的lpc系列单片机。在学习过程中我发现,虽然网络上关于lpc单片机的资料相对于stm32要少很多,但是恩智浦官方的英文资料和例程却十分详细,整个EVK板十分容易上手。虽然毕业之后从事的工作和嵌入式关系不大,但我还是挺喜欢嵌入式的,感谢funpack这一系列的活动给我们带来了各种厂家的不同的开发板。这种完成任务就能免费拿板子的活动能让我这种懒人在工作之外有动力去尝试不同的芯片、不同的开发环境。希望日后还会有funpack类似的活动。