最近在写一个串程序,业务用要求用java web从串口中读取数据,并显在文本框中。具体串口中的信息是从一个能扫描条形码(Barcode)的手持备上获取的,手持设怎扫描,怎么将信息写入串口我不用关心,我要做的就是从串口中信息读取出
说到串口,许很多人要怀疑,这什么年代了,USB设已经如及了,谁还能想起个老掉牙的通端口呀,其实,在现实生活中,串口正因为它老,会实际使用中经常用到。举个简单例子:工业制造及其设备与计算机之间的通讯、还有在各种电子工厂测试设备的过程中,都无一例外使用的串口。因为它可以不用像USB设备一样必须有软件驱动的支持才可以进行作。现如今,台式电脑基本还保留着一个串甚至是个串,但笔记本电上串口,被越来多的制造商抛弃。有很多从事工控、测试等行业的工作人员,选购笔记本的时候,串口成他们心中的永远的痛。看似一单的接口,对他们来说是重
关于什么串,口的分类,以及串口长的什么样子,大家可以去网上搜一下,上一段的要信息就是要
第二
如的面上提供一种usb串口工具,具体可以在百度搜索usb转串口,我是去向隔壁部门借的,据说十几块钱一个,当然得需要两个,我们一般试使用这种九针的就以了,有了这个东西,那就开始动手吧~如图:我的和这个不一样,我还带一根延
1、插上u转备,安装u转串口的驱动,这时右击我的电脑,选择设备
器,如果安装
图:
2、问题又来了,两个口笔记是能识别,但是这两个串口怎么连起来呢,对此以去电脑耗店买一种叫做“串口交叉线”的线,这种线能两个usb转出来的两串口连接起来(两个usb转成的串口都是带针的口,也就是所谓的公口),这种“串口交叉线”的两头都是母口,所以正好能连接起来。可惜不幸是,我转遍了学校周,也没有找“串口线”,人都没听过,没办法,他们一点也专业,都不是卖电脑耗材的,本市有卖电脑耗材的地方,可是远,来回半天,就只为了根6块钱的
网上搜,两个串口可以简单的相连,就能达到通信的目的,具体看下面的9针串口功能一览
针脚 功能
1 载波检测 (DCD)
2 接收数据 (RXD)
3 发送数据(TXD)
4 数据终端准备好 (DTR)
5 信号地 (GND)
6 数据准备好 (DSR)
7 发送请求 (RTS)
8 发送清除 (CTS)
9 振铃指示 (RI)
我们做口试,只需要2口和3口就了。意思是将A串口的2针到B串口的3针,将A串口的3针接到B串口的2针,这就是所谓的串口交,另外一个就是5是号地,可以直连,也可以不连,剩下的针脚据说从开发出来今还没用
就好办了,我找嵌入式的同学问一下能不能做个串口交叉线,结果他给了我根线,我不知
有了这样的两跟线,
java读取串口信息(二)
2011-11-18 11:15
串口连
1.准备
下载Communication包
下载地址下:http://mdubuc.freeshell.org/Jolt/javacomm20-win32.zip。 2.配
解压缩javacomm20-win32.zip
把win32com.dll拷贝到{JAVA_HOME}\jre\bin
把comm.jar拷贝到{JAVA_HOME}\jre\lib\ext
把javax.comm.properties拷贝到{JAVA_HOME}\jre\lib
再环境变量的CLASSPATH中添加一项:{JAVA_HOME}\jre\lib\ext\comm.jar;
我的CLASSPATH添加后为:
.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\jre\lib\ext\comm.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\jtds.jar;%Tomcat_Home%\common\lib\servlet-api.jar;
3.
void listPortChoices() {
CommPortIdentifier portId;
Enumeration en = CommPortIdentifier.getPortIdentifiers();
// iterate through the ports.
while (en.hasMoreElements()) {
portId = (CommPortIdentifier) en.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.println(portId.getName());
}
}
portChoice.select(parameters.getPortName());
}
以上代码可以列当前系统所有可用的串口名称,我的机器上输出的
4.
下载地址:http://www.onlinedown.net/soft/54540.htm
安装后,它会自
5.程序
package cn.edu.lzjtu.comm;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.TooManyListenersException; import javax.comm.CommPortIdentifier; import javax.comm.PortInUseException; import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener; import javax.comm.UnsupportedCommOperationException;
public class Readstr {
static String str = "000000";
public void init()
{
try{
CommPortIdentifier portId =
CommPortIdentifier.getPortIdentifier("COM3");
// 直接取得COM3端口
System.out.println(portId.getName()+":开启");
@SuppressWarnings("unused")
Read reader = new Read(portId);
}catch(Exception ex){
ex.printStackTrace();
}
}
class Read implements Runnable, SerialPortEventListener {
InputStream inputStream;
SerialPort serialPort;
Thread readThread;
public Read(CommPortIdentifier portId) throws InterruptedException
{
try {
serialPort = (SerialPort) portId.open("MyReader", 2000);
//portId.open("串口所有
} catch (PortInUseException e) {
//如果端口被占用就抛出这个异常
e.printStackTrace();
}
try {
inputStream = serialPort.getInputStream();
//从COM3获取数据
} catch (IOException e) {}
try {
serialPort.addEventListener(this);
//添加监听器
} catch (TooManyListenersException e) {}
serialPort.notifyOnDataAvailable(true);
/* 侦听到串口有数据,触发串口事件*/
try {
serialPort.setSerialPortParams(9600,//波特
SerialPort.DATABITS_8,//数据位
SerialPort.STOPBITS_1,//停止
SerialPort.PARITY_NONE);//校
} catch (UnsupportedCommOperationException e) {}
readThread = new Thread(this);
readThread.start();
//启动线程
}
public void run() {
try {
Thread.sleep(30000);
serialPort.close();
System.out.println("COM3:关闭");
//设定30秒后端口关闭,程序随之结
} catch (InterruptedException e) {}
}
/**
* BI -通讯中断.
CD -载波检测.
CTS -清除发送.
DATA_AVAILABLE -有数据到达.
DSR -数据设备准备好.
FE -帧错误.
OE -溢位错误.
OUTPUT_BUFFER_EMPTY -输出缓冲区已清空.
PE -奇偶校验错.
RI - 振铃指示.
一般最常
*/
public void serialEvent(SerialPortEvent event) {
switch(event.getEventType()) {
case SerialPortEvent.BI:
case SerialPortEvent.OE:
case SerialPortEvent.FE:
case SerialPortEvent.PE:
case SerialPortEvent.CD:
case SerialPortEvent.CTS:
case SerialPortEvent.DSR:
case SerialPortEvent.RI:
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
case SerialPortEvent.DATA_AVAILABLE:
byte[] readBuffer = new byte[20];
try {
while (inputStream.available() > 0) {
int numBytes = inputStream.read(readBuffer);
//System.out.println("numBytes"+numBytes);
}
str = new String(readBuffer).trim();
System.out.println(new String(readBuffer).trim());
//输出读入的字符
} catch (IOException e) {}
break;
}
}
}
public static void main(String [] args)
{
Readstr reader = new Readstr();
reader.init();
}
}
//此程序只监听COM3端口,当程序执行时开启COM3端口,等待30秒
端口COM3关闭,程序随之关闭
//Read 为内部类,这样可以共用读取出来的字符串信息
//在Readstr 定义一个静态量static String str = "000000"; //然后在读出数据后str = new String(readBuffer).trim(); //这样可以在个事件触发后,将str中的值赋给相应的(比如说,让
显示在输入框中)
6.执行程序
执行上边的程,打开超级超级串口调试器,选择除COM3以外的端口,波
改为9600,为上面的程序选择的是COM3端口,波特为9600,也可以将
程序端口改的,反正就是:这个串口调试程序占用一个端口,上边的执
序再占用
如图所示:
好
但项目是B/S的,最终目的是读取出来每个登录客户端的串口信
To Be Continued....
Linux串口读取GPS数据
模板一
一、相关概念
1.GPS(Global Positioning System):全球卫星定位系
美国的24卫星不停地地发GPS信号,只要有一台GPS接收设备,就能定位出你所在的位置高度和度了,它与电图的结合就是通常所说的GPS功能 二、连接
1.串口:计算常通过串口读取gps数据(蓝牙的gps也
1)普通串口设备
打开串口->设置串口->读取数据->恢复串口->关闭串口
2)蓝牙设备
开启蓝牙->与gps设备连接->打开串口->读取数据->关闭串口->gps设备断开->关闭蓝
3)注意
连接gps
用蓝牙gps设备一般不用对串口进行设置
三、gps数据格式
1.从串口中读出的是本数据,每次读出行,一般情况下,一秒收到多行数据 2.有效数以$GP开头,分为$GPGGA、$GPGSA、$GPGSV、$GPRMC… 3. $GPGGA 是GPS定位的主要数据,通过解析它得到经度、纬度、海拔高度、时间、卫星使用情况等基本信息,其中每用逗号分隔,共十四个号,举例如
$GPGGA(语标识头),064746.000(UTC时间),4925.4895(纬度),N(纬度半球),00103.9255(度),E(经度半球),1(定位质量指示),05(使用卫星数量),2.1(水平精确度),-68.0(海拔高度),M(高度单位),47.1(大地面高),M(高度单位),(差分 GPS数据期限),0000(差分参考基站标)*4F(校验)(标记回换行)
1.功能描述
假设蓝牙模与gps已连接,蓝牙的虚拟串口设备是ttyB2 实现从蓝牙设备连接读取100数据,解析(度/纬度/海拔/卫星个数)显示出来 2.
#include
#include
#include
#include
#include
#include
void parseData(char *buf)
{
int ret, nQ, nN, nB, nC;
char cX, cY, cM1, cM2;
float fTime, fX, fY, fP, fH, fB, fD;
if (buf == NULL)
return;
ret = sscanf(buf,
"$GPGGA,%f,%f,%c,%f,%c,%d,%02d,%f,%f,%c,%f,%c,%f,%04d%02x",
&fTime, &fX, &cX, &fY, &cY, &nQ, &nN, &fP, &fH, &cM1, &fB,
&cM2, &fD, &nB, &nC);
printf("x: %c %f, y: %c %f, h %f, satellite: %d\n",
cX, fX, cY, fY, fH, nN);
}
int main(int argc, char **argv) {
int fd, i, ret;
char buf[1024] =
"$GPGGA,064746.000,4925.4895,N,00103.99255,E,1,05,2.1,-68.0,M,47.1,M,,0000*4F\r\n
"; // 此处赋值用于测试
if ((fd = open("/dev/ttyB2", O_RDWR)) == -1)
return -1;
// set fd: tcsetattr... 直接连接串口的设备需要在此设置波特率 for (i = 0; i < 100;="" i++)="" {="">
ret = read(fd, buf, 1024); if (ret > 1)
{
if (strstr(buf, "GPGGA") != NULL) parseData(buf);
}
}
// restore fd: tcsetattr... 直接连串口的设备需要在此恢复波
close(fd);
}
模板二
与其他的关于设备编程的法一,在Linux下,作、控制口也是通操作起设备文件进行的。在Linux下,串的设备文件是/dev/ttyS0或/dev/ttyS1等。因此要读写串口,我们首先要打开串口,然后根据GPS模块的配置参对串口的特率、验、流控制等进行设置,这些参数置均通过对termios结构中c_cflag的配置实现,口配置分函数
I
nt gps::set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O': //奇校
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶校
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //无校
newtio.c_cflag &= ~PARENB;
break;
}
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
{
newtio.c_cflag &= ~CSTOPB;
}
else if ( nStop == 2 )
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
qDebug()<<"com set=""><"com>
return -1;
}
qDebug()<<"set><"set>
return 0;
}
在GPS数据的处理上首将窗数据存入一个字符串,接着通过字符串据的判断来提取数据内容,判断分为两步,首先断是什么类型的数据,在本程序的设计中需要读取$GPRMC和$GPGGA两组数据,因此首先判断字符串GPS_BUF[5]是C还是A,由于是过符号“,”进行隔开,因此过查找“,”来确定数据位置。在实现上将到逗号位置函数封装调,程序
//
int gps::GetComma(int num,char *str) {
int i,j=0;
int len=strlen(str);
for(i=0;i
{
if(str[i]==',')
{
j++;
}
if(j==num)
return i+1;
}
return 0;
}
接下来根据
void gps::gps_parse()
{
int tmp;
char c;
c = GPS_BUF[5];
if(c=='C')
{
//"GPRMC"
GPS->D.hour =(GPS_BUF[ 7]-'0')*10+(GPS_BUF[ 8]-'0');
GPS->D.minute =(GPS_BUF[ 9]-'0')*10+(GPS_BUF[10]-'0');
GPS->D.second =(GPS_BUF[11]-'0')*10+(GPS_BUF[12]-'0');
tmp = GetComma(9,GPS_BUF);
GPS->D.day =(GPS_BUF[tmp+0]-'0')*10+(GPS_BUF[tmp+1]-'0');
GPS->D.month =(GPS_BUF[tmp+2]-'0')*10+(GPS_BUF[tmp+3]-'0');
GPS->D.year =(GPS_BUF[tmp+4]-'0')*10+(GPS_BUF[tmp+5]-'0')+2000;
GPS->status = GPS_BUF[GetComma(2,GPS_BUF)];
GPS->latitude = get_locate(get_double_number(&GPS_BUF[GetComma(3,GPS_BUF)]));
GPS->NS = GPS_BUF[GetComma(4,GPS_BUF)];
GPS->longitude=
get_locate(get_double_number(&GPS_BUF[GetComma(5,GPS_BUF)]));
GPS->EW = GPS_BUF[GetComma(6,GPS_BUF)];
GPS->speed = get_double_number(&GPS_BUF[GetComma(7,GPS_BUF)]);
UTC2BTC(&GPS->D);
}
if(c=='A')
{
//"$GPGGA"
GPS->high = get_double_number(&GPS_BUF[GetComma(9,GPS_BUF)]);
}
}
//将
double gps::get_double_number(char *s)
{
char buf[128];
int i;
double rev;
i=GetComma(1,s);
strncpy(buf,s,i);
buf[i]=0;
rev=atof(buf);
return rev;
}
double gps::get_locate(double temp)
{
int m;
double n;
m=(int)temp/100;
n=(temp-m*100)/60;
n=n+m;
return n;
}
模板3
ARM开发板
分类: LINUX
硬件平台:开发维特jx2410,gps模块HOLUX GR-87,USB转串口线一
程序是在嵌
#include #include #include #include #include #include #include #include #include #include "serial.h" // #define UInt32 unsigned int #define Int16 short #define UInt16 unsigned short #define UInt8 unsigned char #define Boolean int #define false 0 #define true 1 #define GPS_RECV_CMD_MAX_BUF 256 //the buffer size //the gga info struct typedef struct GGAINFO{ int bIsGPGGA; UInt8 hour, bjhour, min, sec, secFrac; double latitude; UInt8 latNS; double longitude; UInt8 lgtEW; // UInt8 hour, bjhour, min, sec, secFrac; UInt8 satellites; Int16 altitude; // UInt8 altUnit; }GGAINFO; int main(void) { int fd; int i; char buffer[GPS_RECV_CMD_MAX_BUF];//receive buffer char tmp; GGAINFO ggainfo; char Degree[4]; char Minute[8]; char Hour[4]; char Minu[4]; char Second[4]; char Satnum[4]; int no = 0; //open the COM if((fd=open_port(fd,4))<0)>0)> { perror("open_port error"); return; } printf("fd=%d\n",fd); //set the COM if((i=set_opt(fd,9600,8,'N',1))<0)>0)> { perror("set_opt error"); return; } // while(1) { while(!Is_startGP(fd)); // printf("start to receive\n"); //receive the info for(i = 0; i { read(fd,&tmp,1); buffer[i]=tmp; // printf("%c",buffer[i]); if(tmp=='\n')break; } // printf("\n"); //proc the GGA info if(Is_GGA(buffer)) { ggainfo.bIsGPGGA = 1; //Time:6-15 no = 6; for(i = 0;i < 4;i++)=""> Hour[i]=0; Hour[0]=buffer[no]; Hour[1]=buffer[no+1]; no += 2; for(i = 0;i < 4;i++)=""> Minu[i]=0; Minu[0]=buffer[no]; Minu[1]=buffer[no+1]; no += 2; for(i = 0;i < 4;i++)=""> Second[i]=0; Second[0]=buffer[no]; Second[1]=buffer[no+1]; ggainfo.hour = atoi(Hour); ggainfo.min = atoi(Minu); ggainfo.sec = atoi(Second); ggainfo.secFrac = 0; ggainfo.bjhour = ggainfo.hour + 8; if(ggainfo.bjhour > 24) ggainfo.bjhour -= 24; //Latitude:17-25 no = 17; for(i = 0;i <> Degree[i]=0; Degree[0]=buffer[no]; Degree[1]=buffer[no+1]; no+=2; for(i=0;i<8;i++)>8;i++)> Minute[i]=0; for(i=0;i<7;i++)>7;i++)> Minute[i]=buffer[no+i]; // int l=atoi(Degree); ggainfo.latitude=(atof(Minute)) / 60.0 + atoi(Degree); //NS:27 ggainfo.latNS = buffer[27]; //Longitude:29-38 no = 29; for(i=0;i<4;i++)>4;i++)> Degree[i]=0; Degree[0]=buffer[no]; Degree[1]=buffer[no+1]; Degree[2]=buffer[no+2]; no+=3; for(i=0;i<8;i++)>8;i++)> Minute[i]=0; for(i=0;i<7;i++)>7;i++)> Minute[i]=buffer[no+i]; // int B=atoi(Degree); ggainfo.longitude=(atof(Minute)) / 60.0 + atoi(Degree); //WE:40 ggainfo.lgtEW = buffer[40]; //the number of satellite:44-45 no = 44; for(i = 0;i < 4;i++)=""> Satnum[i]=0; Satnum[0]=buffer[no]; Satnum[1]=buffer[no+1]; ggainfo.satellites = atoi(Satnum); printf("UTC Time:%d h %d m %d s\n",ggainfo.hour,ggainfo.min,ggainfo.sec); printf("BJ Time:%d h %d m %d s\n",ggainfo.bjhour,ggainfo.min,ggainfo.sec); printf("Latitude:%c wei %f \n",ggainfo.latNS,ggainfo.latitude); printf("Longitude:%c jing %f \n",ggainfo.lgtEW,ggainfo.longitude); printf("Satellites:%d \n",ggainfo.satellites); printf("\n"); } else continue; sleep(1); } close(fd); return 0; } int Is_startGP(int fp) { int status=0; char cc,tmp; read(fp,&cc,1); tmp=cc; if(tmp=='$')status=1; return status; } int Is_GGA(char p[GPS_RECV_CMD_MAX_BUF]) { int status=0; if(p[2] == 'G' && p[3] == 'G' && p[4] == 'A') status=1; return status; } 读取串口数据 方法一:使用 VC++提供串行通控件 MSComm ,在对话框创建通信控,若 Control 工具栏中缺少该件,可通过菜 Project --> Add to Project --> Components and Control 插入即可,再将该控从工具箱中拉到对框中。此时,你只要心件提供的对 Windows 通讯驱程序的 API 函数的接口。 换句话说, 需要设置和监视 MSComm 控 在 ClassWizard 中为新建的通控件义成员对象(CMSComm m_Serial),通过该对 象便可以对串口属性进行设置, MSComm 控件有 27个属性,这里介其中几个常用属性: CommPort 设置并返回通讯端口号, Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止 PortOpen 设置并返回通讯端口的状态,也可以打开和关闭端 Input 从接收缓冲区返回和删除字符。 Output 向发送缓冲区写一个字符串。 InputLen 每次 Input 读入的字符个数,缺省值 0,表读取接收缓冲 区中的全部 内 InBufferCount 返回接收缓冲区中接收到的符数,其置 0可以清除接收缓 冲区。 InputMode 定义 Input 属性获取数据的方式(为 0:文本方式;为 1:二进制方式)。 RThreshold 和 SThreshold 属性,表示在 OnComm 事件发生之前,接收缓冲区或发送缓 区中可接收的 以下是通 BOOL CSampleDlg:: PortOpen() { BOOL m_Opened; ...... m_Serial.SetCommPort(2); // 指定串 m_Serial.SetSettings( m_Serial.SetInBufferSize(1024); // 指定接收缓冲区 m_Serial.SetInBufferCount(0); // 清空接收缓 m_Serial.InputMode(1); // 设置数据获取 m_Serial.SetInputLen(0); // 设置读取 m_Opened=m_Serail.SetPortOpen(1); // 打开指定的 return m_Opened; } 打开所需串口后,需要虑串口通的时机。在接收或发送数据过程中,需要监视并 应一些事和错误,所以事件驱动是处理串行端口交互用一种非常有效的法。使用 OnComm 事件和 CommEvent 属性捕捉并检查通讯事件和错误的值。 发生通讯事件或错误时, 将 触发 OnComm 事, CommEvent 属性的值被改变,应程序查 CommEvent 属性并作 相应的反应。在程序中用 ClassWizard CMSComm 控件 OnComm 消息 void CSampleDlg::OnComm() { ...... switch(m_Serial.GetCommEvent()) { case 2: // 串行口数据接收,处理; } } 方法二: 控件简单易用, 但于必须拿到话框使, 在一些需要在线程中实通信的应用场合, 控件的使用显得捉襟见肘。 此时, 若能够按不需要定制灵活的串通类将弥补控件的不足, 以下将介绍如何在单线程中建立定义的通 该通信类 CSimpleComm 需手动加入头文件与源文件,其基为 CObject ,大致建立步骤如 (1) 打开串口,获取串口资源句柄 通信程序从 CreateFile 处指串口设备及关的操作属性。再返回个句柄,该柄将 被用于后续通信操作, 贯穿整个通信过程。 CreateFile()函数有几值得注意的参数设 :串口共享方应设为 0,串口为不可共享设备;创建方式必须为 OPEN_EXISTING,即打开已 有的串口。对于 dwFlagAndAttribute 参数,对串口有意义的值是 FILE_FLAG_OVERLAPPED,该 标表明串口用步通信式,可进重操;若值为 NULL ,为同步信方式,在同 步方式下,应用程序将始终控制程序流,直到程序结束,遭遇通信故障等因素,将导致应用 序的永久等待,所以一般多采异 (2)串口设置 串口打开后, 其属性设置为认值, 根据具体需要, 通过调 GetCommState(hComm,&dcb)读取当前串口设备制块 DCB (Device Control Block)设置,修改后通过 SetCommState(hComm,&dcb)将其写入。 再需注意异步读的超时控制设置, 过 COMMTIMEOUTS 结构设置超时,调用 SetCommTimeouts(hComm,&timeouts)将结果写入。以下是温度控程序 中口初始化 BOOL CSimpleComm::Open( ) { DCB dcb; m_hIDComDev=CreateFile( GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ NORMAL|FILE_FLAG_OVE RLAPPED, NULL ); // 打开串口,异步操作 if( m_hIDComDev == NULL ) return( FALSE ); dcb.DCBlength = sizeof( DCB ); GetCommState( m_hIDComDev, &dcb ); // 获得端口默认 dcb.BaudRate=CBR_4800; dcb.ByteSize=8; dcb.Parity= NOPARITY; dcb.StopBits=(BYTE) ONESTOPBIT; ...... } (3)串口读写操作 主要运用 ReadFile ()与 WriteFile () API 数,若为步通信方式,两函数中最后一 个参数为指 OVERLAPPED 结构的非空指针,在读写函数返回值为 FALSE 的情况下,调用 GetLastError ()函数,返回值为 ERROR_IO_PENDING,表 I/O作悬,即操作转入后台 继续执行。此时,可以用 WaitForSingleObject()来等待结束信号并置最长等待间,举 BOOL bReadStatus; bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead ); if(!bReadStatus) { if(GetLastError()==ERROR_IO_PENDING) { WaitForSingleObject(m_OverlappedRead.hEvent,1000); return ((int)dwBytesRead); } return(0); } return ((int)dwBytesRead); 定义全局变量 m_Serial作为新建通信类 CSimpleComm 的对象,通过调用类的成员函 可实现所需串行通功。与方法一相,方法赋予行通信程序设计较大的灵活性,口 的读写可选择较简单的查询式,或通过设置与外设数据发送时间间隔 TimeCycle 相同的定 :SetTimer(1,TimeCycle,NULL),进定时读取或 CSampleView:: OnTimer(UINT nIDEvent) { char InputData[30]; m_Serial.ReadData(InputData,30); // 数据处理 } 若对端口据的响应时求较严格,可采用事件驱动 I/O读写, Windows 定了 9种串 口通信事件,较常用的 EV_RXCHAR: 接收到一个字节,并放入输入缓冲区。 EV_TXEMPTY: 输出缓冲区中的最后一个字符发送出 EV_RXFLAG: 接收到事件字符 (DCB结构中 EvtChar 成员 ) ,放入输入缓冲 在用 SetCommMask()指定了有用的事件后,应用程序可调用 WaitCommEvent()来等待事件 的发 SetCommMask(hComm,0)可使 WaitCommEvent()中 方法 方法一,二适用单线通信。在很工业控系统,常通过扩展串口连接多个外, 各外设发送数据的重复频率不同,要求后台实时无差错捕捉,采集,处理,记各端口数据, 这就要自定义的串行通信类中创建端口监视线程, 以便在指定的事件生时向相关 发送通知消息。 线程的基本概念可见 VC++参书目, Windows 内部的先调度序在活动的线程之间分 配 CPU 时间, Win 32 区分两种不同类型的线程,一种是用户界面线程 UI (User Interface Thread ) , 它含消息循环或消息,用于处接到消;另一种是工作线程(Work Thread ),它没有消息循环,用于执行台任务。用于监视事件的程即为工 多线程通信类编在端口的置,接分与单线程通信类相同,在端口配置完毕后, 最重要的是根据实际情况,建立多线程之的同步对象,如号,临界区,事件等,相关细 节可参考 VC++ 中的同 一切 CWinThrea *CommThread = AfxBegin Thread(CommWatchThread, // 线程函 (LPVOID) m_pTTYInfo, // 传递的参数 THREAD_PRIORITY_ABOVE_NORMAL, // 设置线程优 (UINT) 0, // 最大堆栈大小 (DWORD) Create_SUSPENDED , // 创建 (LPSECURITY_ATTRIBUTES) NULL); // 安全性 同时,在串口事件监视线程中: if(WaitCommEvent(pTTYInfo->idComDev,&dwEvtMask,NULL)) { if((dwEvtMask & pTTYInfo->dwEvtMask )== pTTYInfo->dwEvtMask) { WaitForSingleObject(pTTYInfo->hPostEvent,0xFFFFFFFF); ResetEvent(pTTYInfo->hPostEvent); // 置同步事件对象为非信号态 ::PostMessage(CSampleView,ID_COM1_DATA,0,0); // 发送通 } 用 PostMessage()指定窗口的消息队列发送通知消息,相应地,需要在该窗口建立消息 与员函数间的映,用 ON_MESSAGE将消息与成员函数名 BEGIN_MESSAGE_MAP(CSampleView, CView) //{{AFX_MSG_MAP(CSampleView) ON_MESSAGE(ID_COM1_DATA, OnProcessCom1Data) ON_MESSAGE(ID_COM2_DATA, OnProcessCom2Data) ..... //}}AFX_MSG_MAP END_MESSAGE_MAP() 然后在各成函数中完成对口数据的接收处理, 但必须保证在下一次监测到有数据到 来前,能够完所的中间处理工作。否则将造成数据的捕捉错 多线程的实现可使各端口独立, 准确实串行通信, 使串口通信具有广泛的灵活性 与严格性,且充分利用了 CPU 时间。但在具体的实监控系统中如何协调个程,线程之间 以何种方式实现同步也是在多线程串行通信序实现的 一个读串口的函数: HANDLE m_hIDComDev; int ReceiveComm(char* RecCommData) { DWORD dRead,dReadNum; COMSTAT ComStat; LPDWORD ComError; char *Data; ClearCommBreak(m_hIDComDev); ClearCommError(m_hIDComDev,ComError,&ComStat); dRead=ReadFile(m_hIDComDev, Data, ComStat.cbInQue, &dReadNum, NULL); //接收 200个 字符 //dReadNum为实际接收字节数 PurgeComm(m_hIDComDev,PURGE_RXCLEAR);//清空接收缓 for(int i = 0 ;i < comstat.cbinque;=""> { *RecCommData = *Data; RecCommData++; Data++; } *RecCommData = '\0'; if(dRead) return 1; else return 0; } 一、C#串口操作之读取串口数据: try { axMSComm2.CommPort = 1i; axMSComm2.InputMode = MSCommLib.InputModeConstants.comInputModeBinary; //用 //此例是通过Input axMSComm2.InBufferCount = 0; //于返回输 } catch (Exception e) { MessageBox.Show(e.ToString()); } 在axMSComm的OnComm事件里写: private void axMSComm2_OnComm(object sender, EventArgs e) { switch (axMSComm2.CommEvent) //查询CommEvent属性 { case (short)(MSCommLib.OnCommConstants.comEvReceive): //当接 //进 CommData(); //接收缓冲区内数据 break; } } private void CommData() //接收数据 { int BufferDataNumStart = 0; //定 int BufferDataNumEnd = 0; //定义最 byte[] CommBufferData = new byte[1024]; byte[] ComByte = new byte[8]; BufferDataNumStart = axMSComm2.InBufferCount; ; //将缓冲区等读取的字节数 //则返 //读 axMSComm2.InputLen = 0; while (true) { System.Threading.Thread.Sleep(50); //延时,以确保数据完全接收 BufferDataNumEnd = axMSComm2.InBufferCount; //再次读取缓冲区内字节个数 if (BufferDataNumStart == BufferDataNumEnd) break; //如果BufferDataNumStart==BufferDataNumEnd, //说 BufferDataNumStart = BufferDataNumEnd; //否则,将BufferDataNumEnd赋给BufferDataNumStart, //并 } object objIn; objIn = axMSComm2.Input; //这里注意MSComm.Input返回的是一个object的类型, //所 CommBufferData = (byte[])objIn; //CommBufferData为串口缓冲区内所有数据 //存取 //存储 //以便于 //需在添 //将上次未 //此部 //以至于 for (int i = 0; i < bufferdatanumend;="" i++)="" {=""> ReceiveDataNum++; UnsettledDataNum++; ReceivedData[ReceiveDataNum - 1] = CommBufferData[i]; } // } private void DealData() //数据处理 { for (int i = 0; i < receiveddata.length="" -="" 7;="" i++)=""> { if (ReceivedData[i] == 0xff && ReceivedData[i + 1] == 0x04)判断通讯头 { zhou++; INTzhouzhong[zhou] = int.Parse(ReceivedData[i + 4].ToString("X")) * 10000 + int.Parse(ReceivedData[i + 3].ToString("X")) * 100 + int.Parse(ReceivedData[i + 2].ToString("X")); } } ReceiveDataNum = 0; UnsettledDataNum = 0; } 二、C#串口操作之发送数据 try { axMSComm1.CommPort = zifuchuankou; axMSComm1.Settings = "9600,N,8,1"; axMSComm1.PortOpen = true; } catch { MessageBox.Show("COM3初始化失败~"); } byte[] b1 = { 0x0A, 0x46, 0x31, 0x31, 0x31, 0x2E, 0x31, 0x0D }; axMSComm1.Output = b3; 解决办法, AxMSComm1_OnComm() Select Case Me.AxMSComm1.CommEvent Case MSCommLib.OnCommConstants.comEvReceive '接受 System.Threading.Thread.CurrentThread.Sleep(2) '当前线程sleep延时2ms doMyOwn1() Case MSCommLib.OnCommConstants.comEvSend '发送数 System.Threading.Thread.CurrentThread.Sleep(2) '当前线程sleep延时2ms doMyOwn2() End Select 不断读取 Use the Mscomm control, continue to read serial MSComml.Input data. Attribute description CommPort sets or returns the communication port number Settings sets or returns baud rates, parity, data bits, and stop bits in the form of strings PortOpen sets or returns the status of the communication port. You can also open and close ports Input returns and deletes characters in the receive buffer Output writes the string to the send buffer The CommEvent property returns one of the following values for communication events or errors. These constants can also be found in the object library of the control. Constant value description ComEventBreak 1001 received the break signal ComEventCTSTO 1002, Clear, To, Send, Timeout. When sending characters, the CTS (Clear, To, Send) line is low in the 1 things specified by the system ComEventDSRTO 1003, Data, Set, Ready, Timeout. When sending characters, the DSR (Data, Set, Ready) line is low in the system specified event ComEventFrame 1004 data frame error. The hardware detected a data frame error ComEventOverrun 1006 port overflow. The characters in the hardware are not yet read. The next character arrives and is lost ComEventCDTO 1007, Carrier, Detect, Time. When sending characters, the CD (Carrier, Detect) line is low in the system specified event. CD is also known as RLSD (Receive, Line, Singal, Detect, receive line signal detection) ComEventRxOver 1008 receives buffer overflow. There is no space in the receive buffer ComEventRxParity 1009 parity error. The hardware detected parity error 7 ComEventTxFull 1010 sends buffer full. When sending queued characters, the sending buffer is full An unexpected error occurred when ComEventDCB 1011 checked the port DCB (Device Control Blick) "Open the serial port MSComml.CommPort =2 Setting 'Com2' If MSComml.PortOpen = False Then MSComm1.Settings = 9600, N, 8,1" '9600 baud rate, no checksum, 8 bit data bits, 1 bit stop bits MSComm1.PortOpen = True "Open the serial port End if MSComm1.OutBufferCount = 0 Empty the send buffer MSComm1.InBufferCount = 0 'slide empty receive buffer' Receive binary data MSComm1.InputMode= ComInputModeBinary Buffer=MSComm1.Input 'receive character data MSComm1.InputMode=comInputModeText Buffer = MSComml.Input Mscomm control Attribute description CommPort sets or returns the communication port number Settings sets or returns baud rates, parity, data bits, and stop bits in the form of strings PortOpen sets or returns the status of the communication port. You can also open and close ports Input returns and deletes characters in the receive buffer Output writes the string to the send buffer The CommEvent property returns one of the following values for communication events or errors. These constants can also be found in the object library of the control. Constant value description ComEventBreak 1001 received the break signal ComEventCTSTO 1002, Clear, To, Send, Timeout. When sending characters, the CTS (Clear, To, Send) line is low in the 1 things specified by the system ComEventDSRTO 1003, Data, Set, Ready, Timeout. When sending characters, the DSR (Data, Set, Ready) line is low in the system specified event ComEventFrame 1004 data frame error. The hardware detected a data frame error ComEventOverrun 1006 port overflow. The characters in the hardware are not yet read. The next character arrives and is lost ComEventCDTO 1007, Carrier, Detect, Time. When sending characters, the CD (Carrier, Detect) line is low in the system specified event. CD is also known as RLSD (Receive, Line, Singal, Detect, receive line signal detection) ComEventRxOver 1008 receives buffer overflow. There is no space in the receive buffer ComEventRxParity 1009 parity error. The hardware detected parity error 7 ComEventTxFull 1010 sends buffer full. When sending queued characters, the sending buffer is full An unexpected error occurred when ComEventDCB 1011 checked the port DCB (Device Control Blick) "Open the serial port MSComml.CommPort =2 Setting 'Com2' If MSComml.PortOpen = False Then MSComm1.Settings = 9600, N, 8,1" '9600 baud rate, no checksum, 8 bit data bits, 1 bit stop bits MSComm1.PortOpen = True (open serial port) -----------------------MSComm1.PortOpen=False'(closed serial port) "Open the serial port End if MSComm1.OutBufferCount = 0 Empty the send buffer MSComm1.InBufferCount = 0 'slide empty receive buffer' Receive binary data MSComm1.InputMode= ComInputModeBinary Buffer=MSComm1.Input 'receive character data MSComm1.InputMode=comInputModeText Buffer = MSComml.Input 转载请注明出处范文大全网 » java读取串口信息读取串口数据
C_串口操作之读取串口数据
不断读取串口MSComml.Input数据