关键词: RVB2601、RISC-V开发板、例程,玄铁E906、低功耗,玄铁E906,AliOS Things,  RISC-V  MCU,上手,好用,控制,智能控制,开关,WiFi&BLE

1. 前言

本例程基于YoC软件平台av组件采用http协议播放一首网络mp3歌曲。当开发板成功通过sal(底层通过at指令连接内置的网卡芯片)连接网络后,可输入相应串口命令行从web服务器上拉取mp3歌曲实现边拉取音频源数据边播放的功能。开发者可基于该例程实现更为丰富的网络播放功能。 本例程名为ch2601_webplayer_demo,可以通过CDK直接从OCC拉取。

2. 如何使用

2.1 下载代码并编译运行

  • 通过cdk搜索ch2601_webplayer_demo并下载工程代码打开后,会有如下界面。其中框1为解决方案组件,框2中是该解决方案依赖的子功能组件。
  • 在本例程中,主要依赖av(音视频软件框架)、pvmp3dec(mp3解码器)、drv_wifi_at_w800(wifi驱动)等组件。

  • 在IDE上编译通过后,点击下载进行烧录。烧录成功后,复位运行。成功运行后,串口会有如何打印输出:

2.2 网络连接

通过ifconfig命令可配置需要连接的热点。具体命令为:

ifconfig ap wifi_ssid wifi_psk

热点配置成功后,会有下图如下打印:

2.3 命令行播放控制

可通过在串口下输入如下命令来控制歌曲的播放

# player helpplayer play welcom/url[http://]  #播放内置开机音频或网络歌曲player pause                     #暂停播放player resume                    #恢复播放player stop                      #停止播放player help                      #播放器帮助命令

播放http歌曲player play http://yocbook.oss-cn-hangzhou.aliyuncs.com/av_repo/alibaba.mp3,示例如下:

player play http://yocbook.oss-cn-hangzhou.aliyuncs.com/av_repo/alibaba.mp3# [  13.620]<E>w800_api domain to ip: 47.110.23.146
[  13.630]<D>sals remote_port -- : 80
[  13.710]<D>WEB http request:
GET /av_repo/alibaba.mp3 HTTP/1.0
Host: yocbook.oss-cn-hangzhou.aliyuncs.com
User-Agent: CSKY/YOC[  15.000]<D>stream upto cache threshold2, pos =        553, cache_pos =        809, diff = 256
[  15.420]<D>avparser find a parser, name = mp3, id = 1
[  15.440]<D>ad find a decode, name = pvmp3dec, id = 1
[  15.450]<D>filter_swr open a avfilter, name = swr
[  15.470]<D>filter_vol open a avfilter, name = vol
[  15.470]<D>ao_alsa  ao open
[  15.490]<D>ao ao ref: openref =  1, startref =  0, fun = __ao_open
[  15.510]<D>ao ori sf ==> sf = 90317074, rate = 44100, ch = 2, bits = 16, siged = 1, float = 0, endian = 0
[  15.540]<D>ao ao  sf ==> sf = 90316946, rate = 44100, ch = 1, bits = 16, siged = 1, float = 0, endian = 0
[  15.810]<D>ao ao ref: openref =  1, startref =  1, fun = __ao_start
[  15.820]<D>player_demo =====_player_event, 24, type = 2
[  15.820]<D>player player_get_media_info, 809 enter. player = 20009E00
[  15.830]<D>player player_get_media_info, 821 leave. player = 20009E00
[  15.830]<D>player_demo =====rc = 0, duration = 415807ms, bps = 64000, size = 3326462

3. 例程开发

3.1 主要代码解析

3.1.1 主函数流程

主函数位于ch2601_webplayer_demo/app/src/app_main.c中。详细的解释如下:

static void network_event(uint32_t event_id, const void *param, void *context)
{switch(event_id) {case EVENT_NETMGR_GOT_IP:LOGD(TAG, "net got ip");break;case EVENT_NETMGR_NET_DISCON:LOGD(TAG, "net disconnect");break;}/*do exception process */app_exception_event(event_id);
}int main(void)
{board_yoc_init();     // 板级配置、kv文件系统、声卡驱动、网卡驱动等初始化player_init();        // 播放器模块初始化cli_reg_cmd_player(); // 播放器命令行注册/* Subscribe */event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);     // 订阅网络连接事件event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL); // 订阅网络断开事件
}

