搜索
bottom↓
回复: 161

VC串口上位机编程学习笔记

  [复制链接]

出0入0汤圆

发表于 2011-4-25 22:34:54 | 显示全部楼层 |阅读模式
这几天需要研究USB,翻出了去年的一些资料,去年六一儿童节,在网上看到别人做的模拟飞行外设,一下心血来潮也想自己做点东西。那会儿我还在用着PRO\E,画着CAD,在我印象中计算机中的C语言还是跟DOS挂上钩的,觉得做个带界面的程序应该用点什么牛B的语言才行。

我花了两天的时间决定学哪种语言,最后找到如鹏网,很好的一个网站,发现纯C也能干出界面来,刚好下位机也用C,就学上了。结果一发不可收拾,就这么一路走过来了。今年初放弃了之前两年的积累,转行搞电子,个中辛苦只有自己知道。

坛子里比我菜的应该没几个,这两篇学习日记是自学第一个月做出上位机软件写的总结,希望能对和我一样的菜鸟有所帮助。上位机用纯C+API函数写的,参考了微软的一个例子。有一些串口调试工具连续处理大量数据的时候就会假死,估计是使用了单线程阻塞方式,而使用多线程异步方式操作串口,CPU占用率在这种情况下也很低。源码请参考附件中的微软代码,理清脉络的话很快就能做出自己的串口上位机来。

