0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

USB一线通监控副屏设计方案

恩智浦MCU加油站 来源:RT-Thread社区 2024-11-28 09:45 次阅读

在2024年全国大学生嵌入式芯片与系统设计竞赛中,各大高校学子纷纷展现出卓越的创新能力和扎实的威廉希尔官方网站 功底。今天,特别为大家分享获奖作品——USB一线通监控副屏,它以其独特的设计和实用的功能赢得广泛好评与认可。

原文链接:https://club.rt-thread.org/ask/article/fd0a9bdab79b7c65.html

环境搭建

环境变量配置

为了提高一些编译的速度,选择了在Linux系统下进行开发,在Linux上开发N947需要先安装 env 工具https://github.com/RT-Thread/env,按照说明文档进行安装即可,然后配置一些环境变量:

其中 /opt/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin 是自己的编译工具链的路径,/home/book/rt-thread 是rt-thread根目录的路径:

 source ~/.env/env.sh
 export RTT_CC=gcc
 export RTT_ROOT=/home/book/rt-thread
 export RTT_DIR=/home/book/rt-thread
 export RTT_EXEC_PATH=/opt/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin
exportPATH=$PATH:$RTT_EXEC_PATH

如果需要将N947的例程从rt-thread的根文件夹中独立出来的话,需要删除工程中Kconfig文件的这行代码:

5132eec6-ad23-11ef-93f3-92fbcf53809c.png

代码高亮

这里使用VSCode中的Clang插件,代码高亮和补全可以通过使用编译时候生成的 compile_commands.json文件来实现,而RT-Thread的工程是采用的scons工具,所以可以使用scons_compiledb这个python包来生成compile_commands.json 实现代码高亮,修改过的SConstruct文件如下:

import os
import sys
import rtconfig
import scons_compiledb
if os.getenv('RTT_ROOT'):
    RTT_ROOT = os.getenv('RTT_ROOT')
else:
    RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../../..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
try:
    from building import *
except:
    print('Cannot found RT-Thread root directory, please check RTT_ROOT')
    print(RTT_ROOT)
    exit(-1)
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
if rtconfig.PLATFORM == 'armcc':
    env = Environment(tools = ['mingw'],
        AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
        CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
        CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
        AR = rtconfig.AR, ARFLAGS = '-rc',
        LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS,
        # overwrite cflags, because cflags has '--C99'
        CXXCOM = '$CXX -o $TARGET --cpp -c $CXXFLAGS $_CCCOMCOM $SOURCES')
else:
    env = Environment(tools = ['mingw'],
        AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
        CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
        CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
        AR = rtconfig.AR, ARFLAGS = '-rc',
        LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS,
        CXXCOM = '$CXX -o $TARGET -c $CXXFLAGS $_CCCOMCOM $SOURCES')
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
scons_compiledb.enable(env)
env.CompileDb()
if rtconfig.PLATFORM in ['iccarm']:
    env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES'])
    env.Replace(ARFLAGS = [''])
    env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map')
Export('RTT_ROOT')
Export('rtconfig')
SDK_ROOT = os.path.abspath('./')
if os.path.exists(SDK_ROOT + '/Libraries'):
    libraries_path_prefix = SDK_ROOT + '/Libraries'
else:
    libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/Libraries'
SDK_LIB = libraries_path_prefix
Export('SDK_LIB')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
objs.extend(SConscript(os.path.join(libraries_path_prefix, 'drivers', 'SConscript')))
# include cmsis
objs.extend(SConscript(os.path.join(libraries_path_prefix, rtconfig.BSP_LIBRARY_TYPE, 'SConscript')))
# make a building
DoBuilding(TARGET,objs)

最终搭建完成的效果如下所示,代码高亮十分且方便查看代码:

5137d936-ad23-11ef-93f3-92fbcf53809c.jpg

LVGL适配

屏幕拓展板

FRDM-MCXN947这个开发板预留了一个FlexIO接口可以适配8080的并口屏,于是做了一个屏幕拓展板,把手里闲置的屏幕用起来:

513f1430-ad23-11ef-93f3-92fbcf53809c.jpg

实物如下,触摸排线座子有点偏下,不过不影响功能:

51531732-ad23-11ef-93f3-92fbcf53809c.jpg