3.1.2 声卡、网卡驱动注册等

代码位于ch2601_webplayer_demo/app/src/init.c中。

static void network_init()
{w800_wifi_param_t w800_param;/* init wifi driver and network */w800_param.reset_pin      = PA21;w800_param.baud           = 1*1000000;w800_param.cs_pin         = PA15;w800_param.wakeup_pin     = PA25;w800_param.int_pin        = PA22;w800_param.channel_id     = 0;w800_param.buffer_size    = 4*1024;wifi_w800_register(NULL, &w800_param);app_netmgr_hdl = netmgr_dev_wifi_init();if (app_netmgr_hdl) {utask_t *task = utask_new("netmgr", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);netmgr_service_init(task);netmgr_start(app_netmgr_hdl);}
}void board_yoc_init(void)
{board_init();                                 // 板级初始化event_service_init(NULL);                     // 发布订阅服务初始化console_init(CONSOLE_UART_IDX, 115200, 512);  // 串口初始化ulog_init();                                  // 日志初始化aos_set_log_level(AOS_LL_DEBUG);              // 配置默认日志打印级别int ret = partition_init();                   // 分区初始化if (ret <= 0) {LOGE(TAG, "partition init failed");} else {LOGI(TAG, "find %d partitions", ret);}aos_kv_init("kv");                            // kv文件系统初始化,可用于保存网络ssid&psksnd_card_alkaid_register(NULL);               // 声卡初始化,可用于播放&采集network_init();                               // 网络初始化board_cli_init();                             // 命令行初始化并注册默认的命令
}

3.1.3 网络底层通信

2601主芯片是通过spi与无线网卡芯片w800通信的。w800中运行有完整的lwip网络协议栈。 drv_wifi_at_w800组件将底层spi收到的网络数据(采用at协议封装)处理后递交到sal(socket abstract layer)组件中。2601通过sal来屏蔽底层网卡驱动的差异,向上提供标准的BSD网络套接字接口。 此部分代码位于components/drv_wifi_at_w800/w800_at_port.c中。