点击此处下载 ourdev_633596DAISVK.doc(文件大小:29K) (原文件名:使用API进行多线程异步串口通迅(Serial Communications in Win32读书笔记)1.doc)
点击此处下载 ourdev_633597AYU5YT.doc(文件大小:43K) (原文件名:使用API进行多线程异步串口通迅(Serial Communications in Win32读书笔记)2.doc)
点击此处下载 ourdev_633598XRQTHO.pdf(文件大小:207K) (原文件名:Serial Communications in WIN32.pdf)
点击此处下载 ourdev_633599PJCTGH.rar(文件大小:75K) (原文件名:MS串口源码.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2011-4-25 22:35:23 | 显示全部楼层
我发现目前网上搜到的中文VC串口编程资料,要么把相关的API函数罗列一遍,要么就是以管窥豹肢离破碎,更有甚者完全是误人子弟(包括一些流传相当广的所谓教程),靠这些乱七八糟的资料来学习,估计最后会只会练得走火入魔。
这些搜索给我唯一的帮助就是知道了MSDN里的绝世好文:
Serial Communications in Win32 http://msdn.microsoft.com/en-us/library/ms810467.aspx
这个SAMPLE把串口通讯的方方面面都涉及到了,里面还有例程源码,把它的CODE研究清楚,串口通讯的一切脉落自然了然于心。当然里面没有具体说打开、设置串口之类的基础操作,碰到不认识的就MSDN吧。另外讲解虽然是连续的,但SAMPLE CODE里的函数是分散的,需要灵活使用IDE的查看代码功能快速地在不同代码间跳跃。
下面就结合自己的理解,分析MTTY的SAMPLE CODE,就当读书笔记吧。希望对打算用API进行串口编程的朋友有所帮助,能尽快读懂MTTY的源码,建立起串口编程的思想框架,高手请飘过。阅读这篇文章需要你有阅读MSDN的英文能力,对串口概念有基本的认识。
开讲之前再啰嗦一把,按我找的资料来看,有几个普遍观点:1 WINNT串口不能用同步模式工作 2 简单地应用用同步模式、开单线程,实时性高地用异步单线程或多线程,因为异步+多线程比同步\异步+单线程要复杂得多。先说第二点,首先异步多线程确实要复杂得多,但也不至于有登天那么难,以我现在的水平就能基本搞明白,我从6月1日儿童节头脑发热决心研究编程,要知道那时候我还以为VC是一种语言,而且最开始的几天都花在纠结该学哪种语言上,半路出家,完全没有基础。其次出于学习考虑,找最难的整,学到的东西才多,至少学完串口能对多线程的使用有一定地直观了解。再次,从性能上说,异步多线程是最好的,而且使用非常灵活,能应付一切需求。所以初学串口,就咬紧牙搞异步多线程吧,CreatFile时用上OVERLAPPED,哈哈,那就一发不可收拾了。差点忘了说第一点,我从来不打算用同步模式,我也不知道行不行。
以下 xxx()表示一个函数,没有特别说明的话指SAMPLE CODE里的自定义函数。
第一:串口工作环境地建立
点击FILE里的CONNECT后,调用 INIT.C里的SetupCommPort()进行串口初始化:
1打开串口
用API函数CreateFile
2设置串口
调用UpdateConnection(),先建立一个dcb结构体(记得一定要初始化后再使用),然后用API函数GetCommState把现在的串口配置存入新建的dcb中,因为一般对串口参数的设置就是波特率之类,其他用默认即可,获取现在串口配置保存到我们建立的 dcb中,再根据需要进行修改会方便得多。根据需要对dcb内的成员赋值后,再用API函数SetCommState使设置好的 dcb生效,下一步就是用API函数SetCommTimeouts进行超时设置。
最后用用API函数SetupComm设置输入输出缓存。
至此,串口已经准备好,可以供我们使用了。
无论什么时候需要开始使用串口,按上面的步骤进行初始化操作都是必须而且有效的。
这里有另外两个API函数顺便说一下,1CommConfigDialog,2PurgeComm。
第一个是调用WINDOWS自带的串口设置对话框设置串口参数,这需要新建立一个COMMCONFIG 结构体来接收设置,COMMCONFIG里也有一个dcb结构,通话框里的设置自然就是保存到这里边来了,这个结构体在使用前记得要初始化。在调用CommConfigDialog前把现在的dcb 结构存到COMMCONFIG里是个好办法,不然对话框里的参数都是系统默认的,还得一个一个改。另外COMMCONFIG 在使用前要对成员wVersion和dwSize 赋值,否则执行会有异常,具体设置在MSDN里有详细说明。有人说其中的dwSize 不能填 sizeof COMMCONFIG,但MSDN里用的就是SIZEOF,我也用得很好,没有任何问题。
第二个函数在MSDN的说明是:Discards all characters from the output or input buffer of a specified communications resource. It can also terminate pending read or write operations on the resource.简单说就是立即中断串口的一切操作,当用CommConfigDialog设置好串口参数后,当然是希望串口按新的状态工作,所以应该接着调用PurgeComm。如果你想等所有的读写(包括未决的)操作都完成再生效,就需要使用事件“event”,在后面会说到它。
最后用StartThreads(void)建立读、写线程,MTTY里的监视和读是同一个线程。
至此这里串口的工作环境建立完成。
第二 让串口按我们的要求进行读写
串口工作环境地建立比较程式化,一步一步做完即可。那怎么按我们的要求让串口工作起来呢?下面说说怎么具体地实现利用多线程进行异步串口操作。我也只是有了初步概念,以下叙述若有错误,日后再更正。
转载请注明出处!

出0入0汤圆

 楼主| 发表于 2011-4-25 22:36:12 | 显示全部楼层
第二 让串口按我们的要求进行读写
串口工作环境地建立比较程式化,一步一步做完即可。那怎么按我们的要求让串口工作起来呢?下面说说怎么具体地实现利用多线程进行异步串口操作。我也只是有了初步概念,以下叙述若有错误,日后再更正。
先回忆一下上一节的内容,如何建立串口的工作环境:
1.打开串口,用CreateFile
2.DCB xxx ,xxx就是我们要用的串口配置结构体。可以选择用GetCommState获取当前串口配置,存入xxx。
3.按需求填写串口配置块xxx。这时可以用用CommConfigDialog。
4.SetCommState让串口配置块xxx生效
5.设置超时,用SetCommTimeouts
6.设置缓存,用SetupComm
7.创建读、写、监视线程
还是以写串口为例子,我的程序里需要定时更新仪表面板数据,那段程序执行时间最多能达到150ms,它是在主进程里执行的,更新面板数据后还要把数据写到串口,又是一段不短的时间,这样接口程序运行起来让人感觉老是慢半拍,更严重的是如果这个时候下位机发了数据上来,是完全不会得到响应的。所以非常有必要把读、写、监视串口用单独的线程来执行。
我的接口程序最开始写串口时对CPU的点用是近100%,后来把写单独做一个线程,CPU占用率降到25%,再用简单的处理办法:在更新面板数据时让写线程挂起,更新完成后再唤醒写线程,CPU占用率降到可以乎略不计。
平时常用的串口调试助手,同时打开两个,其中一个向另一个循环发字符,CPU(单核闪龙3400+)占用率立即会飙到100%,但做同样的事情,MS的MTTY工作得就非常好,CPU占用率在5%以内,足见多线程的威力。
创建了线程,当然就有对应线程的函数,MTTY里对应写线程的是
DWORD WINAPI WriterProc(LPVOID lpV),LPVOID lpV是传递给线程函数的参数,在MTTY里这个值是NULL。
写串口是主动的,我们需要在需要写串口的时候让写串口线程函数里的程序工作起来,平时碰到类似的任务一般是用设flag实现,但是我们写串口的时候需要知道上一次的写操作是否已经结束,这又需要一个flag,其他还有很多需要设flag的地方,flag这么多,怎么安排得过来。还好,WINDOWS有办法解决这个问题,那就是用event (事件)。
跟事件相关的API函数有
CreatEvent, 创建一个事件,需要用到事件时就创建它
SetEvent, 置事件为有信号的
ResetEvent, 重置事件为无信号
WaitForSingleObjects, 等待一个事件
WaitForMultipleObjects,等待多个事件
来打个比方说说这些函数的作用:
一个个的事件就像是一个个的信号灯,我们想知道谁的状态,那就用CreatEvent做几盏灯给他戴到头上,一个状态对应一盏灯。状态发生了就用SetEvent让灯亮(让事情有信号)代表对应的状态发生了,状态结束了就用ResetEvent(重置事件没无信号)让灯灭掉代表嘛事都没有了。然后谁想偷_窥别人了,就用WaitForMultipleObjects或者WaitForSingleObjects这两个马仔来监视,当然得先告诉马仔你想监视谁的哪个状态,马仔就会不间断地把人家的头顶都瞅一遍,要是你想要的状态代表的灯亮了,它立马会告诉你,碰到其他情况它也会给你相应的信息,你再根据不同的信息做不同的处理。
还有一种情况,就是你想让别人控制你,那你就自己建信号灯然后自己盯着头顶,别人调用SetEvent和ResetEvent来控制你的灯,你自己再根据灯的亮灭做相应的操作。MTTY里的写线程函数就是这么干的。
下面开始分析MTTY里神奇的SENDREPEATEDLY:
从这开始case ID_TRANSFER_SENDREPEATEDLY:,这个case里最后的操作是调用TransferRepeatCreate,我们来看看这个函数干了什么,看这个函数的代码,它干了不少事情,怎么没有在里边没看到操作串口?前边我们已经说了,为写串口单独建立了一个线程,所以操作操口的勾当绝对是在线程函数里干的。
我们只关心重点,既然是repeatedly,定时的话,那肯定是用定时器了,果然有
mmTimer = timeSetEvent((UINT) dwFrequency, 10, TransferRepeatDo, dwRead, TIME_PERIODIC);
TransferRepeatDo就是定时器的回调函数,我们再看看它干了什么,只是调用了WriterAddNewNodeTimeout,看意思是新增加一个节点,这个写串口还跟节点扯什么关系?再看这个函数干了什么:Adds a new write request packet, timesout if can't allocate packet.里边的第一句就是 PWRITEREQUEST pWrite;
这个PWRITEREQUESTtypedef struct WRITEREQUEST
{
DWORD      dwWriteType;        // char, file start, file abort, file packet
DWORD      dwSize;             // size of buffer
char       ch;                 // ch to send
char *     lpBuf;              // address of buffer to send
HANDLE     hHeap;              // heap containing buffer
HWND       hWndProgress;       // status bar window handle
struct WRITEREQUEST *pNext;    // next node in the list
struct WRITEREQUEST *pPrev;    // prev node in the list
} WRITEREQUEST, *PWRITEREQUEST;
明白了前面为啥是addnewnode了,这里用到了链表lined list ,因为要写的数据可能很多,串口只能一个一个写,要写的数据先放到链表里,然后串口再依次地写。把建立要写的数据和写数据地操作分开来,那两者就互不影响了。
建完新的数据节点,下一步当然就是把节点放到链表里,倒数第二句AddToLinkedList(pWrite);
这个函数里就是典型的链表增加节点地操作,重点在后面SetEvent(ghWriterEvent),增加完节点,让ghWriterEvent这个信号灯亮起来,直觉告诉我们,这就是亮给写线程看的,看一下都有谁使用它,真相揭晓,传说中的写线程函数终于闪亮登场:
DWORD WINAPI WriterProc(LPVOID lpV)
这里边的细枝末节比较多,照例只关心重点,里面建立了两个事件
ghWriterEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (ghWriterEvent == NULL)
        ErrorInComm("CreateEvent(writ request event)");
    ghTransferCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (ghTransferCompleteEvent == NULL)
        ErrorInComm("CreateEvent(transfer complete event)");
ghWriterEvent 就是给AddToLinkedList(pWrite);用的,它更新完链表就通知写线程去写串口,那写线程是怎么等这个消息的呢?就是在这里:
hArray[0] = ghWriterEvent;
hArray[1] = ghThreadExitEvent;
while ( !fDone )
{
        dwRes = WaitForMultipleObjects(2, hArray, FALSE, WRITE_CHECK_TIMEOUT);
        switch(dwRes)
        {
            case WAIT_TIMEOUT:
                    break;
            case WAIT_FAILED:
                    ErrorReporter("WaitForMultipleObjects( writer proc )");
                    break;
            //
            // write request event
            //
            case WAIT_OBJECT_0:
                    HandleWriteRequests();
                    break;
            //
            // thread exit event
            //
            case WAIT_OBJECT_0 + 1:
                    fDone = TRUE;
                    break;
        }
    }
    CloseHandle(ghTransferCompleteEvent);
    CloseHandle(ghWriterEvent);
    //
    // Destroy WRITE_REQUEST heap
    //
    HeapDestroy(ghWriterHeap);
    return 1;
}
ghWriterEvent是事件组hArray的第一个,那如果这个事件有信号后, WaitForMultipleObjects返回   WAIT_OBJECT_0:
        case WAIT_OBJECT_0:
                    HandleWriteRequests();
                    break;
