aardio 官方社区

 找回密码
 注册会员

QQ登录

只需一步,快速开始

搜索
查看: 11324|回复: 2

使用aardio写(Pocomm)串口通讯遇到问题<已解决>

[复制链接]

8

主题

110

回帖

904

积分

三级会员

积分
904
发表于 2013-1-21 10:49:47 | 显示全部楼层 |阅读模式
本帖最后由 renmin 于 2013-1-21 11:26 编辑

看过论坛上面的串口通讯的例子,于是想自己弄一个出来,主要参考sishau 所写
我也是第一次接触这个东西,下面是我写的源代码,也弄了好几天时间,排版有点乱,
  1. import win.ui;
  2. import win.ui.menu;
  3. import win.ui.ctrl.afpicturebox;
  4. import win.ui.statusbar;
  5. /*DSG{{*/
  6. mainForm = ..win.form( bottom=474;parent=...;text="aardio Form";right=647 )
  7. mainForm.add(
  8. button2={ bottom=162;text="发送";left=152;top=123;z=8;right=208;cls="button" };
  9. edit2={ text="edit2";bottom=426;right=641;left=238;multiline=1;top=8;z=11;edge=1;cls="edit" };
  10. edit={ text="FE 03 04 01 FC";bottom=154;right=150;left=13;multiline=1;top=128;z=10;edge=1;cls="edit" };
  11. button4={ bottom=207;text="命令2";left=121;top=171;z=15;right=222;cls="button" };
  12. static={ bottom=54;right=66;left=18;text="串口号:";top=40;transparent=1;z=2;cls="static" };
  13. static2={ bottom=78;right=66;left=18;text="波特率:";top=64;transparent=1;z=3;cls="static" };
  14. button3={ bottom=207;text="命令1";left=9;top=171;z=9;right=110;cls="button" };
  15. groupbox2={ bottom=110;text="数据选项";left=141;top=15;z=12;right=236;edge=1;cls="groupbox" };
  16. radiobutton={ bottom=71;text="收发AISCII码";left=144;top=46;z=13;right=231;cls="radiobutton" };
  17. radiobutton1={ checked=1;bottom=107;right=226;left=144;top=80;z=14;text="收发Hex码";cls="radiobutton" };
  18. afpicturebox2={ bottom=109;right=136;left=95;dt=1;top=77;font=LOGFONT( name='宋体' );transparent=1;z=5;cls="afpicturebox" };
  19. button={ bottom=106;text="开打串口";left=21;top=82;z=7;right=92;cls="button" };
  20. combobox2={ bottom=76;right=135;left=64;
  21. items={ "1200";"2400";"4800";"9600";"38400";"57600";"115200" };text="combobox2";z=6;top=56;mode="dropdownlist";edge=1;cls="combobox" };
  22. groupbox={ bottom=110;text="串口选项";left=10;top=15;z=1;right=138;edge=1;cls="groupbox" };
  23. combobox={ bottom=52;right=136;left=64;
  24. items={  };text="combobox";z=4;top=32;mode="dropdownlist";edge=1;cls="combobox" }
  25. )
  26. /*}}*/

  27. //---串口波特率全局定义---
  28. var Serial_port = 1;
  29. var Serial_baud = 0x0c;//波特率9600
  30. var cdata = raw.buffer(256);  //分配串口发送数据内存


  31. //----下面是状态栏函数------------
  32. status=win.ui.statusbar(mainForm)
  33. status.addItem("端口状态:", (mainForm.right - mainForm.left)/2/*宽度*/)
  34. status.addItem("1", (mainForm.right - mainForm.left)/2/*宽度*/)
  35. status.setText("操作状态:",2 /*第几个分块*/)

  36. //---创建菜单---
  37. var menu = win.ui.menu(mainForm);//创建主菜单
  38. menu.addTable(
  39. {
  40.     {
  41.         "文件";
  42.         {
  43.             //----------------
  44.             {
  45.                 "子菜单";
  46.                 function(id)
  47.                 {
  48.                     mainForm.msgbox("文件->子菜单")
  49.                 }
  50.             };
  51.             {{"---分割线---"}};//分隔线
  52.             {
  53.                 "子菜单2";
  54.                 function(id)
  55.                 {
  56.                     mainForm.msgbox("文件->子菜单2")
  57.                 }
  58.             }
  59.             {{"---分割线---"}};//分隔线
  60.             {"退出"; function(id)
  61.                 {
  62.                     mainForm.close();
  63.                 }
  64.             };//分隔线
  65.         } //----------------
  66.     };
  67.     {
  68.         "编辑";
  69.         {
  70.             //----------------
  71.             {
  72.                 "子菜单";
  73.                 function(id)
  74.                 {
  75.                     mainForm.msgbox("编辑->子菜单")
  76.                 }
  77.             };
  78.             {
  79.                 "子菜单2";
  80.                 function(id)
  81.                 {
  82.                     mainForm.msgbox("编辑->子菜单2")
  83.                 }
  84.             }
  85.         } //----------------
  86.     };
  87.     {
  88.         "编辑2";
  89.         {
  90.             //----------------
  91.             {
  92.                 "子菜单";
  93.                 function(id)
  94.                 {
  95.                     mainForm.msgbox("编辑2->子菜单")
  96.                 }
  97.             };
  98.             {
  99.                 "子菜单2";
  100.                 function(id)
  101.                 {
  102.                     mainForm.msgbox("编辑2->子菜单2")
  103.                 }
  104.             }
  105.         } //----------------
  106.     };
  107. } )
  108. //---启动前初始化组合框---
  109. for(i=1; 10; 1){
  110.     mainForm.combobox.add("COM"+tostring(i))
  111.     // mainForm.combobox2.add(tostring(i))
  112. }
  113. mainForm.combobox.selIndex = 1;
  114. /*
  115. mainForm.combobox2.insert("9600",-1);
  116. mainForm.combobox2.insert("38400",-1);
  117. mainForm.combobox2.insert("115200",-1);
  118. mainForm.combobox2.insert("9600",-1);
  119. */
  120. mainForm.combobox2.selIndex=1;
  121. //---创建串口显示图标---
  122. mainForm.afpicturebox2.image = string.load("\res\2.ico");
  123. //---加载dll,声明函数---
  124. Pcom = raw.loadDll("\res\Pcomm.dll");
  125. //打开串口,正确返回0;C代码int WINAPI sio_open(int port);
  126. sio_open = Pcom.api("sio_open","int(int Serial_port)");
  127. //关闭串口,正确返回0;C代码int WINAPI sio_close(int port);
  128. sio_close = Pcom.api("sio_close","int(int port)" );
  129. //设置串口参数,正确返回0;C代码int WINAPI sio_ioctl(int port, int baud, int mode);
  130. sio_ioctl = Pcom.api("sio_ioctl","int(int port, int baud, int mode)" );
  131. //读取缓冲区数据,返回数据长度,为0表示没有读到数据;C代码int WINAPI sio_read(int port, char *buf, int len);
  132. sio_read = Pcom.api("sio_read","int(int port, pointer buf, int len)");
  133. //写入缓冲区数据,返回数据长度;C代码int WINAPI sio_write(int port, char *buf, int len);
  134. sio_write = Pcom.api("sio_write","int(int port, pointer buf, int len)");
  135. //设置中断函数,用来在接收大量数据的时候产生中断;C代码int WINAPI sio_cnt_irq(int port,VOID (CALLBACK *func)(int port), int count);
  136. sio_cnt_irq = Pcom.api("sio_cnt_irq","int(int port, func(int port), int count)");

  137. //------下面是初始化串口部分------
  138. //var Serial_port = 1;                       这个在后面获取端口号下拉组合框中的选项值
  139. //var Serial_baud = 0x0c;//波特率9600        这个在后面获取波特率下拉组合框中的选项值
  140. /*baud = (bits/sec)
  141. 0 = 50          6 = 600         12 = 9600           18 = 460800
  142. 1 = 75          7 = 1200        13 = 19200          19 = 921600
  143. 2 = 110         8 = 1800        14 = 38400
  144. 3 = 134.5       9 = 2400        15 = 57600
  145. 4 = 150         10 = 4800       16 = 115200
  146. 5 = 300         11 = 7200       17 = 230400
  147. */
  148. var wordlength = 0x03;//数据位bit_8
  149. /*bit_cnt (bit 0, 1) =  0x00 = bit_5
  150.                         0x01 = bit_6
  151.                         0x02 = bit_7
  152.                         0x03 = bit_8
  153. */
  154. var parity = 0x00; //奇偶校验EVEN
  155. /*parity (bit 3,4 5) =  0x00 = none
  156.                         0x08 = odd
  157.                         0x18 = even
  158.                         0x28 = mark
  159.                         0x38 = space
  160. */
  161. var stopbits = 0x00;//停止位stop_1
  162. /*stop_bit (bit 2) =    0x00 = stop_1
  163.                         0x04 = stop_2
  164. */
  165. //-----------上面是串口初始化部分-----------------------
  166. //*******下面是公共函数***********//
  167. //---串口打开函数---
  168. comopen = function(Serial_port,Serial_baud,parity,stopbits,wordlength){
  169.     var ret = 0;
  170.     var i = 0;
  171.     ret = sio_open(Serial_port);//打开串口
  172.     if(ret != 0)
  173.     {
  174.         win.msgboxTimeout("错误码:"+ret,"串口打开错误");
  175.         mainForm.button.text = "打开串口";
  176.         mainForm.afpicturebox2.image = string.load("\res\2.ico");
  177.         return 0;
  178.     }
  179.     ret = sio_ioctl (Serial_port, Serial_baud, parity | stopbits | wordlength  );//设置串口参数:波特率、奇偶校验、停止位、数据位
  180.     if(ret != 0)
  181.     {
  182.         win.msgboxTimeout("错误码:"+ret,"串口设置错误");
  183.         mainForm.button.text = "打开串口";
  184.         mainForm.afpicturebox2.image = string.load("\res\2.ico");
  185.         return 0;
  186.     }
  187. }
  188. //---串口发送数据函数---
  189. comwrite = function(Serial_port,str,buf){
  190.     str = string.replace(str,"\s","");//去除空格及换行符
  191.     for(i=1; #str;2){
  192.         buf[(i+1)/2] = eval("0X"+string.slice(str,i,i+1));
  193.     }
  194.     var len = sio_write(Serial_port,buf,#str/2)
  195.               return len;
  196. }
  197. //---串口接收数据函数---
  198. comread = function(Serial_port,buf){
  199.     var len = sio_read(Serial_port,buf,#buf);
  200.     var str = ""
  201.       for(i=1; len; 1)
  202.             {
  203.                if(mainForm.radiobutton.checked != true){
  204.                        str = str++" "++string.right(string.format("%02X", buf[ i ]),2);//默认转换成有符号字节,因此取最右边两位
  205.                }else {
  206.                        str = str ++ string.pack(buf[i]);//默认转换成AISCII《这个地方感觉中断回调函数有问题》
  207.                }       
  208.             }
  209.     return str,len;
  210. }

  211. //---串口号(需要写配置项)---
  212. mainForm.combobox.oncommand = function(id,event){
  213.     //mainForm.msgbox( mainForm.combobox.text );
  214.     if( event = 0x1/*_CBN_SELCHANGE*/ ){
  215.         var selText = mainForm.combobox.selText;
  216.         
  217.         Serial_port = string.match(selText,"\d+");//给全局变量的串口端口赋值
  218.         /*
  219. select(selText) {
  220.             case "COM1" {
  221.                 win.msgboxTimeout("当前串口号:"+tostring(string.match(selText,"\d+")));
  222.             
  223.             }
  224.             case "COM2" {
  225.                  win.msgboxTimeout("当前串口号:"+selText)
  226.             }
  227.             case "COM3" {
  228.                  win.msgboxTimeout("当前串口号:"+selText)
  229.             }
  230.         }
  231. */
  232.     }  
  233. }

  234. //---波特率(需要写配置项)---
  235. mainForm.combobox2.oncommand = function(id,event){
  236.     //mainForm.msgbox( mainForm.combobox2.text );
  237.     if( event = 0x1/*_CBN_SELCHANGE*/ ){
  238.    
  239.         var selText = mainForm.combobox2.selText;
  240.         status.setText("操作状态:当前波特率"+selText + "重新打开串口生效", /*第几个分块*/)   
  241.                   
  242.         select(selText) {
  243.             case "1200" {
  244.                  Serial_baud = 0x07;
  245.             }
  246.             case "2400" {
  247.                  Serial_baud = 0x09;
  248.             }
  249.             case "4800" {
  250.                  Serial_baud = 0x0a;
  251.             }
  252.             case "9600" {
  253.                  Serial_baud = 0x0c;
  254.             }
  255.             case "38400" {
  256.                  Serial_baud = 0x0e;
  257.             }
  258.             case "57600" {
  259.                  Serial_baud = 0x0f;
  260.             }
  261.             case "115200" {
  262.                  Serial_baud = 0x10;
  263.             }
  264.         }
  265.     }
  266. }
  267.            
  268. //---开关串口---
  269. mainForm.button.oncommand = function(id,event){
  270.     if(mainForm.button.text != "关闭串口")
  271.     {
  272.         mainForm.button.text = "关闭串口";
  273.         mainForm.afpicturebox2.image = string.load("\res\4.ico");
  274.         
  275.             comopen(Serial_port,Serial_baud,parity,stopbits,wordlength);//打开串口并设置串口参数;
  276.     }
  277.     else
  278.     {
  279.         mainForm.button.text = "打开串口";
  280.         mainForm.afpicturebox2.image = string.load("\res\2.ico");
  281.         sio_close(Serial_port);                            //关闭串口
  282.     }
  283. }

  284. mainForm.button2.oncommand = function(id,event){
  285.     //mainForm.msgbox( mainForm.button2.text );
  286.     var str = mainForm.edit.text;
  287.    len = comwrite(Serial_port,str,cdata);             //发送
  288.    status.setText("端口状态:已发送[ "+tostring(len)+" ]字节",1 /*第几个分块*/);
  289. }

  290. mainForm.button3.oncommand = function(id,event){
  291.         //mainForm.msgbox( mainForm.button3.text );
  292.        
  293. }
  294. //---下面使用定时器查询串口接收状态---
  295. //使用定时器查询有一个严重缺陷,如果发送的速度快,那么接收端显示出来的数据就不准确
  296. tmid = mainForm.setInterval(
  297.         100/*毫秒*/,
  298.         function(hwnd,msg,id,tick){//定时执行代码
  299.                 str1, len1 = comread(Serial_port,cdata)              //接收
  300.                 if(len1 == -1){ return ; }
  301.                 if(len1 != 0){
  302.                  status.setText("接收状态:已收到[ "+tostring(len1)+" ]字节;"+str1,2 /*第几个分块*/);//问题就是这个地方统计不准确
  303.                  mainForm.edit2.appendText(str1);       
  304.                 }       
  305.                 //mainForm.clearInterval(id)//移除此定时器
  306.                 //mainForm.changeInterval(id,2000)//重新设定时间间隔
  307.         }
  308. );

  309. mainForm.show()
  310. win.loopMessage();
复制代码
现在能完成的事情,发送没有发送AISCII码,接收的时候发现有几个地方遇到了麻烦,
接收函数
  1. //---串口接收数据函数---
  2. comread = function(Serial_port,buf){
  3.     var len = sio_read(Serial_port,buf,#buf);
  4.     var str = ""
  5.       for(i=1; len; 1)
  6.             {
  7.                if(mainForm.radiobutton.checked != true){
  8.                        str = str++" "++string.right(string.format("%02X", buf[ i ]),2);//默认转换成有符号字节,因此取最右边两位
  9.                }else {
  10.                        str = str ++ string.pack(buf[i]);//默认转换成AISCII《这个地方感觉中断回调函数有问题》
  11.                }       
  12.             }
  13.     return str,len;
  14. }
复制代码
统计接收的字节有问题,我想应该是我没有设置接收中断,接收的时候,比如发送端发送FE 03 04 01 02 03 00 FC,但是接收到的数据是对的,要分几次接收,不明白这一点,另外在接收AISCII码的时候也是,如果不是用str = str ++ string.pack(buf);而使用str = str + string.pack(buf);就收不完一条命令,希望高手指点一下。

另外是接收部分使用定时器去查询,感觉这样完全是处于被动,我的查询接收如下:
  1. //---下面使用定时器查询串口接收状态---
  2. //使用定时器查询有一个严重缺陷,如果发送的速度快,那么接收端显示出来的数据就不准确
  3. tmid = mainForm.setInterval(
  4.         100/*毫秒*/,
  5.         function(hwnd,msg,id,tick){//定时执行代码
  6.                 str1, len1 = comread(Serial_port,cdata)              //接收
  7.                 if(len1 == -1){ return ; }
  8.                 if(len1 != 0){
  9.                  status.setText("接收状态:已收到[ "+tostring(len1)+" ]字节;"+str1,2 /*第几个分块*/);//问题就是这个地方统计不准确
  10.                  mainForm.edit2.appendText(str1);       
  11.                 }       
  12.                 //mainForm.clearInterval(id)//移除此定时器
  13.                 //mainForm.changeInterval(id,2000)//重新设定时间间隔
  14.         }
  15. );
复制代码
上面这种接收方式存在严重缺陷,我想接到数据就马上处理,而不需要我去查询,但是也许是我的能力有限,还没有明白如何处理,不知道论坛上面的高手是怎么接收数据的,希望指点我一下,谢谢。

AAuto工程5.rar

71.24 KB, 下载次数: 334

这个是根据电车男的提示修改过的

13

主题

92

回帖

719

积分

三级会员

积分
719
QQ
发表于 2013-1-21 10:59:41 | 显示全部楼层
  1. //---下面使用定时器查询串口接收状态---
  2. //使用定时器查询有一个严重缺陷,如果发送的速度快,那么接收端显示出来的数据就不准确
  3. tmid = mainForm.setInterval(
  4.         100/*毫秒*/,
  5.         function(hwnd,msg,id,tick){//定时执行代码
  6.                 mainForm.changeInterval(id,20000) //设置20秒
  7.                 str1, len1 = comread(Serial_port,cdata)              //接收
  8.                 if(len1 == -1){ return ; }
  9.                 if(len1 != 0){
  10.                  status.setText("接收状态:已收到[ "+tostring(len1)+" ]字节;"+str1,2 /*第几个分块*/);//问题就是这个地方统计不准确
  11.                  mainForm.edit2.appendText(str1);       
  12.                 }       
  13.                 mainForm.changeInterval(id,100) //重新设置100毫秒
  14.                 //mainForm.clearInterval(id)//移除此定时器
  15.                 //mainForm.changeInterval(id,2000)//重新设定时间间隔
  16.         }
  17. );
复制代码
改成这样
你进定时器的时候设置下次执行时间为20秒
执行完你的代码段之后 重新设置为100ms
————————————————————————
我认为定时器就是单独的线程,我一般把定时器当做线程用的时候都这样干,进入定时器的时候加大间隔时间,执行完代码段之后再改回去。

8

主题

110

回帖

904

积分

三级会员

积分
904
 楼主| 发表于 2013-1-21 11:11:01 | 显示全部楼层
stillywud 发表于 2013-1-21 10:59
改成这样
你进定时器的时候设置下次执行时间为20秒
执行完你的代码段之后 重新设置为100ms

谢谢
电车男
这样做确实可以避免我之前的问题,后续我再去摸索看看,目前问题解决,但是在把数据添加到edit显示的时候,感觉还是存在问题,一条命令分两次显示出去的
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|aardio.com|aardio 官方社区 ( 皖ICP备09012014号 )

GMT+8, 2025-2-13 17:50 , Processed in 0.157349 second(s), 26 queries .

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

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