static int spi_resp_len(void)
{uint16_t temp = 0;uint8_t a,b;uint8_t cmd = SPI_REG_INT_STTS;int recv_len = 0;while (1) {CS_LOW;csi_spi_send(&spi_handle, &cmd, 1, AOS_WAIT_FOREVER);       // 检查是否存在有效数据csi_spi_receive(&spi_handle, &a, 1, AOS_WAIT_FOREVER);csi_spi_receive(&spi_handle, &b, 1, AOS_WAIT_FOREVER);CS_HIGH;temp = a | (b << 8);if((temp != 0xffff) && (temp & 0x01)) {cmd = SPI_REG_RX_DAT_LEN;CS_LOW;csi_spi_send(&spi_handle, &cmd, 1, AOS_WAIT_FOREVER);   // 获取接收数据长度 csi_spi_receive(&spi_handle, &a, 1, AOS_WAIT_FOREVER);csi_spi_receive(&spi_handle, &b, 1, AOS_WAIT_FOREVER);CS_HIGH;recv_len = a | (b << 8);// printf("recv len:%d\r\n", recv_len);break;}aos_msleep(100);}return recv_len;
}static void at_spi_recv_task(void *priv)
{int      len  = 0;uint8_t *recv = NULL;while(1) {aos_sem_wait(&spi_recv_sem, AOS_WAIT_FOREVER); // 是否有中断过来,通过GIIO来触发中断len = spi_resp_len();               // 获取对端发送过来的数据长度if (len)recv = aos_malloc_check(len);elsecontinue;spi_recv(recv, len);                // 获取实际有效数据while (ringbuffer_available_write_space(&spi_ringbuffer) < (len -1)) {aos_msleep(100);}int w_len = ringbuffer_write(&spi_ringbuffer, recv, len-1); // 写入到环形缓冲中if (w_len != (len-1)) {LOGD(TAG, "spi buffer is full\r\n");} else {spi_channel_cb(AT_CHANNEL_EVENT_READ, spi_channel_priv);}if (recv) {aos_free(recv);recv = NULL;}}
}static void *at_spi_init(const char *name, void *config)
{int      ret  = 0;csi_pin_set_mux(PA16, PA16_SPI0_SCK);                            // 配置管脚复用csi_pin_set_mux(PA17, PA17_SPI0_MOSI);csi_pin_set_mux(PA18, PA18_SPI0_MISO);// csi_pin_set_mux(PA15, PA15_SPI0_CS); // CScsi_pin_set_mux(PA15, PIN_FUNC_GPIO); // CScsi_pin_set_mux(PA22, PIN_FUNC_GPIO); // INTcsi_gpio_pin_init(&spi_int_pin, PA22);                           // gpio配置csi_gpio_pin_dir(&spi_int_pin,GPIO_DIRECTION_INPUT);csi_gpio_pin_mode(&spi_int_pin,GPIO_MODE_PULLNONE);csi_gpio_pin_debounce(&spi_int_pin, true);csi_gpio_pin_attach_callback(&spi_int_pin, spi_in_int_cb, NULL); // 根据gpio来通知是否存在网络数据csi_gpio_pin_irq_mode(&spi_int_pin,GPIO_IRQ_MODE_FALLING_EDGE);csi_gpio_pin_irq_enable(&spi_int_pin, 1);csi_gpio_pin_init(&spi_cs_pin, PA15);csi_gpio_pin_mode(&spi_cs_pin,GPIO_MODE_PULLUP);csi_gpio_pin_dir(&spi_cs_pin,GPIO_DIRECTION_OUTPUT);CS_HIGH;csi_gpio_pin_init(&spi_wakeup_pin, PA25);csi_gpio_pin_mode(&spi_wakeup_pin,GPIO_MODE_PULLUP);csi_gpio_pin_dir(&spi_wakeup_pin,GPIO_DIRECTION_OUTPUT);csi_gpio_pin_write(&spi_wakeup_pin, GPIO_PIN_HIGH);ret = csi_spi_init(&spi_handle, 0);if (ret < 0) {printf("csi spi init failed\r\n");return NULL;}csi_spi_mode(&spi_handle, SPI_MASTER);        // 2601侧作为masterret = csi_spi_baud(&spi_handle, 1*1000000);   // 波特率配置默认1MLOGD(TAG, "#######################spi speed:%d\r\n", ret);csi_spi_cp_format(&spi_handle, SPI_FORMAT_CPOL0_CPHA0);csi_spi_frame_len(&spi_handle, SPI_FRAME_LEN_8);csi_spi_select_slave(&spi_handle, 0);         // 建立与w800间的spi通信,w800网卡作为slave 0aos_task_t task;ret = aos_sem_new(&spi_recv_sem, 0);          // 用于gpio中断通知// aos_check(ret, NULL);ret = aos_task_new_ext(&task, "spi_recv", at_spi_recv_task, NULL, 1536, 9);// aos_check(ret, NULL);spi_recv_buffer = (char *)aos_malloc_check(SPI_RX_BUFFER_LEN); // 创建环形buffer,用于接收网络数据ringbuffer_create(&spi_ringbuffer, spi_recv_buffer, SPI_RX_BUFFER_LEN);return (void*)1;
}at_channel_t spi_channel = {.init       = at_spi_init,.set_event  = at_spi_set_event,.send       = at_spi_send,.recv       = at_spi_recv,
};

3.2 网络播放器使用及配置

YoC平台中的播放器可以支持wav、mp3、m4a、amrnb、amrwb、flac、adts等多种音频格式的播放。同时也支持sd卡、http(s)、fifo、mem等多种取流方式。url格式的详细定义如下:

流类型

URL前缀

URL格式

网络流

http(s)://

http(s)://ip:port/xx.mp3

文件流(SD卡)

file://

file:///fatfs0/xx.mp3?avformat=%s&avcodec=%s&channel=%u&rate=%u

内存流

mem://

mem://addr=%u&size=%u&avformat=%s&avcodec=%s&channel=%u&rate=%u

fifo流

fifo://

fifo://tts/1?avformat=%s&avcodec=%s&channel=%u&rate=%u

加密流

crypto://

crypto://http://ip:port/xx.mp3?key=%s&iv=%s

hls流

http(s)://

http(s)://ip:port/xx.m3u8

播放器相关组件详细的设计和使用方法请访问以下链接: https://yoc.docs.t-head.cn/yocbook/Chapter5-%E7%BB%84%E4%BB%B6/%E5%A4%9A%E5%AA%92%E4%BD%93%E6%92%AD%E6%94%BE%E5%99%A8/av.html

3.2.1 网络播放器在2601芯片上的应用

网络播放器典型代码解析如下:

static player_t *g_player;static void _player_event(player_t *player, uint8_t type, const void *data, uint32_t len)
{int rc;UNUSED(len);UNUSED(data);UNUSED(handle);LOGD(TAG, "=====%s, %d, type = %d", __FUNCTION__, __LINE__, type);switch (type) {case PLAYER_EVENT_ERROR:      // 播放出错事件rc = player_stop(player);break;case PLAYER_EVENT_START: {    // 开始播放事件media_info_t minfo;memset(&minfo, 0, sizeof(media_info_t));rc = player_get_media_info(player, &minfo);  // 获取媒体时长、大小等信息LOGD(TAG, "=====rc = %d, duration = %llums, bps = %llu, size = %u", rc, minfo.duration, minfo.bps, minfo.size);break;}case PLAYER_EVENT_FINISH:     // 播放结束事件player_stop(player);      // 停止播放break;default:break;}
}player_t *get_player_demo()
{if (!g_player) {ply_conf_t ply_cnf;player_conf_init(&ply_cnf);               // 初始化播放器默认配置ply_cnf.vol_en         = 1;               // 使能数字音量功能ply_cnf.vol_index      = 160;             // 0~255ply_cnf.event_cb       = _player_event;   // 播放事件回调函数ply_cnf.period_num     = 12;              // 底层音频输出缓冲周期,用于控制音频输出缓冲大小ply_cnf.cache_size     = 32 * 1024;       // 网络时的播放缓冲大小g_player = player_new(&ply_cnf);          // 创建播放器}return g_player;
}

3.2.2 网络播放器相关宏配置

鉴于2601的硬件资源比较受限,而网络播放器又提供了很多的功能。所以不太可能将播放器提供的所有功能都能够包含进去。此时就需要开发根据具体产品需要开启或配置相关功能。 例程中典型宏定义配置如下:

CONFIG_AEFXER_IPC=0                     #音效处理,2601不涉及
CONFIG_AEFXER_SONA=0                    #音效处理,2601不涉及
CONFIG_AO_MIXER_SUPPORT=0               #混音播放,默认关闭
CONFIG_ATEMPOER_IPC=0                   #核间变速播放,2601不涉及
CONFIG_ATEMPOER_SONIC=1                 #变速播放
CONFIG_AV_AO_CHANNEL_NUM=1              #单声道音频输出
CONFIG_AV_PROBE_SIZE_MAX=1024           #音频格式探测最大长度
CONFIG_AV_SAMPLE_NUM_PER_FRAME_MAX=80   #控制wav音频帧的最大采样数
CONFIG_AV_STREAM_INNER_BUF_SIZE=256     #stream内部buf大小,用于性能优化
CONFIG_DECODER_ADPCM_MS=0               #adpcm_ms解码
CONFIG_DECODER_ALAW=0                   #alaw解码
CONFIG_DECODER_AMRNB=0                  #amrnb解码
CONFIG_DECODER_AMRWB=0                  #amrwb解码
CONFIG_DECODER_FLAC=0                   #flac解码
CONFIG_DECODER_IPC=0                    #核间解码,2601不涉及
CONFIG_DECODER_MULAW=0                  #ulaw解码
CONFIG_DECODER_OPUS=0                   #opus解码
CONFIG_DECODER_PCM=1                    #pcm裸流解码
CONFIG_DECODER_PVMP3=1                  #mp3解码
CONFIG_DECODER_SPEEX=0                  #speex解码
CONFIG_DEMUXER_ADTS=0                   #adts解复用
CONFIG_DEMUXER_AMR=0                    #amr解复用
CONFIG_DEMUXER_ASF=0                    #asf解复用
CONFIG_DEMUXER_FLAC=0                   #flac解复用
CONFIG_DEMUXER_MP3=1                    #mp3解复用
CONFIG_DEMUXER_MP4=0                    #mp4解复用
CONFIG_DEMUXER_OGG=0                    #ogg解复用
CONFIG_DEMUXER_RAWAUDIO=0               #rawaudio解复用
CONFIG_DEMUXER_TS=0                     #ts解复用
CONFIG_DEMUXER_WAV=0                    #wav解复用
CONFIG_EQXER_IPC=0                      #量化器,2601不涉及
CONFIG_EQXER_SILAN=0                    #量化器,2601不涉及
CONFIG_FFTXER_IPC=0                     #fft变换,2601不涉及
CONFIG_FFTXER_SPEEX=0                   #fft变换,2601不涉及
CONFIG_PLAYER_TASK_STACK_SIZE=2048      #播放器任务栈大小
CONFIG_RESAMPLER_IPC=0                  #核间音频重采样
CONFIG_RESAMPLER_SPEEX=0                #speex重采样
CONFIG_STREAMER_CRYPTO=0                #加密流
CONFIG_STREAMER_FIFO=0                  #队列流
CONFIG_STREAMER_FILE=0                  #文件流
CONFIG_STREAMER_HLS=0                   #http live stream
CONFIG_STREAMER_HTTP=1                  #http网络流
CONFIG_STREAMER_MEM=1                   #内存流
CONFIG_WEB_CACHE_TASK_STACK_SIZE=2048   #网络流缓冲任务栈大小

AV组件中宏配置的具体说明请参考此链接中的功能配置与裁剪小节。该链接中同时会介绍典型音频播放场景的相关配置。

3.2.3 在CDK中如何配置宏

  • 在解决方案名称上右击,选择弹出框中第一项,如下图所示:

  • 在弹出框中选中Compile选项卡,单击下图中的红色框可配置相关宏

  • 在弹出框中,根据功能需要配置对应的宏,保存后重新编译

注意事项:

  • Package中的子功能组件在Options选项中会有默认的配置项(如果存在)
  • 解决方案在依赖子功能组件时,可通过Options选项自行重新配置相关的宏。其在编译时会覆盖子功能组件的默认配置

4. 参考资料

YoC软件平台:https://yoc.docs.t-head.cn/yocbook/

多媒体播放器组件:https://yoc.docs.t-head.cn/yocbook/Chapter5-%E7%BB%84%E4%BB%B6/%E5%A4%9A%E5%AA%92%E4%BD%93%E6%92%AD%E6%94%BE%E5%99%A8/

SAL组件:https://yoc.docs.t-head.cn/yocbook/Chapter4-%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97/%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5/%E5%A5%97%E6%8E%A5%E5%AD%97%E9%80%82%E9%85%8D%E5%B1%82SAL.html

AT组件:https://yoc.docs.t-head.cn/yocbook/Chapter4-%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97/AT%E5%91%BD%E4%BB%A4/

网络管理器组件:https://yoc.docs.t-head.cn/yocbook/Chapter4-%E6%A0%B8%E5%BF%83%E6%A8%A1%E5%9D%97/%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5/%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E5%99%A8.html

本文转自平头哥芯片开放社区(occ),更多详情请点击【这里】。

RVB2601应用开发实战系列六:网络播放器设计(二)相关推荐

  1. 利用DirectShow开发C#版的MP3播放器(二)

    继上一次利用DirectShow编写了一个C#版的简单MP3播放器之后,这两天利用空余时间对其作了初步的完善,主要工作如下:     1.对原有的代码进行拆分,主要拆分成五个类,包括一个Form类Fr ...

  2. [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互

    文章目录 原理 交互实现 容器控件 手势开始 手势运行 手势结束 使用控件 拖拽物 创建pit集合 项目地址 原理 定义一个拖拽物,和它拖拽的目标,拖拽物可以理解为一个平底锅(pan),拖拽目标是一个 ...

  3. springboot 插入返回id_Spring Boot实现分布式微服务开发实战系列(七)

    今天已经进入第七讲了,整个微服务架构的搭建工作也基本完成.那到目前为止究竟使用了那些技术及实现了什么功能呢?我们先回顾一下. 使用的技术:SpringBoot.Dubbo.Zookeeper.Redi ...

  4. [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

    这是一篇系列博文.请关注我,学习更多.NET MAUI开发知识! [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构 [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互 [MAU ...

  5. Android音视频学习系列(七) — 从0~1开发一款Android端播放器(支持多协议网络拉流本地文件)

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  6. 鸿蒙开发实战系列之三:网络请求(原生+ Retrofit)

    鸿蒙开发实战系列之一:鸿蒙开发实战系列之一:圆角 鸿蒙开发实战系列之二:鸿蒙开发实战系列之二:事件总线EventBus/RxBus 前言 过了一个漫长的中秋+国庆假期,大家伙的鸿蒙内功修炼的怎么样了? ...

  7. Android开发本地及网络Mp3音乐播放器(十二)创建NetMusicListAdapter、SearchResult显示网络音乐列表

    转载请注明出处:http://blog.csdn.net/iwanghang/article/details/51290181 觉得博文有用,请点赞,请留言,请关注,谢谢!~ 实现功能: 实现NetM ...

  8. WCF开发实战系列四:使用Windows服务发布WCF服务

    WCF开发实战系列四:使用Windows服务发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇文章中我们通过编写的控制台程序或WinForm程序来为本 ...

  9. 鸿蒙开发实战系列之五:鸿蒙系统原生数据库

    鸿蒙开发实战系列之一:鸿蒙开发实战系列之一:圆角 鸿蒙开发实战系列之二:鸿蒙开发实战系列之二:事件总线EventBus/RxBus 鸿蒙开发实战系列之三:鸿蒙开发实战系列之三:网络请求(原生+ Ret ...

  10. 【直播回顾】云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第19讲):Java Spring Cloud微服务架构模式与开发实战...

    主讲人:徐雷(云栖社区特邀Java专家) 徐雷,花名:徐雷frank:资深架构师,MongoDB中文社区联席主席,吉林大学计算机学士,上海交通大学硕士.从事了 10年+开发工作,专注于分布式架构,Ja ...

最新文章

  1. 【055】长江水文数据自动记录程序
  2. 聊聊、Zookeeper 客户端 Curator
  3. python怎么编辑文件夹_python创建修改文件
  4. ncut算法matlab实现,ncut_multiscale_1_6 经典的图像分割算法 的Matlab代码。 238万源代码下载- www.pudn.com...
  5. angular的性能分析 -随记
  6. vue.js项目中,关于element-ui完整引入、按需引入的介绍
  7. python partition只能切割一次吗_Python3的字符串方法
  8. java c混合编程 linux_linux下C与C++混合编程
  9. java在未来_如何在java中创建一个完整的未来
  10. 看懂别人的代码,和自己能写代码是两回事
  11. 前端开发-jQuery基本语法
  12. matlab qpsk代码 博客,完整版QPSK调制原理及matlab程序实现
  13. ARM学习(8) axf 工具解析
  14. 如何清除谷歌浏览器中的counterflix广告病毒
  15. 陕西国防学院计算机系网络教研室,陕西国防工业职业技术学院:全卫强副院长赴各院部调研教师发展工作...
  16. java实现阿里云邮箱发送邮件
  17. 网站服务器在什么地方怎么查,如何查询一个网站所在服务器信息
  18. exo文件_eXo平台概述
  19. iOS之POP动画使用和实战
  20. 单台计算机 双ip设置,单网卡设双IP也有优先级

热门文章

  1. linux下while循环,Bash 中的 while 循环详解
  2. python循环语句while教案_while循环教学设计
  3. HC-SR04 超声波原理图讲解与时序分析与arduino使用
  4. 以贝叶斯思维看待世界
  5. 2018最新第三方支付牌照公司名单「完整」
  6. Ubuntu设置dns
  7. Java 数据填充到word模板中
  8. 奥克兰大学 计算机硕士 GPA,奥克兰大学GPA
  9. 网络安全---数字签名
  10. 评弱水三千,该取几瓢饮?———贪恋还是专情