HandleWriteRequests处理写串口请求,绕了这么多弯,终于要写串口了,激动,冲过去一看,靠,就是一堆case,原来这里是要根据不同的数据包选择不同的写串口函数,这就是所谓的全能型软件了。我们写的是file,那就是这个case
case WRITE_FILE:          WriterFile(pWrite);
                                      //
                                      // free data block
                                      //
                                      EnterCriticalSection(&gcsDataHeap);
                                      fRes = HeapFree(pWrite->hHeap, 0, pWrite->lpBuf);
                                      LeaveCriticalSection(&gcsDataHeap);
                                      if (!fRes)
                                          ErrorReporter("HeapFree(file transfer buffer)");
                                      break;
WriteFile里是WriterGeneric,看到了吧,这个WriterGeneric就是典型的写串口函数了,跟Serial Communications in WIN32里一模一样,这个在里边有详细的说明,这里就不讲了。
再来考虑另一个问题,线程函数内的代码一旦执行完成,线程函数就返回了,然后线程就结束了,那我们肯定是希望线程在我们要求它结束时他才结束,其他时候他就老老实实地听命令定串口,那这是怎么实现的呢?就是在这里while ( !fDone )很简单吧,就是一个while,while里面就是马仔
dwRes = WaitForMultipleObjects(2, hArray, FALSE, WRITE_CHECK_TIMEOUT);
        switch(dwRes)
        {
            case WAIT_TIMEOUT:
                    break;
            case WAIT_FAILED:
                    ErrorReporter("WaitForMultipleObjects( writer proc )");
                    break;
            //
            // write request event
            //
            case WAIT_OBJECT_0:
                    HandleWriteRequests();
                    break;
            //
            // thread exit event
            //
            case WAIT_OBJECT_0 + 1:
                    fDone = TRUE;
                    break;
        }
    }