屏幕手册说明分辨率是240*320驱动芯片是ST7789V、触摸芯片是FT6336G,而官方的SDK中是有ST7796和FT5406的驱动代码的,后续还需要稍作修改:515a9aac-ad23-11ef-93f3-92fbcf53809c.jpg

驱动适配

在官方的SDK中有ST7796和FT5406的驱动程序,直接移植过来即可,同时也把 EDMA和SMARTDMA的驱动复制了过来,修改一下屏幕的初始化序列即可驱动屏幕:

5167f760-ad23-11ef-93f3-92fbcf53809c.jpg

LVGL 适配

将SDK中的 lvgl_support复制到工程中,修改屏幕的宽高为240*320:

51727fb4-ad23-11ef-93f3-92fbcf53809c.jpg

然后在board中新建一个lv_conf.h文件,填入关于LVGL的一些配置,因为许多配置在menuconfig中有所设置,所以这里的配置项并不多:

#ifndef LV_CONF_H
#define LV_CONF_H
#include 
#define LV_USE_SYSMON           1
#define LV_USE_PERF_MONITOR     0
#define LV_COLOR_DEPTH          16
#define LV_HOR_RES_MAX          240
#define LV_VER_RES_MAX          320
#define LV_COLOR_16_SWAP        0
#define BSP_USING_LVGL_BENCHMARK_DEMO
#define BSP_USING_LVGL_WIDGETS_DEMO
#ifdef BSP_USING_LVGL_DAVE2D
    #define LV_USE_DRAW_DAVE2D      1
#endif
#ifdef BSP_USING_LVGL_WIDGETS_DEMO
    #define LV_USE_DEMO_WIDGETS 1
    #define LV_DEMO_WIDGETS_SLIDESHOW   0
#endif  /* BSP_USING_LVGL_WIDGETS_DEMO */
/*Benchmark your system*/
#ifdef BSP_USING_LVGL_BENCHMARK_DEMO
    #define LV_USE_DEMO_BENCHMARK 1
    /*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
    #define LV_DEMO_BENCHMARK_RGB565A8  1
    #define LV_FONT_MONTSERRAT_14       1
    #define LV_FONT_MONTSERRAT_24       1
#endif  /* BSP_USING_LVGL_BENCHMARK_DEMO */
/*Stress test for LVGL*/
#ifdef BSP_USING_LVGL_STRESS_DEMO
    #define LV_USE_DEMO_STRESS 1
#endif  /* BSP_USING_LVGL_STRESS_DEMO */
/*Render test for LVGL*/
#ifdef BSP_USING_LVGL_RENDER_DEMO
    #define LV_USE_DEMO_RENDER 1
#endif  /* BSP_USING_LVGL_RENDER_DEMO */
/*Music player demo*/
#ifdef BSP_USING_LVGL_MUSIC_DEMO
    #define LV_USE_DEMO_MUSIC 1
    #define LV_DEMO_MUSIC_SQUARE    1
    #define LV_DEMO_MUSIC_LANDSCAPE 0
    #define LV_DEMO_MUSIC_ROUND     0
    #define LV_DEMO_MUSIC_LARGE     0
    #define LV_DEMO_MUSIC_AUTO_PLAY 0
    #define LV_FONT_MONTSERRAT_12   1
    #define LV_FONT_MONTSERRAT_16   1
#endif  /* BSP_USING_LVGL_MUSIC_DEMO */
#endif

‍复制过来的lvgl_support中有对FreeRTOS的支持,这里将FreeRTOS的API修改为RTT的API,例如如下这段代码:

517ce99a-ad23-11ef-93f3-92fbcf53809c.jpg

并且 N947 的驱动程序有EDMA + FlexIO和SMARTDMA + FlexIO两种驱动方式,具体区别不太了解,不过可以运行LVGL的Benchmark测试来看下结果,左边是SMARTDMA运行的结果,右边是EDMA的结果,可以看到前者的FPS更高。后续也就继续采用SMARTDMA + FlexIO的驱动方式:

51848862-ad23-11ef-93f3-92fbcf53809c.jpg

界面设计

使用操作简便的GUI Guider设计一个界面,生成绘制界面的代码,然后添加到工程中:

5197a032-ad23-11ef-93f3-92fbcf53809c.jpg

还需要修改工程文件夹中的 rtconfig.py,增加一个 LV_LVGL_H_INCLUDE_SIMPLE 的预定义,因为生成的代码默认包含lvgl.h是#include "lvgl/lvgl.h",

