|
本帖最后由 renmin 于 2013-1-21 11:26 编辑
看过论坛上面的串口通讯的例子,于是想自己弄一个出来,主要参考sishau 所写,
我也是第一次接触这个东西,下面是我写的源代码,也弄了好几天时间,排版有点乱,- import win.ui;
- import win.ui.menu;
- import win.ui.ctrl.afpicturebox;
- import win.ui.statusbar;
- /*DSG{{*/
- mainForm = ..win.form( bottom=474;parent=...;text="aardio Form";right=647 )
- mainForm.add(
- button2={ bottom=162;text="发送";left=152;top=123;z=8;right=208;cls="button" };
- edit2={ text="edit2";bottom=426;right=641;left=238;multiline=1;top=8;z=11;edge=1;cls="edit" };
- edit={ text="FE 03 04 01 FC";bottom=154;right=150;left=13;multiline=1;top=128;z=10;edge=1;cls="edit" };
- button4={ bottom=207;text="命令2";left=121;top=171;z=15;right=222;cls="button" };
- static={ bottom=54;right=66;left=18;text="串口号:";top=40;transparent=1;z=2;cls="static" };
- static2={ bottom=78;right=66;left=18;text="波特率:";top=64;transparent=1;z=3;cls="static" };
- button3={ bottom=207;text="命令1";left=9;top=171;z=9;right=110;cls="button" };
- groupbox2={ bottom=110;text="数据选项";left=141;top=15;z=12;right=236;edge=1;cls="groupbox" };
- radiobutton={ bottom=71;text="收发AISCII码";left=144;top=46;z=13;right=231;cls="radiobutton" };
- radiobutton1={ checked=1;bottom=107;right=226;left=144;top=80;z=14;text="收发Hex码";cls="radiobutton" };
- afpicturebox2={ bottom=109;right=136;left=95;dt=1;top=77;font=LOGFONT( name='宋体' );transparent=1;z=5;cls="afpicturebox" };
- button={ bottom=106;text="开打串口";left=21;top=82;z=7;right=92;cls="button" };
- combobox2={ bottom=76;right=135;left=64;
- items={ "1200";"2400";"4800";"9600";"38400";"57600";"115200" };text="combobox2";z=6;top=56;mode="dropdownlist";edge=1;cls="combobox" };
- groupbox={ bottom=110;text="串口选项";left=10;top=15;z=1;right=138;edge=1;cls="groupbox" };
- combobox={ bottom=52;right=136;left=64;
- items={ };text="combobox";z=4;top=32;mode="dropdownlist";edge=1;cls="combobox" }
- )
- /*}}*/
- //---串口波特率全局定义---
- var Serial_port = 1;
- var Serial_baud = 0x0c;//波特率9600
- var cdata = raw.buffer(256); //分配串口发送数据内存
- //----下面是状态栏函数------------
- status=win.ui.statusbar(mainForm)
- status.addItem("端口状态:", (mainForm.right - mainForm.left)/2/*宽度*/)
- status.addItem("1", (mainForm.right - mainForm.left)/2/*宽度*/)
- status.setText("操作状态:",2 /*第几个分块*/)
- //---创建菜单---
- var menu = win.ui.menu(mainForm);//创建主菜单
- menu.addTable(
- {
- {
- "文件";
- {
- //----------------
- {
- "子菜单";
- function(id)
- {
- mainForm.msgbox("文件->子菜单")
- }
- };
- {{"---分割线---"}};//分隔线
- {
- "子菜单2";
- function(id)
- {
- mainForm.msgbox("文件->子菜单2")
- }
- }
- {{"---分割线---"}};//分隔线
- {"退出"; function(id)
- {
- mainForm.close();
- }
- };//分隔线
- } //----------------
- };
- {
- "编辑";
- {
- //----------------
- {
- "子菜单";
- function(id)
- {
- mainForm.msgbox("编辑->子菜单")
- }
- };
- {
- "子菜单2";
- function(id)
- {
- mainForm.msgbox("编辑->子菜单2")
- }
- }
- } //----------------
- };
- {
- "编辑2";
- {
- //----------------
- {
- "子菜单";
- function(id)
- {
- mainForm.msgbox("编辑2->子菜单")
- }
- };
- {
- "子菜单2";
- function(id)
- {
- mainForm.msgbox("编辑2->子菜单2")
- }
- }
- } //----------------
- };
- } )
- //---启动前初始化组合框---
- for(i=1; 10; 1){
- mainForm.combobox.add("COM"+tostring(i))
- // mainForm.combobox2.add(tostring(i))
- }
- mainForm.combobox.selIndex = 1;
- /*
- mainForm.combobox2.insert("9600",-1);
- mainForm.combobox2.insert("38400",-1);
- mainForm.combobox2.insert("115200",-1);
- mainForm.combobox2.insert("9600",-1);
- */
- mainForm.combobox2.selIndex=1;
- //---创建串口显示图标---
- mainForm.afpicturebox2.image = string.load("\res\2.ico");
- //---加载dll,声明函数---
- Pcom = raw.loadDll("\res\Pcomm.dll");
- //打开串口,正确返回0;C代码int WINAPI sio_open(int port);
- sio_open = Pcom.api("sio_open","int(int Serial_port)");
- //关闭串口,正确返回0;C代码int WINAPI sio_close(int port);
- sio_close = Pcom.api("sio_close","int(int port)" );
- //设置串口参数,正确返回0;C代码int WINAPI sio_ioctl(int port, int baud, int mode);
- sio_ioctl = Pcom.api("sio_ioctl","int(int port, int baud, int mode)" );
- //读取缓冲区数据,返回数据长度,为0表示没有读到数据;C代码int WINAPI sio_read(int port, char *buf, int len);
- sio_read = Pcom.api("sio_read","int(int port, pointer buf, int len)");
- //写入缓冲区数据,返回数据长度;C代码int WINAPI sio_write(int port, char *buf, int len);
- sio_write = Pcom.api("sio_write","int(int port, pointer buf, int len)");
- //设置中断函数,用来在接收大量数据的时候产生中断;C代码int WINAPI sio_cnt_irq(int port,VOID (CALLBACK *func)(int port), int count);
- sio_cnt_irq = Pcom.api("sio_cnt_irq","int(int port, func(int port), int count)");
- //------下面是初始化串口部分------
- //var Serial_port = 1; 这个在后面获取端口号下拉组合框中的选项值
- //var Serial_baud = 0x0c;//波特率9600 这个在后面获取波特率下拉组合框中的选项值
- /*baud = (bits/sec)
- 0 = 50 6 = 600 12 = 9600 18 = 460800
- 1 = 75 7 = 1200 13 = 19200 19 = 921600
- 2 = 110 8 = 1800 14 = 38400
- 3 = 134.5 9 = 2400 15 = 57600
- 4 = 150 10 = 4800 16 = 115200
- 5 = 300 11 = 7200 17 = 230400
- */
- var wordlength = 0x03;//数据位bit_8
- /*bit_cnt (bit 0, 1) = 0x00 = bit_5
- 0x01 = bit_6
- 0x02 = bit_7
- 0x03 = bit_8
- */
- var parity = 0x00; //奇偶校验EVEN
- /*parity (bit 3,4 5) = 0x00 = none
- 0x08 = odd
- 0x18 = even
- 0x28 = mark
- 0x38 = space
- */
- var stopbits = 0x00;//停止位stop_1
- /*stop_bit (bit 2) = 0x00 = stop_1
- 0x04 = stop_2
- */
- //-----------上面是串口初始化部分-----------------------
- //*******下面是公共函数***********//
- //---串口打开函数---
- comopen = function(Serial_port,Serial_baud,parity,stopbits,wordlength){
- var ret = 0;
- var i = 0;
- ret = sio_open(Serial_port);//打开串口
- if(ret != 0)
- {
- win.msgboxTimeout("错误码:"+ret,"串口打开错误");
- mainForm.button.text = "打开串口";
- mainForm.afpicturebox2.image = string.load("\res\2.ico");
- return 0;
- }
- ret = sio_ioctl (Serial_port, Serial_baud, parity | stopbits | wordlength );//设置串口参数:波特率、奇偶校验、停止位、数据位
- if(ret != 0)
- {
- win.msgboxTimeout("错误码:"+ret,"串口设置错误");
- mainForm.button.text = "打开串口";
- mainForm.afpicturebox2.image = string.load("\res\2.ico");
- return 0;
- }
- }
- //---串口发送数据函数---
- comwrite = function(Serial_port,str,buf){
- str = string.replace(str,"\s","");//去除空格及换行符
- for(i=1; #str;2){
- buf[(i+1)/2] = eval("0X"+string.slice(str,i,i+1));
- }
- var len = sio_write(Serial_port,buf,#str/2)
- return len;
- }
- //---串口接收数据函数---
- comread = function(Serial_port,buf){
- var len = sio_read(Serial_port,buf,#buf);
- var str = ""
- for(i=1; len; 1)
- {
- if(mainForm.radiobutton.checked != true){
- str = str++" "++string.right(string.format("%02X", buf[ i ]),2);//默认转换成有符号字节,因此取最右边两位
- }else {
- str = str ++ string.pack(buf[i]);//默认转换成AISCII《这个地方感觉中断回调函数有问题》
- }
- }
- return str,len;
- }
- //---串口号(需要写配置项)---
- mainForm.combobox.oncommand = function(id,event){
- //mainForm.msgbox( mainForm.combobox.text );
- if( event = 0x1/*_CBN_SELCHANGE*/ ){
- var selText = mainForm.combobox.selText;
-
- Serial_port = string.match(selText,"\d+");//给全局变量的串口端口赋值
- /*
- select(selText) {
- case "COM1" {
- win.msgboxTimeout("当前串口号:"+tostring(string.match(selText,"\d+")));
-
- }
- case "COM2" {
- win.msgboxTimeout("当前串口号:"+selText)
- }
- case "COM3" {
- win.msgboxTimeout("当前串口号:"+selText)
- }
- }
- */
- }
- }
- //---波特率(需要写配置项)---
- mainForm.combobox2.oncommand = function(id,event){
- //mainForm.msgbox( mainForm.combobox2.text );
- if( event = 0x1/*_CBN_SELCHANGE*/ ){
-
- var selText = mainForm.combobox2.selText;
- status.setText("操作状态:当前波特率"+selText + "重新打开串口生效", /*第几个分块*/)
-
- select(selText) {
- case "1200" {
- Serial_baud = 0x07;
- }
- case "2400" {
- Serial_baud = 0x09;
- }
- case "4800" {
- Serial_baud = 0x0a;
- }
- case "9600" {
- Serial_baud = 0x0c;
- }
- case "38400" {
- Serial_baud = 0x0e;
- }
- case "57600" {
- Serial_baud = 0x0f;
- }
- case "115200" {
- Serial_baud = 0x10;
- }
- }
- }
- }
-
- //---开关串口---
- mainForm.button.oncommand = function(id,event){
- if(mainForm.button.text != "关闭串口")
- {
- mainForm.button.text = "关闭串口";
- mainForm.afpicturebox2.image = string.load("\res\4.ico");
-
- comopen(Serial_port,Serial_baud,parity,stopbits,wordlength);//打开串口并设置串口参数;
- }
- else
- {
- mainForm.button.text = "打开串口";
- mainForm.afpicturebox2.image = string.load("\res\2.ico");
- sio_close(Serial_port); //关闭串口
- }
- }
- mainForm.button2.oncommand = function(id,event){
- //mainForm.msgbox( mainForm.button2.text );
- var str = mainForm.edit.text;
- len = comwrite(Serial_port,str,cdata); //发送
- status.setText("端口状态:已发送[ "+tostring(len)+" ]字节",1 /*第几个分块*/);
- }
- mainForm.button3.oncommand = function(id,event){
- //mainForm.msgbox( mainForm.button3.text );
-
- }
- //---下面使用定时器查询串口接收状态---
- //使用定时器查询有一个严重缺陷,如果发送的速度快,那么接收端显示出来的数据就不准确
- tmid = mainForm.setInterval(
- 100/*毫秒*/,
- function(hwnd,msg,id,tick){//定时执行代码
- str1, len1 = comread(Serial_port,cdata) //接收
- if(len1 == -1){ return ; }
- if(len1 != 0){
- status.setText("接收状态:已收到[ "+tostring(len1)+" ]字节;"+str1,2 /*第几个分块*/);//问题就是这个地方统计不准确
- mainForm.edit2.appendText(str1);
- }
- //mainForm.clearInterval(id)//移除此定时器
- //mainForm.changeInterval(id,2000)//重新设定时间间隔
- }
- );
- mainForm.show()
- win.loopMessage();
复制代码 现在能完成的事情,发送没有发送AISCII码,接收的时候发现有几个地方遇到了麻烦,
接收函数- //---串口接收数据函数---
- comread = function(Serial_port,buf){
- var len = sio_read(Serial_port,buf,#buf);
- var str = ""
- for(i=1; len; 1)
- {
- if(mainForm.radiobutton.checked != true){
- str = str++" "++string.right(string.format("%02X", buf[ i ]),2);//默认转换成有符号字节,因此取最右边两位
- }else {
- str = str ++ string.pack(buf[i]);//默认转换成AISCII《这个地方感觉中断回调函数有问题》
- }
- }
- return str,len;
- }
复制代码 统计接收的字节有问题,我想应该是我没有设置接收中断,接收的时候,比如发送端发送FE 03 04 01 02 03 00 FC,但是接收到的数据是对的,要分几次接收,不明白这一点,另外在接收AISCII码的时候也是,如果不是用str = str ++ string.pack(buf);而使用str = str + string.pack(buf);就收不完一条命令,希望高手指点一下。
另外是接收部分使用定时器去查询,感觉这样完全是处于被动,我的查询接收如下:- //---下面使用定时器查询串口接收状态---
- //使用定时器查询有一个严重缺陷,如果发送的速度快,那么接收端显示出来的数据就不准确
- tmid = mainForm.setInterval(
- 100/*毫秒*/,
- function(hwnd,msg,id,tick){//定时执行代码
- str1, len1 = comread(Serial_port,cdata) //接收
- if(len1 == -1){ return ; }
- if(len1 != 0){
- status.setText("接收状态:已收到[ "+tostring(len1)+" ]字节;"+str1,2 /*第几个分块*/);//问题就是这个地方统计不准确
- mainForm.edit2.appendText(str1);
- }
- //mainForm.clearInterval(id)//移除此定时器
- //mainForm.changeInterval(id,2000)//重新设定时间间隔
- }
- );
复制代码 上面这种接收方式存在严重缺陷,我想接到数据就马上处理,而不需要我去查询,但是也许是我的能力有限,还没有明白如何处理,不知道论坛上面的高手是怎么接收数据的,希望指点我一下,谢谢。 |
|