我们再看看这个fDone是谁控制的,最后一个case
case WAIT_OBJECT_0 + 1:
                    fDone = TRUE;
                    break;
当fDone为真,那while就退出了,然后线程函数内的代码执行完,线程也就结束了。那WAIT_OBJECT_0 + 1:又是表示哪个事件有信号呢?看前面:hArray[1] = ghThreadExitEvent;, ghThreadExitEvent,这是一个全局变量,字面意思就是进程退出事件,我们先来想想,什么时候才需要退出写线程,是不是应该在关闭串口的时候,看看ghThreadExitEvent被谁引用了
就是这个DWORD WaitForThreads(DWORD dwTimeout),里边有一句SetEvent(ghThreadExitEvent);这句代码一执行ghThreadExitEvent就置为有信号。
我们可以看到,可以在函数内用局部的flag ,但跟别的线程通信一定要用event
DWORD WaitForThreads是在BOOL BreakDownCommPort()调用的,跟设想的一样,在关闭串口时结束写线程。再看看是谁调用了它,case ID_FILE_DISCONNECT:,点击菜单内的DISCONNECT关闭串口。
SENDREPEATEDLY的代码描绘了多线程异步串口的写操作,虽然层层包装但功能清淅,读懂了这部分,其他功能再研究起来就很简单了,读串口也就是多了SetCommMask之类的东西而已。
转载请注明出处!