CFLAGS = DEVICE + ' -Wall -D__FPU_PRESENT -DLV_LVGL_H_INCLUDE_SIMPLE'

最终适配完成的LVGL代码和GUI Guider的代码目录如下,LVGL 的UI绘制代码段如图右边所示,具体代码可见开源地址:

519be750-ad23-11ef-93f3-92fbcf53809c.jpg

USB通讯

适配 CDC

完成了下位机的界面的初始化绘制,后续的任务当然就是怎么把数据采集并发送给下位机来更新界面的数据了,下面先完成USB的通讯,这里使用的是RTT官方推荐的CherryUSB这个开源USB协议栈:

51a83d84-ad23-11ef-93f3-92fbcf53809c.jpg

将如下链接中的适配代码复制到工程中:

https://github.com/CherryUSB/cherryusb_mcx

因为传输的数据比较单一,这里使用串口屏的思路,直接用CDC_ACM的通讯方式,也就是在上位机显示为一个USB转串口设备,直接使用串口API完成通讯。

将RTT根目录中 rt-thread/components/drivers/usb/cherryusb/demo文件夹中的CDC_ACM例程复制到工程中,并且把根目录中的这两行代码屏蔽:

51b3d91e-ad23-11ef-93f3-92fbcf53809c.jpg

修改工程中的cherryusb_port.c文件,添加对CDC_ACM的支持:

/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024/04/23     sakumisu    first version
 */
#include 
#include 
/* low level init here, this has implemented in cherryusb */
/* low level deinit here, this has implemented in cherryusb */
#ifdef RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
int cherryusb_devinit(void)
{
    // extern void cherryusb_devinit(uint8_t busid, uintptr_t reg_base);
    extern void cdc_acm_init(uint8_t busid, uintptr_t reg_base);
    cdc_acm_init(0, USBHS1__USBC_BASE);
    return 0;
}
INIT_COMPONENT_EXPORT(cherryusb_devinit);
#endif
#ifdef RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
int cherryusb_devinit(void)
{
    extern void msc_ram_init(uint8_t busid, uintptr_t reg_base);
    msc_ram_init(0, USBHS1__USBC_BASE);
    return 0;
}
INIT_COMPONENT_EXPORT(cherryusb_devinit);
#endif
#ifdef RT_CHERRYUSB_HOST
#include "usbh_core.h"
int cherryusb_hostinit(void)
{
    usbh_initialize(0, USBHS1__USBC_BASE);
    return 0;
}
INIT_COMPONENT_EXPORT(cherryusb_hostinit);
#endif

将刚才复制到工程中的CDC_ACM 的 demo程序中端点收发的程序做如下修改,增加对于输入信息的回显:

