Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
网络学习营
【7天入门RTOS网络编程】Nautilus day8 关于webclient-v2.0.1的bug...
发布于 2018-10-26 21:42:54 浏览:2801
订阅该版
* 本帖最后由 yukelab 于 2018-10-26 21:49 编辑 * 关于使用webclient-v2.0.1进行百度语音识别不成功的同学可以看过来了,这个webclient-v2.0.1有些bug,具体间下 很开心有了个满意的结果1. Package webclient-v2.0.1 webclient.c中的static int webclient_send_header(struct webclient_session *session,int method) 函数有在POST条件分支下有bug,会导致web header拼接错误,从而导致header发送失败;大概是截图部位,行数没有截取,主要是我在里面插入了v1.0.0的webclient_send_header函数,所以为免去错误引导大家,故此略去![6.png](/uploads/201810/26/214549a349pz2os9r7zsip.png)2. 接收响应数据时,我这里会经常出错误码-2, timeout,所以我加了 webclient_set_timeout(session, 100000);函数,至于为啥设100000ms,因为我设置较小的化,还是会出错误码-23. 建议在接收响应数据 int content_length =webclient_content_length_get(session);函数后加一小段延时,再read数据4. 由于webclient-v2.0.1中没有解析数据的函数,具体在v1.0.0为static char *webclient_header_skip_prefix(char *line, constchar *prefix),所以接收到的数据如下图所示,加了http的各种头![7.png](/uploads/201810/26/214616r3xlxr17wp73j3j5.png)终于可以有个满意的答复了,至于webclient-v2.0.1中的大bug,等闲下来了,整整;最后,贴上代码,如果大家想快速高效的完成大作业,建议使用webclient-v1.0.0![8.png](/uploads/201810/26/214636t2ncdch4bsqhcxmd.png) Webclient.c 文件中添加```int webclient_send_header_100(struct webclient_session *session, int method, const char *header, size_t header_sz) { int rc = WEBCLIENT_OK; unsigned char *header_buffer = RT_NULL, *header_ptr; if (header == RT_NULL) { header_buffer = web_malloc(WEBCLIENT_HEADER_BUFSZ); if (header_buffer == RT_NULL) { rc = -WEBCLIENT_NOMEM; goto __exit; } header_ptr = header_buffer; header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "GET %s HTTP/1.1
", session->req_url ? session->req_url : "/"); header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "Host: %s
", session->host); header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "User-Agent: RT-Thread HTTP Agent
"); webclient_write(session, header_buffer, header_ptr - header_buffer); } else { if (method != WEBCLIENT_USER_METHOD) { header_buffer = web_malloc(WEBCLIENT_HEADER_BUFSZ); if (header_buffer == RT_NULL) { rc = -WEBCLIENT_NOMEM; goto __exit; } header_ptr = header_buffer; if (strstr(header, "HTTP/1.") == RT_NULL) { if (method == WEBCLIENT_GET) header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "GET %s HTTP/1.1
", session->req_url ? session->req_url : "/"); else if (method == WEBCLIENT_POST) header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "POST %s HTTP/1.1
", session->req_url ? session->req_url : "/"); } if (strstr(header, "Host:") == RT_NULL) { header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "Host: %s
", session->host); } if (strstr(header, "User-Agent:") == RT_NULL) { header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "User-Agent: RT-Thread HTTP Agent
"); } if (strstr(header, "Accept: ") == RT_NULL) { header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "Accept: */*
"); } if ((WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer)) < (int) header_sz + 3) { rc = -WEBCLIENT_NOBUFFER; goto __exit; } /* append user's header */ memcpy(header_ptr, header, header_sz); header_ptr += header_sz; header_ptr += rt_snprintf((char *) header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header_buffer), "
"); webclient_write(session, header_buffer, header_ptr - header_buffer); } else { webclient_write(session, (unsigned char *) header, header_sz); } } __exit: web_free(header_buffer); return rc; } ```修改![9.png](/uploads/201810/26/214837vckzpddwt4pcc0wo.png)贴一下代码语音识别的代码吧```#include
#include
#include "webclient.h" #include
/* 当需要使用文件操作时,需要包含这个头文件 */ /* 语音合成 */ #define GET_RESP_BUFSZ 2048 #define GET_HEADER_BUFSZ 2048 #define GET_URL_LEN_MAX 2048 //需要语音合成 #define FILE_NAME_MAX 32 #define MP3_FILE "/baidu/%s.wav" /* 语音识别 */ #define POST_FILE_URL "http://vop.baidu.com/server_api?dev_pid=1536&cuid=74-E5-F9-56-EF-B4&token=24.3f9eb59e31d150561c7a0cda5835b69b.2592000.1542944661.282335-14532805" /* Content-Type: audio/pcm;rate=16000 */ #define C_TYPE "audio/pcm;rate=16000" /* debug */ #include
int webclient_post_file_baidu(const char* URI, const char* filename, const char* form_data) { size_t length; char boundary[60]; int fd = -1, rc = WEBCLIENT_OK; char *header = RT_NULL, *header_ptr; unsigned char *buffer = RT_NULL, *buffer_ptr; struct webclient_session* session = RT_NULL; int bytes_read = 0, index = 0; int resp_status; int ret = 0; int send_count = 0; fd = open(filename, O_RDONLY, 0); if (fd < 0) { LOG_D("post file failed, open file(%s) error.", filename); rc = -WEBCLIENT_FILE_ERROR; goto __exit; } /* get the size of file */ length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ); if (buffer == RT_NULL) { LOG_D("post file failed, no memory for response buffer."); rc = -WEBCLIENT_NOMEM; goto __exit; } header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ); if (header == RT_NULL) { LOG_D("post file failed, no memory for header buffer."); rc = -WEBCLIENT_NOMEM; goto __exit; } header_ptr = header; /* build boundary */ rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get()); /* mine part */ /* build encapsulated mime_multipart information*/ buffer_ptr = buffer; /* first boundary */ buffer_ptr += rt_snprintf((char*) buffer_ptr, WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s
", boundary); buffer_ptr += rt_snprintf((char*) buffer_ptr, WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "Content-Disposition: form-data; %s
", form_data); buffer_ptr += rt_snprintf((char*) buffer_ptr, WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "Content-Type: application/octet-stream--%s
", boundary); /* calculate content-length */ length += buffer_ptr - buffer; length += rt_strlen(boundary) + 6; /* add the last boundary */ rt_kprintf("buffer len: %d
", buffer_ptr-buffer); for (index = 0; index < buffer_ptr - buffer; index++) { rt_kprintf("%c", buffer[index]); } /* build header for upload */ header_ptr += rt_snprintf(header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header), "Content-Length: %d
", length); header_ptr += rt_snprintf(header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header), "Content-Type: %s
", form_data); session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ); if(session == RT_NULL) { rc = -WEBCLIENT_NOMEM; rt_kprintf("create session error!
"); goto __exit; } rt_kprintf("header: %s
", header); /* me: 字符串复制到session->header->buffer */ session->header->buffer = web_strdup(header); /* 若定义了session->header->length,则会导致header发送失败 */ /* 为了使用post方式,这里还是需要对session->header->length进行赋值 */ /* session->header->length = header_ptr - header; */ /* 建立连接 */ rc = webclient_post(session, URI, NULL); if( rc< 0) { rt_kprintf("webclient post data error!
"); goto __exit; } else if (rc == 0) { rt_kprintf("webclient connected and send header msg!
"); } else { rt_kprintf("rc code: %d!
", rc); } rt_kprintf("echo header data after connect:
"); for (index = 0; index < session->header->length; index++) { rt_kprintf("%c", session->header->buffer[index]); } /* send mime_multipart */ /* rt_kprintf("mime_mutipart msg: %s;
", buffer ); */ rt_kprintf("mime_mutipart msg:"); for (index = 0; index < buffer_ptr - buffer; index ++) { rt_kprintf("%c",buffer[index]); } #if 1 rt_kprintf("
mime_mutipart len: %d
",(int)(buffer_ptr - buffer)); ret = webclient_write(session, buffer, buffer_ptr - buffer); if (ret < 0) { rt_kprintf("webclient write mime_mutipart error!
"); goto __exit; } else { rt_kprintf("webclient write mime_mutipart scuessed!
"); } #endif /* send file data */ while (1) { length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ); if (length <= 0) { break; } rt_kprintf("read file data length %d; webclient write %d cnt!
",length, ++send_count); ret = webclient_write(session, buffer, length); if (ret < 0) { rt_kprintf("webclient write error!
"); break; } } /* send last boundary */ rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "
--%s--
", boundary); webclient_write(session, buffer, rt_strlen(boundary) + 6); if (fd >= 0) { close(fd); fd = -1; } rt_kprintf("send file completed!
"); #if 1 webclient_set_timeout(session, 100000); int content_pos = 0; /* 获取接收的响应数据长度 */ int content_length = webclient_content_length_get(session); rt_thread_delay(100); /* 循环接收响应数据直到数据接收完毕 */ do { /* 总是返回超时错误 */ bytes_read = webclient_read(session, buffer, 1024); if (bytes_read <= 0) { break; } /* 打印响应数据 */ for (index = 0; index < bytes_read; index++) { rt_kprintf("%c", buffer[index]); } content_pos += bytes_read; } while (content_pos < content_length); #endif __exit: if (fd >= 0) { close(fd); } if ((session != RT_NULL)) { webclient_close(session); } if (buffer != RT_NULL) { web_free(buffer); } if (header != RT_NULL) { web_free(header); } return 0; } /* 使用Raw 方式上传 */ int webclient_post_voice_file_to_identify(int argc, char **argv) { char *URI = RT_NULL; int ret = 0; // int bytes_read, resp_status; /* int resp_status; */ char *file_name = RT_NULL; URI = web_strdup(POST_FILE_URL); if(URI == RT_NULL) { rt_kprintf("no memory for create URI buffer.
"); return -1; } if (argc == 1) { file_name = rt_calloc(1, FILE_NAME_MAX); if (file_name == RT_NULL) { rt_kprintf("No memory for file name!
"); return -1; } /* 拼接 GET 网址 */ rt_snprintf(file_name, FILE_NAME_MAX, MP3_FILE, "1"); } else { rt_kprintf("webclient_post_test [URI] - webclient POST request test.
"); return -1; } if ((webclient_post_file_baidu(URI, file_name, C_TYPE))) /* if ((webclient_post_file(URI, file_name, C_TYPE))) */ { /* rt_kprintf("webclient POST request failed, response(%d) error.
", resp_status); */ ret = -RT_ERROR; goto __exit; } rt_kprintf("
"); __exit: if (URI) { web_free(URI); } if (file_name) { web_free(file_name); } return ret; } #ifdef FINSH_USING_MSH #include
MSH_CMD_EXPORT_ALIAS(webclient_post_voice_file_to_identify, baidu_indentify, webclient_post_test [URI] - webclient POST request test.); #endif /* FINSH_USING_MSH */ ``` ok,搞了三天这个东西,大家可以参考下ps:终于可以不用附件了
查看更多
14
个回答
默认排序
按发布时间排序
Cheney_Chen
2018-10-27
这家伙很懒,什么也没写!
[i=s] 本帖最后由 Cheney_Chen 于 2018-11-5 10:55 编辑 [/i] [md]楼主你好,首先感谢你对 webclient 软件包的使用和支持,可以看到楼主花了很长时间和精力在软件包问题的整理和调试上。 然后是关于楼主的问题,总结楼主上述提到的问题是: webclient 2.0.0 POST 上传数据的时候发送的头部信息不正确。 查看代码之后发现,其实问题的根本是楼主代码中 ** webclient 2.0.0 POST 上传使用方式不正确** webclient 2.0.0 发布之后附带添加了许多文档说明(在 README 可以找到),其中使用指南中明确给出了 POST 发送数据的正确流程,链接如下:https://github.com/RT-Thread-packages/webclient/blob/master/docs/user-guide.md#post-%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F , POST sample 示例中也给出了基本的使用流程。 查看使用指南可以发现,webclient 2.0.0 头文件拼接方式相比较 1.0.0 有了很大改变,使用了自带的简单的函数拼接头部方式,原来 1.0.0 头部信息都需要使用字符串拼接使用过于复杂。回到楼主的问题,可以看到其代码中使用了字符串拼接方式拼接了头部信息,然后直接拷贝给 `session->header->buffer` 中,这是错误的操作,直接导致解析 header 的时候出现错误,正确的方式是使用 `webclient_header_fields_add` 拼接头部数据。 这里花了点时间修改了楼主的代码,**不用修改 webclient 2.0.0 源码**,使用 pcm 文件验证语音识别正确,下面贴上修改后的代码:[/md] ``` #include
#include
#include "webclient.h" #include
/* 当需要使用文件操作时,需要包含这个头文件 */ /* 语音合成 */ #define GET_RESP_BUFSZ 2048 #define GET_HEADER_BUFSZ 2048 #define GET_URL_LEN_MAX 2048 //需要语音合成 #define FILE_NAME_MAX 32 #define MP3_FILE "/baidu/%s.pcm" /* 语音识别 */ #define POST_FILE_URL "http://vop.baidu.com/server_api?dev_pid=1536&cuid=74-E5-F9-56-EF-B4&token=24.3f9eb59e31d150561c7a0cda5835b69b.2592000.1542944661.282335-14532805" /* Content-Type: audio/pcm;rate=16000 */ #define C_TYPE "audio/pcm;rate=16000" #define DBG_ENABLE #define DBG_SECTION_NAME "web.baidu" #define DBG_LEVEL DBG_LOG #define DBG_COLOR #include
int webclient_post_file_baidu(const char* URI, const char* filename, const char* form_data) { size_t length; int fd = -1, rc = WEBCLIENT_OK; unsigned char *buffer = RT_NULL; struct webclient_session* session = RT_NULL; int bytes_read = 0, index = 0; int ret = 0; int send_count = 0; fd = open(filename, O_RDONLY, 0); if (fd < 0) { LOG_D("post file failed, open file(%s) error.", filename); rc = -WEBCLIENT_FILE_ERROR; goto __exit; } /* get the size of file */ length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ); if (buffer == RT_NULL) { LOG_D("post file failed, no memory for response buffer."); rc = -WEBCLIENT_NOMEM; goto __exit; } session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ); if (session == RT_NULL) { rc = -WEBCLIENT_NOMEM; rt_kprintf("create session error!\n"); goto __exit; } /* build header for upload */ webclient_header_fields_add(session, "Content-Length: %d\r\n", length); webclient_header_fields_add(session, "Content-Type: %s\r\n", form_data); rc = webclient_post(session, URI, NULL); if (rc < 0) { rt_kprintf("webclient post data error!\n"); goto __exit; } else if (rc == 0) { rt_kprintf("webclient connected and send header msg!\n"); } else { rt_kprintf("rc code: %d!\n", rc); } /* send file data */ while (1) { rt_memset(buffer, 0x00, WEBCLIENT_RESPONSE_BUFSZ); length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ); if (length <= 0) { break; } rt_kprintf("read file data length %d; webclient write %d cnt!\n", length, ++send_count); ret = webclient_write(session, buffer, length); if (ret < 0) { rt_kprintf("webclient write error!\n"); break; } rt_thread_mdelay(100); } rt_kprintf("send file completed!\n"); if( webclient_handle_response(session) != 200) { LOG_E("get handle resposne error!"); goto __exit; } // webclient_set_timeout(session, 100000); int content_pos = 0; /* 获取接收的响应数据长度 */ int content_length = webclient_content_length_get(session); rt_thread_delay(100); /* 循环接收响应数据直到数据接收完毕 */ do { bytes_read = webclient_read(session, buffer, 1024); if (bytes_read <= 0) { break; } /* 打印响应数据 */ for (index = 0; index < bytes_read; index++) { rt_kprintf("%c", buffer[index]); } content_pos += bytes_read; } while (content_pos < content_length); __exit: if (fd >= 0) { close(fd); } if ((session != RT_NULL)) { webclient_close(session); } if (buffer != RT_NULL) { web_free(buffer); } return 0; } /* 使用Raw 方式上传 */ int webclient_post_voice_file_to_identify(int argc, char **argv) { char *URI = RT_NULL; int ret = 0; // int bytes_read, resp_status; /* int resp_status; */ char *file_name = RT_NULL; URI = web_strdup(POST_FILE_URL); if (URI == RT_NULL) { rt_kprintf("no memory for create URI buffer.\n"); return -1; } if (argc == 1) { file_name = rt_calloc(1, FILE_NAME_MAX); if (file_name == RT_NULL) { rt_kprintf("No memory for file name!\n"); return -1; } /* 拼接 GET 网址 */ rt_snprintf(file_name, FILE_NAME_MAX, MP3_FILE, "on1"); } else { rt_kprintf("webclient_post_test [URI] - webclient POST request test.\n"); return -1; } if ((webclient_post_file_baidu(URI, file_name, C_TYPE))) /* if ((webclient_post_file(URI, file_name, C_TYPE))) */ { /* rt_kprintf("webclient POST request failed, response(%d) error.\n", resp_status); */ ret = -RT_ERROR; goto __exit; } rt_kprintf("\n"); __exit: if (URI) { web_free(URI); } if (file_name) { web_free(file_name); } return ret; } #ifdef FINSH_USING_MSH #include
MSH_CMD_EXPORT_ALIAS(webclient_post_voice_file_to_identify, baidu_indentify, webclient_post_test [URI] - webclient POST request test.); #endif /* FINSH_USING_MSH */ ``` [md]最后, webclient 2.0.0 发布不是很久,我们也在一直推进和改善中,希望大家能多多使用,有什么问题可以直接提出来一起讨论验证,有问题我们会及时修复和完善,然后希望大家使用之前先认真查看 webclient 文档,相信大家会更加快速全面的掌握软件包的使用。[/md]
san兄弟
2018-10-26
这家伙很懒,什么也没写!
膜拜一下,然后慢慢消化
yukelab
2018-10-27
这家伙很懒,什么也没写!
补充一下:第一条下的主要是头部拼接后,session-host内容发生变化,后面的向header添加host时,出错
Cheney_Chen
2018-10-27
这家伙很懒,什么也没写!
这是上面测试使用的文件
yukelab
2018-10-27
这家伙很懒,什么也没写!
>Cheney_Chen 发表于 2018-10-27 12:23 >这是上面测试使用的文件 --- 确实存在没有认真看文档的问题。 这个代码主要是参考webclient_post_file函数写的,然后就陷进去了。嗯,你可以看下,修正一下这个函数,在webclient_file.c中 另外请教个问题 header字符串拼接代码中大量用了memcmp做字符匹配,虽然效率高,但memcmp可能导致重复添加,为何不用strstr
Cheney_Chen
2018-10-27
这家伙很懒,什么也没写!
>确实存在没有认真看文档的问题。 >这个代码主要是参考webclient_post_file函数写的,然后就陷进去了。嗯, ... --- 感谢楼主问题反馈,原操作确实会出现重复添加的问题,问题已经确认修复,可以更新使用 laster 最新版软件包
yukelab
2018-10-27
这家伙很懒,什么也没写!
>Cheney_Chen 发表于 2018-10-27 12:23 >这是上面测试使用的文件 --- 还有一个问题 如果在webclient_write过程中出错,会释放session内存,但是session并未置为RT_NULL,如果在application中使用if(session != RT_NULL) rt_free(session),这样就会重复释放内存,导致qemu崩溃。
Cheney_Chen
2018-10-27
这家伙很懒,什么也没写!
>还有一个问题 >如果在webclient_write过程中出错,会释放session内存,但是session并未置为RT_NULL,如果 ... --- 正常情况是直接调用 webclient_close 函数关闭 session ,webclient_close 中有做置空处理,我没有看到楼主说的 webclient_write 出错会释放 session 的操作
yukelab
2018-10-27
这家伙很懒,什么也没写!
>Cheney_Chen 发表于 2018-10-27 12:23 >这是上面测试使用的文件 --- 具体看一下我的这个帖子的描述 https://www.rt-thread.org/qa/data/attachment/forum/201810/25/203454l7i8xi18112i111j.png 手头没有电脑,下周我再复现一下,手机敲字不容易啊
yukelab
2018-10-29
这家伙很懒,什么也没写!
>正常情况是直接调用 webclient_close 函数关闭 session ,webclient_close 中有做置空处理,我没有看到楼 ... --- 重新使用v2.0.1版本测试了一下,使用帖子开始所述的错误头部拼接方式,进行的头部数据的拼接,进行测试;返回如下错误,然后qemu 处于假死状态,键盘无法输入。 [attach]6693[/attach] [attach]6694[/attach]
撰写答案
登录
注册新账号
关注者
0
被浏览
2.8k
关于作者
yukelab
这家伙很懒,什么也没写!
提问
17
回答
47
被采纳
1
关注TA
发私信
相关问题
1
【LWIP学习营】第一关开发环境搭建
2
LWIP学习营第一周入门移植问题汇总贴
3
【LWIP学习营】f407+lan8720A小结
4
【LwIP学习营】【第一周】仅零散记录,无主题
5
【LWIP学习营】正点原子探索者F407+LAN8720第一周小结
6
【LwIP学习营】【第一周】网络通信基础及实现TCP 聊天客户端
7
【LwIP学习营】【第一周】LWIP移植
8
【LwIP学习营】【第一周】LWIP移植
9
【LwIP学习营】【第一周】开发板适配
10
【LwIP学习营】【第一周】环境搭建和配置验证
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用RC522软件包驱动FM1722
2
常量数据类型和表达式陷阱分享
3
进行i2c驱动移植的经验总结
4
在VSCode中使用clang-format
5
我该如何使用这个微雪的WIFI400 WIFI-LPB-100在rtt里或者我该怎样为它开发驱动
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
289
次被采纳
张世争
809
个答案
175
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部