出0入0汤圆

发表于 2011-4-25 22:40:09 | 显示全部楼层
要是MSComm的就好了,正在学习中......

出0入0汤圆

 楼主| 发表于 2011-4-25 22:50:13 | 显示全部楼层
MSComm是一个控件吧,初学的话自己实现能学到很多东西

我现在也在学MFC,用代码写界面太累了

出0入0汤圆

 楼主| 发表于 2011-4-25 23:51:02 | 显示全部楼层
再传一个学API必看的教程:

点击此处下载 ourdev_633640XIIDP6.pdf(文件大小:538K) (原文件名:forgers-win32-tutorial.pdf)
点击此处下载 ourdev_633641ZZM86D.zip(文件大小:414K) (原文件名:source.zip)

出0入0汤圆

发表于 2011-4-26 00:43:18 | 显示全部楼层
佩服楼主深钻的精神,而且还够谦虚,学习!

出0入0汤圆

发表于 2011-4-26 07:17:54 | 显示全部楼层
学习! 学习!

出0入0汤圆

发表于 2011-4-26 08:26:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-26 09:27:29 | 显示全部楼层
学习!

出0入0汤圆

发表于 2011-4-26 09:44:02 | 显示全部楼层
很好的资料

出0入0汤圆

发表于 2011-4-26 12:00:56 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-5-6 23:20:16 | 显示全部楼层
非常给力的教程.我也正准备在学.共勉之.

出0入46汤圆

发表于 2011-5-7 00:21:33 | 显示全部楼层
写的很好!

出0入0汤圆

发表于 2011-5-7 00:24:45 | 显示全部楼层
再仔细研究下

出0入0汤圆

发表于 2011-5-8 00:22:20 | 显示全部楼层
楼主好辛苦啊!

出0入0汤圆

发表于 2011-5-9 21:55:45 | 显示全部楼层
Great

