tag 标签: 编程

相关帖子
相关博文
  • 热度 2
    2024-8-25 18:19
    833 次阅读|
    0 个评论
    Gokit2.0针对硬件开发者的智能硬件开发板GoKit,用于帮助开发者快速实现智能硬件的原型开发。GoKit支持开发者将产品接入目前行业中各大流行的模组方案,帮助他们与高通、庆科、博通、 汉枫等对接,开发者只需扫一下相应的二维码就可以连接机智云2.0,通过机智云后台定义产品,产品通过WiFi模块上的GAgent接入机智云M2M服务器,扫描二维码直接控制设备。GoKit上还集成了马达、1600万色的LED、Wifi模块、红外光感、温湿度等传感器。 与其他硬件开发平台Aduino不同,GoKit的定位是帮助开发者做出可以商业化的产品,所以在技术选型上参考了市面上成功的智能家居产品,并且做了优化。而且GoKit有原生的网络服务支持,开发者可以快速在机智云2.0平台上定制手机App和网络轻应用。 机智云Gokit2.0开发板自带了名为“微信宠物屋”整体性DEMO,不仅在主板注入了固件,还有APP、微信小程序。按照自带的说明书卡片很容易体验到这一整体解决方案的便利、简洁。 需要注意的是:支持2.4G的WIFI,不支持5G的WIFI,需要手机连接至2.4G信号源。 配网的方式有两种: GoKit提供三种配置方式:AirLink 、WebConfig、 SoftAP。我们可用AirLink 、 SoftAP两种方式配置开发板的无线网络。 1.长按[KEY2]3~5秒直到[RGB LED]亮绿灯,表示设备AirLink模式已经开启。“AirLink”模式,开启后设备会不断接收特定编码的WiFi广播包,手机连接可用的WiFi网络后,通过指定的App发送编码后的WiFi网络的SSID和密码广播,设备接收到之后自动尝试连接此WiFi网络,连接成功即配置完成。 2.短按[KEY2]直到[RGB LED]亮红灯,表示GoKit已经初始化。而GoKit在初始状态下将自动进入“SoftAP”模式。手机进入“系统设置”中的“WiFi设置”,找到“XPG-GAgent-XXXX”(XXXX是你的GoKit MAC地址后4位)并连接此WiFi网络,如需密码请输入:123456789 。打开“IoE Demo” App,此时App会自动进入SoftAP配置模式,选择或手动输入你附近的可用WiFi网络SSIS及密码,点击“确定”。 配置完网络,就打通了开发板和手机app的数据链路,就可以通过app界面实现对开发板的远程遥控了。可以控制全彩LED的灯光颜色、电机转向转速,还能看到实时的温度、湿度值。此时可以关闭手机WiFi,体验一下在世界任何角落依靠移动流量就能操控在家的设备“听话”地运作。 微信宠物屋模拟演示了主人外出条件下遥控照顾在家的宠物的情景,同样的场景会有很多,比如农业大棚智能的远程环境检测和调控,而这个app的名称也是可以根据需要修改的,就在界面右上角… 机智云提供了云端的数据储存、传递的桥梁,这一机制称为GAgent。GAgent主要的作用是数据转发,是设备数据、机智云、应用端(APP)的数据交互桥梁。可将GAgent移植到WiFi模组、GPRS模组、PC端等。 机智云提供了云端的数据存储、转发的桥梁,如果有更多的数据需要转发可以通过注册登录机智云,通过添加数据点实现。 通过机智云的开发向导,可以一次性完成开发板固件、手机端APP等多个软件套件式开发,非常便捷。
  • 热度 2
    2024-2-23 21:30
    727 次阅读|
    0 个评论
    51单片机大学生入门记录【1-1流水灯】
    成果展示----流水灯 代码展示 #include void Delay1ms(unsigned int xms) //@12.000MHz { unsigned char i, j; while(xms) { i = 2; j = 239; do { while (--j); } while (--i); xms--; } } void main() { while(1) { P1=0xFE; Delay1ms(500); P1=0xFD; Delay1ms(500); P1=0xFB; Delay1ms(500); P1=0xF7; Delay1ms(500); P1=0xEF; Delay1ms(500); P1=0xDF; Delay1ms(500); P1=0xBF; Delay1ms(500); P1=0x7F; Delay1ms(500); } } 硬件解析 我们可以看到8颗LED灯分别接在了 P1-P1.7 引脚上面,并且都出串联了限流电阻(起保护作用) P1-P1.7全部都在P1总线上面,所以在代码部分只需要控制P1的"开关"即可控制全部LED灯 并且可以看到,电路采用的是"灌电流"输出,意味着io口相当于接地的作用 所以 LED灯低电平点亮,高电平熄灭 代码解析----点亮一个LED 首先我们需要搞清楚,LED灯在什么时候才能点亮,由上面的硬件解析可以得出,LED灯在P1处于低电平时点亮,处于高电平的时候是熄灭状态 所以p1-p1.7在熄灭时候对应的二进制为 1111 1111 (1为高电平,0为低电平) p1-p1.7全部都位于1高电平,所以全部熄灭 若二进制为 1111 1110 第一位p1为0,其余p1.1-p1.7为1,则p1对应的LED灯亮,因为p1此时为0低电平,其余都为1高电平 所以在代码部分,我们应该写 P1=11111110,但是软件是基于c语言编程的,所以c语言不能识别二进制,所以我们需要把 二进制转换成十六进制 11111110转十六进制就是 FE 所以我们在代码上就应该写FE 因为 是便于解释器的识别, 是十六进制的标志 所以FE前面我们应该把十六进制的前缀加上,则 0xFE 此时上传代码应该可以看到,LED的第一个灯被点亮了 代码解析----循环函数 首先,我们可以在stc-isp里面生成一个1ms的循环函数 然后我们可以自己定义一个函数(xms) 这样我们输入多少,就会循环多少次1ms达到这样一个效果 假如,我xms输入一个500 首先会进行500次循环 每循环一次,函数会自己减去1 则,我输入500,循环一次完成后,就自动变成499次循环 这个函数是软件给我们生成的1ms的循环 如果500次1ms,那就是500ms,相当于0.5秒的循环 所以,我们在main函数里面引用这个延迟函数,然后在延迟函数里面给他定义一个500次 相当于延迟了0.5秒然后跳转到下一步 代码解析----流水灯的循环 我们在知道灯的原理,同时也知道循环的原理之后,就可以做一个相关的流水灯 现在的代码就非常好理解了,在第一个LED灯亮了之后,然后延迟500ms,自动跳到下一个灯,以此类推,一直循环下去 这里再细细讲解一下 第一个灯,对应的二进制为1111 1110 【FE】 第二个灯,对应的二进制为1111 1101 【FD】 第三个灯,对应的二进制为1111 1011 【FB】 。。。以此类推 所以到最后一个灯就应该是 0111 1111 【7E】 总结 51单片机对于新手来说还是比较友好的,基本上懂了LED点亮的原理,以及二进制转换十六进制的方法之后,这个项目就非常容易做了! 而且要理解一下循环函数的原理。简单来说如果我要定时500ms,其实相当于是把1ms循环了500遍这样 最后,祝大家学有所用!
  • 2022-7-22 16:10
    0 个评论
    本篇测评由电子工程世界的优秀测评者“bloong”提供。 此次测试的项目,是异构处理器间相互通讯项目。 MYD-JX8MPQ配备了一颗异构的Cortex-M7协处理器,可以同时运行Linux和RTOS。本文主要介绍协处理器M7使用方法。M7在运行时可能会涉及到和A53核共用资源,这里列举出会冲突资源如下: ECSPI0/ECSPI2,FLEXCAN,GPIO1/GPIO5,GPT1,I2C3,I2S3,UART4,PWM4,SDMA1/SDMA2,所以在一起使用时,需要将A53的这些资源关闭,这里就需要用到myd-jx8mp-rpmsg.dtb设备树。这里的M7使用uart4 作为串口。 下文介绍如何使用M7,以及编译M7程序的方法: M7使用方法 接两个串口:1个是开发板的Debug串口,另一个是M7的 UART4 串口。 1、Debug口为J4及TYPE-C Debug; 2、UART4口为J6,下图中红色箭头指示位置为pin1即UART4_TXD,据此pin2即UART4_RXD,pin3为GND。接这3根线就可以。 ​ 查看分区信息 启动开发板按任意键进入uboot模式,查看vfat分区中存在的文件。 fatls mmc 2 29209088 Image 8208 imx8mp_m7_TCM_hello_world.bin 19040 imx8mp_m7_TCM_rpmsg_lite_pingpong_rtos_linux_remote.bin 18528 imx8mp_m7_TCM_rpmsg_lite_str_ echo _rtos.bin 40948 imx8mp_m7_TCM_sai_low_power_audio.bin 62815 myd-jx8mp-atk- 10 .dtb 61702 myd-jx8mp-base.dtb 62815 myd-jx8mp-hontron- 7 .dtb 62846 myd-jx8mp -lt 8912.dtb 62555 myd-jx8mp-m190etn01- 19 .dtb 62619 myd-jx8mp-rpmsg.dtb 2113024 tee.bin 12 file(s), 0 dir(s) 设置M7设备树 kernel加载的设备树由fdt_file变量决定,这里设置成M7专用设备树。 printenv fdt_file fdt_file=myd-jx8mp-base.dtb setenv fdt_file myd-jx8mp-rpmsg.dtb save Saving Environment to MMC... Writing to MMC( 2 )... OK printenv fdt_file fdt_file=myd-jx8mp-rpmsg.dtb 设置M7启动参数 M7启动流程也是加载M7程序到内存,用bootaux命令启动, 正常kernel启动也一样,只是最后用bootm启动。 printenv fdt_file fdt_file=myd-jx8mp-base.dtb setenv fdt_file myd-jx8mp-rpmsg.dtb save Saving Environment to MMC... Writing to MMC( 2 )... OK printenv fdt_file fdt_file=myd-jx8mp-rpmsg.dtb setenv m7_image imx8mp_m7_TCM_rpmsg_lite_str_echo_rtos.bin setenv m7_boot_temp_addr 0x48000000 setenv m7_boot_addr 0x7E0000 setenv m7_run 'fatload mmc ${mmcdev}:${mmcpart} ${m7_boot_tem p_addr} ${m7_image};cp.b ${m7_boot_temp_addr} ${m7_boot_addr} 0x20000; bo otaux ${m7_boot_addr}' setenv m7_run 'fatload mmc ${mmcdev}:${mmcpart} ${m7_boot_tem p_addr} ${m7_image};cp.b ${m7_boot_temp_addr} ${m7_boot_addr} 0x20000; bootaux ${m7_boot_addr}' setenv mmcboot "run m7_run;${mmcboot}" save Saving Environment to MMC... Writing to MMC( 2 )... OK 测试M7程序 此时已经设置好了M7启动,只需要重启开发板,那么在A53启动kernel同时,也会启动M7中的程序。启动之后A53的串口执行如下2句,既可以看到M7中串口出现 对应的打印。 myd-jx8mp login: root root @myd - jx8mp: ~ # modprobe imx_rpmsg_tty root @myd - jx8mp: ~ # can1-stby: disabling can2- stby: disabling VSD_3V3 : disabling m2_keyb_pwr: disabling echo "hi m7!" /dev/tty RPMSG3 0 root @myd - jx8mp: ~ # cat /dev/ttyRPMSG30 hi m7! 想要了解优秀测评者“ bloong ”关于MYD-JX8MPQ开发板测评原文的可以复制下方链接查看: http://bbs.eeworld.com.cn/thread-1198858-1-1.html
  • 热度 5
    2022-7-1 16:54
    1567 次阅读|
    0 个评论
    OK3568-C开发板是飞凌嵌入式新推出的嵌入式开发板,采用核心板+底板的分体式设计,基于 Rockchip RK3568 处理器设计,该处理器具有高性能、低功耗特点,功能丰富,可玩性极高。 OK3568-C开发板简介 OK3568-C开发板基于RK3568处理器设计,RK3568 采用先进的22nm制程工艺,四核64位 Cortex -A55架构,拥有 独立的NEON协处理器和神经网络处理器NPU,可应用于计算机、手机、个人移动互联网,数字多媒体设备。 OK3568-C开发平台核心板和底板采用接插件的连接方式,板载外设资源和接口很多。 详细的功能参数以及接口请到飞凌嵌入式官网参看OK3568-C开发板的产品简介: https://www.forlinx.com/product/147.html OK3568-C测试 下面对OK3568-C进行功能以及接口测试。 2.1 准备工作 在测试之前,需要准备以下材料: 1.12v2A DC电源线 2.网线 3. Type -C数据线 4.鼠标键盘 5.HDMI线(非必须) 值得注意的是,HDMI、 MIPI-DSI、LVDS显示方式默认都打开了,可根据自己手头的显示设备选择相应的显示方式,当然,不使用显示设备也可以的。 2.2登录系统 进入设备的方式有很多种,如果不使用屏幕,可以使用串口和SSH登录,但是SSH登录需要先连接网络。 2.2.1 QT界面测试 笔者这里使用的是HDMI的方式,连接设备后界面如 下: 以上就是所有应用,使用鼠标就可打开相应功能界面,主要有硬解码、Camera、OpenGL、音频、网络(以太网和WIFi)、UA RT 、 SPI 等功能,这些操作都很简单,具体方式请参看《OK3568-C_ Linux 用户使用手册》,笔者不再赘述了。 2.2.2串口登录 将Type-C 的调试串口接到PC,如果串口驱动没有问题,在设备管理器可看到串口号。 值得注意的是, 在使用串口登录前,先安装串口驱动,串口 芯片 是CP201x,笔者的电脑已经安装过了。 接下来就可使用终端工具登录系统,笔者这里使用的是Xshell,当然也可使用其他的工具,比如putty。 登录成功后打印信息如下: 串口设置: 波特率 115200、数据位 8、停止位 1、无校验位、无流控制。 2.2.3 SSH登录 在使用之前,需要事先连接网络,笔者这里使用的是以太网,事先需要使用串口的登录,然后输入以下 命令 查看IP地址: # ifconfig 也可修改网络 IP地址 ,使用以下命令: # ifconfig eth0 192.168.101.5 当然啦,如果已经将以太网配置成DHCP模式,那么在只要插上网线就会得到一个IP地址。修改/etc/network/inteRFaces文件即可,修改内容如下: 然后就可使用ifconfig查看IP。 接下来就可使用SSH登录系统了,还是可以使用Xshell等工具,当然也可在 ubuntu 系统中使用SSH登录。 值得注意的是,登录用户和密码默认都是root,如果忘记密码可以通过串口登录进系统,使用passwd修改。成功登录打印信息如下: 和使用串口登录一样。 2.3测试 2.3.1系统信息 1.硬件检测 # dmesg #检测硬件的boot启动信息,也就是系统启动的log信息。 2.查看内核和CPU信息 # uname -a #系统概述 # cat /proc/cpuinfo # CPU信息 3.查看内存信息 # cat /proc/meminfo #内存参数 # free -m # 内存使用情况(-m for MB) 4.设备信息 # cat /proc/devices # 显示设备以及对应的设备号 2.3.2 存储设备速度测试 1.DDR读写测试 OK3568-C的内存是使用镁光的D9WFH DDR4,读写速度测试命令如下: 读速度测试:# bw_mem 100M rd 写速度测试: # bw_mem 100M wr 读写速率分别为5257.07MB/s、1526.48MB/s。 读写速度还是可以的。 2.eMMC读写测试 OK3568-C使用闪迪的eMMC,读写速度测试命令如下: 读取测试: #time dd if=/test of=/dev/null bs=1M 写入测试: # time dd if=/dev/zero of=/test bs=1M count=500 conv=fsync 读写速率分别为1. 5G B/s、77.0MB/s。 3.TF卡测试 将 TF 卡插入开发板底板上的 TF 卡插槽,终端打印信息如下: 默认情况下 TF 卡挂载到文件系统 /run/media/目录 写入测试: # time dd if=/dev/zero of=/run/media/mmcblk1p1/test bs=1Mcount=500 conv=fsync 读取测试: # time dd if=/run/media/mmcblk1p1/test of=/dev/null bs=1M 读写速率分别为1.5GB/s、19.6MB/s,当然啦,不同品牌的TF卡速度会有差异。值得注意的是,先要进行写测试再进行读测试。 4.USB 2.0/USB3.0 OK3568支持两个USB2.0和一个USB3.0接口,用户可以在任何一个板载USB HOST接口上连接USB鼠标、 USB键盘、 U盘等设备。 下面先测试USB2.0的接口,插入U盘,打印信息如下: 首先查看U盘设备: # ls -l /run/media/ 写入测试: # time dd if=/dev/zero of=/run/media/sda/test bs=1Mcount=500 conv=fsync 读取测试: # time dd if=/run/media/sda/test of=/dev/null bs=1M 当然,不同种类的U盘也会影响读写速度。 下面测试USB3.0的接口,USB3.0和OTG复用,通过拨码开关切换使用,使用USB3.0接口时请确认拨码开关在ON位置,插入U盘后,打印信息如下: 首先查看U盘设备: # ls -l /run/media/ 写入测试: # time dd if=/dev/zero of=/run/media/sda/test bs=1Mcount=500 conv=fsync 读取测试: # time dd if=/run/media/sda/test of=/dev/null bs=1M 从上面的测试结果来看,USB3.0还是要比USB2.0快很多的。 2.3.3网络测试 OK3568-C开发板配备2个 千兆网 口,还有一个WiFi,网速测试方法都是一样的,笔者这是测试的千兆网口(ETH0)。 这里使用系统自带的Iperf工具测试TCP带宽。Iperf 是一个网络性能测试工具。Iperf可以测试TCP和UDP带宽质量。Iperf可以测量最大TCP带宽和UDP特性。 TCP测试: 服务器执行:#iperf -s -i 1 -w1M 客户端执行:#iperf -c host -i1 -w 1M 其中-w表示TCP window size,host需替换成服务器地址。 UDP测试 服务器执行:#iperf -u -s 客户端执行:#iperf -u -c10.32.0.254 -b 900M -i 1 -w 1M -t 60 下面以TCP为例进行测试,这里测试的是ETH0。先打开服务器:# iperf -s -i 1 -w 1M 然后使用SSH登录,新建一个终端,再次打开一个终端:# iperf -c 192.168.101.5 -i 1 速度还是可以的。 2.3.4串行总线测试 1.串口测试 OK3568平台支持多路串口,用户可用串口分别为UAR T3 和UART4、UART5,在开发板中对应设备名称分别为ttyS3、ttyS4、ttyS5。 在开始测试前可将串口的RT和TX短接,这里以UART3为例,也就是短接RX3和TX3。 # fltest_uarttest -d /dev/ttyS3 以上表明通信正常。 2.SPI测试 OK3568 底板上引出 2 路 SPI 接口,默认软件上将其配置为 spidev 用于回环测试。测试前需短接MOSI和MISO。这里以SPI2为例。 # fltest_spidev_test -D /dev/spidev2.0 以上表明通信正常。 2.3.5 WEB测试 OK3568开发板预装了lighttpdweb服务器,并且系统启动时已经自动启动了lighttpd服务,在浏览器中输入开发板的IP 地址即可浏览开发板webserver 中的网页。 界面和使用HDMI是一样的,操作也差不多,这里就不再赘述了。 想要了解更多功能及测试,请联系您的销售工程师或留言获取《OK3568-C_Linux用户使用手册》。 http://https://www.forlinx.com/product/146.html
  • 热度 8
    2022-6-29 14:57
    905 次阅读|
    0 个评论
    本文硬件平台以凌OK1028A-C 开发板 为基础进行示例,其他厂商开发平台,因各个厂家设置不同,可供参考使用。内容包含 LS1028A开发板 设置默认CPU调频策略, LA1028A 开发板环境变量配置文件uEnv.txt使用方法, LS1028A 开发板开机自启动程序, LS1028 A开发板LVDS配置说明,LS1028A开发板旋转屏幕说明,LS1028A开发板Qtcreator安装使用说明 一、LS1028A开发板设置默认CPU调频策略 默认情况下OK1028A-C启动后CPU调频策略为ondemand root@forlinx:/# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ondemand 如果想使用其它策略,以高性能模式为例,可以进行如下设置 root@forlinx:/# systemctl disable ondemand.service root@forlinx:/# apt-get install cpufrequtils 修改 root@forlinx:/# vi /etc/default/cpufrequtils 添加 GOVERNOR="performance" 重启测试 root@forlinx:/# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor performance 注意:这里以操作cpu0为例,实际过程cpu1、cpu2、cpu3会同时改变。 二、LA1028A开发板环境变量配置文件uEnv.txt使用方法 OK1028A-C平台支持启动过程中通过文件导入部分环境变量,例如可以将默认的网卡MAC地址写在uEnv.txt文件中设置固定的网卡MAC地址。 启动时系统会读取eMMC第二个分区boot目录中的内核以及设备树文件,如果存在uEnv.txt则将其中的环境变量导入到系统中。以修改网卡MAC为例进行测试。 创建uEnv.txt文件 root@forlinx:~# vi /boot/uEnv.txt 添加如上环境变量,重启系统。 启动过程中可以看到log信息Importing environment from uEnv.txt ... 可以看出,我们添加的环境变量已经生效。在批量生产时,您可以将uEnv.txt放入烧写U盘的boot目录,烧写时将自动将uEnv.txt烧入eMMC中。 三、LS1028A开发板开机Logo制作方法 OK1028A-C平台支持开机Logo,支持8bit索引bmp图片。下面简单介绍使用photopshop制作开机logo的步骤。 首先使用photoshop打开一张普通的图片 点击“图像”-》“模式”,将RGB颜色修改为索引颜色 在弹出的“索引颜色”对话框中直接点击确定。 完成后在文件菜单中选择存储为,保存为logo.bmp即可。 烧写时,将logo.bmp放入烧写TF卡的boot目录即可。 四、LS1028A开发板Qtcreator安装使用说明 OK1028-C平台目前没有qt的交叉编译环境,如果需要进行qt应用程序的开发,建议直接在开发板上安装qtcreator。下面简单介绍qtcreator在OK1028-C平台上的安装及使用。 root@forlinx:/#apt-get install qtcreator root@forlinx:/#qtcreator 点击“New Project”创建新工程: 点击“Qt Widgets Application”: 输入项目名称,以“hello”为例: 点击“Next”: 点击“Next”: 点击“Finish”: 点击左下角的运行按钮: 将自动编译并运行。 注意:为了节约磁盘空间, 飞凌 提供的文件系统中只提供了qtbase qtwayland等部分必要核心模块,如需其他模块,可以使用apt-get进行安装。 五、LS1028A开发板LVDS配置说明 OK1028A-C底板上默认焊接了DP转LVDS 芯片 ,如果您需要适配自己的LVDS屏幕,可以参考如下步骤进行适配。 1.修改时序参数 时序参数需要修改:drivers/gpu/drm/bridge/cadence/cdns-dp-core.c 参数值的含义,可以参考DRM_MODE的 宏定义 : 2.修改DP 时钟 LS1028A DP时钟计算方法如下: DP像素时钟=fpll_phi=fpll_VCO/PLLDV fpll_VCO需要在设备数中指定,系统启动后无法修改,位于600M-1300M之间。 PLLDV 的范围为1-64,只需要保证VCO可以整除lvds的像素时钟,且位于1-64之间即可。 例如飞凌默认的屏幕时钟为71100khz,这里指定的vco-frequency=1066500000,PLLDV =15 更详细的说明可以参考:LSDKUG_rev20.04.pdf 459页,及内核驱动:drivers/clk/clk-plldig.c 3.修改启动参数 configs/board/ls1028ardb/manifest 修改完成后使用如下 命令 重新编译: flex-builder -i mkdistroscr 六、LS1028A开发板旋转屏幕说明 weston支持0、90、180、270度屏幕旋转功能,可修改配置文件/etc/xdg/weston/weston.ini进行设置,例如旋转90度,可将transform选项设置为90。 name=DP-1 mode=1280x800@60 force-on=true transform=90 七、LS1028A开发板开机自启动程序 在此介绍一种使用systemd方式来配置任意开机自启动程序的方法。 执行如下命令创建一个脚本文件,并修改权限: /helloworld.sh /helloworld.sh root@forlinx:/# chmod 777 /helloworld.sh 进入到“/lib/systemd/system/”目录下,并新建一个helloworld.service文件,命令如下: root@forlinx:/# cd /lib/systemd/system root@forlinx:/# vi helloworld.service 文件的内容如下: Description=helloworld After=basic.service X.service thermal-zone-init.service ExecStart=/helloworld.sh WantedBy=multi-user.target 其中Description一行需写入服务名,ExecStart需要写入可执行文件的绝对路径。 保存退出后,在终端上执行如下命令: root@forlinx:/# systemctl -f enable /lib/systemd/system/helloworld.service 此时即可将新添加的自启动服务生效,重启开发板后,此程序即可自动运行,在默认端的音频即可听到音频输出。http://https://www.forlinx.com/
