删除被占用的串口
点击“开始”,选择“运行”,之后输入cmd,回车。
在对话框内输入”set devmgr_show_nonpresent_devices=1”,回车。 接着输入“start devmgmt.msc”,回车。
打开设备管理器,选择“查看”菜单中的“显示隐藏设备”,展开USB相关驱动,选择不需要的卸载即可。
不要试图卸载COM1,COM2
1、串口的初始化
在MTK平台上,串口的操作和常见的操作系统不太一样,串口句柄并不是以文件形式的出现,而是有点类似单片机的做法,即每个串口有固定的编号,串口的初始化不需要有类似Windows/Unix等打开设备文件的操作(实际上是有UART_Open这个函数的,不过我们没有用到,大概是底层硬件初始化会用到,这里我们简单的理解成不需要Open就好了),下面我们对照实际的初始化代码逐句讲解初始化所需要做的事情,如下所示:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 我们要用到的串口, uart_port1是枚举型数值,usb串口的编号
#define HELLO_WORLD_UART_PORT uart_port1 // 手机接USB下载线的地方
// 定义我们的应用所属系统的哪一个模块
// 这里是MMI模块,实际上我更愿意称MMI为一个子系统,将我们的应用称为模块
#define MOD_HELLO_WORLD MOD_MMI
// 数据接收Buffer大小
#define MAX_ECHO_PACKET_LEN 128
// 睡眠模式句柄
static kal_uint8 ghSleepMode;
// 我们要用到的串口之前的占用者
static module_type gnOrigUartOwner;
static kal_bool gbUartInitialized = KAL_FALSE;
static void init_uart(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
if(gbUartInitialized)
{
return;
}
ghSleepMode = L1SM_GetHandle();
// 禁止休眠,休眠后串口收发会有问题
// 问题:如何做到串口唤醒? FIXME
L1SM_SleepDisable(ghSleepMode);
// 记录我们要用的串口的当前占有者
gnOrigUartOwner = UART_GetOwnerID(HELLO_WORLD_UART_PORT);
// 下面我们申明要占用这个串口了
UART_SetOwner(HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
// 以上对串口占用的申明,我理解更多是一种编程者之间的约定 // 当发现串口的占用者不是本程序所属模块时,说明我们申明占用之后
// 又有其他模块申明占用同一个串口,此时如果收到数据应不予处理 // 当然,也有可能同一模块的其他程序申明占用同一串口
// 这需要在设计应用时统一协调,避免数据发生混乱
// 设置波特率,缺省的起停位和校验为:8,n,1,即8个数据位,1个停止位,无校验
UART_SetBaudRate(HELLO_WORLD_UART_PORT, UART_BAUD_115200, MOD_HELLO_WORLD);
// 其他串口设定(如起停位、校验等)使用函数 UART_ReadDCBConfig 和 UART_SetDCBConfig
// 详细参数见结构体 UARTDCBStruct
// 注册一个事件钩子函数,当串口(任何)有数据到达时,我们的钩子函数将被调用
// 注意,同一种事件同时只能注册一个钩子函数,因此:
// 如果在我们的程序处理串口的同时还有其他程序要读取和处理(任何)串口数据,
// 就必须由当前的钩子函数代为处理
// 实际上我觉得系统底层可以改一下,改成Windows钩子的方式,可以挂多个,能够依次调用或跳过
SetProtocolEventHandler(mmi_HelloWorld_uart_readyToRead_ind_handler, MSG_ID_UART_READY_TO_READ_IND);
gbUartInitialized = KAL_TRUE;
#endif
}
2、从串口读数据
这里有两个相关的函数,第一个是上面初始化部分提到的钩子函数mmi_HelloWorld_uart_readyToRead_ind_handler,另外一个是读函数,函数体如下所示:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void mmi_HelloWorld_uart_readyToRead_ind_handler(void *msg) {
#ifdef __MMI_HELLOWORLD_ENABLED__
uart_ready_to_read_ind_struct* uart_rtr_ind =
(uart_ready_to_read_ind_struct*)msg;
// 检查一下端口以及所有者信息,不匹配的数据略过
// 注意,作为例子程序,我们只是查看和处理我们关心的数据
// 其他与此同时需要监听和处理串口数据的程序,须由相关的代码完成代理的工作
if( KAL_FALSE == gbUartEchoStarted ||
HELLO_WORLD_UART_PORT != uart_rtr_ind->port || MOD_HELLO_WORLD !=
UART_GetOwnerID(uart_rtr_ind->port) )
{
// 如果底层能做成钩子链,这里就可以调用钩子链的下一个钩子了
return;
}
gwLenUartBuffer = read_from_uart(gabyUartBuffer,
sizeof(gabyUartBuffer), HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
// 呼叫数据处理部分
uart_echo_process();
#endif
}
static U16 read_from_uart(U8 *pbyBuf, U16 wLenMax, UART_PORT hPort, module_type hOwner)
{
U16 wLenAvail;
U16 wLenRead;
U16 wLenRet = 0;
U8 byStatus = 0;
#ifdef __MMI_HELLOWORLD_ENABLED__
// 收取数据,超出最大包长的数据将简单丢弃,这一层需要具体的应用协议做相应处理
while( (wLenAvail = UART_GetBytesAvail(hPort) > 0 && wLenRet < wLenMax) )
{
if (wLenAvail + wLenRet > wLenMax)
{
wLenAvail = wLenMax - wLenRet;
}
wLenRead = UART_GetBytes(hPort, (kal_uint8 *)(pbyBuf + wLenRet), (kal_uint16)wLenAvail, &byStatus, hOwner);
wLenRet += wLenRead;
}
// 读完之后,清除接收Buffer
UART_ClrRxBuffer(hPort, hOwner);
#endif
return wLenRet;
}
3、向串口写数据
static U8 write_to_uart(U8 *pbyBuf, U16 wLenBuf, UART_PORT hPort, module_type hOwner)
{
U16 wSent= 0;
U8 bRet = FALSE;
#ifdef __MMI_HELLOWORLD_ENABLED__
// 发送前清FIFO和Buffer,注意:这一步必须做,否则收发会有问题
UART_Purge(hPort, RX_BUF, hOwner); // 清除设备输入FIFO
UART_Purge(hPort, TX_BUF, hOwner); // 清除设备输出FIFO
UART_ClrTxBuffer(hPort, hOwner); // 清除发送Buffer
UART_ClrRxBuffer(hPort, hOwner); // 清除接收Buffer
wSent = UART_PutBytes(hPort, (kal_uint8 *)pbyBuf, (kal_uint16)wLenBuf, hOwner);
#endif
if (wSent == wLenBuf)
{
bRet = TRUE;
}
return bRet ;
}
4、关闭串口
关闭串口实际上是将相关的设置改动恢复到之前的状态,不需要有close的动作,如下所示:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void exit_uart()
{
#ifdef __MMI_HELLOWORLD_ENABLED__
if(gbUartInitialized)
{
// 恢复成原有的端口占用者
UART_SetOwner(HELLO_WORLD_UART_PORT, (kal_uint8) gnOrigUartOwner);
// 允许休眠
L1SM_SleepEnable(ghSleepMode);
gbUartInitialized = KAL_FALSE;
}
#endif
}
5、下载测试
Make remake一下->下载程序到手机->关闭下载工具->运行串口工具,打开USB下载线对应的串口,设定为115200,8N1->手机开机(此时下载线不要拔下,我们用的就是这个下载线测试的)->手机工具菜单->Hello World->手机左键启动串口Echo(启动后再按左键停止串口Echo)。
注1:串口的部分在仿真器上模拟不了,链接的时候也会提示找不到相关函数符号。
注2:在HelloWorld的串口Echo停止工作时我们也能偶尔看到串口会原样回显,这应该是其他程序在处理,不是我们的HelloWorld,我们的HelloWorld会将输入转成全大写再回显。
注3:使用手机的USB下载口当作串口时,要用USB下载线进行连接,同时要注意相关的工程设置为以下:
--------------
TST Config
< 无 >
< 115200 >
PS Config
< UART 1 >
< 115200 >
--------------
设置方法:
待机界面下(拨号)输入 *#3646633# (进入 工程模式)->设备->"Set UART"->"UART Setting"
程序运行后的电脑端截图如下:
我采用1ms定时发送“Hello, World!\r\n”, 每毫秒15字节的速度,接收比发送多,这是因为启动Echo时,我有送一个串“Hello World Uart Echo Example Started! \r\n”(40字节)过来,不过接收多出的部分应该不止10个字节
(1928380 – 1928370),应该是40个字节,数据似乎有部分丢失(刚好2个包, 15 * 2 = 30 = 40 - 10),应该是电脑端发送太快的原因(115200 / (8 + 1) / 1000 = 12.8字节/毫秒,小于15,而且还有数据处理和echo的时间),这样的响应速度算相当不错了。
6、完整的C程序
下面贴出比较完整的HelloWorld.c程序,供大家参考,由于时间的关系,开发心得暂时到此为止,感谢华禹公司及其兄弟公司的支持,感谢各位网友! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stdC.h"
#include "MMI_Features.h" /* 编译开关会出现在这个由make update生成的文件里面 */
#include "L4Dr.h"
#include "L4Dr1.h"
#include "AllAppGprot.h"
#include "FrameworkStruct.h"
#include "GlobalConstants.h"
#include "EventsGprot.h"
#include "mmiappfnptrs.h"
#include "HistoryGprot.h"
#include "HelloWorldProt.h"
#include "HelloWorldTypes.h"
#include "HelloWorldDefs.h"
#include "MainMenuDef.h"
#include "wgui_categories.h"
#include "Unicodexdcl.h"
#include "gui_data_types.h"
#include "Uart_sw.h"
// 我们要用到的串口, uart_port1是枚举型数值,usb串口的编号
#define HELLO_WORLD_UART_PORT uart_port1 // 手机接USB下载线的地方
// 定义我们的应用所属系统的哪一个模块
// 这里是MMI模块,实际上我更愿意称MMI为一个子系统,将我们的应用称为模块
#define MOD_HELLO_WORLD MOD_MMI
// 数据接收Buffer大小
#define MAX_ECHO_PACKET_LEN 128
// 外部函数申明,没有对应头文件,手动加吧
extern module_type UART_GetOwnerID(UART_PORT port);
extern void UART_ClrTxBuffer(UART_PORT port, module_type ownerid); extern void UART_ClrRxBuffer(UART_PORT port, module_type ownerid);
// 本程序内部使用的函数申明
static void init_uart(void);
static void mmi_HelloWorld_uart_readyToRead_ind_handler(void *msg); static U16 read_from_uart(U8 *pbyBuf, U16 wLenMax, UART_PORT hPort, module_type hOwner);
static U8 write_to_uart(U8 *pbyBuf, U16 wLenBuf, UART_PORT hPort, module_type hOwner);
static void exit_uart();
static void start_uart_echo(void);
static void uart_echo_process(void);
static void stop_uart_echo(void);
// 睡眠模式句柄
static kal_uint8 ghSleepMode;
// 我们要用到的串口之前的占用者
static module_type gnOrigUartOwner;
static kal_bool gbUartInitialized = KAL_FALSE;
static kal_bool gbUartEchoStarted = KAL_FALSE;
static U16 gwLenUartBuffer = 0;
static U8 gabyUartBuffer[MAX_ECHO_PACKET_LEN];
static void init_uart(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
if(gbUartInitialized)
{
return;
}
ghSleepMode = L1SM_GetHandle();
// 禁止休眠,休眠后串口收发会有问题
// 问题:如何做到串口唤醒? FIXME
L1SM_SleepDisable(ghSleepMode);
// 记录我们要用的串口的当前占有者
gnOrigUartOwner = UART_GetOwnerID(HELLO_WORLD_UART_PORT);
// 下面我们申明要占用这个串口了
UART_SetOwner(HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD); // 以上对串口占用的申明,我理解更多是一种编程者之间的约定 // 当发现串口的占用者不是本程序所属模块时,说明我们申明占用之后
// 又有其他模块申明占用同一个串口,此时如果收到数据应不予处理 // 当然,也有可能同一模块的其他程序申明占用同一串口
// 这需要在设计应用时统一协调,避免数据发生混乱
// 设置波特率,缺省的起停位和校验为:8,n,1,即8个数据位,1个停止位,无校验
UART_SetBaudRate(HELLO_WORLD_UART_PORT, UART_BAUD_115200, MOD_HELLO_WORLD);
// 其他串口设定(如起停位、校验等)使用函数 UART_ReadDCBConfig 和 UART_SetDCBConfig
// 详细参数见结构体 UARTDCBStruct
// 注册一个事件钩子函数,当串口(任何)有数据到达时,我们的钩子函数将被调用
// 注意,同一种事件同时只能注册一个钩子函数,因此:
// 如果在我们的程序处理串口的同时还有其他程序要读取和处理(任何)串口数据,
// 就必须由当前的钩子函数代为处理
// 实际上我觉得系统底层可以改一下,改成Windows钩子的方式,可以挂多个,能够依次调用或跳过
SetProtocolEventHandler(mmi_HelloWorld_uart_readyToRead_ind_handler, MSG_ID_UART_READY_TO_READ_IND);
gbUartInitialized = KAL_TRUE;
#endif
}
static U16 read_from_uart(U8 *pbyBuf, U16 wLenMax, UART_PORT hPort, module_type hOwner)
{
U16 wLenAvail;
U16 wLenRead;
U16 wLenRet = 0;
U8 byStatus = 0;
#ifdef __MMI_HELLOWORLD_ENABLED__
// 收取数据,超出最大包长的数据将简单丢弃,这一层需要具体的应用协议做相应处理
while( (wLenAvail = UART_GetBytesAvail(hPort) > 0 && wLenRet < wLenMax) )
{
if (wLenAvail + wLenRet > wLenMax)
{
wLenAvail = wLenMax - wLenRet;
}
wLenRead = UART_GetBytes(hPort, (kal_uint8 *)(pbyBuf + wLenRet), (kal_uint16)wLenAvail, &byStatus, hOwner);
wLenRet += wLenRead;
}
// 读完之后,清除接收Buffer
UART_ClrRxBuffer(hPort, hOwner);
#endif
return wLenRet;
}
static U8 write_to_uart(U8 *pbyBuf, U16 wLenBuf, UART_PORT hPort, module_type hOwner)
{
U16 wSent= 0;
U8 bRet = FALSE;
#ifdef __MMI_HELLOWORLD_ENABLED__
// 发送前清FIFO和Buffer,注意:这一步必须做,否则收发会有问题 UART_Purge(hPort, RX_BUF, hOwner); // 清除设备输入FIFO UART_Purge(hPort, TX_BUF, hOwner); // 清除设备输出FIFO UART_ClrTxBuffer(hPort, hOwner); // 清除发送Buffer UART_ClrRxBuffer(hPort, hOwner); // 清除接收Buffer
wSent = UART_PutBytes(hPort, (kal_uint8 *)pbyBuf,
(kal_uint16)wLenBuf, hOwner);
#endif
if (wSent == wLenBuf)
{
bRet = TRUE;
}
return bRet ;
}
static void exit_uart()
{
#ifdef __MMI_HELLOWORLD_ENABLED__
if(gbUartInitialized)
{
// 恢复成原有的端口占用者
UART_SetOwner(HELLO_WORLD_UART_PORT, (kal_uint8) gnOrigUartOwner);
// 允许休眠
L1SM_SleepEnable(ghSleepMode);
gbUartInitialized = KAL_FALSE;
}
#endif
}
static void mmi_HelloWorld_uart_readyToRead_ind_handler(void *msg) {
#ifdef __MMI_HELLOWORLD_ENABLED__
uart_ready_to_read_ind_struct* uart_rtr_ind =
(uart_ready_to_read_ind_struct*)msg;
// 检查一下端口以及所有者信息,不匹配的数据略过
// 注意,作为例子程序,我们只是查看和处理我们关心的数据
// 其他与此同时需要监听和处理串口数据的程序,须由相关的代码完成代理的工作
if( KAL_FALSE == gbUartEchoStarted ||
HELLO_WORLD_UART_PORT != uart_rtr_ind->port || MOD_HELLO_WORLD !=
UART_GetOwnerID(uart_rtr_ind->port) )
{
// 如果底层能做成钩子链,这里就可以调用钩子链的下一个钩子了
return;
}
gwLenUartBuffer = read_from_uart(gabyUartBuffer,
sizeof(gabyUartBuffer), HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
// 呼叫数据处理部分
uart_echo_process();
#endif
}
static void start_uart_echo(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
S8 strHello[] = "Hello World Uart Echo Example Started!\r\n";
if(gbUartEchoStarted)
{
return;
}
init_uart();
write_to_uart((kal_uint8*)strHello,
(kal_uint16)strlen(strHello), HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
gbUartEchoStarted = KAL_TRUE;
SetKeyHandler(stop_uart_echo, KEY_LSK, KEY_EVENT_UP); #endif
}
static void uart_echo_process(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
U8 i;
// 稍稍处理一下,这样就能看出是否确实是我们的程序在处理数据 for(i = 0; i < gwLenUartBuffer; i++)
{
if(gabyUartBuffer[i] >= 'a' && gabyUartBuffer[i] <= 'z')
{
gabyUartBuffer[i] -= 0x20;
}
}
// 回显
write_to_uart(gabyUartBuffer, gwLenUartBuffer,
HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
#endif
}
static void stop_uart_echo(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
S8 strBye[] = "Hello World Uart Echo Example Stop!\r\n";
if(gbUartEchoStarted)
{
write_to_uart((kal_uint8*)strBye,
(kal_uint16)strlen(strBye), HELLO_WORLD_UART_PORT, MOD_HELLO_WORLD);
gbUartEchoStarted = KAL_FALSE;
SetKeyHandler(start_uart_echo, KEY_LSK, KEY_EVENT_UP); }
exit_uart();
#endif
}
gdi_handle hAnimation;
void stop_play_anim(void)
{
gdi_anim_stop(hAnimation);
}
/* 模块入口 */
void mmi_HelloWorld_entry(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
S32 x, y, w, h;
color colorText = {255, 255, 128, 100};
color colorFill = {207, 252, 109, 100};
color colorShadow = {166, 201, 81, 100};
stFontAttribute tFont = {0};
U8 dotted_line_bitvalues[] = {1, 0, 1, 0, 1, 0, 1};
UI_filled_area tFiller = {0};
static color g_colors[3] = {{255, 0, 0}, {0, 255, 0}, {0, 0, 255}}; static U8 perc[2] = {50, 50};
gradient_color gc = {g_colors, perc, 3};
tFont.size = LARGE_FONT;
tFont.italic = 1;
/* 强制退出当前屏幕,之后进入到我们的模块了 */
/* 上电缺省是idle屏幕,现进入MAIN_MENU_SCREENID屏 */
/* 注意看第二个参数,这个是当我们模块被强制退出时执行的一些操作 */
EntryNewScreen(SCR_HELLOWORLD, mmi_HelloWorld_exit, NULL, NULL);
gui_lock_double_buffer();
/* 关掉屏幕顶部的状态条,我们要用整个屏幕 */
entry_full_screen();
/* 擦除当前背景 */
clear_screen();
tFiller.flags = UI_FILLED_AREA_TYPE_GRADIENT_COLOR | UI_FILLED_AREA_VERTICAL_FILL | UI_FILLED_AREA_DOUBLE_BORDER; tFiller.border_color = UI_COLOR_GREEN;
tFiller.gc = &gc;
gui_draw_filled_area(0, 0, UI_device_width - 1, UI_device_height - 1, &tFiller);
/* 设置字体颜色 */
gui_set_text_color(colorText/*UI_COLOR_RED*/);
gui_set_font(&tFont);
gui_set_text_border_color(UI_COLOR_GREEN);
gui_measure_string((UI_string_type)GetString(STR_HELLOWORLD_HELLO), &w, &h);
x = (UI_device_width - w) >> 1;
y = UI_device_height - ((UI_device_height - h) >> 2);
gui_draw_rectangle(x - 7, y - 7, x + w + 7, y + h + 7, UI_COLOR_RED); gui_fill_rectangle(x - 6, y - 6, x + w + 6, y + h + 6, colorFill); gui_line(x - 4, y + h + 4, x + w + 4, y + h + 4, colorShadow); gui_line(x - 5, y + h + 5, x + w + 5, y + h + 5, colorShadow); gui_line(x - 6, y + h + 6, x + w + 6, y + h + 6, colorShadow); gui_line(x + w + 4, y - 4, x + w + 4, y + h + 4, colorShadow); gui_line(x + w + 5, y - 5, x + w + 5, y + h + 5, colorShadow); gui_line(x + w + 6, y - 6, x + w + 6, y + h + 6, colorShadow); /* 移动文本输出光标 */
gui_move_text_cursor(x, y);
/* 输出文本到显示缓冲, 注意是Unicode编码 */
//
gui_print_text((UI_string_type)GetString(STR_HELLOWORLD_HELLO));
gui_print_bordered_text((UI_string_type)GetString(STR_HELLOWORLD_HELLO));
gdi_draw_line_style(x, y + h + 2, x + w + 2, y + h + 2, gdi_act_color_from_rgb(100, 255, 0, 0),
sizeof(dotted_line_bitvalues),
dotted_line_bitvalues);
// 显示图片
gdi_image_get_dimension_id(MAIN_MENU_MATRIX_ORGANIZER_ICON, &w, &h);
x = (UI_device_width - w) >> 1;
y = (UI_device_height - h) >> 1;
gdi_image_draw_id(x, 10, MAIN_MENU_MATRIX_ORGANIZER_ICON);
// 显示动画
gdi_image_get_dimension_id(MAIN_MENU_MATRIX_ORGANIZER_ANIMATION, &w, &h);
x = (UI_device_width - w) >> 1;
y = (UI_device_height - h) >> 1;
gdi_anim_draw_id(x, 10 + h,
MAIN_MENU_MATRIX_ORGANIZER_ANIMATION, &hAnimation);
gui_unlock_double_buffer();
/* 刷新屏幕显示,MMI用的是双缓冲绘图方式,而且需要显式刷新 */ gui_BLT_double_buffer(0, 0, UI_device_width - 1,
UI_device_height - 1);
/* 注册一个按键处理,右软键弹起时返回到之前被我们强制退出的模块 */
SetKeyHandler(GoBackHistory, KEY_RSK, KEY_EVENT_UP); // SetKeyHandler(stop_play_anim, KEY_LSK, KEY_EVENT_UP); SetKeyHandler(start_uart_echo, KEY_LSK, KEY_EVENT_UP); #endif
}
/* 模块出口
* 当我们的模块被其他模块强制退出时会执行这个函数,
* 这个函数的常见写法,包括:
* 1、模块已申请资源的释放(如果需要的话),这一步可选
* 2、手动把自己压栈到窗口(实际是整个屏)堆栈里面,
* 便于强制我们退出的模块执行完后重新把我们叫出来
* 不像Window的窗口管理是自动压栈的,Pluto MMI需要手动压栈 * 3、其他一些清理动作
*/
void mmi_HelloWorld_exit(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
history currHistory;
S16 nHistory = 0;
currHistory.scrnID = MAIN_MENU_SCREENID;
currHistory.entryFuncPtr = mmi_HelloWorld_entry;
pfnUnicodeStrcpy( (S8*)currHistory.inputBuffer,
(S8*)&nHistory);
AddHistory(currHistory);
stop_uart_echo();
#endif
}
void mmi_HelloWorld_hilite(void)
{
#ifdef __MMI_HELLOWORLD_ENABLED__
SetLeftSoftkeyFunction(mmi_HelloWorld_entry, KEY_EVENT_UP); #endif
}
void mmi_HelloWorld_init(void)
{
#ifdef
#endif
}
__MMI_HELLOWORLD_ENABLED__ SetHiliteHandler(MENU_ID_HELLOWORLD, mmi_HelloWorld_hilite);
Windows下如何查看被占用的端口号及如何释放被占用的端口号我不太喜欢迅雷这款软件的一点是迅雷首选的会去占用80端口下面一个小例…
如何查询端口号被哪个程序占用以下文章主要以80端口号为例如果想知道其他的端口号也可以使用该方法quot到底是谁占用了80端口该怎么…
第一步打开运行窗口输入cmd回车第二步在窗口中输入netstatnaoFINDSTR端口号其中FINDSTR与端口号之间必须要有空…
如何查看端口号被哪个程序占用了一1Cmd输入netstatano可以看到2例如我查80端口被什么占用了对应的进程id是3600再输…
彻底解决COM端口被占用在使用中问题的办法如何删除电脑中使用过的COM端口我的电脑经常使用蓝牙手机数据线之类的东西每次装一个新的设…
彻底解决COM端口被占用在使用中问题的办法如何删除电脑中使用过的COM端口我的电脑经常使用蓝牙手机数据线之类的东西每次装一个新的设…
彻底解决COM端口被占用在使用中问题的办法打开注册表HKEYLOCALMACHINESYSTEMCurrentControlSet…
USB转串口号查找方法1将转串口插到电脑USB口2查找串口号首先找到桌面图标右击如下选择设备管理器进入设备管理器找到端口项在下拉菜…
USB虚拟串口被占用软件可用串口有限COM1COM4如何释放和删除被占用的串口A可以通过删除注册表中的一个数值项来清除这些配置在运…
A可以通过删除注册表中的一个数值项来清除这些配置在运行对话框中输入regedit进入注册表然后进入NameHKEYLOCALMAC…