基于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);
    }




         

0 0
原创粉丝点击