@zhoudaxia3000 这么看好像是8+1=9和11+1=12,有没有懂的老哥说一下什么情况
bigfly 发布的帖子
-
回复: RT-Thread on D1H. LCD work, USB in progress.
@ylyamin 在 RT-Thread on D1H. LCD work, USB in progress. 中说:
I’m writing a series of articles covering the knowledge and experience I’ve gained:
D1-1. Introduction - Motivation and intention.
D1-2. Boot process - Existing Allwinner D1H bootloaders best practice in example with booting Linux and RT-Thread, also JTAG and GDB.
D1-3. RT-Thread overview and Build - Overview of RT-Thread structure and libraries. Compile RT-Thread for Allwinner D1H platform.
D1-4. Makefile and Hardware changes - My repository structure, Makefile and Hardware changes was needed to be done.
D1-5. LCD Display driver - Display driver for DevTerm R-01, uConsole R-01 and Sipeed Lichee RV.
D1-6. USB Keyboard - USB Keyboard driver for ClockworkPi DevTerm, still not working.Detailed article,nice
-
回复: 更改分区
@yyyyppppp Tina Linux 存储介质切换:eMMC,SPI NAND,SPI NOR,SD Card,SD NAND
https://bbs.aw-ol.com/topic/1701/share/1 -
更换lcd屏幕
我手上有一块480854的屏幕,现在想测试一下 在.fex文件中我发现,只要我把下面的这两个参数改成480854,在后面打包、烧录运行时就会出现问题
fb0_width = 480 fb0_height = 854
问题如下:
/etc/init.d/rcS: line 60: 1231 Segmentation fault insmod /system/vendor/modules/mali.ko
挂载mali.ko文件显示段错误,具体打印消息如下:
我这种情况是gpu不能用吗?我应该怎么解决这个问题[ 4.223285] Mali: Enable gpu power successfully. [ 4.223364] Mali: Set gpu frequency to 384 MHz [ 4.223434] Mali: Mali GPU initialization finished. [ 4.223881] Mali: ERR: /home/forlinx/work/lichee/linux-3.10/modules/gpu/mali400/kernel_mode/driver/src/devicedrv/mali/common/mali_mem_validation.c [ 4.223892] mali_mem_validation_add_range() 35 Failed to add frame buffer memory; incorrect alignment [ 4.223906] Mali: ERR: /home/forlinx/work/lichee/linux-3.10/modules/gpu/mali400/kernel_mode/driver/src/devicedrv/mali/common/mali_kernel_core.c [ 4.223912] mali_parse_config_memory() 700 Failed to register frame buffer memory region [ 4.224137] Unable to handle kernel paging request at virtual address 00100104 [ 4.224146] pgd = e1938000 [ 4.224152] [00100104] *pgd=6232e831, *pte=00000000, *ppte=00000000 [ 4.224169] Internal error: Oops: 817 [#1] PREEMPT SMP ARM [ 4.224177] Modules linked in: mali(O+) gt9xxnew_ts [ 4.224196] CPU: 0 PID: 1231 Comm: insmod Tainted: G W O 3.10.65 #446 [ 4.224205] task: e2f47a80 ti: e183a000 task.ti: e183a000 [ 4.224221] PC is at unregister_shrinker+0x30/0x5c [ 4.224232] LR is at _raw_spin_unlock_irqrestore+0x38/0x58 [ 4.224241] pc : [<c00d4614>] lr : [<c06ff900>] psr: 40070013 sp : e183bc80 ip : e183bc20 fp : e183bc94 [ 4.224249] r10: e22a9664 r9 : 00000001 r8 : bf03f564 [ 4.224257] r7 : 00000000 r6 : e2e9d600 r5 : c0ad4eb0 r4 : bf03f364 [ 4.224264] r3 : 00200200 r2 : 00100100 r1 : 60070013 r0 : c0ad4eb0 [ 4.224273] Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 4.224280] Control: 10c53c7d Table: 6193806a DAC: 00000015 [ 4.224286] PC: 0xc00d4594: [ 4.224292] 4594 e24cb004 e52de004 e8bd4000 e3a03000 e1a05000 e59f4030 e5803014 e1a00004 [ 4.224316] 45b4 eb18a540 e5943014 e285200c e2841010 e5842014 e585100c e1a00004 e5853010 [ 4.224339] 45d4 e5832000 ebfdd6c9 e89da830 c0ad4eb0 e1a0c00d e92dd830 e24cb004 e52de004 [ 4.224362] 45f4 e8bd4000 e1a04000 e59f5030 e1a00005 eb18a52c e5943010 e1a00005 e594200c [ 4.224385] 4614 e5823004 e5832000 e59f3014 e584300c e59f3010 e5843010 ebfdd6b4 e89da830 [ 4.224408] 4634 c0ad4eb0 00100100 00200200 e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000 [ 4.224431] 4654 e1a03001 e590214c e1a00003 e59f1004 eb014a32 e89da800 c00d4670 e1a0c00d [ 4.224454] 4674 e92dd8f0 e24cb004 e24dd008 e52de004 e8bd4000 e59f5074 e3e03000 e50b3024 [ 4.224479] LR: 0xc06ff880: [ 4.224485] f880 e52de004 e8bd4000 f57ff05b e1d030b0 e2833001 e1c030b0 f57ff04f e320f004 [ 4.224508] f8a0 e3a00001 eb000a32 e1a0300d e3c33d7f e3c3303f e5933000 e3130002 089da800 [ 4.224531] f8c0 ebfffc6d e89da800 e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000 f57ff05b [ 4.224554] f8e0 e1d030b0 e2833001 e1c030b0 f57ff04f e320f004 e121f001 e3a00001 eb000a1c [ 4.224577] f900 e1a0300d e3c33d7f e3c3303f e5933000 e3130002 089da800 ebfffc57 e89da800 [ 4.224600] f920 e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000 f57ff05b e1d030b0 e2833001 [ 4.224623] f940 e1c030b0 f57ff04f e320f004 f1080080 e3a00001 eb000a06 e1a0300d e3c33d7f [ 4.224646] f960 e3c3303f e5933000 e3130002 089da800 ebfffc41 e89da800 e1a0c00d e92dd800 [ 4.224670] SP: 0xe183bc00: [ 4.224676] bc00 c003d4d0 c06ff4e0 e183bc2c c06ff900 e183bc2c e183bc20 c00d4614 40070013 [ 4.224699] bc20 ffffffff e183bc6c e183bc94 e183bc38 c0700098 c000a16c c0ad4eb0 60070013 [ 4.224722] bc40 00100100 00200200 bf03f364 c0ad4eb0 e2e9d600 00000000 bf03f564 00000001 [ 4.224744] bc60 e22a9664 e183bc94 e183bc20 e183bc80 c06ff900 c00d4614 40070013 ffffffff [ 4.224767] bc80 bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000 [ 4.224790] bca0 e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8 bf0138a0 e183bcdc e183bcc8 [ 4.224813] bcc0 bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c e183bce0 bf01acc4 bf01aafc [ 4.224836] bce0 00000001 bf03ff88 00000000 e2e9d600 00000000 bf03f564 00000001 e22a9664 [ 4.224859] IP: 0xe183bba0: [ 4.224865] bba0 00000000 c06ff958 e183bbc4 e1876b80 00000004 c0bec00c e183bc04 e183bbc8 [ 4.224888] bbc0 c003d04c c004dec8 e183bbfc 00000000 c00fcbb0 e1876b80 e23e75c0 e1876b80 [ 4.224910] bbe0 e183bc24 e183bc30 e1876bc0 e1876b90 00000005 c003d4d0 e183bc6c e183bc08 [ 4.224933] bc00 c003d4d0 c06ff4e0 e183bc2c c06ff900 e183bc2c e183bc20 c00d4614 40070013 [ 4.224956] bc20 ffffffff e183bc6c e183bc94 e183bc38 c0700098 c000a16c c0ad4eb0 60070013 [ 4.224979] bc40 00100100 00200200 bf03f364 c0ad4eb0 e2e9d600 00000000 bf03f564 00000001 [ 4.225001] bc60 e22a9664 e183bc94 e183bc20 e183bc80 c06ff900 c00d4614 40070013 ffffffff [ 4.225024] bc80 bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000 [ 4.225048] FP: 0xe183bc14: [ 4.225054] bc14 e183bc20 c00d4614 40070013 ffffffff e183bc6c e183bc94 e183bc38 c0700098 [ 4.225077] bc34 c000a16c c0ad4eb0 60070013 00100100 00200200 bf03f364 c0ad4eb0 e2e9d600 [ 4.225100] bc54 00000000 bf03f564 00000001 e22a9664 e183bc94 e183bc20 e183bc80 c06ff900 [ 4.225122] bc74 c00d4614 40070013 ffffffff bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 [ 4.225145] bc94 c00d45f0 bf040434 00000000 e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8 [ 4.225168] bcb4 bf0138a0 e183bcdc e183bcc8 bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c [ 4.225191] bcd4 e183bce0 bf01acc4 bf01aafc 00000001 bf03ff88 00000000 e2e9d600 00000000 [ 4.225213] bcf4 bf03f564 00000001 e22a9664 e183bd2c e183bd10 bf01035c c0040e8c bf040468 [ 4.225237] R0: 0xc0ad4e30: [ 4.225243] 4e30 00000020 00000000 000001f4 0000000a 00000000 00000000 00000000 61666544 [ 4.225264] 4e50 00746c75 65646f4e 00000000 656e6f5a 00000000 00000001 00000000 c0ad4e6c [ 4.225286] 4e70 c0ad4e6c 00000000 00000000 0000086f c0c1562c c0c1562c ffff8ca3 c0c15101 [ 4.225309] 4e90 c00ce330 00000000 ffffffff 00000014 0000000a 00000070 00000bb8 000001f4 [ 4.225331] 4eb0 ffffffff 003d003d c0ad4eb8 c0ad4eb8 e2c3ee64 e2030a64 0000003c c00d44f4 [ 4.225353] 4ed0 c00a708c c00a708c c00a708c c00d4444 c00a708c c00a708c c00a708c c00d4280 [ 4.225376] 4ef0 c00a708c c00a708c c00a708c c00d4208 c00a708c c00a708c c00a708c c00d4388 [ 4.225399] 4f10 c00a708c c00a708c c00a708c c00d41bc c00a708c c00a708c c00a708c c00d42f8 [ 4.225424] R5: 0xc0ad4e30: [ 4.225430] 4e30 00000020 00000000 000001f4 0000000a 00000000 00000000 00000000 61666544 [ 4.225452] 4e50 00746c75 65646f4e 00000000 656e6f5a 00000000 00000001 00000000 c0ad4e6c [ 4.225473] 4e70 c0ad4e6c 00000000 00000000 0000086f c0c1562c c0c1562c ffff8ca3 c0c15101 [ 4.225496] 4e90 c00ce330 00000000 ffffffff 00000014 0000000a 00000070 00000bb8 000001f4 [ 4.225518] 4eb0 ffffffff 003d003d c0ad4eb8 c0ad4eb8 e2c3ee64 e2030a64 0000003c c00d44f4 [ 4.225541] 4ed0 c00a708c c00a708c c00a708c c00d4444 c00a708c c00a708c c00a708c c00d4280 [ 4.225564] 4ef0 c00a708c c00a708c c00a708c c00d4208 c00a708c c00a708c c00a708c c00d4388 [ 4.225587] 4f10 c00a708c c00a708c c00a708c c00d41bc c00a708c c00a708c c00a708c c00d42f8 [ 4.225611] R6: 0xe2e9d580: [ 4.225617] d580 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225638] d5a0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225658] d5c0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225679] d5e0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225700] d600 e2e9ec40 ffffffff 00000000 00000000 00000000 e2e97740 e2e9ec40 e2e9d41c [ 4.225722] d620 e2e9d81c e2d0434c e2d04340 c0b9cfd8 e2da48c8 00000002 00000007 00000000 [ 4.225744] d640 00000000 00000000 00000000 e2e9d64c e2e9d64c e2f47a80 00000000 c0b9d290 [ 4.225766] d660 bf03f564 e20532c0 00000000 00000020 00050005 e2e9d474 e2e9d874 7fffffff [ 4.225790] R10: 0xe22a95e4: [ 4.225796] 95e4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 e22a95c0 [ 4.225817] 9604 e22a9604 e22a9604 bf03fe58 00000000 c0adf9c8 e219d3c8 00000001 00000003 [ 4.225839] 9624 00000000 00000000 00000000 00000000 00000000 00000000 00000000 e22a9600 [ 4.225861] 9644 00000001 e22a9d00 00000124 00000024 bf031518 c0078a5c 00000000 00000000 [ 4.225883] 9664 00000000 00000000 00000000 00000000 00000000 00000000 00000000 74636573 [ 4.225904] 9684 736e6f69 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225925] 96a4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7274732e [ 4.225946] 96c4 00626174 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 4.225970] Process insmod (pid: 1231, stack limit = 0xe183a238) [ 4.225978] Stack: (0xe183bc80 to 0xe183c000) [ 4.225990] bc80: bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000 [ 4.226002] bca0: e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8 bf0138a0 e183bcdc e183bcc8 [ 4.226014] bcc0: bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c e183bce0 bf01acc4 bf01aafc [ 4.226025] bce0: 00000001 bf03ff88 00000000 e2e9d600 00000000 bf03f564 00000001 e22a9664 [ 4.226037] bd00: e183bd2c e183bd10 bf01035c c0040e8c bf040468 bf040468 e2e9d600 00000000 [ 4.226048] bd20: e183bd4c e183bd30 bf01c390 bf01abcc e2e9d610 c0c5e31c 00000000 00000001 [ 4.226060] bd40: e183bd5c e183bd50 c0311a48 bf01c2e8 e183bd84 e183bd60 c031061c c0311a30 [ 4.226072] bd60: e2e9d610 e2e9d644 bf03f564 c0b9d290 00000000 00000001 e183bda4 e183bd88 [ 4.226084] bd80: c031082c c0310564 00000000 bf03f564 c03107b4 c0b9d290 e183bdcc e183bda8 [ 4.226095] bda0: c030eb1c c03107c0 e2d1e3dc e2e97774 c06ff8a8 bf03f564 00000000 e2782ac0 [ 4.226107] bdc0: e183bddc e183bdd0 c03100e4 c030eaac e183be04 e183bde0 c030fc80 c03100c8 [ 4.226119] bde0: bf034a1b e183bdf0 bf03f564 bf01c540 c0bf3700 bf03fe58 e183be24 e183be08 [ 4.226132] be00: c0310e3c c030fb98 e183a000 bf01c540 c0bf3700 bf03fe58 e183be34 e183be28 [ 4.226144] be20: c031203c c0310d9c e183be4c e183be38 bf01c55c c0311ff4 e183a000 bf01c540 [ 4.226156] be40: e183be8c e183be50 c000a4d8 bf01c54c c00f4e2c e183bf48 00000001 bf03fe10 [ 4.226167] be60: bf03fe58 e22a9640 e183be8c e183bf48 00000001 bf03fe10 bf03fe58 e22a9640 [ 4.226179] be80: e183bf44 e183be90 c007b3ec c000a43c bf03fe1c 00007fff c00772ec c0be8c40 [ 4.226191] bea0: 000ad8e5 bf03ff74 eb765f84 e183beb8 c0709f2c c0078b88 e22a9648 00000000 [ 4.226203] bec0: bf03fe1c e183a000 c00f5218 c00f49bc ffffffff c007b9f8 c007b9f8 bf03153c [ 4.226213] bee0: 0000000b bf031594 00000003 00000000 00000000 00000000 00000000 00000000 [ 4.226224] bf00: 00000000 00000000 00000000 00000000 00000000 00000000 ffffffff b6952008 [ 4.226236] bf20: 000ad8e5 00442fd4 00000080 c000fac8 e183a000 00000000 e183bfa4 e183bf48 [ 4.226248] bf40: c007ba74 c0079e44 eb323000 00442fd4 eb7655ac eb65dc38 eb66a4dc 00030958 [ 4.226258] bf60: 0003b498 00000000 00000000 00000000 0000003f 00000040 00000028 00000000 [ 4.226270] bf80: 00000016 00000000 c0013994 00000000 00000069 bee8ede4 00000000 e183bfa8 [ 4.226281] bfa0: c000f880 c007b9ac 00000000 00000069 b6952008 00442fd4 000ad8e5 00000000 [ 4.226292] bfc0: 00000000 00000069 bee8ede4 00000080 00000001 bee8edec b6f20000 0009b9aa [ 4.226304] bfe0: b6e29901 bee8ea98 0002810f b6e29908 80080030 b6952008 000027ff 00002800 [ 4.226421] [<c00d4614>] (unregister_shrinker+0x30/0x5c) from [<bf0138b4>] (mali_mem_os_term+0x20/0xd0 [mali]) [ 4.226574] [<bf0138b4>] (mali_mem_os_term+0x20/0xd0 [mali]) from [<bf0124d8>] (mali_memory_terminate+0x20/0x34 [mali]) [ 4.226733] [<bf0124d8>] (mali_memory_terminate+0x20/0x34 [mali]) from [<bf01aba4>] (mali_terminate_subsystems+0xb4/0xd0 [mali]) [ 4.226904] [<bf01aba4>] (mali_terminate_subsystems+0xb4/0xd0 [mali]) from [<bf01acc4>] (mali_initialize_subsystems+0x104/0x518 [mali]) [ 4.227076] [<bf01acc4>] (mali_initialize_subsystems+0x104/0x518 [mali]) from [<bf01c390>] (mali_probe+0xb4/0x220 [mali]) [ 4.227174] [<bf01c390>] (mali_probe+0xb4/0x220 [mali]) from [<c0311a48>] (platform_drv_probe+0x24/0x28) [ 4.227191] [<c0311a48>] (platform_drv_probe+0x24/0x28) from [<c031061c>] (driver_probe_device+0xc4/0x208) [ 4.227205] [<c031061c>] (driver_probe_device+0xc4/0x208) from [<c031082c>] (__driver_attach+0x78/0x9c) [ 4.227219] [<c031082c>] (__driver_attach+0x78/0x9c) from [<c030eb1c>] (bus_for_each_dev+0x7c/0xa0) [ 4.227233] [<c030eb1c>] (bus_for_each_dev+0x7c/0xa0) from [<c03100e4>] (driver_attach+0x28/0x30) [ 4.227247] [<c03100e4>] (driver_attach+0x28/0x30) from [<c030fc80>] (bus_add_driver+0xf4/0x228) [ 4.227261] [<c030fc80>] (bus_add_driver+0xf4/0x228) from [<c0310e3c>] (driver_register+0xac/0x130) [ 4.227276] [<c0310e3c>] (driver_register+0xac/0x130) from [<c031203c>] (platform_driver_register+0x54/0x68) [ 4.227370] [<c031203c>] (platform_driver_register+0x54/0x68) from [<bf01c55c>] (init_module+0x1c/0x64 [mali]) [ 4.227466] [<bf01c55c>] (init_module+0x1c/0x64 [mali]) from [<c000a4d8>] (do_one_initcall+0xa8/0x144) [ 4.227483] [<c000a4d8>] (do_one_initcall+0xa8/0x144) from [<c007b3ec>] (load_module+0x15b4/0x1b68) [ 4.227498] [<c007b3ec>] (load_module+0x15b4/0x1b68) from [<c007ba74>] (SyS_init_module+0xd4/0xdc) [ 4.227512] [<c007ba74>] (SyS_init_module+0xd4/0xdc) from [<c000f880>] (ret_fast_syscall+0x0/0x30) [ 4.227524] Code: eb18a52c e5943010 e1a00005 e594200c (e5823004) [ 4.227534] ---[ end trace c57267c46477aee1 ]--- [ 4.420068] insmod_device_driver [ 4.577148] fbid=0 uiid=0 [ 4.577166] [DISP] sunxi_fb_to_display,line:590:sunxi_fb_to_display fb0 UIid 0 [ 4.577179] [DISP] sunxi_fb_to_display,line:653:sunxi_fb_to_display set fb0 UIid 0 chan[1]lid[0]z[3]
-
【XR806开发板试用】系列之二:出现已经成功编译,但是无法生成镜像文件的问题
本文主要对于编译成功但是烧录出现问题进行解决,用Hello world 和LED点亮代码作为示范
文章仅为参考网络资料和自身理解,如有不正确之处请多指正
1、首先确定自己根目录在哪,我们都在根目录进行hb set和hb build -f,判断方法是寻找ohos_config.json文件所在目录。
点开可以看见其中的配置信息,记录的信息都能与自身环境对应上
2、值得一提的是,我在按照官方步骤操作发现虽然源码已经编译成功但是无法成功烧录到板子上,我刚刚开始找到的原因是product_path下的BUILD.gn文件,官方说明如下,但是我的该目录下的BUILD.gn文件是空的。原来以为是这个的原因导致烧录不成功,经过试错和询问大佬后一直没解决,后面解决后也没有更改这个 BUILD.gn.,所以官方文档可能是想说的从device_path中寻找的BUILD.gn,很是避坑^_^
3、以下简单说明一下如何将自己的代码添加到编译系统进行编译,详细内容仍旧参考官方文档.
首先进入 $(root_path)/device/xradio/xr806/ohosdemo,(root_path含义见第一点中提到的oho_config.json),再找到同目录下的BUILD.gn,将其中的依赖(deps)添加或者取消注释,使其加入编译系统的编译过程
-配置的含义是在相同目录下找到一个名为_hello_world和LED 或者 iot_peripheral/wlan_demo的文件夹,在去到该文件夹中寻找BUILD.gn获取相关源代码和包含头文件的信息,BUILD.gn看不懂不要紧,能够明白流程就够了。
完成以上步骤理论上在根目录使用hb set& hb build -f再使用烧录工具就可以完成烧录,但是总会出现一些意外情况
开始我由于看见了一篇博客【XR806开发板试用】编译中的几个问题以及hello跑起来,让我了解到生成可烧录的镜像文件,如何查找后缀为.a的文件用来链接生成镜像文件:$(root_path)/device/xradio/xr806/xr_skylark 目录下的ohos.mk记录了查找到的文件,果然,当时并没有显示我已经生成的.a文件。博客中说可以手动添加,但是我手动添加会报错,大家可以尝试一下。
接下来,我们就要更改生成ohos.mk的配置文件,配置文件是$(root_path)/device/xradio/xr806 下的 libcopy.py
更改完成后,用file libcopy.py查看文件换行符的格式
若显示结果中有with CRLF line terminators,则用dos2unix
libcopy.py转化成Unix下的换行符格式,如果需要保留源格式,可加上参数-n libcopy_back将原来格式存为备份
更改完成后,可以尝试在跟目录下重新hb build -f编译,如果没有报错,并且在ohos.mk中发现了正确的链接文件地址,那么恭喜你可以开始编写任何你想要的代码了。但是如果出现了这样的报错(注意观察是从哪开始报错的,并且检查error.log)
[OHOS ERROR] [253/254] ACTION //device/xradio/xr806:libSDK(//build/lite/toolchain:arm-none-eabi-gcc) [OHOS ERROR] FAILED: obj/device/xradio/xr806/libSDK_build_ext_components.txt
解决方法论坛原文:
$(root_path)/device/xradio/xr806/xr_skylark/project/demo/wlan_ble_demo/image/xr806中的image_auto_cal.cfg复制一份粘贴到$(root_path)/device/xradio/xr806/xr_skylark/project/demo/audio_demo/image/xr806 下面替换掉image.cfg。 原因可以在$(root_path)/device/xradio/xr806/xr_skylark/project/image_cfg/readme.md 中找到
改完之后就可以通过烧录软件烧录到板子上了^_^
-
【XR806开发板试用】单总线协议驱动DHT11温湿度传感器
1.昨天刚收到极速社区寄来的全志XR806开发板,之前用过很多全志的SOC芯片,但是像这种无线芯片还是第一次用。这次打算使用XR806芯片驱动一下DHT11温湿度传感器。
2.代码如下:
#include "common/framework/platform_init.h" #include <stdio.h> #include "kernel/os/os.h" #include "driver/chip/hal_gpio.h" #define DHT11_Dout_LOW() HAL_GPIO_WritePin(GPIO_PORT_A, GPIO_PIN_12,GPIO_PIN_LOW) #define DHT11_Dout_HIGH() HAL_GPIO_WritePin(GPIO_PORT_A, GPIO_PIN_12,GPIO_PIN_HIGH) #define DHT11_Data_IN() (uint8_t)HAL_GPIO_ReadPin(GPIO_PORT_A, GPIO_PIN_12) typedef struct { uint8_t humi_high8bit; //原始数据:湿度高8位 uint8_t humi_low8bit; //原始数据:湿度低8位 uint8_t temp_high8bit; //原始数据:温度高8位 uint8_t temp_low8bit; //原始数据:温度高8位 uint8_t check_sum; //校验和 float humidity; //实际湿度 float temperature; //实际温度 } DHT11_Data_TypeDef; typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; void delay_us(uint16_t us) { uint16_t i; for(i=0;i<us;i++) { OS_MSleep(0.1); } } static void DHT11_Mode_IPU(void) { GPIO_InitParam param; param.driving = GPIO_DRIVING_LEVEL_1; param.mode = GPIOx_Pn_F0_INPUT; param.pull = GPIO_PULL_NONE; HAL_GPIO_Init(GPIO_PORT_A, GPIO_PIN_12, ¶m); } static void DHT11_Mode_Out_PP(void) { GPIO_InitParam param; param.driving = GPIO_DRIVING_LEVEL_1; param.mode = GPIOx_Pn_F1_OUTPUT; param.pull = GPIO_PULL_NONE; HAL_GPIO_Init(GPIO_PORT_A, GPIO_PIN_12, ¶m); } void DHT11_Init ( void ) { DHT11_Mode_Out_PP(); DHT11_Dout_HIGH(); // 拉高GPIO } static uint8_t DHT11_ReadByte ( void ) { uint8_t i, temp=0; for(i=0;i<8;i++) { /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ while(DHT11_Data_IN()==0); /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”, *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 */ delay_us(33);//延时x us 这个延时需要大于数据0持续的时间即可 if(DHT11_Data_IN()==1)/* x us后仍为高电平表示数据“1” */ { /* 等待数据1的高电平结束 */ while(DHT11_Data_IN()==1); temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 } else // x us后为低电平表示数据“0” { temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行 } } return temp; } uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data) { uint8_t temp; uint16_t humi_temp; /*输出模式*/ DHT11_Mode_Out_PP(); /*主机拉低*/ DHT11_Dout_LOW(); /*延时18ms*/ OS_MSleep(20); /*总线拉高 主机延时30us*/ DHT11_Dout_HIGH(); delay_us(25); //延时30us /*主机设为输入 判断从机响应信号*/ DHT11_Mode_IPU(); delay_us(25); //延时30us /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ if(DHT11_Data_IN()==0) { /*轮询直到从机发出 的80us 低电平 响应信号结束*/ while(DHT11_Data_IN()==0); /*轮询直到从机发出的 80us 高电平 标置信号结束*/ while(DHT11_Data_IN()==1); /*开始接收数据*/ DHT11_Data->humi_high8bit= DHT11_ReadByte(); DHT11_Data->humi_low8bit = DHT11_ReadByte(); DHT11_Data->temp_high8bit= DHT11_ReadByte(); DHT11_Data->temp_low8bit = DHT11_ReadByte(); DHT11_Data->check_sum = DHT11_ReadByte(); /*读取结束,引脚改为输出模式*/ DHT11_Mode_Out_PP(); /*主机拉高*/ DHT11_Dout_HIGH(); /* 对数据进行处理 */ humi_temp=DHT11_Data->humi_high8bit*100+DHT11_Data->humi_low8bit; DHT11_Data->humidity =(float)humi_temp/100; humi_temp=DHT11_Data->temp_high8bit*100+DHT11_Data->temp_low8bit; DHT11_Data->temperature=(float)humi_temp/100; /*检查读取的数据是否正确*/ temp = DHT11_Data->humi_high8bit + DHT11_Data->humi_low8bit + DHT11_Data->temp_high8bit+ DHT11_Data->temp_low8bit; if(DHT11_Data->check_sum==temp) { return SUCCESS; } else return ERROR; } else return ERROR; } DHT11_Data_TypeDef DHT11_Data; uint8_t TempData; uint8_t humidness; int main(void) { platform_init(); DHT11_Init(); while (1) { if(DHT11_Read_TempAndHumidity(&DHT11_Data)==SUCCESS) { } TempData=DHT11_Data.temperature; humidness=DHT11_Data.humidity; printf("Temp=%d\r\n",TempData); printf("humidness=%d\r\n",humidness); OS_MSleep(500); } return 0; }
1.在SDK目录执行make build -j8编译结果如下
2.由于我是用hello_demo改的所以编译路径显示在hello_demo里面
3.输出的镜像在sdk out文件夹下面,然后使用phoenixMC工具烧录接线 :GND接DHT11模块GND,3.3V接模块的VCC,PA19接模块的信号引脚
打开串口调试工具连接好相应端口重启开发板
开发板串口成功地输出了温度和湿度
总结:一开始微妙延时函数使用了OS_MSleep函数输入小数点如:OS_MSleep(0.03);来使用,一直读不出数据,后来用逻辑分析仪测了这种延时方法并不准确,经过逻辑分析仪调试自己写出了delay_us延时函数,终于成功地从DHT11传感器读出了数据。
-
100ask-t113pro lvds调试问题
RGB屏是可以正常显示的,但是配置完lvds设备树内容,显示异常,用fbshow写图片无法显示
设备树lvds配置如下:&lcd0 { lcd_used = <1>; lcd_driver_name = "default_lcd"; lcd_backlight = <50>; lcd_if = <3>; lcd_x = <800>; lcd_y = <600>; lcd_width = <108>; lcd_height = <94>; lcd_dclk_freq = <39>; lcd_pwm_used = <1>; lcd_pwm_ch = <7>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <0>; lcd_hbp = <88>; lcd_ht = <1024>; lcd_hspw = <64>; lcd_vbp = <15>; lcd_vt = <625>; lcd_vspw = <6>; lcd_lvds_if = <0>; lcd_lvds_colordepth = <0>; lcd_lvds_mode = <1>; lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; deu_mode = <0>; lcdgamma4iep = <22>; smart_color = <90>; pinctrl-0 = <&lvds0_pins_a>; pinctrl-1 = <&lvds0_pins_b>; };
请问哪里配置不对吗
-
百问网V853开发板 setusbconfig hid创建hid设备失败
V853开发板,在做usb gadget开发,这板子USB有点毛病,要开下面两条命令后才能用ADB
cat /sys/devices/platform/soc/usbc0/usb_host cat /sys/devices/platform/soc/usbc0/usb_device
而且开第一条命令的时候会不停报错
做mass_storage时也是需要先setusbconfig mass_storage,在重复上面的命令才能用,不过这个问题先放一边。
我把全志D1的setusbconfig脚本替代了我板子上原本的脚本,ADB,mass_storage还是能使用,参考d1-tina-linux-usb-开发指南,开启了内核的HID function
编译,打包,烧入,开机,先关ADB
killall adbd 2>/dev/null setusbconfig none cat /sys/devices/platform/soc/usbc0/usb_null
然后setusbconfig hid,报错
我用命令对/sys/kernel/config/usb_gadget/g1手动配置也是这样的结果
实在没办法了,网上也找不到相关解决办法,求大神解答!
-
芒果派T113编译的时候为什么一直让我配置内核的一些选项?
配置编译的环境来编译驱动,我设置了交叉编译链,还有ARCH参数,以及内核路径,但是我执行make的时候会一直让我配置内核的一些选项,这个是编译时的输出
这个是我的makefile
-
linux下编译完成后打包安全固件失败
linux下编译完成后执行:./build.sh pack_secure
报错
ERROR: dragon toc0 run error
-
Melis4.0测试cedar多媒体解码库,视频和lvgl混合显示
1.测试audio_test命令播放mp3
首先要把cedar模块编译进内核:在 melis 的根目录执行 make menuconfig 命令,选中 cedar 模块。
Modules Setup -->cedar module support
测试命令也包含进来:
Kernel Setup --> Drivers Test Sample --> cedar Test
编译,烧录,运行,输入help命令可以看到下面的命令:
msh />help ...... cedar_close - cedar_close cedar_test - cedar_test audio_close_test - audio_close_test audio_test - audio_play_test ......
1.1 finish命令中文件路径的写法(测试)
audio_test命令的格式为:
audio_test [文件名]
我的sd卡目录下有个 mp3 文件夹,在finish中进入文件夹后的路径为:
cd /mnt/F/mp3 msh /mnt/F/mp3>ls 1906.真的爱你-Beyond.mp3 1912.千千阙歌-陈慧娴.mp3 1916.红日-李克勤.mp3 1917.都是你的错-陈慧琳.mp3 1917.都是你的错65k.mp3 distance.mp3
这时,我要播放distance.mp3,我使用了下面4种路径:
audio_test /mnt/F/mp3/distance.mp3 ------- 播放失败 audio_test \\mnt\\F\\mp3\\distance.mp3 ------- 播放失败 audio_test F:\\mp3\\distance.mp3 ======= 播放成功 audio_test F:/mp3/distance.mp3 ------- 播放失败
只有一种路径是正确的:
audio_test F:\\mp3\\distance.mp3
测试播放纯音频文件不用考虑图层,比较简单。
2.测试cedar_test命令播放mp4
先禁止melis桌面加载,在《startup.sh》注释掉相关内容:
packecho "Execute startup script begin.............." #insmod d:\mod\orange.mod #insmod d:\apps\desktop.mod echo "...............Execute startup script end"
此时开机只显示全志logo。查询一下此时的图层信息:
msh />disp screen 0: # allwinner logo使用 ch[0] lyr[0]图层,alpha_mode = 0 (pixel alpha),alpha = 255,zorder 为 0 BUF enable ch[0] lyr[0] z[0] prem[N] a[pixel 255] fmt[ 0] fb[ 640, 480; 640, 480; 640, 480] crop[ 0, 0, 640, 480] frame[ 80, 0, 640, 480] addr[0x4132b000,0x00000000,0x00000000] flags[0x 0] trd[0,0]
alpha = 255属于全覆盖,不和其他图层混合显示。zorder=0表示最底层,其他图层只要大于0就会覆盖它。当然,覆盖是在图层都是alpha=255的情况下。
2.1 不清除logo图层,无法显示视频
在这种情况下,使用cedar_test播放视频,只有声音,没有图像。
msh />cedar_test F:\\hanfu02.mp4
这种情况下,查看一下图层信息(可以看到2个图层都属于ch[0],图层格式一个是RGB,一个是YUV):
msh />disp screen 0: BUF enable ch[0] lyr[0] z[0] prem[N] a[pixel 255] fmt[ 0] fb[ 640, 480; 640, 480; 640, 480] crop[ 0, 0, 640, 480] frame[ 80, 0, 640, 480] addr[0x4132b000,0x00000000,0x00000000] flags[0x 0] trd[0,0] BUF enable ch[0] lyr[1] z[1] prem[N] a[pixel 0] fmt[ 72] fb[1280, 720; 640, 360; 640, 360] crop[ 0, 0,1280, 720] frame[ 0, 15, 800, 450] addr[0x42b2d000,0x00000000,0x4273a000] flags[0x 0] trd[0,0]
这里是不是说同一通道的4图层,只能使用相同的格式?2.2 使用disp_layer_alpha_test命令清除logo图层,正常播放视频的disp_layer_alpha_test命令再修改一下:
int disp_layer_alpha_test(int argc, char **argv) { ...... if (argc == 2) { // 如果带有一个参数,不用理会参数是什么,清除所有图层 disp_layer_clear_all(0); return 0; }else if(argc == 4){ // 带3个参数,分别是: [1]=mode [2]=alpha [3]=zorder mode = atoi(argv[1]); alpha = atoi(argv[2]); i = atoi(argv[3]); show_ui_layer(&test_cfg, 1, mode, alpha,(unsigned char)i); return 0; } else g_screen_index = 0; ...... }
输入下面的命令,注意:只带一个参数。
msh />disp_layer_alpha_test 0
查询图层信息(可以看到没有图层信息):
msh />disp screen 0: de_rate 300000000 hz, ref_fps: 59 mgr0: 800x480 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_sync[0] unblank direct_show[false] dmabuf: cache[0] cache max[0] umap skip[0] overflow[0] lcd output backlight(192) fps:58.4 800x 480 err:77961 skip:16 irq:124292 vsync:0 vsync_skip:0
现在才可以正常播放视频。播放完毕后,查询图层信息:
msh />disp screen 0: # vi图层ch[0] lyr[1]是,alpha_mode = 0 (pixel alpha),alpha = 0,format = 72,zorder 为 1 BUF enable ch[0] lyr[1] z[1] prem[N] a[pixel 0] fmt[ 72] fb[1280, 720; 640, 360; 640, 360] crop[ 0, 0,1280, 720] frame[ 0, 15, 800, 450] addr[0x42b2d000,0x00000000,0x4273a000] flags[0x 0] trd[0,0]
3. lvgl设置
3.1 ui图层配置
lvgl属于ui图层,所以使用ch[1] lyr[0] ,alpha_mode = 2 (global pixel alpha),alpha = 255,format = 0(ARGB),zorder 为 2(zorder可以改变,其他参数固定)。仿照 show_ui_layer() 写一个show_lvgl_layer() 的函数:
int request_lvgl_layer(unsigned char zorder) { static int isMemInited=0; // struct test_layer_cfg test_cfg; struct test_layer_cfg *cfg = &test_cfg; memset(&test_cfg, 0, sizeof(struct test_layer_cfg)); printf("request mem_id 0,800, 480,\n"); // 第一次初始化,清除所有图层,申请内存;后面就不用了,只是改变zorder if(isMemInited == 0){ disp_layer_clear_all(g_screen_index); disp_mem(0, 800, 480, 0, "r"); memset(g_p_mem_base,0,800*480*4); } isMemInited = 1; cfg->mem_id = 0; cfg->screen_id = 0; cfg->layer_cfg.channel = 1; cfg->layer_id = 0; cfg->layer_cfg.layer_id = 0; cfg->layer_cfg.info.fb.format = 0; cfg->layer_cfg.info.fb.size[0].width = 800; cfg->layer_cfg.info.fb.size[0].height = 480; cfg->layer_cfg.info.fb.crop.x = 0; cfg->layer_cfg.info.fb.crop.y = 0; cfg->layer_cfg.info.fb.crop.width = 800; cfg->layer_cfg.info.fb.crop.height = 480; cfg->layer_cfg.info.fb.align[0] = 4; cfg->layer_cfg.info.mode = 0; cfg->layer_cfg.info.alpha_mode = 2; cfg->layer_cfg.info.alpha_value = 255; cfg->layer_cfg.info.zorder = zorder; cfg->layer_cfg.info.screen_win.x = 0; cfg->layer_cfg.info.screen_win.y = 0; return disp_layer_cfg(cfg); }
3.2 lvgl本身配置
参考文章《LVGL视频播放界面实现方法》。
需要在lv_conf.h中设置参数:
#define LV_COLOR_SCREEN_TRANSP 1
然后设置界面背景色的透明度,LV_OPA_0 为透明,LV_OPA_COVER为覆盖,根据需要配置:
/* init screen style */ static lv_style_t style_scr_act; lv_style_init(&style_scr_act); /* set style to LV_OPA_0 为透明,LV_OPA_COVER为覆盖*/ lv_style_set_bg_opa(&style_scr_act, LV_OPA_0); lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
测试界面源码:
void lv_example_btn_1(void) { // 创建一个组,稍后将需要使用键盘或编码器或按钮控制的部件(对象)添加进去,并且将输入设备和组关联 // 如果将这个组设置为默认组,那么对于那些在创建时会添加到默认组的部件(对象)就可以省略 lv_group_add_obj() lv_group_t * g = lv_group_create(); // 将上面创建的组设置为默认组 // 如果稍后创建的部件(对象),使用默认组那必须要在其创建之前设置好默认组,否则不生效 lv_group_set_default(g); // 将输入设备和组关联(使用前先打开上面注释掉的头文件) lv_indev_set_group(g_keypad_device_object, g); // 键盘 //lv_indev_set_group(lv_win32_encoder_device_object, g); // 鼠标上的滚轮(编码器) /* init screen style */ static lv_style_t style_scr_act; lv_style_init(&style_scr_act); /* set style to LV_OPA_0,no cover*/ lv_style_set_bg_opa(&style_scr_act, LV_OPA_0); lv_obj_add_style(lv_scr_act(), &style_scr_act, 0); #define RIGHT_OFFSET 40 /* 创建一个btn部件(对象) */ lv_obj_t * btn1 = lv_btn_create(lv_scr_act()); // 创建一个btn部件(对象),他的父对象是活动屏幕对象 lv_obj_set_size(btn1, 100, 50); lv_obj_align(btn1, LV_ALIGN_LEFT_MID, 140, 165); lv_obj_t * btn2 = lv_btn_create(lv_scr_act()); // 创建一个btn部件(对象),他的父对象是活动屏幕对象 lv_obj_set_size(btn2, 100, 50); lv_obj_align_to(btn2, btn1, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0); lv_obj_t * btn3 = lv_btn_create(lv_scr_act()); // 创建一个btn部件(对象),他的父对象是活动屏幕对象 lv_obj_set_size(btn3, 100, 50); lv_obj_align_to(btn3, btn2, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0); lv_obj_t * btn4 = lv_btn_create(lv_scr_act()); // 创建一个btn部件(对象),他的父对象是活动屏幕对象 lv_obj_set_size(btn4, 100, 50); lv_obj_align_to(btn4, btn3, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0); lv_obj_t * slider = lv_slider_create(lv_scr_act()); lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, -20); }
3.3 播放视频效果
播放视频效果(按键切换):
原文链接:https://blog.csdn.net/hwd00001/article/details/130145030
-
V853编译的vpm_run sample.txt出现segmentation fault怎么办呢?
想问一下V853编译的vpm_run sample.txt出现segmentation fault如何怎么办呢?
-
mango-MQ-R在移植好的lvgl添加物理按键
没有搞定D1s在Melis下的I2c驱动(gt911触摸屏)。先测试物理按键。
1.lvgl注册keypad驱动
##1.1 在melis的ADC按键中发送消息
先做好ADC按键的驱动,直接在驱动中发送消息。如何在rt-thread中使用消息队列发送消息,请参考官方资料: RT-Thread API参考手册-消息队列
1.1.1 创建消息队列,并初始化
相关代码在
D1s-Melis/ekernel/drivers/drv/source/input/keyboard/sunxi_keyboard.c
中。完整内容点击链接 sunxi_keyboard.c。/* 消息队列控制块 */ struct rt_messagequeue mq; /* 消息队列中用到的放置消息的内存池 */ static rt_uint8_t msg_pool[2048]; int sunxi_keyboard_init(void) { ...... rt_err_t result; /* 初始化消息队列 */ result = rt_mq_init(&mq, "mqt", &msg_pool[0], /* 内存池指向msg_pool */ 1, /* 每个消息的大小是 1 字节 */ sizeof(msg_pool), /* 内存池的大小是msg_pool的大小 */ RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */ if (result != RT_EOK) { rt_kprintf("init message queue failed.\n"); return -1; } return 0; }
1.1.2 扫描按键时,发送按下和松开消息
这部分代码也在
sunxi_keyboard.c
中。int keyboard_irq_callback(uint32_t data_type, uint32_t data) { if (data_type == GPADC_UP && key_flag == 1) { ...... /* 发送按键松开消息到消息队列中 */ key_data->compare_later = 0xf6; result = rt_mq_send(&mq, &(key_data->compare_later), 1); if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } } ....... __log("key: %d",key_data->compare_before); /* 发送按键按下消息到消息队列中 */ result = rt_mq_send(&mq, &(key_data->compare_before), 1); if (result != RT_EOK) { rt_kprintf("rt_mq_send ERR\n"); } return 0; }
1.2 编写读取按键的回调函数
这里只是通过消息队列读取按键按下和松开的消息。
收到按键按下的消息值为0,1,2,3,4;
收到按键松开的消息值为0xF6.extern struct rt_messagequeue mq; uint8_t msgbyte; static void melis_keypad_driver_read_cb(lv_indev_drv_t* indev_drv, lv_indev_data_t* data) { /* 从消息队列中接收消息 */ if (rt_mq_recv(&mq, (void *)&msgbyte, sizeof(msgbyte), RT_WAITING_NO) == RT_EOK) { rt_kprintf("read_cb: recv msg:%d\n", msgbyte); data->state = LV_INDEV_STATE_PR; switch (msgbyte) { case 0: data->key = LV_KEY_PREV; break; case 1: data->key = LV_KEY_NEXT; break; case 2: data->key = LV_KEY_ENTER; break; case 3: data->key = LV_KEY_ENTER; break; case 4: data->key = LV_KEY_ESC; break; case 0xf6: data->state = LV_INDEV_STATE_REL; break; default: break; } } }
1.3 lvgl按键驱动注册
完成前面的准备工作后,就可以在 lv_main()中注册按键驱动,完成lvgl物理按键的初始化。
直接拷贝韦东山老师在windows下键盘的驱动,
00_lv_100ask_sim_codeblocks_win/lv_drivers/win32drv/win32drv.c
完整代码点击链接:static lv_indev_drv_t keypad_driver; lv_indev_drv_init(&keypad_driver); keypad_driver.type = LV_INDEV_TYPE_KEYPAD; keypad_driver.read_cb = lv_win32_keypad_driver_read_callback; lv_win32_keypad_device_object = lv_indev_drv_register(&keypad_driver);
把上面的代码稍作改动。
lv_win32_keypad_driver_read_callback --> melis_keypad_driver_read_cb lv_win32_keypad_device_object --> g_keypad_device_object 【 说明:这个变量其他文件需要用到】
于是,改动后的代码如下(完整代码点击链接 lv_main.c):
#define LV_USE_GPADC 1 lv_indev_t* g_keypad_device_object ; static lv_disp_t * hal_init(void ) { ...... #if LV_USE_GPADC static lv_indev_drv_t keypad_driver; lv_indev_drv_init(&keypad_driver); keypad_driver.type = LV_INDEV_TYPE_KEYPAD; keypad_driver.read_cb = melis_keypad_driver_read_cb; g_keypad_device_object = lv_indev_drv_register(&keypad_driver); #endif lv_disp_t * disp = NULL; return disp; }
2.在gui中测试物理按键效果
在gui中应用物理按键(groups)需要3个步骤:
1.要创建一个 组(Groups) : lv_group_t * g = lv_group_create();
2.然后将一个对象添加到 组(Groups) 中: lv_group_add_obj(g, obj); 也可以指定默认组:lv_group_set_default(g);
3.最后要将组(Groups)与输入设备相关联: lv_indev_set_group(g_keypad_device_object , g);物理按键中有3个必备的按键消息,这3个消息就可以实现焦点切换和触发焦点对象:
消息名称 含义 LV_KEY_NEXT 聚焦到下一个对象 LV_KEY_PREV 聚焦到上一个对象 LV_KEY_ENTER 触发 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件 其他消息:
消息名称 含义 LV_KEY_UP 增加值或向上移动 LV_KEY_DOWN 减少值或向下移动 LV_KEY_RIGHT 增加值或向右移动 LV_KEY_LEFT 减少值或向左移动 LV_KEY_ESC 关闭或退出(例如关闭 下拉列表) LV_KEY_DEL 删除(例如 文本区域 中右侧的字符) LV_KEY_BACKSPACE 删除左边的一个字符(例如在文本区域) LV_KEY_HOME 跳到开头/顶部(例如在 文本区域) LV_KEY_END 跳到最后(例如在 文本区域)) 这里我使用了官方例程 lv_example_btn_1.c。
extern lv_indev_t* g_keypad_device_object ; static void event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_CLICKED) { LV_LOG_USER("Clicked"); } else if(code == LV_EVENT_VALUE_CHANGED) { LV_LOG_USER("Toggled"); } } void lv_example_btn_1(void) { lv_obj_t * label; // 创建一个组,稍后将需要使用键盘或编码器或按钮控制的部件(对象)添加进去,并且将输入设备和组关联 // 如果将这个组设置为默认组,那么对于那些在创建时会添加到默认组的部件(对象)就可以省略 lv_group_add_obj() lv_group_t * g = lv_group_create(); // 将上面创建的组设置为默认组 // 如果稍后创建的部件(对象),使用默认组那必须要在其创建之前设置好默认组,否则不生效 lv_group_set_default(g); lv_obj_t * btn1 = lv_btn_create(lv_scr_act()); lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL); lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40); label = lv_label_create(btn1); lv_label_set_text(label, "Button"); lv_obj_center(label); lv_obj_t * btn2 = lv_btn_create(lv_scr_act()); lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL); lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40); lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE); lv_obj_set_height(btn2, LV_SIZE_CONTENT); label = lv_label_create(btn2); lv_label_set_text(label, "Toggle"); lv_obj_center(label); lv_indev_set_group(g_keypad_device_object, g); }
原文链接:https://blog.csdn.net/hwd00001/article/details/130106367
-
mango-MQ-R基于Melis移植lvgl
1.下载lvgl源码到《D1s-Melis/ekernel/drivers/hal/test/disp2》目录
我使用的源码是https://github.com/lvgl/lv_port_pc_eclipse
,克隆到D1s-Melis/ekernel/drivers/hal/test/disp2
目录。然后在D1s-Melis/ekernel/drivers/hal/test/disp2/lv_port_pc_eclipse》
目录下建立一个Makefile,把全部的C文件都包含进来编译的。这是因为lvgl的所有非必要的C文件都可以通过宏定义配置是否编译。例如lv_bmp.c里面的代码是否编译,取决于 宏定义LV_USE_BMP:
为了简单起见,很多非必要的组件我都没有包含进来,详情见 lv_conf.h 。
/** * @file lv_conf.h * Configuration file for v9.0.0-dev */ /* * Copy this file as `lv_conf.h` * 1. simply next to the `lvgl` folder * 2. or any other places and * - define `LV_CONF_INCLUDE_SIMPLE` * - add the path as include path */ /* clang-format off */ #if 1 /*Set it to "1" to enable content*/ #ifndef LV_CONF_H #define LV_CONF_H #define LV_USE_DEV_VERSION /*==================== COLOR SETTINGS *====================*/ /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 24 (RGB888), 32 (ARGB8888)*/ #define LV_COLOR_DEPTH 32 #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*Enable more complex drawing routines to manage screens transparency. *Can be used if the UI is above another layer, e.g. an OSD menu or video player. *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ #define LV_COLOR_SCREEN_TRANSP 1 /*========================= STDLIB WRAPPER SETTINGS *=========================*/ /*Enable and configure the built-in memory manager*/ #define LV_USE_BUILTIN_MALLOC 1 #if LV_USE_BUILTIN_MALLOC /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ #define LV_MEM_SIZE (128U * 1024U) /*[bytes]*/ /*Size of the memory expand for `lv_malloc()` in bytes*/ #define LV_MEM_POOL_EXPAND_SIZE 0 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ #define LV_MEM_ADR 0 /*0: unused*/ /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ #if LV_MEM_ADR == 0 #undef LV_MEM_POOL_INCLUDE #undef LV_MEM_POOL_ALLOC #endif #endif /*LV_USE_BUILTIN_MALLOC*/ /*Enable lv_memcpy_builtin, lv_memset_builtin, lv_strlen_builtin, lv_strncpy_builtin*/ #define LV_USE_BUILTIN_MEMCPY 1 /*Enable and configure the built-in (v)snprintf */ #define LV_USE_BUILTIN_SNPRINTF 1 #if LV_USE_BUILTIN_SNPRINTF #define LV_SPRINTF_USE_FLOAT 0 #endif /*LV_USE_BUILTIN_SNPRINTF*/ #define LV_STDLIB_INCLUDE <stdint.h> #define LV_STDIO_INCLUDE <stdint.h> #define LV_STRING_INCLUDE <stdint.h> #define LV_MALLOC lv_malloc_builtin #define LV_REALLOC lv_realloc_builtin #define LV_FREE lv_free_builtin #define LV_MEMSET lv_memset_builtin #define LV_MEMCPY lv_memcpy_builtin #define LV_SNPRINTF lv_snprintf_builtin #define LV_VSNPRINTF lv_vsnprintf_builtin #define LV_STRLEN lv_strlen_builtin #define LV_STRNCPY lv_strncpy_builtin #define LV_COLOR_EXTERN_INCLUDE <stdint.h> #define LV_COLOR_MIX lv_color_mix #define LV_COLOR_PREMULT lv_color_premult #define LV_COLOR_MIX_PREMULT lv_color_mix_premult /*==================== HAL SETTINGS *====================*/ /*Default display refresh, input device read and animation step period.*/ #define LV_DEF_REFR_PERIOD 33 /*[ms]*/ /*Use a custom tick source that tells the elapsed time in milliseconds. *It removes the need to manually update the tick with `lv_tick_inc()`)*/ #define LV_TICK_CUSTOM 0 #if LV_TICK_CUSTOM #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ /*If using lvgl as ESP32 component*/ // #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h" // #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL)) #endif /*LV_TICK_CUSTOM*/ /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings. *(Not so important, you can adjust it to modify default sizes and spaces)*/ #define LV_DPI_DEF 130 /*[px/inch]*/ /*======================== * DRAW CONFIGURATION *========================*/ /*Enable the built in mask engine. *Required to draw shadow, rounded corners, circles, arc, skew lines, or any other masks*/ #define LV_USE_DRAW_MASKS 1 #define LV_USE_DRAW_SW 1 #if LV_USE_DRAW_SW /*Enable complex draw engine. *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/ #define LV_DRAW_SW_COMPLEX 1 /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks. * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers * and can't be drawn in chunks. */ /*The target buffer size for simple layer chunks.*/ #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/ /*Used if `LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.*/ #define LV_DRAW_SW_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024) /*[bytes]*/ /*Allow buffering some shadow calculation. *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius` *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/ #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0 /* Set number of maximally cached circle data. * The circumference of 1/4 circle are saved for anti-aliasing * radius * 4 bytes are used per circle (the most often used radiuses are saved) * 0: to disable caching */ #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4 /*Default gradient buffer size. *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again. *LV_DRAW_SW_GRADIENT_CACHE_DEF_SIZE sets the size of this cache in bytes. *If the cache is too small the map will be allocated only while it's required for the drawing. *0 mean no caching.*/ #define LV_DRAW_SW_GRADIENT_CACHE_DEF_SIZE 0 /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display) *LV_DRAW_SW_GRADIENT_DITHER implies allocating one or two more lines of the object's rendering surface *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */ #define LV_DRAW_SW_GRADIENT_DITHER 0 #if LV_DRAW_SW_GRADIENT_DITHER /*Add support for error diffusion dithering. *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing. *The increase in memory consumption is (24 bits * object's width)*/ #define LV_DRAW_SW_GRADIENT_DITHER_ERROR_DIFFUSION 0 #endif /*Enable subpixel rendering*/ #define LV_DRAW_SW_FONT_SUBPX 0 #if LV_DRAW_SW_FONT_SUBPX /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/ #define LV_DRAW_SW_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/ #endif #endif /*Use SDL renderer API*/ #define LV_USE_DRAW_SDL 0 #if LV_USE_DRAW_SDL #define LV_DRAW_SDL_INCLUDE_PATH <SDL2/SDL.h> /*Texture cache size, 8MB by default*/ #define LV_DRAW_SDL_LRU_SIZE (1024 * 1024 * 8) /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/ #define LV_DRAW_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6)) #endif /*===================== * GPU CONFIGURATION *=====================*/ /*Use Arm's 2D acceleration library Arm-2D */ #define LV_USE_GPU_ARM2D 0 /*Use STM32's DMA2D (aka Chrom Art) GPU*/ #define LV_USE_GPU_STM32_DMA2D 0 #if LV_USE_GPU_STM32_DMA2D /*Must be defined to include path of CMSIS header of target processor e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_GPU_DMA2D_CMSIS_INCLUDE #endif /*Use GD32 IPA GPU * This adds support for Image Processing Accelerator on GD32F450 and GD32F470 series MCUs * * NOTE: IPA on GD32F450 has a bug where the fill operation overwrites data beyond the * framebuffer. This driver works around it by saving and restoring affected memory, but * this makes it not thread-safe. GD32F470 is not affected. */ #define LV_USE_GPU_GD32_IPA 0 /*Use NXP's PXP GPU iMX RTxxx platforms*/ #define LV_USE_GPU_NXP_PXP 0 #if LV_USE_GPU_NXP_PXP /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c) * and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS * has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected. *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init() */ #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 #endif /*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ #define LV_USE_GPU_NXP_VG_LITE 0 /*Use SWM341's DMA2D GPU*/ #define LV_USE_GPU_SWM341_DMA2D 0 #if LV_USE_GPU_SWM341_DMA2D #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h" #endif /*======================= * FEATURE CONFIGURATION *=======================*/ /*------------- * Logging *-----------*/ /*Enable the log module*/ #define LV_USE_LOG 0 #if LV_USE_LOG /*How important log should be added: *LV_LOG_LEVEL_TRACE A lot of logs to give detailed information *LV_LOG_LEVEL_INFO Log important events *LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem *LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail *LV_LOG_LEVEL_USER Only logs added by the user *LV_LOG_LEVEL_NONE Do not log anything*/ #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN /*1: Print the log with 'printf'; *0: User need to register a callback with `lv_log_register_print_cb()`*/ #define LV_LOG_PRINTF 0 /*1: Enable print timestamp; *0: Disable print timestamp*/ #define LV_LOG_USE_TIMESTAMP 1 /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/ #define LV_LOG_TRACE_MEM 1 #define LV_LOG_TRACE_TIMER 1 #define LV_LOG_TRACE_INDEV 1 #define LV_LOG_TRACE_DISP_REFR 1 #define LV_LOG_TRACE_EVENT 1 #define LV_LOG_TRACE_OBJ_CREATE 1 #define LV_LOG_TRACE_LAYOUT 1 #define LV_LOG_TRACE_ANIM 1 #define LV_LOG_TRACE_MSG 1 #endif /*LV_USE_LOG*/ /*------------- * Asserts *-----------*/ /*Enable asserts if an operation is failed or an invalid data is found. *If LV_USE_LOG is enabled an error message will be printed on failure*/ #define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/ #define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/ #define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/ #define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/ #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ /*Add a custom handler when assert happens e.g. to restart the MCU*/ #define LV_ASSERT_HANDLER_INCLUDE <stdint.h> #define LV_ASSERT_HANDLER while(1); /*Halt by default*/ /*------------- * Others *-----------*/ /*1: Show CPU usage and FPS count*/ #define LV_USE_PERF_MONITOR 0 #if LV_USE_PERF_MONITOR #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT #endif /*1: Show the used memory and the memory fragmentation * Requires `LV_USE_BUILTIN_MALLOC = 1`*/ #define LV_USE_MEM_MONITOR 0 #if LV_USE_MEM_MONITOR #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT #endif /*1: Draw random colored rectangles over the redrawn areas*/ #define LV_USE_REFR_DEBUG 0 /*Maximum buffer size to allocate for rotation. *Only used if software rotation is enabled in the display driver.*/ #define LV_DISP_ROT_MAX_BUF (10*1024) #define LV_USE_USER_DATA 1 /*Garbage Collector settings *Used if lvgl is bound to higher level language and the memory is managed by that language*/ #define LV_ENABLE_GC 0 #if LV_ENABLE_GC != 0 #define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ #endif /*LV_ENABLE_GC*/ /*Default image cache size. Image caching keeps some images opened. *If only the built-in image formats are used there is no real advantage of caching. *With other image decoders (e.g. PNG or JPG) caching save the continuous open/decode of images. *However the opened images consume additional RAM. *0: to disable caching*/ #define LV_IMG_CACHE_DEF_SIZE 0 /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ #define LV_GRADIENT_MAX_STOPS 2 /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */ #define LV_COLOR_MIX_ROUND_OFS 0 /*===================== * COMPILER SETTINGS *====================*/ /*For big endian systems set to 1*/ #define LV_BIG_ENDIAN_SYSTEM 0 /*Define a custom attribute to `lv_tick_inc` function*/ #define LV_ATTRIBUTE_TICK_INC /*Define a custom attribute to `lv_timer_handler` function*/ #define LV_ATTRIBUTE_TIMER_HANDLER /*Define a custom attribute to `lv_disp_flush_ready` function*/ #define LV_ATTRIBUTE_FLUSH_READY /*Required alignment size for buffers*/ #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). * E.g. __attribute__((aligned(4)))*/ #define LV_ATTRIBUTE_MEM_ALIGN /*Attribute to mark large constant arrays for example font's bitmaps*/ #define LV_ATTRIBUTE_LARGE_CONST /*Compiler prefix for a big array declaration in RAM*/ #define LV_ATTRIBUTE_LARGE_RAM_ARRAY /*Place performance critical functions into a faster memory (e.g RAM)*/ #define LV_ATTRIBUTE_FAST_MEM /*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that *should also appear on LVGL binding API such as Micropython.*/ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/ /*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/ #define LV_USE_LARGE_COORD 0 /*================== * FONT USAGE *===================*/ /*Montserrat fonts with ASCII range and some symbols using bpp = 4 *https://fonts.google.com/specimen/Montserrat*/ #define LV_FONT_MONTSERRAT_8 1 #define LV_FONT_MONTSERRAT_10 1 #define LV_FONT_MONTSERRAT_12 1 #define LV_FONT_MONTSERRAT_14 1 #define LV_FONT_MONTSERRAT_16 1 #define LV_FONT_MONTSERRAT_18 1 #define LV_FONT_MONTSERRAT_20 1 #define LV_FONT_MONTSERRAT_22 1 #define LV_FONT_MONTSERRAT_24 1 #define LV_FONT_MONTSERRAT_26 1 #define LV_FONT_MONTSERRAT_28 1 #define LV_FONT_MONTSERRAT_30 1 #define LV_FONT_MONTSERRAT_32 1 #define LV_FONT_MONTSERRAT_34 1 #define LV_FONT_MONTSERRAT_36 1 #define LV_FONT_MONTSERRAT_38 1 #define LV_FONT_MONTSERRAT_40 1 #define LV_FONT_MONTSERRAT_42 1 #define LV_FONT_MONTSERRAT_44 1 #define LV_FONT_MONTSERRAT_46 1 #define LV_FONT_MONTSERRAT_48 1 /*Demonstrate special features*/ #define LV_FONT_MONTSERRAT_12_SUBPX 1 #define LV_FONT_MONTSERRAT_28_COMPRESSED 1 /*bpp = 3*/ #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 1 /*Hebrew, Arabic, Persian letters and all their forms*/ #define LV_FONT_SIMSUN_16_CJK 1 /*1000 most common CJK radicals*/ /*Pixel perfect monospace fonts*/ #define LV_FONT_UNSCII_8 1 #define LV_FONT_UNSCII_16 1 /*Optionally declare custom fonts here. *You can use these fonts as default font too and they will be available globally. *E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/ #define LV_FONT_CUSTOM_DECLARE /*Always set a default font*/ #define LV_FONT_DEFAULT &lv_font_montserrat_14 /*Enable handling large font and/or fonts with a lot of characters. *The limit depends on the font size, font face and bpp. *Compiler error will be triggered if a font needs it.*/ #define LV_FONT_FMT_TXT_LARGE 1 /*Enables/disables support for compressed fonts.*/ #define LV_USE_FONT_COMPRESSED 1 /*Enable drawing placeholders when glyph dsc is not found*/ #define LV_USE_FONT_PLACEHOLDER 1 /*================= * TEXT SETTINGS *=================*/ /** * Select a character encoding for strings. * Your IDE or editor should have the same character encoding * - LV_TXT_ENC_UTF8 * - LV_TXT_ENC_ASCII */ #define LV_TXT_ENC LV_TXT_ENC_UTF8 /*Can break (wrap) texts on these chars*/ #define LV_TXT_BREAK_CHARS " ,.;:-_)]}" /*If a word is at least this long, will break wherever "prettiest" *To disable, set to a value <= 0*/ #define LV_TXT_LINE_BREAK_LONG_LEN 0 /*Minimum number of characters in a long word to put on a line before a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /*Minimum number of characters in a long word to put on a line after a break. *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/ #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 /*The control character to use for signalling text recoloring.*/ #define LV_TXT_COLOR_CMD "#" /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts. *The direction will be processed according to the Unicode Bidirectional Algorithm: *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ #define LV_USE_BIDI 1 #if LV_USE_BIDI /*Set the default direction. Supported values: *`LV_BASE_DIR_LTR` Left-to-Right *`LV_BASE_DIR_RTL` Right-to-Left *`LV_BASE_DIR_AUTO` detect texts base direction*/ #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO #endif /*Enable Arabic/Persian processing *In these languages characters should be replaced with an other form based on their position in the text*/ #define LV_USE_ARABIC_PERSIAN_CHARS 1 /*================== * WIDGETS *================*/ /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/ #define LV_USE_ANIMIMG 1 #define LV_USE_ARC 1 #define LV_USE_BAR 1 #define LV_USE_BTN 1 #define LV_USE_BTNMATRIX 1 #define LV_USE_CALENDAR 1 #if LV_USE_CALENDAR #define LV_CALENDAR_WEEK_STARTS_MONDAY 0 #if LV_CALENDAR_WEEK_STARTS_MONDAY #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"} #else #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"} #endif #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} #define LV_USE_CALENDAR_HEADER_ARROW 1 #define LV_USE_CALENDAR_HEADER_DROPDOWN 1 #endif /*LV_USE_CALENDAR*/ #define LV_USE_CANVAS 1 #define LV_USE_CHART 1 #define LV_USE_CHECKBOX 1 #define LV_USE_COLORWHEEL 1 #define LV_USE_DROPDOWN 1 /*Requires: lv_label*/ #define LV_USE_IMG 1 /*Requires: lv_label*/ #define LV_USE_IMGBTN 1 #define LV_USE_KEYBOARD 1 #define LV_USE_LABEL 1 #if LV_USE_LABEL #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/ #define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/ #endif #define LV_USE_LED 1 #define LV_USE_LINE 1 #define LV_USE_LIST 1 #define LV_USE_MENU 1 #define LV_USE_METER 1 #define LV_USE_MSGBOX 1 #define LV_USE_ROLLER 1 /*Requires: lv_label*/ #define LV_USE_SLIDER 1 /*Requires: lv_bar*/ #define LV_USE_SPAN 1 #if LV_USE_SPAN /*A line text can contain maximum num of span descriptor */ #define LV_SPAN_SNIPPET_STACK_SIZE 64 #endif #define LV_USE_SPINBOX 1 #define LV_USE_SPINNER 1 #define LV_USE_SWITCH 1 #define LV_USE_TEXTAREA 1 /*Requires: lv_label*/ #if LV_USE_TEXTAREA != 0 #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/ #endif #define LV_USE_TABLE 1 #define LV_USE_TABVIEW 1 #define LV_USE_TILEVIEW 1 #define LV_USE_WIN 1 /*================== * THEMES *==================*/ /*A simple, impressive and very complete theme*/ #define LV_USE_THEME_DEFAULT 1 #if LV_USE_THEME_DEFAULT /*0: Light mode; 1: Dark mode*/ #define LV_THEME_DEFAULT_DARK 0 /*1: Enable grow on press*/ #define LV_THEME_DEFAULT_GROW 1 /*Default transition time in [ms]*/ #define LV_THEME_DEFAULT_TRANSITION_TIME 80 #endif /*LV_USE_THEME_DEFAULT*/ /*A very simple theme that is a good starting point for a custom theme*/ #define LV_USE_THEME_BASIC 1 /*A theme designed for monochrome displays*/ #define LV_USE_THEME_MONO 1 /*================== * LAYOUTS *==================*/ /*A layout similar to Flexbox in CSS.*/ #define LV_USE_FLEX 1 /*A layout similar to Grid in CSS.*/ #define LV_USE_GRID 1 /*==================== * 3RD PARTS LIBRARIES *====================*/ /*File system interfaces for common APIs */ /*API for fopen, fread, etc*/ #define LV_USE_FS_STDIO 0 #if LV_USE_FS_STDIO #define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ #define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for open, read, etc*/ #define LV_USE_FS_POSIX 0 #if LV_USE_FS_POSIX #define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ #define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for CreateFile, ReadFile, etc*/ #define LV_USE_FS_WIN32 0 #if LV_USE_FS_WIN32 #define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/ #define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/ #define LV_USE_FS_FATFS 0 #if LV_USE_FS_FATFS #define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/ #define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/ #endif /*PNG decoder library*/ #define LV_USE_PNG 1 /*BMP decoder library*/ #define LV_USE_BMP 1 /* JPG + split JPG decoder library. * Split JPG is a custom format optimized for embedded systems. */ #define LV_USE_SJPG 0 /*GIF decoder library*/ #define LV_USE_GIF 0 /*QR code library*/ #define LV_USE_QRCODE 0 /*Barcode code library*/ #define LV_USE_BARCODE 0 /*FreeType library*/ #define LV_USE_FREETYPE 0 #if LV_USE_FREETYPE /*Memory used by FreeType to cache characters [bytes]*/ #define LV_FREETYPE_CACHE_SIZE (64 * 1024) /*Let FreeType to use LVGL memory and file porting*/ #define LV_FREETYPE_USE_LVGL_PORT 0 /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ /* if font size >= 256, must be configured as image cache */ #define LV_FREETYPE_SBIT_CACHE 0 /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ /* (0:use system defaults) */ #define LV_FREETYPE_CACHE_FT_FACES 4 #define LV_FREETYPE_CACHE_FT_SIZES 4 #endif /* Built-in TTF decoder */ #define LV_USE_TINY_TTF 1 #if LV_USE_TINY_TTF /* Enable loading TTF data from files */ #define LV_TINY_TTF_FILE_SUPPORT 0 #endif /*Rlottie library*/ #define LV_USE_RLOTTIE 0 /*FFmpeg library for image decoding and playing videos *Supports all major image formats so do not enable other image decoder with it*/ #define LV_USE_FFMPEG 0 #if LV_USE_FFMPEG /*Dump input information to stderr*/ #define LV_FFMPEG_DUMP_FORMAT 0 #endif /*================== * OTHERS *==================*/ /*1: Enable API to take snapshot for object*/ #define LV_USE_SNAPSHOT 1 /*1: Enable Monkey test*/ #define LV_USE_MONKEY 1 /*1: Enable grid navigation*/ #define LV_USE_GRIDNAV 1 /*1: Enable lv_obj fragment*/ #define LV_USE_FRAGMENT 1 /*1: Support using images as font in label or span widgets */ #define LV_USE_IMGFONT 1 #if LV_USE_IMGFONT /*Imgfont image file path maximum length*/ #define LV_IMGFONT_PATH_MAX_LEN 64 /*1: Use img cache to buffer header information*/ #define LV_IMGFONT_USE_IMG_CACHE_HEADER 0 #endif /*1: Enable a published subscriber based messaging system */ #define LV_USE_MSG 1 /*1: Enable Pinyin input method*/ /*Requires: lv_keyboard*/ #define LV_USE_IME_PINYIN 0 #if LV_USE_IME_PINYIN /*1: Use default thesaurus*/ /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/ #define LV_IME_PINYIN_USE_DEFAULT_DICT 1 /*Set the maximum number of candidate panels that can be displayed*/ /*This needs to be adjusted according to the size of the screen*/ #define LV_IME_PINYIN_CAND_TEXT_NUM 6 /*Use 9 key input(k9)*/ #define LV_IME_PINYIN_USE_K9_MODE 1 #if LV_IME_PINYIN_USE_K9_MODE == 1 #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3 #endif // LV_IME_PINYIN_USE_K9_MODE #endif /*1: Enable file explorer*/ /*Requires: lv_table*/ #define LV_USE_FILE_EXPLORER 0 #if LV_USE_FILE_EXPLORER /*Maximum length of path*/ #define LV_FILE_EXPLORER_PATH_MAX_LEN (128) /*Quick access bar, 1:use, 0:not use*/ /*Requires: lv_list*/ #define LV_FILE_EXPLORER_QUICK_ACCESS 1 #endif /*================== * DEVICES *==================*/ /*Use SDL to open window on PC and handle mouse and keyboard*/ #define LV_USE_SDL 0 #if LV_USE_SDL #define LV_SDL_INCLUDE_PATH <SDL2/SDL.h> #define LV_SDL_PARTIAL_MODE 0 /*Recommended only to emulate a setup with a display controller*/ #endif /*Driver for /dev/fb*/ #define LV_USE_LINUX_FBDEV 0 #if LV_USE_LINUX_FBDEV #define LV_LINUX_FBDEV_BSD 0 #endif /*Interface for TFT_eSPI*/ #define LV_USE_TFT_ESPI 0 /*================== * EXAMPLES *==================*/ /*Enable the examples to be built with the library*/ #define LV_BUILD_EXAMPLES 1 /*=================== * DEMO USAGE ====================*/ /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ #define LV_USE_DEMO_WIDGETS 1 #if LV_USE_DEMO_WIDGETS #define LV_DEMO_WIDGETS_SLIDESHOW 0 #endif /*Demonstrate the usage of encoder and keyboard*/ #define LV_USE_DEMO_KEYPAD_AND_ENCODER 1 /*Benchmark your system*/ #define LV_USE_DEMO_BENCHMARK 0 #if LV_USE_DEMO_BENCHMARK /*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/ #define LV_DEMO_BENCHMARK_RGB565A8 0 #endif /*Stress test for LVGL*/ #define LV_USE_DEMO_STRESS 0 /*Music player demo*/ #define LV_USE_DEMO_MUSIC 0 #if LV_USE_DEMO_MUSIC #define LV_DEMO_MUSIC_SQUARE 0 #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 #endif /*Flex layout demo*/ #define LV_USE_DEMO_FLEX_LAYOUT 0 /*--END OF LV_CONF_H--*/ #endif /*LV_CONF_H*/ #endif /*End of "Content enable"*/
1.1 修改Makefile
先在
disp2
目录下的Makefile把子目录disp2/lv_port_pc_eclipse
包含进来:subdir-ccflags-y += -I$(srctree)/ekernel/drivers/include \ -I$(srctree)/ekernel/core/rt-thread/include \ -I$(srctree)/ekernel/drivers/drv/source/disp2/soc obj-y += disp_layer_cfg.o disp_mem_hwd.o #disp_mem.o obj-y += disp_layer_alpha_test.o obj-y += disp_layer_scal_test.o obj-y += disp_layer_format_test.o obj-y += disp_lbc_test.o obj-y += lv_port_pc_eclipse/
再将
isp2/lv_port_pc_eclipse
目录下的Makefile改为下面内容(节选):obj-y += \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_alpha16.o \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_argb.o \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_chroma_keyed.o \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.o \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb.o \ lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb565a8.o \ lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_12_compr_az.c.o \ lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_16_compr_az.c.o \ lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_28_compr_az.c.o \ lvgl/demos/benchmark/lv_demo_benchmark.o \ lvgl/demos/keypad_encoder/lv_demo_keypad_encoder.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_corner_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_list_pause.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_list_pause_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_list_play.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_list_play_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_loop.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_loop_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_next.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_next_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_pause.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_pause_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_play.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_play_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_prev.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_prev_large.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_rnd.o \ lvgl/demos/music/assets/img_lv_demo_music_btn_rnd_large.o \ lvgl/demos/music/assets/img_lv_demo_music_corner_left.o \ lvgl/demos/music/assets/img_lv_demo_music_corner_left_large.o \ lvgl/demos/music/assets/img_lv_demo_music_corner_right.o \ lvgl/demos/music/assets/img_lv_demo_music_corner_right_large.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_1.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_1_large.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_2.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_2_large.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_3.o \ lvgl/demos/music/assets/img_lv_demo_music_cover_3_large.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_1.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_1_large.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_2.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_2_large.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_3.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_3_large.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_4.o \ lvgl/demos/music/assets/img_lv_demo_music_icon_4_large.o \ lvgl/demos/music/assets/img_lv_demo_music_list_border.o \ lvgl/demos/music/assets/img_lv_demo_music_list_border_large.o \ lvgl/demos/music/assets/img_lv_demo_music_logo.o \ lvgl/demos/music/assets/img_lv_demo_music_slider_knob.o \ lvgl/demos/music/assets/img_lv_demo_music_slider_knob_large.o \ lvgl/demos/music/assets/img_lv_demo_music_wave_bottom.o \ lvgl/demos/music/assets/img_lv_demo_music_wave_bottom_large.o \ lvgl/demos/music/assets/img_lv_demo_music_wave_top.o \ lvgl/demos/music/assets/img_lv_demo_music_wave_top_large.o \ lvgl/demos/music/lv_demo_music.o \ lvgl/demos/music/lv_demo_music_list.o \ lvgl/demos/music/lv_demo_music_main.o \ lvgl/demos/stress/lv_demo_stress.o \ lvgl/demos/widgets/assets/img_clothes.o \ lvgl/demos/widgets/assets/img_demo_widgets_avatar.o \ lvgl/demos/widgets/assets/img_lvgl_logo.o \ lvgl/demos/widgets/lv_demo_widgets.o \ lvgl/examples/anim/lv_example_anim_1.o \ lvgl/examples/anim/lv_example_anim_2.o \ lvgl/examples/anim/lv_example_anim_3.o \ lvgl/examples/anim/lv_example_anim_timeline_1.o \ lvgl/examples/assets/animimg001.o \ lvgl/examples/assets/animimg002.o \ lvgl/examples/assets/animimg003.o \ lvgl/examples/assets/emoji/img_emoji_F617.o \ lvgl/examples/assets/img_caret_down.o \ lvgl/examples/assets/img_cogwheel_alpha16.o \ lvgl/examples/assets/img_cogwheel_argb.o \ lvgl/examples/assets/img_cogwheel_chroma_keyed.o \ lvgl/examples/assets/img_cogwheel_indexed16.o \ lvgl/examples/assets/img_cogwheel_rgb.o \ lvgl/examples/assets/img_hand.o \ lvgl/examples/assets/img_skew_strip.o \ lvgl/examples/assets/img_star.o \ lvgl/examples/assets/imgbtn_left.o \ lvgl/examples/assets/imgbtn_mid.o \ lvgl/examples/assets/imgbtn_right.o \ lvgl/examples/event/lv_example_event_1.o \ lvgl/examples/event/lv_example_event_2.o \ lvgl/examples/event/lv_example_event_3.o \ lvgl/examples/event/lv_example_event_4.o \ lvgl/examples/get_started/lv_example_get_started_1.o \ lvgl/examples/get_started/lv_example_get_started_2.o \ lvgl/examples/get_started/lv_example_get_started_3.o \ lvgl/examples/layouts/flex/lv_example_flex_1.o \ lvgl/examples/layouts/flex/lv_example_flex_2.o \ lvgl/examples/layouts/flex/lv_example_flex_3.o \ lvgl/examples/layouts/flex/lv_example_flex_4.o \ lvgl/examples/layouts/flex/lv_example_flex_5.o \ lvgl/examples/layouts/flex/lv_example_flex_6.o \ lvgl/examples/layouts/grid/lv_example_grid_1.o \ lvgl/examples/layouts/grid/lv_example_grid_2.o \ lvgl/examples/layouts/grid/lv_example_grid_3.o \ lvgl/examples/layouts/grid/lv_example_grid_4.o \ lvgl/examples/layouts/grid/lv_example_grid_5.o \ lvgl/examples/layouts/grid/lv_example_grid_6.o \ lvgl/examples/libs/bmp/lv_example_bmp_1.o \ lvgl/examples/libs/ffmpeg/lv_example_ffmpeg_1.o \ lvgl/examples/libs/ffmpeg/lv_example_ffmpeg_2.o \ lvgl/examples/libs/freetype/lv_example_freetype_1.o \ lvgl/examples/libs/gif/img_bulb_gif.o \ lvgl/examples/libs/gif/lv_example_gif_1.o \ lvgl/examples/libs/png/img_wink_png.o \ lvgl/examples/libs/png/lv_example_png_1.o \ lvgl/examples/libs/qrcode/lv_example_qrcode_1.o \ lvgl/examples/libs/rlottie/lv_example_rlottie_1.o \ lvgl/examples/libs/rlottie/lv_example_rlottie_2.o \ lvgl/examples/libs/rlottie/lv_example_rlottie_approve.o \ lvgl/examples/libs/sjpg/lv_example_sjpg_1.o \ lvgl/examples/others/fragment/lv_example_fragment_1.o \ lvgl/examples/others/fragment/lv_example_fragment_2.o \ lvgl/examples/others/gridnav/lv_example_gridnav_1.o \ lvgl/examples/others/gridnav/lv_example_gridnav_2.o \ lvgl/examples/others/gridnav/lv_example_gridnav_3.o \ lvgl/examples/others/gridnav/lv_example_gridnav_4.o \ lvgl/examples/others/ime/lv_example_ime_pinyin_1.o \ lvgl/examples/others/ime/lv_example_ime_pinyin_2.o \ lvgl/examples/others/imgfont/lv_example_imgfont_1.o \ lvgl/examples/others/monkey/lv_example_monkey_1.o \ lvgl/examples/others/monkey/lv_example_monkey_2.o \ lvgl/examples/others/monkey/lv_example_monkey_3.o \ lvgl/examples/others/msg/lv_example_msg_1.o \ lvgl/examples/others/msg/lv_example_msg_2.o \ lvgl/examples/others/msg/lv_example_msg_3.o \ lvgl/examples/others/snapshot/lv_example_snapshot_1.o \ lvgl/examples/porting/lv_port_disp_template.o \ lvgl/examples/porting/lv_port_fs_template.o \ lvgl/examples/porting/lv_port_indev_template.o \ lvgl/examples/scroll/lv_example_scroll_1.o \ lvgl/examples/scroll/lv_example_scroll_2.o \ lvgl/examples/scroll/lv_example_scroll_3.o \ lvgl/examples/scroll/lv_example_scroll_4.o \ lvgl/examples/scroll/lv_example_scroll_5.o \ lvgl/examples/scroll/lv_example_scroll_6.o \ lvgl/examples/styles/lv_example_style_1.o \ lvgl/examples/styles/lv_example_style_10.o \ lvgl/examples/styles/lv_example_style_11.o \ lvgl/examples/styles/lv_example_style_12.o \ lvgl/examples/styles/lv_example_style_13.o \ lvgl/examples/styles/lv_example_style_14.o \ lvgl/examples/styles/lv_example_style_15.o \ lvgl/examples/styles/lv_example_style_2.o \ lvgl/examples/styles/lv_example_style_3.o \ lvgl/examples/styles/lv_example_style_4.o \ lvgl/examples/styles/lv_example_style_5.o \ lvgl/examples/styles/lv_example_style_6.o \ lvgl/examples/styles/lv_example_style_7.o \ lvgl/examples/styles/lv_example_style_8.o \ lvgl/examples/styles/lv_example_style_9.o \ lvgl/examples/widgets/animimg/lv_example_animimg_1.o \ lvgl/examples/widgets/arc/lv_example_arc_1.o \ lvgl/examples/widgets/arc/lv_example_arc_2.o \ lvgl/examples/widgets/bar/lv_example_bar_1.o \ lvgl/examples/widgets/bar/lv_example_bar_2.o \ lvgl/examples/widgets/bar/lv_example_bar_3.o \ lvgl/examples/widgets/bar/lv_example_bar_4.o \ lvgl/examples/widgets/bar/lv_example_bar_5.o \ lvgl/examples/widgets/bar/lv_example_bar_6.o \ lvgl/examples/widgets/btn/lv_example_btn_1.o \ lvgl/examples/widgets/btn/lv_example_btn_2.o \ lvgl/examples/widgets/btn/lv_example_btn_3.o \ lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_1.o \ lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_2.o \ lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_3.o \ lvgl/examples/widgets/calendar/lv_example_calendar_1.o \ lvgl/examples/widgets/canvas/lv_example_canvas_1.o \ lvgl/examples/widgets/canvas/lv_example_canvas_2.o \ lvgl/examples/widgets/chart/lv_example_chart_1.o \ lvgl/examples/widgets/chart/lv_example_chart_2.o \ lvgl/examples/widgets/chart/lv_example_chart_3.o \ lvgl/examples/widgets/chart/lv_example_chart_4.o \ lvgl/examples/widgets/chart/lv_example_chart_5.o \ lvgl/examples/widgets/chart/lv_example_chart_6.o \ lvgl/examples/widgets/chart/lv_example_chart_7.o \ lvgl/examples/widgets/chart/lv_example_chart_8.o \ lvgl/examples/widgets/chart/lv_example_chart_9.o \ lvgl/examples/widgets/checkbox/lv_example_checkbox_1.o \ lvgl/examples/widgets/checkbox/lv_example_checkbox_2.o \ lvgl/examples/widgets/colorwheel/lv_example_colorwheel_1.o \ lvgl/examples/widgets/dropdown/lv_example_dropdown_1.o \ lvgl/examples/widgets/dropdown/lv_example_dropdown_2.o \ lvgl/examples/widgets/dropdown/lv_example_dropdown_3.o \ lvgl/examples/widgets/img/lv_example_img_1.o \ lvgl/examples/widgets/img/lv_example_img_2.o \ lvgl/examples/widgets/img/lv_example_img_3.o \ lvgl/examples/widgets/img/lv_example_img_4.o \ lvgl/examples/widgets/imgbtn/lv_example_imgbtn_1.o \ lvgl/examples/widgets/keyboard/lv_example_keyboard_1.o \ lvgl/examples/widgets/label/lv_example_label_1.o \ lvgl/examples/widgets/label/lv_example_label_2.o \ lvgl/examples/widgets/label/lv_example_label_3.o \ lvgl/examples/widgets/label/lv_example_label_4.o \ lvgl/examples/widgets/label/lv_example_label_5.o \ lvgl/examples/widgets/led/lv_example_led_1.o \ lvgl/examples/widgets/line/lv_example_line_1.o \ lvgl/examples/widgets/list/lv_example_list_1.o \ lvgl/examples/widgets/list/lv_example_list_2.o \ lvgl/examples/widgets/menu/lv_example_menu_1.o \ lvgl/examples/widgets/menu/lv_example_menu_2.o \ lvgl/examples/widgets/menu/lv_example_menu_3.o \ lvgl/examples/widgets/menu/lv_example_menu_4.o \ lvgl/examples/widgets/menu/lv_example_menu_5.o \ lvgl/examples/widgets/meter/lv_example_meter_1.o \ lvgl/examples/widgets/meter/lv_example_meter_2.o \ lvgl/examples/widgets/meter/lv_example_meter_3.o \ lvgl/examples/widgets/meter/lv_example_meter_4.o \ lvgl/examples/widgets/msgbox/lv_example_msgbox_1.o \ lvgl/examples/widgets/obj/lv_example_obj_1.o \ lvgl/examples/widgets/obj/lv_example_obj_2.o \ lvgl/examples/widgets/roller/lv_example_roller_1.o \ lvgl/examples/widgets/roller/lv_example_roller_2.o \ lvgl/examples/widgets/roller/lv_example_roller_3.o \ lvgl/examples/widgets/slider/lv_example_slider_1.o \ lvgl/examples/widgets/slider/lv_example_slider_2.o \ lvgl/examples/widgets/slider/lv_example_slider_3.o \ lvgl/examples/widgets/span/lv_example_span_1.o \ lvgl/examples/widgets/spinbox/lv_example_spinbox_1.o \ lvgl/examples/widgets/spinner/lv_example_spinner_1.o \ lvgl/examples/widgets/switch/lv_example_switch_1.o \ lvgl/examples/widgets/table/lv_example_table_1.o \ lvgl/examples/widgets/table/lv_example_table_2.o \ lvgl/examples/widgets/tabview/lv_example_tabview_1.o \ lvgl/examples/widgets/tabview/lv_example_tabview_2.o \ lvgl/examples/widgets/textarea/lv_example_textarea_1.o \ lvgl/examples/widgets/textarea/lv_example_textarea_2.o \ lvgl/examples/widgets/textarea/lv_example_textarea_3.o \ lvgl/examples/widgets/tileview/lv_example_tileview_1.o \ lvgl/examples/widgets/win/lv_example_win_1.o \ lvgl/src/core/lv_disp.o \ lvgl/src/core/lv_event.o \ lvgl/src/core/lv_group.o \ lvgl/src/core/lv_indev.o \ lvgl/src/core/lv_indev_scroll.o \ lvgl/src/core/lv_obj.o \ lvgl/src/core/lv_obj_class.o \ lvgl/src/core/lv_obj_draw.o \ lvgl/src/core/lv_obj_pos.o \ lvgl/src/core/lv_obj_scroll.o \ lvgl/src/core/lv_obj_style.o \ lvgl/src/core/lv_obj_style_gen.o \ lvgl/src/core/lv_obj_tree.o \ lvgl/src/core/lv_refr.o \ lvgl/src/core/lv_theme.o \ lvgl/src/draw/arm2d/lv_gpu_arm2d.o \ lvgl/src/draw/lv_draw.o \ lvgl/src/draw/lv_draw_arc.o \ lvgl/src/draw/lv_draw_img.o \ lvgl/src/draw/lv_draw_label.o \ lvgl/src/draw/lv_draw_layer.o \ lvgl/src/draw/lv_draw_line.o \ lvgl/src/draw/lv_draw_mask.o \ lvgl/src/draw/lv_draw_rect.o \ lvgl/src/draw/lv_draw_transform.o \ lvgl/src/draw/lv_draw_triangle.o \ lvgl/src/draw/lv_img_buf.o \ lvgl/src/draw/lv_img_cache.o \ lvgl/src/draw/lv_img_decoder.o \ lvgl/src/draw/nxp/lv_gpu_nxp.o \ lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.o \ lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.o \ lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.o \ lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.o \ lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.o \ lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.o \ lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.o \ lvgl/src/draw/sdl/lv_draw_sdl.o \ lvgl/src/draw/sdl/lv_draw_sdl_arc.o \ lvgl/src/draw/sdl/lv_draw_sdl_bg.o \ lvgl/src/draw/sdl/lv_draw_sdl_composite.o \ lvgl/src/draw/sdl/lv_draw_sdl_img.o \ lvgl/src/draw/sdl/lv_draw_sdl_label.o \ lvgl/src/draw/sdl/lv_draw_sdl_layer.o \ lvgl/src/draw/sdl/lv_draw_sdl_line.o \ lvgl/src/draw/sdl/lv_draw_sdl_mask.o \ lvgl/src/draw/sdl/lv_draw_sdl_polygon.o \ lvgl/src/draw/sdl/lv_draw_sdl_rect.o \ lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.o \ lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.o \ lvgl/src/draw/sdl/lv_draw_sdl_utils.o \ lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.o \ lvgl/src/draw/sw/lv_draw_sw.o \ lvgl/src/draw/sw/lv_draw_sw_arc.o \ lvgl/src/draw/sw/lv_draw_sw_blend.o \ lvgl/src/draw/sw/lv_draw_sw_dither.o \ lvgl/src/draw/sw/lv_draw_sw_gradient.o \ lvgl/src/draw/sw/lv_draw_sw_img.o \ lvgl/src/draw/sw/lv_draw_sw_layer.o \ lvgl/src/draw/sw/lv_draw_sw_letter.o \ lvgl/src/draw/sw/lv_draw_sw_line.o \ lvgl/src/draw/sw/lv_draw_sw_polygon.o \ lvgl/src/draw/sw/lv_draw_sw_rect.o \ lvgl/src/draw/sw/lv_draw_sw_transform.o \ lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.o \ lvgl/src/extra/layouts/flex/lv_flex.o \ lvgl/src/extra/layouts/grid/lv_grid.o \ lvgl/src/extra/libs/bmp/lv_bmp.o \ lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.o \ lvgl/src/extra/libs/freetype/lv_freetype.o \ lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.o \ lvgl/src/extra/libs/fsdrv/lv_fs_posix.o \ lvgl/src/extra/libs/fsdrv/lv_fs_stdio.o \ lvgl/src/extra/libs/fsdrv/lv_fs_win32.o \ lvgl/src/extra/libs/gif/gifdec.o \ lvgl/src/extra/libs/gif/lv_gif.o \ lvgl/src/extra/libs/png/lodepng.o \ lvgl/src/extra/libs/png/lv_png.o \ lvgl/src/extra/libs/qrcode/lv_qrcode.o \ lvgl/src/extra/libs/qrcode/qrcodegen.o \ lvgl/src/extra/libs/rlottie/lv_rlottie.o \ lvgl/src/extra/libs/sjpg/lv_sjpg.o \ lvgl/src/extra/libs/sjpg/tjpgd.o \ lvgl/src/extra/lv_extra.o \ lvgl/src/extra/others/fragment/lv_fragment.o \ lvgl/src/extra/others/fragment/lv_fragment_manager.o \ lvgl/src/extra/others/gridnav/lv_gridnav.o \ lvgl/src/extra/others/ime/lv_ime_pinyin.o \ lvgl/src/extra/others/imgfont/lv_imgfont.o \ lvgl/src/extra/others/monkey/lv_monkey.o \ lvgl/src/extra/others/msg/lv_msg.o \ lvgl/src/extra/others/snapshot/lv_snapshot.o \ lvgl/src/extra/themes/basic/lv_theme_basic.o \ lvgl/src/extra/themes/default/lv_theme_default.o \ lvgl/src/extra/themes/mono/lv_theme_mono.o \ lvgl/src/extra/widgets/animimg/lv_animimg.o \ lvgl/src/extra/widgets/calendar/lv_calendar.o \ lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.o \ lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.o \ lvgl/src/extra/widgets/chart/lv_chart.o \ lvgl/src/extra/widgets/colorwheel/lv_colorwheel.o \ lvgl/src/extra/widgets/imgbtn/lv_imgbtn.o \ lvgl/src/extra/widgets/keyboard/lv_keyboard.o \ lvgl/src/extra/widgets/led/lv_led.o \ lvgl/src/extra/widgets/list/lv_list.o \ lvgl/src/extra/widgets/menu/lv_menu.o \ lvgl/src/extra/widgets/meter/lv_meter.o \ lvgl/src/extra/widgets/msgbox/lv_msgbox.o \ lvgl/src/extra/widgets/span/lv_span.o \ lvgl/src/extra/widgets/spinbox/lv_spinbox.o \ lvgl/src/extra/widgets/spinner/lv_spinner.o \ lvgl/src/extra/widgets/tabview/lv_tabview.o \ lvgl/src/extra/widgets/tileview/lv_tileview.o \ lvgl/src/extra/widgets/win/lv_win.o \ lvgl/src/font/lv_font.o \ lvgl/src/font/lv_font_dejavu_16_persian_hebrew.o \ lvgl/src/font/lv_font_fmt_txt.o \ lvgl/src/font/lv_font_loader.o \ lvgl/src/font/lv_font_montserrat_10.o \ lvgl/src/font/lv_font_montserrat_12.o \ lvgl/src/font/lv_font_montserrat_12_subpx.o \ lvgl/src/font/lv_font_montserrat_14.o \ lvgl/src/font/lv_font_montserrat_16.o \ lvgl/src/font/lv_font_montserrat_18.o \ lvgl/src/font/lv_font_montserrat_20.o \ lvgl/src/font/lv_font_montserrat_22.o \ lvgl/src/font/lv_font_montserrat_24.o \ lvgl/src/font/lv_font_montserrat_26.o \ lvgl/src/font/lv_font_montserrat_28.o \ lvgl/src/font/lv_font_montserrat_28_compressed.o \ lvgl/src/font/lv_font_montserrat_30.o \ lvgl/src/font/lv_font_montserrat_32.o \ lvgl/src/font/lv_font_montserrat_34.o \ lvgl/src/font/lv_font_montserrat_36.o \ lvgl/src/font/lv_font_montserrat_38.o \ lvgl/src/font/lv_font_montserrat_40.o \ lvgl/src/font/lv_font_montserrat_42.o \ lvgl/src/font/lv_font_montserrat_44.o \ lvgl/src/font/lv_font_montserrat_46.o \ lvgl/src/font/lv_font_montserrat_48.o \ lvgl/src/font/lv_font_montserrat_8.o \ lvgl/src/font/lv_font_simsun_16_cjk.o \ lvgl/src/font/lv_font_unscii_16.o \ lvgl/src/font/lv_font_unscii_8.o \ lvgl/src/hal/lv_hal_disp.o \ lvgl/src/hal/lv_hal_indev.o \ lvgl/src/hal/lv_hal_tick.o \ lvgl/src/misc/lv_anim.o \ lvgl/src/misc/lv_anim_timeline.o \ lvgl/src/misc/lv_area.o \ lvgl/src/misc/lv_async.o \ lvgl/src/misc/lv_bidi.o \ lvgl/src/misc/lv_color.o \ lvgl/src/misc/lv_fs.o \ lvgl/src/misc/lv_gc.o \ lvgl/src/misc/lv_ll.o \ lvgl/src/misc/lv_log.o \ lvgl/src/misc/lv_lru.o \ lvgl/src/misc/lv_math.o \ lvgl/src/misc/lv_mem.o \ lvgl/src/misc/lv_printf.o \ lvgl/src/misc/lv_style.o \ lvgl/src/misc/lv_style_gen.o \ lvgl/src/misc/lv_templ.o \ lvgl/src/misc/lv_timer.o \ lvgl/src/misc/lv_tlsf.o \ lvgl/src/misc/lv_txt.o \ lvgl/src/misc/lv_txt_ap.o \ lvgl/src/misc/lv_utils.o \ lvgl/src/widgets/lv_arc.o \ lvgl/src/widgets/lv_bar.o \ lvgl/src/widgets/lv_btn.o \ lvgl/src/widgets/lv_btnmatrix.o \ lvgl/src/widgets/lv_canvas.o \ lvgl/src/widgets/lv_checkbox.o \ lvgl/src/widgets/lv_dropdown.o \ lvgl/src/widgets/lv_img.o \ lvgl/src/widgets/lv_label.o \ lvgl/src/widgets/lv_line.o \ lvgl/src/widgets/lv_objx_templ.o \ lvgl/src/widgets/lv_roller.o \ lvgl/src/widgets/lv_slider.o \ lvgl/src/widgets/lv_switch.o \ lvgl/src/widgets/lv_table.o \ lvgl/src/widgets/lv_textarea.o \
1.2 快速测试Makefile修改是否有效
把主函数中和硬件相关的显示,输入等初始化代码屏蔽,main改为lv_main
,并把lv_main
变成一个命令:int lv_main(int argc, char **argv) { //(void *)argc; /*Unused*/ //(void)argv; /*Unused*/ printf("lv_main."); #if 0 /*Initialize LVGL*/ lv_init(); /*Create a default group for keyboard navigation*/ lv_group_set_default(lv_group_create()); /*Initialize the HAL (display, input devices, tick) for LVGL*/ hal_init(); ..... #endif return 0; } static lv_disp_t * hal_init(void ) { #if 0 disp_layer_cfg_def(); static lv_disp_draw_buf_t draw_buf; lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); ...... lv_disp_drv_register(&disp_drv); #endif lv_disp_t * disp = NULL; return disp; } FINSH_FUNCTION_EXPORT_ALIAS(lv_main, lv_main, lv_main );
编译通过,烧录测试。输入help,可以看到lv_main命令,输入lv_main,打印“lv_main”:
msh />help RT-Thread shell commands: ...... lv_main - lv_main ...... msh />lv_main lv_main
2.移植刷新显示内存函数dummy_flush_cb
只要往显存地址mem = g_disp_mm[mem_id].info_base
里面填写像素数据,就可以得到我们要显示的内容,把这个地址传给一个全局变量,在lvgl中使用这个全局变量即可。
于是我们在disp_mem
源码所在的C文件声明一个全局变量:uint32_t * g_p_mem_base;
把显存地址传给g_p_mem_base:
g_p_mem_base = g_disp_mm[mem_id].info_base;
有了这个地址,我们就可以编写自己的显示回调函数:
#define HOR_RES 800 #define VER_RES 480 extern uint32_t * g_p_mem_base; #define line_length 800 * sizeof(rt_uint32_t) / 4 static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { /*Truncate the area to the screen*/ int32_t act_x1 = area->x1 < 0 ? 0 : area->x1; int32_t act_y1 = area->y1 < 0 ? 0 : area->y1; int32_t act_x2 = area->x2 > (int32_t)HOR_RES - 1 ? (int32_t)HOR_RES - 1 : area->x2; int32_t act_y2 = area->y2 > (int32_t)VER_RES - 1 ? (int32_t)VER_RES - 1 : area->y2; lv_coord_t w = (act_x2 - act_x1 + 1); long int location = 0; /* 32 bit per pixel */ uint32_t *fbp32 = (uint32_t *)g_p_mem_base; uint32_t y; for (y = act_y1; y <= act_y2; y++) { location = act_x1 + y * line_length; rt_memcpy(&fbp32[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 4); color_p += w; } lv_disp_flush_ready(disp_drv); } static lv_color_t disp_buf1[HOR_RES * VER_RES]; static lv_color_t disp_buf2[HOR_RES * VER_RES]; int disp_layer_cfg_def(void); static lv_disp_t * hal_init(void ) { #if 1 disp_layer_cfg_def(); static lv_disp_draw_buf_t draw_buf; lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &draw_buf; disp_drv.flush_cb = dummy_flush_cb; disp_drv.hor_res = HOR_RES; disp_drv.ver_res = VER_RES; lv_disp_drv_register(&disp_drv); #endif lv_disp_t * disp = NULL; return disp; }
再make编译,通过。
3.创建一个定时器调用lvgl心跳lv_tick_inc()
Melis使用rt-thread内核,rt-thread的节拍由宏定义 CONFIG_HZ决定:#define RT_TICK_PER_SECOND CONFIG_HZ
CONFIG_HZ通过 命令 make menuconfig 配置:
这里是200Hz,也就是一个时钟节拍为5ms。
static rt_timer_t timer1; // lv_tick_inc(5); static lv_disp_t * hal_init(void ) { #if 1 /* 创建定时器1 周期定时器 */ timer1 = rt_timer_create("timer1", lv_tick_inc, // 回调函数 5, // 回调函数的传入参数 1, // 一个时钟节拍调用一次回调函数,具体是5ms RT_TIMER_FLAG_PERIODIC); /* 启动定时器1 */ if (timer1 != RT_NULL) rt_timer_start(timer1); disp_layer_cfg_def(); ...... #endif lv_disp_t * disp = NULL; return disp; }
lv_timer_handler()调用间隔是10ms,而lv_tick_inc()调用间隔是5ms,这样比较合理。
4.pack打包出错:
root@SK-JNTINRTMRDZW:/home/book/D1s-Melis-master# pack INFO: temporarily Enter pack directory: "/home/book/D1s-Melis-master/out/d1s-mq/image", will be back when terminated INFO: copying config/boot binary/phoenix plugin files /home/book/D1s-Melis-master/tools/phoenixplugin/Tools.fex ...... ...... INFO: running the function do_finish "sys_partition_nor.bin" partitation file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sys_partition_nor.bin mbr_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sunxi_mbr_nor.fex download_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/dlinfo.fex ERROR: dl file melis_pkg_nor.fex size too large ERROR: filename = melis_pkg_nor.fex ERROR: dl_file_size = 2272 sector ERROR: part_size = 2048 sector ERROR: update mbr file fail ERROR: update_mbr failed
melis_pkg_nor.fex
文件比分配的空间要大,装不下。
修改分区文件D1s-Melis/projects/d1s-mq/configs/sys_partition_nor.fex
第44,45行:
;--------------------------------------------------------------------------------------------------------- ; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串 ;--------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------- ; 固件下载参数配置 ;-------------------------------------------------------------------------------------------------- ;**************************************************** ; mbr的大小, 以Kbyte为单位 ;**************************************************** [mbr] size = 16 ;******************************************************************************************************** ; 分区配置 ; ; ; partition 定义范例: ; [partition] ; //表示是一个分区 ; name = USERFS2 ; //分区名称 ; size = 16384 ; //分区大小 单位: 扇区.分区表示个数最多2^31 * 512 = 2T ; downloadfile = "123.fex" ; //下载文件的路径和名称,可以使用相对路径,相对是指相对于image.cfg文件所在分区。也可以使用绝对路径 ; keydata = 1 ; //私有数据分区,重新量产数据将不丢失 ; encrypt = 1 ; //采用加密方式烧录,将提供数据加密,但损失烧录速度 ; user_type = ? ; //私有用法 ; verify = 1 ; //要求量产完成后校验是否正确 ; ; 注:1、name唯一, 不允许同名 ; 2、name最大12个字符 ; 3、size = 0, 将创建一个无大小的空分区 ; 4、为了安全和效率考虑,分区大小最好保证为16M字节的整数倍 ;******************************************************************************************************** [partition_start] ;[partition] ; name = boot ; size = 6656 ; downloadfile = "boot.fex" ; user_type = 0x8000 [partition] name = bootA ;size = 2048 size = 4096 downloadfile = "melis_pkg_nor.fex" user_type = 0x8000 ;[partition] ; name = bootB ; size = 6144 ; downloadfile = "melis_pkg_nor.fex" ; user_type = 0x8000 ;[partition] ; name = env ; size = 8 ; downloadfile = "env.fex" ; user_type = 0x8000 ;[partition] ; name = env-redund ; size = 8 ; downloadfile = "env.fex" ; user_type = 0x8000 ;rootfs 7616 sector in rootfs.ini make 7616*1024/512=15232 sectors for it. [partition] name = ROOTFS size = 10240 ;size = 20336 downloadfile = "data_udisk.fex" user_type = 0x8000 [partition] name = UDISK ;size = flash size - (boot0 + mbr) size - env - env-redund - ROOTFS ;8(or 16) * 1024 * 2 - 64 * 2 - 5632 - 8 - 8 - 10240 ;size = 20336 ;downloadfile = "data_udisk.fex" user_type = 0x8000
再次pack打包成功。烧录运行,输入lv_main命令:
msh />lv_main
5.设置开机启动
修改startup.sh
(位于目录 D1s-Melis/projects/d1s-mq/data/UDISK/startup.sh):echo "Execute startup script begin.............." #insmod d:\mod\display.mod #insmod d:\mod\orange.mod #insmod d:\apps\desktop.mod lv_main echo "...............Execute startup script end"
6.源码下载
源码没有startup.sh 和 melis_pkg_nor.fex ,这两个文件的修改比较简单。
源码链接:https://gitee.com/huangweide001/linux-d1-h-test/tree/master/disp2
源码包含了可以直接烧录的img文件 melis_d1s-mq_uart0_8Mnor_lvgl.img 。————————————————
本文为CSDN博主「hwd00001」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hwd00001/article/details/130017849 -
按照东山派的官方教程编译buildroot(东山哪吒,D1-H)踩坑记录
原文链接:https://blog.csdn.net/hwd00001/article/details/127896895
作者 @ hwd00001整个编译的耗时主要是github的下载速度,很多依赖包都需要从github下载。
这里我以东山派的官方教程为主,根据我的实际情况稍作调整,梳理一下编译buildroot流程。
官方教程链接:使用buildroot-SDK编译构建系统
1.编译流程
1.1获取sdk源码
有2个服务器github和gitee,我使用gitee的源。
依次执行命令:
book@virtual-machine:~$ git clone https://gitee.com/weidognshan/buildroot_dongshannezhastu book@virtual-machine:~$ cd buildroot_dshannezhastu book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --init --recursive book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --recursive --remote
这个步骤还是比较快的,10分钟以内,取决于网速。
1.2 补充:下载riscv64-glibc-gcc-thead_20200702.tar.xz
这个步骤参考后面的问题2.
1.3 补充:安装mtool工具
这个步骤参考后面的问题3.
1.4 安装必要依赖包
sudo apt-get install -y libncurses5-dev u-boot-tools
1.5 编译sdcard 最小系统镜像
book@virtual-machine:~/buildroot_dongshannezhastu$ cd buildroot-awol/ book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make BR2_EXTERNAL="../br2lvgl ../br2qt5 ../br2nezhastu" dongshannezhastu_sdcard_core_defconfig book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make
1.6 烧录最小镜像系统到tf(SD)卡
原文档:东山哪吒快速启动
1.6.1 安装烧录工具
1.6.2 格式化SD卡
1.6.3 烧录镜像到sd卡
1.7 运行系统
把SD卡插到开发板,上电,检查一下是不是最新编译的:
我对比一下原来的一张烧录官方提供的image的文件日期:
2.问题踩坑记录
问题1:make指令不执行
root@SK-JNTINRTMRDZW:/home/hwd/buildroot_dongshannezhastu/buildroot-awol> make Your PATH contains spaces, TABs, and/or newline (\n) characters. This doesn't work. Fix you PATH. support/dependencies/dependencies.mk:27: recipe for target 'dependencies' failed make: *** [dependencies] Error 1
百度解决方法:《This doesn‘t work. Fix you PATH》
采用这个方法顺利解决(切换环境变量)。
问题2:riscv64-glibc-gcc-thead_20200702.tar.xz File format not recognized
WARNING: no hash file for riscv64-glibc-gcc-thead_20200702.tar.xz ....../riscv64-glibc-gcc-thead_20200702.tar.xz: File format not recognized tar: This does not look like a tar archive tar: Exiting with failure status due to previous errors
去到该文件所在目录
/home/hwd/buildroot_dongshannezhastu/buildroot-awol/dl/toolchain-external-custom
看到,文件的大小只有1k,不知道是什么原因导致的。
继续百度搜到《为全志D1/RISCV64设备移植openwrt-22.03系统》,提到要手动下载riscv64-glibc-gcc-thead_20200702.tar.xz
,提供了东山派的官方链接:《快速使用Tina-SDK 指南》:下载完成后,发现文件名是
riscv64-glibc-gcc-thead_20200702tar.xz
:
增加小数点后,不用解压,重新执行make,自动解压成功,往下进行。问题3: /bin/sh: 1: mcopy: not found
没有安装mtool工具:
apt-get install mtools
重新make,终于完成:
-
求推荐一个视频录像的芯片方案
需要的功能如下:
- 支持数字摄像头输入,
- cvbs输入(和数字摄像头输入不是同时进行),
- cvbs输出,
- LCD屏幕显示(和cvbs输出不是同时进行),
- 支持编码器和解码器,最高支持1920X1080@30fps,可以更高。
- 支持SD
我看F1C100S的datasheet,没有H.264编码器。是不是就可以直接排除F1C100S了?
-
回复: 参照大佬的教程在Tina下适配 i80 LCD 显示屏,一接屏幕就报错重启
@bayche 谢谢大佬,还有个问题
disp_al_manager_apply ouput_type:0 怎么把 ouput_type:改为1,是修改board.dts的disp么 ? -
参照大佬的教程在Tina下适配 i80 LCD 显示屏,一接屏幕就报错重启
参照大佬的教程来做的:https://www.gloomyghost.com/live/20220424.aspx
然后一装上屏幕就会报以下错误
然后就重启了,是 板子的io没有配制好还是 电路有问题?
-
【米尔MYD-YT507开发板试用】基于Fluter+Django+OpenCV的米尔行车记录仪
经过充分的学习T507开发板,最终选择应用Fluter+Django+OpenCV架构,来实现了一款米尔行车记录仪,现将实现的具体内容,与大家分享。
目录:
- 行车记录仪业务逻辑规划
- 硬件设备准备
- 摄像头信息记录和实时画面播放服务开发
- 摄像头视频信息记录
- 摄像头服务的完整代码
- 历史数据RestFul服务开发
- Flutter Web界面开发
- 整体运行效果
- 车试
- 实际代码使用
- 感谢
- 总结
一、行车记录仪业务逻辑规划
经过详细的分析,规划了如下的基本业务逻辑结构:
整体分为三个部分:
-
记录服务:用于记录摄像头拍摄的视频信息,以及提供摄像头当前画面的实时播放服务。
-
Django服务:包括RestFul提供API接口获取历史数据信息,以及为Flutter的Web界面提供访问服务。
-
Flutter Web界面,用于实时画面播放、历史记录播放的界面。
为了又快又好的开发行车记录仪的实际界面,以及后续进行各移动平台的App开发,选择了Flutter。事实证明,坑太多了。不过,跨平台特性,确实好。
二、硬件设备准备:
开发这款行车记录仪,实际使用到的硬件设备如下:
1.主控板:米尔MYD-YT507开发板
2.摄像头:海康威视DS-E11 720P USB摄像头
3.存储卡:闪迪32GB高速MicroSD存储卡
4.路由器:云来宝盒无线路由器路由器没有拍照,用普通无线路由器即可,当然带宽越高越好。
开发板上有两个USB3.0接口,选一个接上路由器即可。
然后,将开发板使用网线连接到路由器,再上电,就可以进行实际的操作了。
我这边实际使用中,电源接口有点松,容易突然断电,所以使用胶带进行了加固。
三、摄像头实时画面播放服务开发
在之前尝试MJPEG视频流直播的时候,使用了mjpeg_streamer,但不清楚如何进行视频的分割。
因为行车记录仪,一般都是按照一定的时间进行视频的分割存放,避免单个视频过大。
经过仔细的学习了解,OpenCV也可以获取摄像头的信息,并按照需要写入文件。
最后,采用了Python+OpenCV的方案,有Python负责具体的逻辑,Python-OpenCV负责摄像头视频数据的采集。
视频采集部分,包含的具体功能为:
- 能够采集摄像头的数据
- 能够提供实时视频查看
- 能够按时间写入视频数据到文件,自动进行分割
采集摄像头的数据,Python-opencv搞定。
写入视频数据到文件,Python简单搞定。
提供实时视频预览,这个花了不少功夫。
因为同时要写入到文件,还要提供预览,数据需要复用。
经过学习了解,可以将Python-opencv采集的画面,按帧在HTTP以JPEG数据发送,那么播放端,就能收到MJPEG数据流,进行播放了。
因此,第一版,参考资料,实现了一个Python版的MJPEG播放服务,读取帧,写入临时文件,然后从临时文件读取数据返回。
为了提高效率,还进行了优化,不写入临时文件,直接在内存中进行转换。
最终形成的代码如下:
# http服务器请求处理:网页、MJPEG数据流 class CamHandler(BaseHTTPRequestHandler): def do_GET(self): # mjpeg推流 if self.path.endswith('.mjpg'): self.send_response(200) self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary') self.end_headers() while True: if is_stop: break try: # rc,img = cameraCapture.read() rc,img = success,frame if not rc: continue if True: imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) jpg = Image.fromarray(imgRGB) tmpFile = BytesIO() jpg.save(tmpFile,'JPEG') self.wfile.write(b"--jpgboundary") self.send_header(b'Content-type','image/jpeg') self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes)) self.end_headers() jpg.save(self.wfile,'JPEG') else: img_fps = JPEG_QUALITY_VALUE img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps] img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format self.send_header('Content-type','image/jpeg') self.end_headers() self.wfile.write(img_str) self.wfile.write(b" --jpgboundary ") # end of this part time.sleep(0.033) except KeyboardInterrupt: self.wfile.write(b" --jpgboundary-- ") break except BrokenPipeError: continue return # 网页 if self.path == '/' or self.path.endswith('.html'): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write(b'<html><head><title>Live video</title></head><body>') self.wfile.write(('<img src="http://%s/live.mjpg"/>' % self.headers.get('Host')).encode()) self.wfile.write(b'</body></html>') return
这段代码,提供了两个功能:
-
如果通过浏览器访问http://ip:端口/index.html,就会返回包含MJPEG调用地址的网页
-
如果通过浏览器访问http://ip:端口/live.mjpg,就会返回MJPEG流媒体数据,以便播放
在开发过程中,运行该服务后,随时可以通过浏览器查看效果。
其中涉及到opencv相关的知识,以及webserver相关的知识,大家可以了解相关的资料做基础,这里就不详细说了。
本来以为提供了MJPEG服务,就能够在Flutter开发的Web界面中调用了。然而,实际使用时,发现坑来了。
Flutter的公共库里面,有MJPEG的库,但是在目前的版本中,已经不能使用了。且官方认为用的人不多,在可预见的将来,不会修复。悲催啊!!!
条条大道通罗马,此处不通开新路。
经过再次的学习了解,Flutter的Video功能,支持Stream模式,其可以采用WebSocket的方式来获取数据,然后进行播放。
那么,只要能够在服务端,将获取的帧数据,使用WebSocket提供,就能够正常播放了。
最终,使用Python开发了能够提供实时视频数据的WebSocket服务,具体代码如下:
# websocket服务请求处理 async def CamTransmitHandler(websocket, path): print("Client Connected !") try : while True: # rc,img = cameraCapture.read() rc,img = success,frame if not rc: continue img_fps = JPEG_QUALITY_VALUE img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps] encoded = cv2.imencode('.jpg', img, img_param)[1] data = str(base64.b64encode(encoded)) data = data[2:len(data)-1] await websocket.send(data) # cv2.imshow("Transimission", frame) # if cv2.waitKey(1) & 0xFF == ord('q'): # break # cap.release() except EXCEPTION_CONNECTION_CLOSE as e: print("Client Disconnected !") # cap.release() except: print("Someting went Wrong !")
这个部分比之前的更简单,就是简单的转换数据,喂数据给WebSocket即可。
上述的两部分代码中,都没有包含完整的逻辑处理过程,只有关键代码部分。
各部分分别讲完以后,将提供完整的代码以供学习。
到这里,实时流媒体功能就实现了。
四、摄像头视频信息记录
实际上,上一步的实时视频功能,也依赖于这一步,因为其需要共享实际获取的摄像头信息。
其基本逻辑也比较简单,步骤如下:- 初始化opencv,开始摄像头数据帧的获取
- 检测是否达到预定时间
- 未达到时间,则继续写入当前视频
- 达到时间了,则关闭当前视频,写入缩略图,并开启新的文件写入
具体代码如下:
# 捕获摄像头 cameraCapture = cv2.VideoCapture(CAMERA_NO) # 摄像头参数设置 cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240) cameraCapture.set(cv2.CAP_PROP_SATURATION, 135) fps = 30 size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 读取捕获的数据 success,frame = cameraCapture.read()
...
while True: if is_stop: success = False break; success,frame = cameraCapture.read() if not success: continue time_now = get_current_time() if time_now["time"] - time_record["time"] >= ROTATE_TIME: if time_record_prev: thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg') print("[Info] write to thumb: %s" % thubm_file) if not os.path.isfile(thubm_file): cv2.imwrite(thubm_file, frame) time_record = time_now time_record_prev = get_current_time() video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT) print("[Info] write to video: %s" % video_file) # encode = cv2.VideoWriter_fourcc(*"mp4v") encode = cv2.VideoWriter_fourcc(*'X264') # encode = cv2.VideoWriter_fourcc(*'AVC1') # encode = cv2.VideoWriter_fourcc(*'XVID') # encode = cv2.VideoWriter_fourcc(*'H264') videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4 numFrameRemaining = ROTATE_TIME * fps #摄像头捕获持续时间 while success and numFrameRemaining > 0: videoWriter.write(frame) success,frame = cameraCapture.read() numFrameRemaining -= 1 cameraCapture.release()
上述代码的逻辑其实很清晰,有opencv的基础,一看就懂。
有一个关键点需要注意的就是
encode = cv2.VideoWriter_fourcc(*'X264')
,在不同的环境下面,提供的编码方式不完全相同。在米尔MYD-YT507开发板的Ubuntu环境中,可以使用X264编码。
上述代码,会持续不断的读取摄像头的数据帧,存放到frame变量中,然后写入到视频文件中。并进行时间判断,以确定是否需要写入到新的视频文件中。
frame变量,在之前实时视频服务中,也会使用,相当于是共享了。
五、摄像头服务的完整代码
经过上面的两个部分,就完成了摄像头部分的服务代码。
整体的代码如下:
# -*- coding: utf-8 -*- import signal import cv2 import time from PIL import Image from threading import Thread from http.server import BaseHTTPRequestHandler,HTTPServer from socketserver import ThreadingMixIn from io import BytesIO import os import sys import websockets import asyncio import base64 import ctypes import inspect CAMERA_NO = 2 ROTATE_TIME = 120 MJPEG_ENABLE = 1 WEBSOCKET_ENABLE = 1 MJPEG_SERVER_PORT = 28888 WEBSOCKET_PORT = 28889 JPEG_QUALITY_VALUE = 65 STORE_DIR = "./data/" if os.uname()[0] == 'Darwin' else "/sdcard/data/" MEDIA_EXT = "mkv" EXCEPTION_CONNECTION_CLOSE = websockets.exceptions.ConnectionClosed if sys.version[:3] == '3.6' else websockets.ConnectionClosed def _async_raise(tid, exctype): """raises the exception, performs cleanup if needed""" try: tid = ctypes.c_long(tid) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) if res == 0: # pass raise ValueError("invalid thread id") elif res != 1: # """if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect""" ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed") except Exception as err: print(err) def stop_thread(thread): """终止线程""" _async_raise(thread.ident, SystemExit) # 信号处理回调 def signal_handler(signum, frame): # global cameraCapture # global thread # global server # global is_stop # global success print('signal_handler: caught signal ' + str(signum)) if signum == signal.SIGINT.value: print('stop server:') is_stop = True success = False print("mjpeg server.socket.close...") server.socket.close() print("mjpeg server.shutdown...") server.shutdown() print("ws server.socket.close...") server_ws.ws_server.close() time.sleep(1) # print("ws server.shutdown...") # await server_ws.ws_server.wait_closed() print("mjpeg thread.shutdown...") thread_mjpeg.join() print("ws loop.shutdown...") # event_loop_ws.stop() event_loop_ws.call_soon_threadsafe(event_loop_ws.stop) time.sleep(1) # print("ws thread.shutdown...") # stop_thread(thread_ws) # time.sleep(1) # print(server) # print(server_ws) print(thread_mjpeg.is_alive()) print(thread_ws.is_alive()) print(event_loop_ws.is_running()) # thread_ws.join() print("cameraCapture.release...") cameraCapture.release() print("quit...") # print(server_ws) sys.exit(0) # http服务器请求处理:网页、MJPEG数据流 class CamHandler(BaseHTTPRequestHandler): def do_GET(self): # mjpeg推流 if self.path.endswith('.mjpg'): self.send_response(200) self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary') self.end_headers() while True: if is_stop: break try: # rc,img = cameraCapture.read() rc,img = success,frame if not rc: continue if True: imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) jpg = Image.fromarray(imgRGB) tmpFile = BytesIO() jpg.save(tmpFile,'JPEG') self.wfile.write(b"--jpgboundary") self.send_header(b'Content-type','image/jpeg') self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes)) self.end_headers() jpg.save(self.wfile,'JPEG') else: img_fps = JPEG_QUALITY_VALUE img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps] img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format self.send_header('Content-type','image/jpeg') self.end_headers() self.wfile.write(img_str) self.wfile.write(b" --jpgboundary ") # end of this part time.sleep(0.033) except KeyboardInterrupt: self.wfile.write(b" --jpgboundary-- ") break except BrokenPipeError: continue return # 网页 if self.path == '/' or self.path.endswith('.html'): self.send_response(200) self.send_header('Content-type','text/html') self.end_headers() self.wfile.write(b'<html><head><title>Live video</title></head><body>') self.wfile.write(('<img src="http://%s/live.mjpg"/>' % self.headers.get('Host')).encode()) self.wfile.write(b'</body></html>') return class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread.""" # 启动MJPEG服务 def mjpeg_server_star(): global success global server global thread_mjpeg try: server = ThreadedHTTPServer(('0.0.0.0', MJPEG_SERVER_PORT), CamHandler) print("mjpeg server started: http://0.0.0.0:%d" % MJPEG_SERVER_PORT) # server.serve_forever() thread_mjpeg = Thread(target=server.serve_forever); thread_mjpeg.start() except KeyboardInterrupt: print("mjpeg server stoping...") server.socket.close() server.shutdown() print("mjpeg server stoped") # websocket服务请求处理 async def CamTransmitHandler(websocket, path): print("Client Connected !") try : while True: # rc,img = cameraCapture.read() rc,img = success,frame if not rc: continue img_fps = JPEG_QUALITY_VALUE img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps] encoded = cv2.imencode('.jpg', img, img_param)[1] data = str(base64.b64encode(encoded)) data = data[2:len(data)-1] await websocket.send(data) # cv2.imshow("Transimission", frame) # if cv2.waitKey(1) & 0xFF == ord('q'): # break # cap.release() except EXCEPTION_CONNECTION_CLOSE as e: print("Client Disconnected !") # cap.release() except: print("Someting went Wrong !") # websocket服务器启动 def websocket_server_start(): global thread_ws global server_ws global event_loop_ws event_loop_ws = asyncio.new_event_loop() def run_server(): global server_ws print("websocket server started: ws://0.0.0.0:%d" % WEBSOCKET_PORT) server_ws = websockets.serve(CamTransmitHandler, port=WEBSOCKET_PORT, loop=event_loop_ws) event_loop_ws.run_until_complete(server_ws) event_loop_ws.run_forever() thread_ws = Thread(target=run_server) thread_ws.start() # try: # yield # except e: # print("An exception occurred") # finally: # event_loop.call_soon_threadsafe(event_loop.stop) # 获取存储的文件名 def get_file_name(time_obj, path, ext): file_name_time = "%04d-%02d-%02d_%02d-%02d-%02d" % (time_obj["year"], time_obj["month"], time_obj["day"], time_obj["hour"], time_obj["min"], 0) return '%s/%s/%s.%s' % (STORE_DIR, path, file_name_time, ext) # 获取当前整分时间 def get_current_time(): time_now = time.localtime() time_int = int(time.time()) return { "year": time_now.tm_year, "month": time_now.tm_mon, "day": time_now.tm_mday, "hour": time_now.tm_hour, "min": time_now.tm_min, "sec": time_now.tm_sec, "time": time_int - time_now.tm_sec } # 设置信号回调 signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # 捕获摄像头 cameraCapture = cv2.VideoCapture(CAMERA_NO) # 摄像头参数设置 cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240) cameraCapture.set(cv2.CAP_PROP_SATURATION, 135) fps = 30 size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 读取捕获的数据 success,frame = cameraCapture.read() if not success: print("camera start failed.") quit() is_stop = False server = None server_ws = None event_loop_ws = None thread_mjpeg = None thread_ws = None mjpeg_server_star() websocket_server_start() print("record server star:") thubm_file = None video_file = None time_start = int(time.time()) time_record = {"time":0} time_record_prev = None while True: if is_stop: success = False break; success,frame = cameraCapture.read() if not success: continue time_now = get_current_time() if time_now["time"] - time_record["time"] >= ROTATE_TIME: if time_record_prev: thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg') print("[Info] write to thumb: %s" % thubm_file) if not os.path.isfile(thubm_file): cv2.imwrite(thubm_file, frame) time_record = time_now time_record_prev = get_current_time() video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT) print("[Info] write to video: %s" % video_file) # encode = cv2.VideoWriter_fourcc(*"mp4v") encode = cv2.VideoWriter_fourcc(*'X264') # encode = cv2.VideoWriter_fourcc(*'AVC1') # encode = cv2.VideoWriter_fourcc(*'XVID') # encode = cv2.VideoWriter_fourcc(*'H264') videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4 numFrameRemaining = ROTATE_TIME * fps #摄像头捕获持续时间 while success and numFrameRemaining > 0: videoWriter.write(frame) success,frame = cameraCapture.read() numFrameRemaining -= 1 cameraCapture.release()
在上述代码中,除了前面说过的三个部分,还包括启动web和websocket线程的部分。因为核心逻辑为读取视频数据并写入文件,所以其他部分,以线程的模式启动,以便同时进行处理。
将上述代码保存为DrivingRecorderAndMjpegServer.py,然后运行即可。(依赖包,见代码库中requirements.txt)
实际访问效果如下:
六、历史数据RestFul服务开发
历史数据服务,本来也可以使用Python直接手写,但考虑到可扩展性,使用Django来进行了编写。
Djano服务,需要提供如下的功能:
- 提供api接口,以便获取历史数据记录列表,便于前端界面呈现展示
- 提供Flutter Web界面代码文件的托管,以便通过浏览器访问
- 提供静态文件的访问,例如查看历史视频文件
2和3本质都是一个问题,通过Django的static功能,就能实现。
也就是在settings.py配置中,提供下面的配置即可:
STATIC_URL = 'static/' STATICFILES_DIRS = [ BASE_DIR / "static" ]
1对外提供api服务,则需要设置对应的url接口,以及读取历史文件信息,生成前端需要的json数据结构,这部分的具体代码如下:
# 媒体文件存放目录,以及缩略图和视频文件的后缀 THUMB_HOME_DIR = "%s/%s/data/thumbs/" % (BASE_DIR, STATIC_URL) VIDEO_HOME_DIR = "%s/%s/data/videos/" % (BASE_DIR, STATIC_URL) IMG_FILTER = [".jpg"] MEDIA_FILTER = [ ".mkv"]
import json from django.shortcuts import render, HttpResponse from rest_framework.response import Response from rest_framework.permissions import AllowAny from rest_framework.decorators import api_view, permission_classes import os from django.conf import settings THUMB_HOME_DIR = settings.THUMB_HOME_DIR VIDEO_HOME_DIR = settings.VIDEO_HOME_DIR IMG_FILTER = settings.IMG_FILTER MEDIA_FILTER = settings.MEDIA_FILTER # Create your views here. @api_view(['GET'],) @permission_classes([AllowAny],) def hello_django(request): str = '''[ { "id": 1, "time": "2022-07-28 21:00", "title": "2022-07-28 21:00", "body": "videos/2022-07-28_2100.mp4" }, { "id": 2, "time": "2022-07-28 23:00", "title": "2022-07-28 23:00", "body": "videos/2022-07-28_2300.mp4" }, { "id": 3, "time": "2022-07-28 25:00", "title": "2022-07-28 25:00", "body": "videos/2022-07-28_2500.mp4" } ]''' _json = json.loads(str) return HttpResponse(json.dumps(_json), content_type='application/json') @api_view(['GET'],) @permission_classes([AllowAny],) def history_list(request): next = request.GET.get("next", '') print(f"thumb next = {next}") path = "/".join(request.path.split("/")[3:]) print(f"thumb request.path= {request.path}") print(f"thumb path = {path}") #print os.listdir(FILE_HOME_DIR+".none/") data = {"files":[], "dirs":[]} print(data) child_path = THUMB_HOME_DIR+next print(f"child_path = {child_path}") data['cur_dir'] = path+next print(data) for dir in os.listdir(child_path): if os.path.isfile(child_path+"/"+dir): if os.path.splitext(dir)[1] in IMG_FILTER: data['files'].append(dir) else: data['dirs'].append(dir) print(data) data['files']=sorted(data['files']) data['files'].reverse() data['infos'] = [] for i in range(0,len(data['files'])): thumb_name = data['files'][i] video_name = thumb_name.replace('.jpg', MEDIA_FILTER[0]) file_time = thumb_name.replace('.jpg', '').replace('_', ' ') data['infos'].append( { "id": i, "time": file_time, "title": file_time, "body": thumb_name, 'thumb': thumb_name, 'video': video_name } ) return Response(data['infos'], status = 200)
其中有两个接口:
hello_django
是最开始学习使用的,返回写死的json数据。history_list
,则是自动遍历缩略图文件夹,获取缩略图文件信息,并生成所需要的json数据格式。在对应的代码库文件中,也包含了requirements.txt,其中标明了实际需要的依赖库。
下载代码,进入manage.py所在的目录后,执行下面的命令即可启动:
访问 192.168.1.15:8000/app/hellodjango :
访问:History List – Django REST framework
可以看到 history_list接口,已经可以提供实际需要的数据了。
七、Flutter Web界面开发
这个部分设计的代码比较多,所以只对关键部分的代码进行说明。
开发的实际代码,位于lib目录,具体为:
- globals.dart:全局变量定义
- main.dart:程序入口
- home_page.dart:首页
- live_page.dart:实时播放
- live_page_mp4.dart:测试播放mp4视频
- history_page.dart:历史记录列表页面
- video_detail.dart:单条历史记录详情
- video_play.dart:播放具体的历史视频
- video_model.dart:单条记录的数据模型
- http_service.dart:请求RestFul接口
- websocket.dart:实时视频的WebSocket请求
整个界面,使用了
Scaffold
来模拟手机/Pad的操作界面,具体界面如下:在实时画面界面中,使用了WebSocket监听,获取到信息,就使用Stream模式,推送给视频播放。
在历史记录界面中,则通过RestFul请求列表数据,然后呈现。
八、整体运行效果
实际的运行效果,不用多说,看界面就成:
实时画面:
历史记录列表:
历史记录播放:
九、车试:
经过反复的测试验证,确保各项功能完整后,进行了上车实测。
因为最近的疫情原因,所以只在村里转了一圈,进行了实际测试,可以查看最后的视频。后续有机会,再找个晴朗的天气,去环境优美的地方实际拍摄录制。
十、实际代码说明:
完整的代码,请通过 米尔行车记录仪: 米尔行车记录仪 (https://gitee.com/honestqiao/MYiR-Driving-Recorder) 获取。
代码目录说明如下:
- DrivingRecorder:摄像头服务
- backend:RestFul服务
- frontend:Flutter Web界面
在以上仓库中,包含了详细的代码使用说明。
在实际应用中,将记录视频的data目录与后端static/data目录关联,以便两者统一。
十一、感谢
在研究学习的过程中,参考了数十篇各类资料,先将部分列出如下。对所有学习过的资料的作者,表示深深的感谢。
janakj/py-mjpeg: Python MJPEG streaming utilities (github.com)
Simple Python Motion Jpeg (mjpeg server) from webcam. Using: OpenCV,BaseHTTPServer (github.com)
Python 使用USB Camera录制MP4视频_Frank_Abagnale的博客-CSDN博客
用 Python、nginx 搭建在线家庭影院 - 知乎 (zhihu.com)
Django报错解决:RuntimeError: Model class ...apps... doesn't declare an explicit app_label and isn't in a_lyp039078的博客-CSDN博客
Python OpenCV 调用摄像头并截图保存_Clannad_niu的博客-CSDN博客
用 Python、nginx 搭建在线家庭影院mob604756e97f09的技术博客51CTO博客
Python-OpenCV录制H264编码的MP4视频 - 掘金 (juejin.cn)
[VideoWriter]保存H264/MPEG4格式MP4视频 - image processing (zj-image-processing.readthedocs.io)
Manual USB camera settings in Linux | KUROKESU
UVC Web Cameras (indilib.org)
编写你的第一个 Flutter 网页应用 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
macOS install | Flutter
[Django 設定 LANGUAGE_CODE 時所遇到的麻煩] OSError: No translation files found for default language zh-TW. (github.com)**
Django And Flutter — 样板应用程序|的分步教程作者:Clever Tech Memes |中等 (medium.com)
joke2k/django-environ: Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application. (github.com)
django 之跨域访问问题解决 access-control-allow-origin - 腾讯云开发者社区-腾讯云 (tencent.com)
django-cors-headers · PyPI
Django项目解决跨域问题 - SegmentFault 思否
video_player | Flutter Package (pub.dev)
视频的播放和暂停 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
5.7 页面骨架(Scaffold) | 《Flutter实战·第二版》 (flutterchina.club)
itfitness/BottomNavigationBarDemo - 码云 - 开源中国 (gitee.com)
Flutter底部导航 - 简书 (jianshu.com)
Flutter之自定义底部导航条以及页面切换实例——Flutter基础系列houruoyu3的博客-CSDN博客flutter 自定义底部导航
How To Use HTTP Requests in Flutter | DigitalOcean
在Flutter中发起HTTP网络请求 - Flutter中文网 (flutterchina.club)
Fetch data from the internet | Flutter
获取网络数据 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
深入理解 Function & Closure - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
Django And Flutter — A Step by Step Tutorial for a Boilerplate Application | by Clever Tech Memes | Medium
multithreading - Multithreaded web server in python - Stack Overflow
Simple Python HTTP Server with multi-threading and partial-content support (github.com)
meska/mjpeg_stream_webcam: Webcam Streamer for Octoprint MacOs (github.com)
blueimp/mjpeg-server: MJPEG Server implements MJPEG over HTTP using FFmpeg or any other input source capable of piping a multipart JPEG stream to stdout. Its primary use case is providing Webdriver screen recordings. (github.com)
n3wtron/simple_mjpeg_streamer_http_server: simple python mjpeg streamer http server (github.com)
Python3远程监控程序实现肥宅Sean的博客-CSDN博客
opencv imencode跟imdecode函数jpg(python) - PythonTechWorld
flutter_mjpeg | Flutter Package (pub.dev)
Can't work on web platform. · Issue #13 · mylisabox/flutter_mjpeg (github.com)
Consider if fetch is widely supported enough to use · Issue #595 · dart-lang/http (github.com)
在 Flutter | 中创建实时视频流应用程序作者:Mitrajeet Golsangi |开发人员学生社区 Vishwakarma 技术学院,浦那 |中等 (medium.com)
Python websockets.serve方法代碼示例 - 純淨天空 (vimsky.com)
Flutter 常用組件講解 | ImageWidget - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)
Bad State: Stream has already been listened to. · Issue #29105 · flutter/flutter (github.com)
flutter - Streambuilder with WebSockets stream in TabBarView: Bad state: Stream has already been listened to - Stack Overflow
使用WebSockets - Flutter中文网 (flutterchina.club)
VideoStreaming.dart (github.com)
在 Flutter | 中创建实时视频流应用程序作者:Mitrajeet Golsangi |开发人员学生社区 Vishwakarma 技术学院,浦那 |中等 (medium.com)
Flutter:WebSocket封装-实现心跳、重连机制 - 让我留在你身边 (ricardolsw.github.io)
2.3 状态管理 | 《Flutter实战·第二版》 (flutterchina.club)
路由和导航 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
7.6 异步UI更新(FutureBuilder、StreamBuilder) | 《Flutter实战·第二版》 (flutterchina.club)
Flutter 常用組件講解 | ImageWidget - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)
Step By Step Tutorial in Learning Flutter: Lesson 12 — Adding Image (Ice Pokemon) | by Misterflutter | Quick Code | Medium
Django CORS on static asset - Stack Overflow
配置 | Django 文档 | Django (djangoproject.com)
Global Variables in Dart - Stack Overflow
UVC - Community Help Wiki (ubuntu.com)
利用OpenCV进行H264视频编码的简易方式 - 知乎 (zhihu.com)
Documentation for OPENCV_FFMPEG_WRITER_OPTIONS and OPENCV_FFMPEG_CAPTURE_OPTIONS · Issue #21155 · opencv/opencv (github.com)
利用OpenCV进行H264视频编码的简易方式 - 知乎 (zhihu.com)
FFmpeg概述及编码支持 - 知乎 (zhihu.com)
Web 渲染器 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter十二、总结
在研究学习的过程中,对Linux系统下的UVC框架有了进一步的了解,对Flutter进行应用开发有了实际的了解,对OpenCV的实际应用也有了具体的了解。
在实际开发的过程中,遇到的最大的坑来自Flutter,因为变化太快,有一些功能可能兼容性没有跟上。不过更多是自己学艺不精导致的。
另外,目前还只是V1.0版本,后续还存在较大的优化空间。例如对于OpenCV的应用,可以调整参数,优化获取的视频数据的指令和大小等。这些有待于进一步学习后进行。
最主要的,对米尔MYD-YT507开发板有了深入的了解,进行了实际的应用。作为一款车规级处理器T507的开发板,名不虚传!