基于module rtu 协议的串口读写程序
来源:互联网 发布:淘宝卖最快的是 编辑:程序博客网 时间:2024/06/17 02:41
第一次写博客记录一下最近写的一个程序吧,这是在visual studio 2010下用window api写的,主要用于读5个RS485里面的数据进而判断具体有几个sensor响应,然后判断小车的位置。
#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#define address_num 5 //挂载的从设备个数
#define getdata_num 2 //读取数据长度
#define car_length 4 //车的长度
#define sensor_length 2 //sensor 的间隔
HANDLE hCom;
WORD sensor[5]={0x03ff,0x03ff,0x03ff,0x03fff,0x03ff};
struct realmessage{ //最后获取的数据
BYTE address;
WORD data[getdata_num];
}value1[address_num -1];
struct sendmessage{ //发送的命令集包
BYTE data[8];
static const int length = 8;
};
struct getmessage{ //从设备返回的数值
BYTE data[5 + 2*getdata_num];
static const int length=5 + 2*getdata_num;
};
struct dataformat //命令包的数据格式
{
BYTE address[address_num];
BYTE type;
WORD start;
WORD length;
};
//读函数
int readfile(HANDLE hCom,BYTE *str,int count,DWORD *wCount)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ClearCommError(hCom,&dwErrorFlags,&ComStat);
BOOL bReadStatus;
bReadStatus=ReadFile(hCom,str,count,wCount,&m_osRead);
//printf("read status= %d\n",bReadStatus);
if(!bReadStatus) //如果ReadFile函数返回FALSE
{
if(GetLastError()==ERROR_IO_PENDING) //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osRead.hEvent,2000); //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return bReadStatus;
}
return 0;
}
PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return bReadStatus;
}
//写函数
int writefile(HANDLE hCom,BYTE *str,int count,DWORD *wCount)
{
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osWrite;
memset(&m_osWrite,0,sizeof(OVERLAPPED));
m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
ClearCommError(hCom,&dwErrorFlags,&ComStat);
BOOL bReadStatus;
//printf("address = %x type = %d start =%x readlength=%d\n",str[0], str[1], str[3], str[5]);
bReadStatus=WriteFile(hCom,str,count,wCount,&m_osWrite);
//printf("writefile status= %d\n",bReadStatus);
if(!bReadStatus) //如果ReadFile函数返回FALSE
{
if(GetLastError()==ERROR_IO_PENDING) //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osWrite.hEvent,2000); //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,m_osWrite的hEvent事件会变为有信号
PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return bReadStatus;
}
return 0;
}
PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return bReadStatus;
}
//获取校验码
void GetCRC(byte *message, byte *CRC,int length)
{
//Function expects a modbus message of any length as well as a 2 byte CRC array in which to
//return the CRC values:
WORD CRCFull = 0xFFFF;
byte CRCHigh = 0xFF, CRCLow = 0xFF;
char CRCLSB;
for (int i = 0; i < length - 2; i++)
{
CRCFull = (WORD)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
CRCLSB = (char)(CRCFull & 0x0001);
CRCFull = (WORD)((CRCFull >> 1) & 0x7FFF);
if (CRCLSB == 1)
CRCFull = (WORD)(CRCFull ^ 0xA001);
}
}
CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
}
//打包数据
void BuildMessage(BYTE address, BYTE type, WORD start, WORD registers, BYTE *message,int length)
{
//Array to receive CRC bytes:
printf("address = %x type = %d start =%x readlength=%d\n",address, type, start, registers);
BYTE CRC[1]={0};
message[0] = address;
message[1] = type;
message[2] = (BYTE)(start >> 8);
message[3] = (BYTE)start;
message[4] = (BYTE)(registers >> 8);
message[5] = (BYTE)registers;
GetCRC(message, CRC,length);
printf("CRC[0] =%x CRC[1] = %x size = %d\n",CRC[0] , CRC[1],length);
message[length - 2 ] = CRC[0];
message[length - 1] = CRC[1];
}
/*
void init(struct dataformat *data)
{
int i;
for(i=0 ; i<10;i++)
(*data).address[i]=i;
(*data).type = 3;
(*data).start =0x4001;
(*data).length=2;
}
*/
//对读数据进行crc校验
bool checkrespond(byte *response,int length)
{
//Perform a basic CRC check:
byte CRC[1] = {0};
GetCRC(response, CRC,length);
printf("CRC[0] =%x CRC[1] = %x\n",CRC[0] , CRC[1]);
if (CRC[0] == response[length- 2] && CRC[1] == response[length- 1])
return true;
else
return false;
}
bool function(HANDLE hCom,struct sendmessage *val,getmessage *respone,int id)
{
struct dataformat data;
struct sendmessage value =*val;
struct getmessage respond = *respone;
int i;
for(i=0 ; i<address_num;i++) //初始化写数据
{
data.address[i]=i+1 ;
}
data.type = 3;
data.start =0;
data.length=getdata_num;
DWORD wCount;//实际读取的字节数
BuildMessage(data.address[id-1],data.type,data.start,data.length,value.data,value.length);//打包数据
if(!writefile(hCom,value.data,value.length,&wCount)) //向从设备广播
{
printf("写串口失败\n");
return false;
}
if(!readfile(hCom,respond.data,respond.length,&wCount))//读取数据
{
printf("读串口失败!\n");
return false;
}
if(!checkrespond(respond.data,respond.length))
{
printf("读取数据错误\n");
for( i = 0;i<respond.length;i++)
printf(" responddata[%d]=%x ",i , respond.data[i]);
printf("\n");
return false;
}else
{
//Return requested register values:
printf("读取数据success\n");
value1[id-1].address = data.address[id-1];
for ( i = 0; i < (respond.length - 5) / 2; i++)
{
value1[id-1].data[i] = respond.data[2 * i + 3];
value1[id-1].data[i] <<= 8;
value1[id-1].data[i] += respond.data[2 * i + 4];
}
for( i = 0;i<respond.length;i++)
printf(" responddata[%d]=%x ",i , respond.data[i]);
}
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//清空缓存区
return true;
}
int main(int argc, _TCHAR* argv[])
{
COMMTIMEOUTS TimeOuts;
struct _DCB dcb;
bool status;
struct sendmessage value;
struct getmessage respond;
for(int i =0;i<value.length;i++)
value.data[i]=0;
for(int i =0;i<respond.length;i++)
respond.data[i]=0;
hCom = CreateFile(L"COM6", GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, NULL);
if(hCom ==INVALID_HANDLE_VALUE)
{
printf("打开COM失败!");
return FALSE;
// AfxMessageBox("打开COM失败!");
}
if(!GetCommState(hCom, &dcb))//获取串口信息
{
printf("获取串口信息失败");
return 0;
}
printf("ByteSize= 0x%2x buadrate = %d parity = %d stopbits = %d\n",dcb.ByteSize,dcb.BaudRate,dcb.Parity,dcb.StopBits);
SetCommMask(hCom, EV_RXCHAR); // 设定相应监视串口的接收到字符事件响应
if(!SetupComm(hCom,1024,1024)) //设置串口的输入/输出缓冲区大小
{
printf("设置串口读写缓冲区失败");
return 0;
}
TimeOuts.ReadIntervalTimeout=100; //读超时等待时间
TimeOuts.ReadTotalTimeoutMultiplier=5;
TimeOuts.ReadTotalTimeoutConstant=5;
TimeOuts.WriteTotalTimeoutConstant=2;
TimeOuts.WriteTotalTimeoutMultiplier=2;
//SetCommTimeouts(hCom,&TimeOuts);
if(!SetCommTimeouts(hCom,&TimeOuts)) //与串口绑定失败返回
{
printf("与串口绑定失败\n");
return 0;
}
dcb.BaudRate=115200; //波特率为9600
dcb.ByteSize=8; //每个字节有8位
dcb.Parity=EVENPARITY; //偶校验位
dcb.StopBits=ONESTOPBIT; //一个停止位
if(!SetCommState(hCom,&dcb))//设置串口信息
{
printf("设置串口失败\n");
return 0 ;
}
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//清空缓存区
printf("ByteSize= 0x%2x buadrate = %d parity = %d stopbits = %d\n",dcb.ByteSize,dcb.BaudRate,dcb.Parity,dcb.StopBits);
int id[address_num]={1,2,3,4,5},k=0;
static int distence[10];
for(int i =address_num-1 ;i>=0;i--)
{
status = function(hCom,&value,&respond, id[i]);
if( (status == 0) || ((value1[i].data[0])== 0))
{
printf("sensor id = %d read function fail \n",i+1);
value1[i].data[1] = 0;
}
printf("data1 = 0x%x data2 = 0x%x\n",value1[i].data[0],value1[i].data[1]);
WORD val1 = 0x8000;
int j=0;
for(int n =15 ;n >= 0;n--)
{
if(((sensor[i]&val1)>>n ) == 1)
{
if(((sensor[i]&val1) >>n) == ((value1[i].data[1]&val1) >> n) )
{
distence[k]=(id[i]-1)*20+20-j*sensor_length;//计算车头的位置
k++;//得出响应的sensor个数
}
j++; //判读sensor位置
}
val1 >>= 1;
}
}
if(k >=car_length/sensor_length)
{
for(int i =0;i<k;i++)
{
if(distence[i] - distence[i+1] <= 2*sensor_length)
{
distence[0]=distence[i];
break ;
}else
distence[0]=0;
}
}else if(k > 0)
distence[0]=0;
printf("distence = %d sensor_num=%d",distence[0],k);
}
- 基于module rtu 协议的串口读写程序
- c#处理基于Modbus协议的串口通讯程序
- 基于Modbus协议RTU模式的HITECH PWS6A00T触摸屏与PIC单片机的通信
- 最简单的串口读写程序
- 基于COMPAC协议的.NET框架实现的串口通信程序
- java 串口读写程序
- 串口读写程序
- 基于SMB协议的共享文件读写
- 基于SMB协议的共享文件读写
- 基于SMB协议的共享文件读写
- MODBUS ASCII协议和RTU协议的比较 -----和利时PLC采用Modbus RTU
- JAVA 编写的串口 读写 程序 以及乱码程序
- JAVA 编写的串口 读写 程序 以及乱码程序
- 编写基于FormView的SDI串口程序
- 基于android下测试串口的程序
- 基于android下测试串口的程序
- Windows下基于API的串口程序
- linux下基于QT的串口程序
- Makefile学习
- PHP笔试题20道
- 阿里云(unbuntu)安装redmine
- SEO中友情链接的解决方案
- iOS 纯代码适配iPhone6,6+
- 基于module rtu 协议的串口读写程序
- sql
- intersection set
- Java异常分类
- jquery $(document).ready() 与window.onload的区别
- 文章标题
- 我的linux 命令1
- SystemClock.sleep和Thread.sleep的区别
- 使用Uploadify插件在struts2中实现多文件上传示例