oid usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    USB_LOG_RAW("actual out len:%d
", nbytes);
    /* setup next out ep read transfer */
    usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
    for (int i = 0; i < nbytes; i++) {
        printf("%02x ", read_buffer[i]);
    }
    printf("
");
}

验证

然后插上开发板的USB HS那个USB接口,用串口工具发个数据包:

51be4cf0-ad23-11ef-93f3-92fbcf53809c.jpg

可以看到已经识别成了USB串行设备,PID 和VID也是我自己设置的0xE6E9和0x1122,后续上位机与开发板建立通讯锁定COM号就是依靠PID VID来查询实现,使用串口工具给开发板发送的数据也可以正常接收到。

上位机 时间原因上位机做的比较简单,实现了如下几个功能:

读取电脑的CPU、GPU的占用率和温度信息、获取当前时间

根据VID、PID查询COM来与开发板通讯,下发采集数据与时间

增加帧头后发送到下位机,固定长度32+2个字节

51c9d016-ad23-11ef-93f3-92fbcf53809c.jpg

下位机数据更新 在开发板端增加一个thread来负责把USB接收到的数据更新到屏幕上面,使用LVGL的API直接修改数据即可,代码如下:

数据结构体:

typedef struct
{
    uint16_t cpu_usage;
    uint16_t mem_usage;
    uint16_t gpu_usage;
    uint16_t cpu_freq;
    uint16_t cpu_temperature;
    uint16_t gpu_temperature;
    uint16_t board_temperature;
} monitor_info_u16_t;
typedef struct {
    uint16_t wYear;
    uint16_t wMonth;
    uint16_t wDayOfWeek;
    uint16_t wDay;
    uint16_t wHour;
    uint16_t wMinute;
    uint16_t wSecond;
    uint16_t wMilliseconds;
} mytime_t;

在USB端点输出的回调函数中增加消息队列发送函数:
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    USB_LOG_RAW("actual out len:%d
", nbytes);
    /* setup next out ep read transfer */
    usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048);
    for (int i = 0; i < nbytes; i++) {
        printf("%02x ", read_buffer[i]);
    }
    printf("
");
    if (34 == nbytes)
    {
        rt_mq_send(&usb_mq, read_buffer, 34);
    }
}

main函数中的接收消息队列:
uint8_t read_buffer[128];
while (1)
{
    /* 从消息队列中接收消息 */
    if (rt_mq_recv(&usb_mq, read_buffer, 34, RT_WAITING_FOREVER) > 0)
    {
        mytime_t* p_time_u16 = (mytime_t*)(read_buffer + 2);
        monitor_info_u16_t* p_info_u16 = (monitor_info_u16_t *)(read_buffer + 2 + sizeof(mytime_t));
        rt_kprintf("wYear         %u
", p_time_u16->wYear);
        rt_kprintf("wMonth        %u
", p_time_u16->wMonth);
        rt_kprintf("wDayOfWeek    %u
", p_time_u16->wDayOfWeek);
        rt_kprintf("wDay          %u
", p_time_u16->wDay);
        rt_kprintf("wHour         %u
", p_time_u16->wHour);
        rt_kprintf("wMinute       %u
", p_time_u16->wMinute);
        rt_kprintf("wSecond       %u
", p_time_u16->wSecond);
        rt_kprintf("wMilliseconds %u
", p_time_u16->wMilliseconds);
        rt_kprintf("cpu_usage         %u
", p_info_u16->cpu_usage);
        rt_kprintf("mem_usage         %u
", p_info_u16->mem_usage);
        rt_kprintf("gpu_usage         %u
", p_info_u16->gpu_usage);
        rt_kprintf("cpu_freq          %u
", p_info_u16->cpu_freq);
        rt_kprintf("cpu_temperature   %u
", p_info_u16->cpu_temperature);
        rt_kprintf("gpu_temperature   %u
", p_info_u16->gpu_temperature);
        rt_kprintf("board_temperature %u
", p_info_u16->board_temperature);
        lv_label_set_text_fmt(guider_ui.screen_label_cpu_temp, "%2d", p_info_u16->cpu_temperature);
        lv_label_set_text_fmt(guider_ui.screen_label_gpu_temp, "%2d", p_info_u16->gpu_temperature);
        lv_label_set_text_fmt(guider_ui.screen_label_cpu_load, "%2d", p_info_u16->cpu_usage);
        lv_label_set_text_fmt(guider_ui.screen_label_gpu_load, "%2d", p_info_u16->gpu_usage);
        lv_arc_set_value(guider_ui.screen_arc_gpu_load, p_info_u16->gpu_usage);
        lv_arc_set_value(guider_ui.screen_arc_gpu_temp, p_info_u16->gpu_temperature);
        lv_label_set_text_fmt(guider_ui.screen_time, "%02d:%02d", p_time_u16->wHour, p_time_u16->wMinute);
        lv_label_set_text_fmt(guider_ui.screen_date, "%02d.%02d.%02d", p_time_u16->wYear, p_time_u16->wMonth, p_time_u16->wDay);
    }
}

成品效果

目前支持了对于时间、日期、CPU、GPU 的占用率和温度信息,其他的信息还在完善当中。

51def28e-ad23-11ef-93f3-92fbcf53809c.jpg

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5082

    文章

    19107

    浏览量

    304833
  • usb
    usb
    +关注

    关注

    60

    文章

    7938

    浏览量

    264487
  • Linux系统
    +关注

    关注

    4

    文章

    593

    浏览量

    27392
  • 代码
    +关注

    关注

    30

    文章

    4780

    浏览量

    68527
  • RT-Thread
    +关注

    关注

    31

    文章

    1285

    浏览量

    40089

原文标题:【24嵌入式设计大赛获奖文章】USB 一线通监控副屏

文章出处:【微信号:NXP_SMART_HARDWARE,微信公众号:恩智浦MCU加油站】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    4.3寸【串口案例】电脑应用

    为HardwareMonitor_V1.0。HardwareMonitor_V1.0软件主要用于UI界面的编辑与烧录。 如图所示,个制作完成的UI工程。 设置完变量地址后即可实现机箱硬件
    发表于 01-31 11:12

    BeagleBone Black USB一线通(1)

    eMMC的内容。二、启动与终端 购置的板子,附送的USB转串口线,是非常有用的。连接u***串口的GND、RXD、TXD,对应到 BBB板上J1的1脚、5脚、4脚。打开串口终端,设置速率115200
    发表于 10-22 17:01

    BeagleBone Black USB一线通(3)

    20来寸的显示器上,还是有些不协调。索性我们使用图形界面远程登陆,实现BB-Black的图形显示。这样的话,仍然是使用那条连接到USB-OTG上面的多接口USB线缆,就可以实现一线通的目的。功能完备又
    发表于 10-22 17:05

    求购套无线视频监控设计方案

    求购套无线视频监控设计方案, 要求有ST芯片的硬件设计经验和firmware开发经验。有意者请联系qq 3045137109
    发表于 01-28 10:52

    介绍种视频监控系统的设计方案

    介绍种视频监控系统的设计方案
    发表于 05-31 07:07

    分享份智能视频监控应用系统的设计方案

    分享份智能视频监控应用系统的设计方案
    发表于 06-08 06:49

    种基于ARM的视频监控系统的设计方案

    本文介绍了种基于ARM的视频监控系统的设计方案,采用软压缩算法,讨论了系统的硬件和软件设计。
    发表于 06-08 06:27

    lcd2004一线仿真

    )图5四,编辑main.c 代码如Proteus8.9 VSM Studio GCC编译器仿真STM32F407ZGT6系列015_lcd2004一线(如下图6所示)图6五,Main.c 代码:/* Main.c file generated by New Projec
    发表于 12-13 07:20

    基于TINI的一线制网络互连威廉希尔官方网站

    概述 TINI的基本概念和工作原理,分析 TINI的软件环境;简述基于一线制威廉希尔官方网站 的温度型iButton DS1920和小型气象仪,给出利用 TINI实现一线制网络与 Internet连接的应用实例。
    发表于 04-13 10:15 20次下载

    一线通校园智能寻址调频广播系统解决方案

    一线通校园智能寻址调频广播系统解决方案,有兴趣的同学可以下载学习
    发表于 05-04 15:48 0次下载

    LED显示厂商:全面奋战一线市场,锁定用户范围

    “当前一线市场不是变差了,而是对手变强了;同样地,一线需求不是变少了,而是用户要求更多了。..。..。”那么,面对这种持续的变化,LED显示企业如何能更好的抢夺用户并转化为产品销量呢?
    发表于 07-30 13:06 726次阅读

    Switch通过Type-C一线直连汽车中控方案

    5 月21 日消息,今日新能源造车势力官方微博剧透新车型。新配置。汽车中控,还有驾娱乐,后舱娱乐,均可以通过 Type-C 接口一线
    的头像 发表于 05-21 19:04 5114次阅读
    Switch通过Type-C<b class='flag-5'>一线</b>直连汽车中控<b class='flag-5'>屏</b><b class='flag-5'>方案</b>

    方案发布|吉方智慧零售一线通可扩展方案

    目前在智能零售行业,触摸收银体机由于其外观符合主流审美、触操作方便,逐渐成为收银终端的主流产品,其主要特点有:双屏、双触摸;也带扩展功能,可接摄像头、刷卡器等设备;产品外观设计
    发表于 08-26 15:00 554次阅读
    <b class='flag-5'>方案</b>发布|吉方智慧零售<b class='flag-5'>一线通</b>可扩展<b class='flag-5'>方案</b>

    typec显示器方案推荐 分别有什么特点

    支持typec一线通的显示方案就是通过条typec线把电脑或者手机画面直接投到显示上,这需
    的头像 发表于 11-04 16:11 6229次阅读

    USB 一线通监控

    环境搭建环境变量配置为了提高些编译的速度,选择了在Linux系统下进行开发,在Linux上开发N947需要先安装e
    的头像 发表于 12-07 01:10 138次阅读
    <b class='flag-5'>USB</b> <b class='flag-5'>一线通</b><b class='flag-5'>监控</b><b class='flag-5'>副</b><b class='flag-5'>屏</b>