出0入0汤圆

发表于 2011-5-9 22:22:44 | 显示全部楼层
good

出0入0汤圆

发表于 2011-6-10 16:40:03 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-6-22 15:05:03 | 显示全部楼层
楼主的钻研精神可嘉!
值得我们学习!
前段时间写了个串口通信程序去控制板子的操作,现在用是能用,但总是觉得有许多隐藏的问题.
看了楼主的文章后,我会重新审视之!

出0入0汤圆

发表于 2011-6-23 09:54:12 | 显示全部楼层
值得学习

出0入0汤圆

发表于 2011-6-23 10:37:10 | 显示全部楼层
回复【楼主位】skystalker
-----------------------------------------------------------------------
mark

出0入0汤圆

发表于 2011-6-23 10:48:02 | 显示全部楼层
正在学习中,谢谢!

出0入0汤圆

发表于 2011-6-23 11:08:29 | 显示全部楼层
标记学习!

出0入0汤圆

发表于 2011-6-23 11:22:05 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-6-23 11:59:54 | 显示全部楼层
马克

出0入0汤圆

发表于 2011-6-24 23:54:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-2 12:06:49 | 显示全部楼层
学习。。记号

出0入0汤圆

发表于 2011-7-2 16:49:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-2 23:53:27 | 显示全部楼层
我把串口的类封装成控件了,好让UI直接调用
楼主的钻研精神值得学习,我好久没静下心来看书了

出0入0汤圆

发表于 2011-7-3 01:01:33 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-7-3 09:59:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-3 11:52:40 | 显示全部楼层
标记个号

出0入0汤圆

发表于 2011-7-4 17:10:44 | 显示全部楼层
也想做个类似的串口程序,楼主给力。

出0入0汤圆

发表于 2011-7-6 14:24:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-8 19:09:36 | 显示全部楼层
回复【1楼】skystalker
-----------------------------------------------------------------------

“那会儿我还在用着PRO\E,画着CAD,在我印象中计算机中的C语言还是跟DOS挂上钩的,觉得做个带界面的程序应该用点什么牛B的语言才行。 ”
O(∩_∩)O哈哈~

出0入0汤圆

发表于 2011-7-8 22:39:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-8 23:17:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-11 11:02:24 | 显示全部楼层
楼主usb研究的怎么样了啊 共享下啊 网上这方面资料不多啊

出0入0汤圆

发表于 2011-7-14 11:20:27 | 显示全部楼层
共同学习

出0入0汤圆

发表于 2011-7-14 11:39:11 | 显示全部楼层
大家可以参考实现下
头像被屏蔽

出0入0汤圆

发表于 2011-7-14 12:21:13 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2011-7-14 21:36:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-14 22:40:28 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-22 14:33:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-22 15:05:53 | 显示全部楼层
不错

出0入0汤圆

发表于 2011-7-26 14:34:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-26 15:51:09 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-8-21 13:43:04 | 显示全部楼层
佩服楼主,感谢楼主。用C编写多线程和界面,真的很难

出0入0汤圆

发表于 2011-9-1 17:52:17 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-9-1 19:13:24 | 显示全部楼层
你是大牛啊! LZ你太谦虚了

出0入0汤圆

发表于 2011-9-1 19:16:38 | 显示全部楼层
马克!!!!

出0入0汤圆

发表于 2011-9-3 15:48:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-7 14:24:25 | 显示全部楼层
我发现目前网上搜到的中文VC串口编程资料,要么把相关的API函数罗列一遍,要么就是以管窥豹肢离破碎,更有甚者完全是误人子弟(包括一些流传相当广的所谓教程),靠这些乱七八糟的资料来学习,估计最后会只会练得走火入魔。

出0入0汤圆

发表于 2011-9-22 14:50:06 | 显示全部楼层
支持

出0入0汤圆

发表于 2011-9-27 00:22:33 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-9-30 21:01:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-1 10:18:06 | 显示全部楼层
谢谢楼主分享。