相关资源
  • 所需E币: 0
    时间: 2024-5-14 09:23
    大小: 2.61KB
    上传者: 开心就很好了
    一、QT概述Qt是1991年由HaavardNord和EirikChambe-Eng开发的跨平台C++图形用户界面应用程序开发框架。发展至今,它既可以开发GUI程序,也可以开发非GUI程序,比如控制台工具和服务器。Qt是一个跨平台的C++应用程序框架,支持Windows、Linux、MacOSX、Android、嵌入式系统等。也就是说,Qt可以同时支持桌面应用程序开发、嵌入式开发和移动开发,覆盖了现有的所有主流平台。开发者只需要编写一次代码,而后在发布到不同平台之前重新编译即可。Qt的工具家族丰富,目前包括QtCreator、QtEmbedded、QtDesigner快速开发工具、国际化工具等。Qt实质上是用C++编写的大型类库,它为跨平台应用开发提供了一个完整的框架。Qt框架包含大量的类,支持GUI、数据库、网络、多媒体等各种应用的编程。Qt还对标准C++语言进行了扩展,引入了信号与槽、属性等机制,为跨平台和GUI程序的对象间通信提供了极大的方便。Qt还提供了一种自创的编程语言QML,它是类似于JavaScript的声明性语言。Qt提供了一个用QML编写的库QtQuick,它类似于QtC++类库,区别是QtQuick中的各种控件被称为QML类型(type)。QML用于描述程序的用户界面,将用户界面描述为对象树,每个对象具有自己的各种属性。Qt也支持Python,Qt类库的Python绑定版本比较多,比较常用的是PyQt和PySide二、Qt6软件特性Qt6是一款专业实用的编程开发工具。Qt6最新版优化了稳定性、功能性,并且包含Qt5.15中的所有常用功能以及为Qt6 添加的新功能。Qt6软件大大扩展了支持平台的范围,支持AppleSilicon上的macOS,同时改进了对WebAssembly的支持。QT6.0加入了许多新功能,以更好地支持现代工作负载,包括开始应用C++17,官方提到,Qt6现在要求使用的C++17兼容编译器,以便在开发QT应用程序时,使用较新的C++语言结构。另外,QT6还更新CMake构建系统,且采用全新的图形架构,并以QtQuick统一2D与3D开发体验。三、软件优点Qt6的架构变化Qt6中进行了一些更广泛的架构更改,包括:Qt6现在依赖于C++17兼容的编译器,这有助于清理和改进代码库,并为用户提供更现代的API在处理大型数据集和性能方面改进了低级容器类持续更新QML语言,使其更安全、更易于使用四、QML访问C++Qt集成了QML引擎和Qt元对象系统,使得QML很容易从C++中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。QML访问C++有两个方法:一是在Qt元对象系统中注册C++类,在QML中实例化、访问;二是在C++中实例化并设置为QML上下文属性,在QML中直接使用。第一种方法可以使C++类在QML中作为一个数据类型,例如函数参数类型或属性类型,也可以使用其枚举类型、单例等,功能更强大。五、C++类的实现C++类要想被QML访问,首先必须满足两个条件:一是派生自QObject类或QObject类的子类,二是使用Q_OBJECT宏。QObject类是所有Qt对象的基类,作为Qt对象模型的核心,提供了信号与槽机制等很多重要特性。Q_OBJECT宏必须在private区(C++默认为private)声明,用来声明信号与槽,使用Qt元对象系统提供的内容,位置一般在语句块首行。Projects选择QtQuickApplication,工程名为Hello。六、Qt版本Qt的版本可以根据许可类型分为商业许可和开源许可,开源许可又分为GPLv2/GPLv3和LGPLv3。(1)商业版:商业许可需要付费,Qt公司目前采用的是按年付费的方式。商业许可允许开发者不公开项目的源代码。商业许可的Qt安装包里有更多的模块,某些模块只有在商业许可的版本中才有。(2)开源版:采用GPLv2/GPLv3许可。若用户编写的程序使用了GPL许可的Qt代码,则用户程序也必须使用GPL许可,也就是用户代码必须开源,但是允许商业化销售。GPLv3还要求用户公开相关硬件信息。简单来说,就是你“免费”使用的东西必须也“免费”提供给别人使用。根据开发目标的不同,Qt提供了3种安装包。安装包具有针对不同主机平台的版本,而且采用了不同的许可协议。
  • 所需E币: 0
    时间: 2024-5-14 13:34
    大小: 2.1KB
    在现代软件开发中,图形用户界面(GUI)是用户与程序交互的重要组成部分。Qt框架提供了一种强大的方式来构建跨平台的GUI应用程序,其中QML(QtMeta-ObjectLanguage)和C++的交互是一个重要的主题。本篇博文将深入探讨如何在QML中创建和操作C++对象,实现双向的交互。在Qt中,任何QML代码都可以访问QObject派生类实例的属性、方法和信号。以下是一个简单的C++类CppObject,演示了如何在QML中创建并操作该类的对象。由于QML引擎与Qt元对象系统的集成,可以从QML中访问任何从QObject继承的类的属性、方法和信号,C++代码既可以在应用中集成,也可以在插件中集成。QML访问C++数据主要有三种方法:1、将C++类的属性暴露给QML;2、从C++定义QML类型;3、用Context属性在QML中嵌入C++对象;自定义数据类型16种基础数据类型以外的其它数据类型是QML所无法识别的,可将它定义为复杂数据类型,结构体数据类型属于复杂数据类型中的一种。由于QObject子类都可以注册为QML对象类型,所以构造结构体对应的自定义类来与QML交互是可行的。创建自定义对象在Qt中,我们可以使用QObject作为基类创建自定义对象。首先,我们需要在C++中定义一个继承自QObject的类,并将其注册到QML中,使得QML可以访问到这个对象。具体的步骤如下:创建一个新的C++类,例如MyObject,并继承自QObject。在MyObject类中声明需要在QML中访问的属性和函数,并使用Q_PROPERTY和Q_INVOKABLE宏进行标记。在MyObject类中添加需要在QML中访问的信号,并使用Q_SIGNAL宏进行标记。在MyObject类中添加相应的槽函数,并在函数实现中处理信号的逻辑。在Qt的主程序中,使用qmlRegisterType函数将MyObject类注册到QML引擎中。如何实现可以被QML访问的C++类C++类要想被QML访问,首先必须满足两个条件:一是派生自QObject类或QObject类的子类,二是使用Q_OBJECT宏。QObject类是所有Qt对象的基类,作为Qt对象模型的核心,提供了信号与槽机制等很多重要特性。Q_OBJECT宏必须在private区(C++默认为private)声明,用来声明信号与槽,使用Qt元对象系统提供的内容,位置一般在语句块首行。下面例子在QtCreator3.1.2中创建,Projects选择QtQuickApplication,工程名为Gemini,Component选择QtQuick2.2,然后在自动生成的文件中添砖加瓦。QML访问C++一个C++类要想被QML访问,必须满足两个条件:1、从QObject类或QObject类的子类派生继承2、使用Q_OBJECT宏这和使用信号与槽的前提条件是一样的。QObject类是所有Qt对象的基类,作为Qt对象模型的核心,提供了信号与槽机制等很多重要特性。这两个条件是为了让一个类能够进入Qt强大的元对象系统(meta-objectsystem)中,而使用元对象系统,一个类的某些方法或属性才可能通过字符串形式的名字来调用。我们知道,QML其实是对JavaScript的扩展,融合了QtObject系统,它是一种新的解释型的语言,QML引擎虽然由QtC++实现,但QML对象的运行环境,说到底和C++对象的上下文环境是不同的,是平行的两个世界。如果你想在QML中访问C++对象,那么必然要找到一种途径来在两个运行环境之间建立沟通桥梁。Qt提供了两种在QML环境中使用C++对象的方式:(1)在C++中实现一个类,注册到QML环境中,QML环境中使用该类型创建对象。(2)在C++中构造一个对象,将这个对象设置为QML的上下文属性,在QML环境中直接使用该属性。
  • 所需E币: 5
    时间: 2024-3-24 22:26
    大小: 17.42MB
    上传者: 电子阔少
    Python编程快速上手.pdf
  • 所需E币: 5
    时间: 2024-3-24 22:28
    大小: 26.17MB
    上传者: 电子阔少
    python网络-编程基础.pdf
  • 所需E币: 5
    时间: 2024-3-1 13:35
    大小: 14.2MB
    上传者: htwdb
    主要工作包括三个方面:  首先,提出了一种编程语言本体人工构建方法,该方法结合编程语言学科特点在“七步法”的基础上进行相关改进,主要步骤包括核心概念及层次关系确定、属性确定及实例化、专家审核及编码化。针对编程语言本体存储管理问题,提出了一种基于本体元素划分的图数据库存储策略,该策略将本体元素划分为结构层和实例层,基于相应元素的映射规则完成本体模型到图数据库模型的存储。实验结果表明所提出的方法是可行有效的。  其次,在编程语言本体构建的基础上,提出了一种半自动的方法完成编程语言知识图谱的扩充。其中,针对信息抽取中多元关系的问题提出了一种多策略融合的信息抽取方法,该方法采用融合术语相关度的规则匹配方法和聚类算法完成定向关系抽取,使用依存句法分析完成非定向关系抽取。针对知识矛盾或冗余的问题,提出了基于同义词典的实体对齐方法,该方法通过构建同义词典来对抽取的知识实体进行规范化表述,并结合相似度计算来为同义词典补充相似实体对。实验结果表明所提出的方法有效的完成对编程语言知识图谱的丰富和完善。     最后,对构建的编程语言知识图谱进行实证应用研究。提出了基于加权共现分析的编程语言图谱评价方法,该方法首先对实际应用题库中习题标签集与编程语言知识图谱中知识实体集的共现元素统计,并利用题库中知识点对应习题量作为加权依据,来计算编程语言图谱对习题标签的加权共现覆盖率。实验结果表明构建完成的编程语言图谱是完备的,验证了本文提出的编程语言知识图谱构建方法的有效性。
  • 所需E币: 0
    时间: 2023-12-22 10:13
    大小: 3.93KB
    上传者: 开心就很好了
    Java并发编程从入门到进阶多场景实战,众所周知,并发编程是优秀工程师的标准之一,但知识庞杂,复杂性高,常常让人望而却步。但如果没有掌握背后的核心原理,你开发的代码可能会成为难以调试和优化的头疼问题。在此,我将通过上百个案例场景驱动教学+动画直观演示,帮助大家深入、直观地理解并发编程核心概念和底层原理。助力大家在实际工作和面试中都能尽早脱颖而出。首先,我们先来了解关于并发的基本概念。并发情况主要会引出三个基本概念,分别是原子性、可见性、有序性三个基本概念Java中线程的状态分为6种:1.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。2.运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。3.阻塞(BLOCKED):表示线程阻塞于锁。4.等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。5.超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。6.终止(TERMINATED):表示该线程已经执行完毕。其实我们可以通过job.setPartitionerClass来设置分区类,不过目前我们是没有设置的,那框架中是不是有默认值啊,是有的,我们可以通过job.getPartitionerClass方法看到默认情况下会使用HashPartitioner这个分区类那我们来看一下HashPartitioner的实现是什么样子的/**Partitionkeysbytheir{@linkObject#hashCode()}.*/@InterfaceAudience.Public@InterfaceStability.StablepublicclassHashPartitioner<K,V>extendsPartitioner<K,V>{ /**Use{@linkObject#hashCode()}topartition.*/ publicintgetPartition(Kkey,Vvalue,             intnumReduceTasks){  return(key.hashCode()&Integer.MAX_VALUE)%numReduceTasks; }}下面我们来具体跑一个这份数据,首先复制一份WordCountJob的代码,新的类名为WordCountJobSkewpackagecom.imooc.mr;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.Path;importorg.apache.hadoop.io.LongWritable;importorg.apache.hadoop.io.Text;importorg.apache.hadoop.mapreduce.Job;importorg.apache.hadoop.mapreduce.Mapper;importorg.apache.hadoop.mapreduce.Reducer;importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.io.IOException;/** *数据倾斜-增加Reduce任务个数 * *Createdbyxuwei */publicclassWordCountJobSkew{  /**   *Map阶段   */  publicstaticclassMyMapperextendsMapper<LongWritable,Text,Text,LongWritable>{    Loggerlogger=LoggerFactory.getLogger(MyMapper.class);    /**     *需要实现map函数     *这个map函数就是可以接收<k1,v1>,产生<k2,v2>     *@paramk1     *@paramv1     *@paramcontext     *@throwsIOException     *@throwsInterruptedException     */    @Override    protectedvoidmap(LongWritablek1,Textv1,Contextcontext)        throwsIOException,InterruptedException{      //输出k1,v1的值      //System.out.println("<k1,v1>=<"+k1.get()+","+v1.toString()+">");      //logger.info("<k1,v1>=<"+k1.get()+","+v1.toString()+">");      //k1代表的是每一行数据的行首偏移量,v1代表的是每一行内容      //对获取到的每一行数据进行切割,把单词切割出来      String[]words=v1.toString().split("");      //把单词封装成<k2,v2>的形式      Textk2=newText(words[0]);      LongWritablev2=newLongWritable(1L);      //把<k2,v2>写出去      context.write(k2,v2);    }  }  /**   *Reduce阶段   */  publicstaticclassMyReducerextendsReducer<Text,LongWritable,Text,LongWritable>{    Loggerlogger=LoggerFactory.getLogger(MyReducer.class);    /**     *针对<k2,{v2...}>的数据进行累加求和,并且最终把数据转化为k3,v3写出去     *@paramk2     *@paramv2s     *@paramcontext     *@throwsIOException     *@throwsInterruptedException     */    @Override    protectedvoidreduce(Textk2,Iterable<LongWritable>v2s,Contextcontext)        throwsIOException,InterruptedException{      //创建一个sum变量,保存v2s的和      longsum=0L;      //对v2s中的数据进行累加求和      for(LongWritablev2:v2s){        //输出k2,v2的值        //System.out.println("<k2,v2>=<"+k2.toString()+","+v2.get()+">");        //logger.info("<k2,v2>=<"+k2.toString()+","+v2.get()+">");        sum+=v2.get();//模拟Reduce的复杂计算消耗的时间        if(sum%200==0){          Thread.sleep(1);        }      }      //组装k3,v3      Textk3=k2;      LongWritablev3=newLongWritable(sum);      //输出k3,v3的值      //System.out.println("<k3,v3>=<"+k3.toString()+","+v3.get()+">");      //logger.info("<k3,v3>=<"+k3.toString()+","+v3.get()+">");      //把结果写出去      context.write(k3,v3);    }  }  /**   *组装Job=Map+Reduce   */  publicstaticvoidmain(String[]args){    try{      if(args.length!=3){        //如果传递的参数不够,程序直接退出        System.exit(100);      }      //指定Job需要的配置参数      Configurationconf=newConfiguration();      //创建一个Job      Jobjob=Job.getInstance(conf);      //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的      job.setJarByClass(WordCountJobSkew.class);      //指定输入路径(可以是文件,也可以是目录)      FileInputFormat.setInputPaths(job,newPath(args[0]));      //指定输出路径(只能指定一个不存在的目录)      FileOutputFormat.setOutputPath(job,newPath(args[1]));      //指定map相关的代码      job.setMapperClass(MyMapper.class);      //指定k2的类型      job.setMapOutputKeyClass(Text.class);      //指定v2的类型      job.setMapOutputValueClass(LongWritable.class);      //指定reduce相关的代码      job.setReducerClass(MyReducer.class);      //指定k3的类型      job.setOutputKeyClass(Text.class);      //指定v3的类型      job.setOutputValueClass(LongWritable.class);      //设置reduce任务个数      job.setNumReduceTasks(Integer.parseInt(args[2]));      //提交job      job.waitForCompletion(true);    }catch(Exceptione){      e.printStackTrace();    }  }}针对这个操作我们需要去修改代码,在这里我们再重新复制一个类,基于WordCountJobSkew复制,新的类名是WordCountJobSkewRandKeypackagecom.imooc.mr;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.Path;importorg.apache.hadoop.io.LongWritable;importorg.apache.hadoop.io.Text;importorg.apache.hadoop.mapreduce.Job;importorg.apache.hadoop.mapreduce.Mapper;importorg.apache.hadoop.mapreduce.Reducer;importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.io.IOException;importjava.util.Random;/** *数据倾斜-把倾斜的数据打散 * *Createdbyxuwei */publicclassWordCountJobSkewRandKey{  /**   *Map阶段   */  publicstaticclassMyMapperextendsMapper<LongWritable,Text,Text,LongWritable>{    Loggerlogger=LoggerFactory.getLogger(MyMapper.class);    Randomrandom=newRandom();    /**     *需要实现map函数     *这个map函数就是可以接收<k1,v1>,产生<k2,v2>     *@paramk1     *@paramv1     *@paramcontext     *@throwsIOException     *@throwsInterruptedException     */    @Override    protectedvoidmap(LongWritablek1,Textv1,Contextcontext)        throwsIOException,InterruptedException{      //输出k1,v1的值      //System.out.println("<k1,v1>=<"+k1.get()+","+v1.toString()+">");      //logger.info("<k1,v1>=<"+k1.get()+","+v1.toString()+">");      //k1代表的是每一行数据的行首偏移量,v1代表的是每一行内容      //对获取到的每一行数据进行切割,把单词切割出来      String[]words=v1.toString().split("");      //把单词封装成<k2,v2>的形式      Stringkey=words[0];      if("5".equals(key)){        //把倾斜的key打散,分成10份        key="5"+"_"+random.nextInt(10);      }      Textk2=newText(key);      LongWritablev2=newLongWritable(1L);      //把<k2,v2>写出去      context.write(k2,v2);    }  }  /**   *Reduce阶段   */  publicstaticclassMyReducerextendsReducer<Text,LongWritable,Text,LongWritable>{    Loggerlogger=LoggerFactory.getLogger(MyReducer.class);    /**     *针对<k2,{v2...}>的数据进行累加求和,并且最终把数据转化为k3,v3写出去     *@paramk2     *@paramv2s     *@paramcontext     *@throwsIOException     *@throwsInterruptedException     */    @Override    protectedvoidreduce(Textk2,Iterable<LongWritable>v2s,Contextcontext)        throwsIOException,InterruptedException{      //创建一个sum变量,保存v2s的和      longsum=0L;      //对v2s中的数据进行累加求和      for(LongWritablev2:v2s){        //输出k2,v2的值        //System.out.println("<k2,v2>=<"+k2.toString()+","+v2.get()+">");        //logger.info("<k2,v2>=<"+k2.toString()+","+v2.get()+">");        sum+=v2.get();        //模拟Reduce的复杂计算消耗的时间        if(sum%200==0){          Thread.sleep(1);        }      }      //组装k3,v3      Textk3=k2;      LongWritablev3=newLongWritable(sum);      //输出k3,v3的值      //System.out.println("<k3,v3>=<"+k3.toString()+","+v3.get()+">");      //logger.info("<k3,v3>=<"+k3.toString()+","+v3.get()+">");      //把结果写出去      context.write(k3,v3);    }  }  /**   *组装Job=Map+Reduce   */  publicstaticvoidmain(String[]args){    try{      if(args.length!=3){        //如果传递的参数不够,程序直接退出        System.exit(100);      }      //指定Job需要的配置参数      Configurationconf=newConfiguration();      //创建一个Job      Jobjob=Job.getInstance(conf);      //注意了:这一行必须设置,否则在集群中执行的时候是找不到WordCountJob这个类的      job.setJarByClass(WordCountJobSkewRandKey.class);      //指定输入路径(可以是文件,也可以是目录)      FileInputFormat.setInputPaths(job,newPath(args[0]));      //指定输出路径(只能指定一个不存在的目录)      FileOutputFormat.setOutputPath(job,newPath(args[1]));      //指定map相关的代码      job.setMapperClass(MyMapper.class);      //指定k2的类型      job.setMapOutputKeyClass(Text.class);      //指定v2的类型      job.setMapOutputValueClass(LongWritable.class);      //指定reduce相关的代码      job.setReducerClass(MyReducer.class);      //指定k3的类型      job.setOutputKeyClass(Text.class);      //指定v3的类型      job.setOutputValueClass(LongWritable.class);      //设置reduce任务个数      job.setNumReduceTasks(Integer.parseInt(args[2]));      //提交job      job.waitForCompletion(true);    }catch(Exceptione){      e.printStackTrace();    }  }}调用parallelize()时,有一个重要的参数可以指定,就是将集合切分成多少个partition。Spark会为每一个partition运行一个task来进行处理。Spark默认会根据集群的配置来设置partition的数量。我们也可以在调用parallelize()方法时,传入第二个参数,来设置RDD的partition数量,例如:parallelize(arr,5)scala代码如下:packagecom.imooc.scalaimportorg.apache.spark.{SparkConf,SparkContext}/** *需求:使用集合创建RDD *Createdbyxuwei */objectCreateRddByArrayScala{ defmain(args:Array[String]):Unit={  //创建SparkContext  valconf=newSparkConf()  conf.setAppName("CreateRddByArrayScala")//设置任务名称  .setMaster("local")//local表示在本地执行  valsc=newSparkContext(conf)  //创建集合  valarr=Array(1,2,3,4,5)  //基于集合创建RDD  valrdd=sc.parallelize(arr)  valsum=rdd.reduce(_+_)  println(sum)  //停止SparkContext  sc.stop() }}
  • 所需E币: 3
    时间: 2023-12-15 09:34
    大小: 10.67MB
    上传者: 二月半
    Linux命令行与shell脚本编程大全(第4版)(RichardBlum、ChristineBresnahan) 
  • 所需E币: 5
    时间: 2023-11-14 17:51
    大小: 21.11MB
    上传者: 浩瀚星蓝
    这是一本学习linux的经典书籍,详细介绍了shell的使用方法
  • 所需E币: 2
    时间: 2023-11-14 15:19
    大小: 45MB
    上传者: 浩瀚星蓝
    这本书是非常有名的编程提升书籍,对你的代码风格以及思路有非常多的提升
  • 所需E币: 0
    时间: 2023-11-10 16:41
    大小: 1018.5KB
    上传者: Argent
    第15讲LinuxC编程
  • 所需E币: 1
    时间: 2023-7-29 16:56
    大小: 5.11MB
    上传者: Argent
    Cortex-M7编程手册(ST官方)
  • 所需E币: 3
    时间: 2023-7-16 15:52
    大小: 64.7MB
    上传者: 电子阔少
    一个非常值得拥有的学习Python的学习资料,Python核心编程(第二版).pdf
  • 所需E币: 1
    时间: 2023-7-12 09:25
    大小: 9.28MB
    上传者: 张红川
    codsys3.x基础编程及应用指南.pdf
  • 所需E币: 1
    时间: 2023-7-12 09:23
    大小: 9.11MB
    上传者: 张红川
    CoDeSys编程手册中文版.pdf
  • 所需E币: 1
    时间: 2023-7-12 09:23
    大小: 874.53KB
    上传者: 张红川
    CoDeSys_SoftMotion_运动控制中文编程手册.pdf
  • 所需E币: 1
    时间: 2023-7-12 09:24
    大小: 10.34MB
    上传者: 张红川
    CoDeSys+2.3+中文教程(学习PLC编程的最好教程).pdf
  • 所需E币: 1
    时间: 2023-7-11 17:38
    大小: 138.87KB
    上传者: 张红川
    day05-V4L2摄像头编程.pdf
  • 所需E币: 1
    时间: 2023-7-11 17:29
    大小: 103.4KB
    上传者: 张红川
    socket编程常用API汇总.pdf
  • 所需E币: 1
    时间: 2023-7-10 15:46
    大小: 11.2MB
    上传者: 张红川
    《LINUX环境编程图文指南》.pdf
  • 所需E币: 2
    时间: 2023-7-9 22:39
    大小: 16.2MB
    上传者: Orima
    单片机原理及接口技术C51编程