出0入0汤圆

发表于 2011-10-1 18:33:07 | 显示全部楼层
回复【楼主位】skystalker
-----------------------------------------------------------------------

最近做个监控电机的系统   正需要编个上位机用来调试  学习学习  谢谢分享

出0入0汤圆

发表于 2011-10-11 11:23:03 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2011-10-19 13:13:37 | 显示全部楼层
MARK!!!

出0入0汤圆

发表于 2011-10-19 13:49:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-19 14:06:37 | 显示全部楼层
mark

出0入97汤圆

发表于 2011-10-19 14:10:05 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2011-10-21 16:44:09 | 显示全部楼层
得好好学习一下  赞一个……

出0入0汤圆

发表于 2011-10-21 22:56:10 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2011-10-26 17:12:10 | 显示全部楼层
果然是好文,正在学习中。

出0入0汤圆

发表于 2011-10-28 10:01:22 | 显示全部楼层
准备学习的,谢谢分享

出0入0汤圆

发表于 2011-10-29 18:13:35 | 显示全部楼层
搞结构的都这么快学会VC了,让我这个用c语言的,一直准备学上位机开发到现在还不知学何种语言的的情何以堪;

出0入0汤圆

发表于 2011-10-29 21:13:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-29 22:21:56 | 显示全部楼层
马克 过几天研究一下

出0入0汤圆

发表于 2011-11-6 20:44:28 | 显示全部楼层
串口能控制步进电机吗

出0入0汤圆

发表于 2011-11-12 16:43:31 | 显示全部楼层
估计是个好贴,MARK一下,以备后查。

出0入0汤圆

发表于 2011-11-13 19:45:28 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-11-18 11:20:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-19 09:18:58 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-11-25 12:23:23 | 显示全部楼层
谢谢楼主

出0入30汤圆

发表于 2011-11-25 14:27:29 | 显示全部楼层
佩服支持顶。LZ V5。向你学习。

出0入0汤圆

发表于 2011-11-25 16:50:23 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-11-28 22:55:54 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2011-11-29 09:29:19 | 显示全部楼层
mark.

出0入0汤圆

发表于 2011-12-5 11:08:15 | 显示全部楼层

出0入0汤圆

发表于 2011-12-5 20:25:49 | 显示全部楼层
回复【楼主位】skystalker
-----------------------------------------------------------------------
很好的资料

出0入0汤圆

发表于 2011-12-5 22:12:03 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-12-5 23:24:13 | 显示全部楼层
楼主做得不错

出0入0汤圆

发表于 2011-12-6 02:48:16 | 显示全部楼层
makr

出0入0汤圆

发表于 2011-12-6 08:16:09 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-12-6 08:25:55 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-12-6 08:33:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-7 15:19:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-29 17:03:04 | 显示全部楼层
要得学学

出0入0汤圆

发表于 2012-1-3 16:24:40 | 显示全部楼层
回复【楼主位】skystalker
-----------------------------------------------------------------------

楼主以前是学机械的么,我以前也是,不过现在也基本转行到电子了。

出0入0汤圆

发表于 2012-1-12 22:15:02 | 显示全部楼层
学习了

出0入0汤圆

发表于 2012-1-12 23:21:28 | 显示全部楼层
好贴!

出0入0汤圆

发表于 2012-1-13 11:13:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-13 11:41:39 | 显示全部楼层
回复【楼主位】skystalker
-----------------------------------------------------------------------

真是让我少走了很多弯路啊  必须顶

出0入0汤圆

发表于 2012-1-13 12:41:53 | 显示全部楼层
这两天都因为串口调试程序烦呢,正好自己学习一下,可以自己写了,谢谢楼主分享

出0入0汤圆

发表于 2012-1-29 21:13:19 | 显示全部楼层
刚开始学VC

出0入0汤圆

发表于 2012-2-15 14:01:49 | 显示全部楼层
学习

出0入0汤圆

发表于 2012-2-15 16:31:44 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 06:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表