3

我已经构建了一个适配器DS9097E并将其连接到DS18B20数字温度计。在 Internet 上,您可以找到从该设备读取温度的 Delphi 和 C 应用程序示例。我正在尝试用 C# 编写它。一开始我依赖.NET,但它不起作用。我遇到了 RESET 和 PRESENCE PULSES 的问题,所以我尝试了 kernel32.dll。昨天我发现了这个库:OpenNETCF。不幸的是,没有它的文档。同时,我尝试编写自己的库:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Activities;
using Microsoft.Win32.SafeHandles;
using System.IO;
using System.Collections.Specialized;
using System.IO.Ports;

namespace COMAPI
{

public class COMutils
{

    private int hCOM = -1;
    private DCB dcb = new DCB();
    private COMMTIMEOUTS commtime = new COMMTIMEOUTS();
    private int bufferSize = 128;
    private byte[] ReceiveBytes;

    #region STALE

        private const int PURGE_TXABORT = 0x01;
        private const int PURGE_RXABORT = 0x02;
        private const int PURGE_TXCLEAR = 0x04;
        private const int PURGE_RXCLEAR = 0x08;
        private const int INVALID_HANDLE_VALUE = -1;
        private const uint GENERIC_READ = 0x80000000; 
        private const uint GENERIC_WRITE = 0x40000000;

    #endregion

    #region KERNEL32

        [DllImport("kernel32.dll")]
        static extern bool PurgeComm(int hFile, int dwFlags);

        [DllImport("kernel32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(int hObject);

        [DllImport("kernel32.dll")]
        static extern bool FlushFileBuffers(int hFile);

        [DllImport("kernel32.dll")]
        static extern bool TransmitCommChar(int hFile, char cChar);

        [DllImport("kernel32.dll")]
        static extern bool WriteFile(int hFile, byte [] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int lpOverlapped);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool ReadFile(int hFile, [Out] byte[] lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int lpOverlapped);

        [DllImport("kernel32.dll")]
        static extern bool GetCommState(int hFile, ref DCB lpDCB);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetCommTimeouts(int hFile, ref COMMTIMEOUTS lpCommTimeouts);

        [DllImport("kernel32.dll")]
        static extern bool SetCommState(int hFile, [In] ref DCB lpDCB);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern int CreateFile(
            string lpFileName,
            [MarshalAs(UnmanagedType.U4)] uint dwDesiredAccess,
            [MarshalAs(UnmanagedType.U4)] int dwShareMode,
            int lpSecurityAttributes,
            [MarshalAs(UnmanagedType.U4)] int dwCreationDisposition,
            [MarshalAs(UnmanagedType.U4)] int dwFlagsAndAttributes,
        int hTemplateFile);

        [DllImport("kernel32.dll")]
            static extern int GetTickCount();



    #endregion

    #region DCB

        [StructLayout(LayoutKind.Sequential)]

        internal struct DCB
        {
            internal uint DCBLength;
            internal uint BaudRate;
            private BitVector32 Flags;

            private ushort wReserved;        // not currently used 
            internal ushort XonLim;           // transmit XON threshold 
            internal ushort XoffLim;          // transmit XOFF threshold             

            internal byte ByteSize;
            internal Parity Parity;
            internal StopBits StopBits;

            internal sbyte XonChar;          // Tx and Rx XON character 
            internal sbyte XoffChar;         // Tx and Rx XOFF character 
            internal sbyte ErrorChar;        // error replacement character 
            internal sbyte EofChar;          // end of input character 
            internal sbyte EvtChar;          // received event character 
            private ushort wReserved1;       // reserved; do not use     

            private static readonly int fBinary;
            private static readonly int fParity;
            private static readonly int fOutxCtsFlow;
            private static readonly int fOutxDsrFlow;
            private static readonly BitVector32.Section fDtrControl;
            private static readonly int fDsrSensitivity;
            private static readonly int fTXContinueOnXoff;
            private static readonly int fOutX;
            private static readonly int fInX;
            private static readonly int fErrorChar;
            private static readonly int fNull;
            private static readonly BitVector32.Section fRtsControl;
            private static readonly int fAbortOnError;


            static DCB()
            {
                // Create Boolean Mask
                int previousMask;
                fBinary = BitVector32.CreateMask();
                fParity = BitVector32.CreateMask(fBinary);
                fOutxCtsFlow = BitVector32.CreateMask(fParity);
                fOutxDsrFlow = BitVector32.CreateMask(fOutxCtsFlow);
                previousMask = BitVector32.CreateMask(fOutxDsrFlow);
                previousMask = BitVector32.CreateMask(previousMask);
                fDsrSensitivity = BitVector32.CreateMask(previousMask);
                fTXContinueOnXoff = BitVector32.CreateMask(fDsrSensitivity);
                fOutX = BitVector32.CreateMask(fTXContinueOnXoff);
                fInX = BitVector32.CreateMask(fOutX);
                fErrorChar = BitVector32.CreateMask(fInX);
                fNull = BitVector32.CreateMask(fErrorChar);
                previousMask = BitVector32.CreateMask(fNull);
                previousMask = BitVector32.CreateMask(previousMask);
                fAbortOnError = BitVector32.CreateMask(previousMask);
            }
        }

    #endregion

    #region COMMTIMEOUTS

        struct COMMTIMEOUTS
        {
            public UInt32 ReadIntervalTimeout;
            public UInt32 ReadTotalTimeoutMultiplier;
            public UInt32 ReadTotalTimeoutConstant;
            public UInt32 WriteTotalTimeoutMultiplier;
            public UInt32 WriteTotalTimeoutConstant;
        }

    #endregion

    #region METODY

        public bool openCOM(int numer)
        {

            hCOM = CreateFile("COM" + numer,   GENERIC_READ | GENERIC_WRITE, 0, 0, 3, 0, 0);
            if (hCOM == INVALID_HANDLE_VALUE) 
               return false;
            if (!GetCommState(hCOM, ref dcb))
               return false;
            if (!GetCommTimeouts(hCOM, ref commtime))
                return false;
            return true;

        }

        public bool closeCOM()
        {
            return CloseHandle(hCOM);
        }

        public bool setCOM(int baud, byte bsize, Parity par, StopBits sbits)
        {
            dcb.BaudRate = (uint)baud;
            dcb.ByteSize = bsize;
            dcb.Parity = par;
            dcb.StopBits = sbits;
            return SetCommState(hCOM, ref dcb);

        }

        public bool cleanCOM()
        {
            return PurgeComm(hCOM, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        }

        public bool flushCOM()
        {
            return FlushFileBuffers(hCOM);
        }

        public bool TxByteCOM(byte dane)
        {
            return TransmitCommChar(hCOM, (char)dane);
        }

        public bool TxDataCOM(byte[] daneW)
        {
            int byteZap = 0;
            return WriteFile(hCOM, daneW, daneW.Length, ref byteZap, 0);
        }

        public byte[] RxDataCOM(byte[] odebraneBytes, int ilosc, int odczytane)
        {
            if(ilosc == 0)
                ilosc = bufferSize;

            if(hCOM != INVALID_HANDLE_VALUE)
            {
                odczytane = 0;
                bool stanOdczytu = true;
                odebraneBytes = new byte[ilosc];
                stanOdczytu = ReadFile (hCOM, odebraneBytes, ilosc, ref odczytane, 0);

                if(stanOdczytu == false)
                {
                    throw new ApplicationException("Błąd odczytu");
                }
                else
                {
                    return odebraneBytes;
                }
            }
            else
            {
                throw new ApplicationException ("Port nie został otwarty");
            }
        }

        public int returnTime()
        {
            return GetTickCount();
        }

        private bool IsOdd(int value)
        {
            return value % 2 != 0;
        }

        public int sendByte(int X)
        {
            int D = 0; 
            int czas, temp;
            byte[] B = new byte[1];

            temp = X;
            setCOM(115200, 8, Parity.None, StopBits.One);
            cleanCOM();
            czas = returnTime() + 50;

            for (int n = 1; n <= 8; n++)
            {
                if (IsOdd(temp)) TxByteCOM(0xFF);
                else TxByteCOM(0x00);

                temp = temp << 1;
                do
                {

                    RxDataCOM(B, 1, D);

                } while ((D > 1) | (czas < returnTime()));

                if (D != 1) break;
                if (IsOdd(B[0])) temp = (temp | 0x80);
                }
            return temp;
        }

        public bool sendCOM(byte[] WrByt)
        {
            int BytesWritten = 0;
            bool writeState = false;

            if (hCOM != INVALID_HANDLE_VALUE)
            {
                PurgeComm(hCOM, PURGE_RXCLEAR | PURGE_TXCLEAR);

                writeState = WriteFile(hCOM, WrByt, WrByt.Length, ref BytesWritten, 0);

                if (writeState == false)
                {
                    throw new ApplicationException("Błąd zapisu do portu ");
                }
            }
            else
            {
                throw new ApplicationException("Port nie został otwarty");
            }
            return writeState;
        }

        public byte[] receiveCOM (int NumBytes)
        {
            if(NumBytes == 0)
                NumBytes = bufferSize;

            if (hCOM != INVALID_HANDLE_VALUE)
            {
                int BytesRead = 0;
                bool readState = true;
                ReceiveBytes = new byte[NumBytes];
                readState = ReadFile(hCOM, ReceiveBytes, NumBytes, ref BytesRead, 0);

                if (readState == false)
                {
                    throw new ApplicationException("Błąd odczytu");
                }
                else
                {
                    return ReceiveBytes;
                }
            }
            else
            {
                throw new ApplicationException("Port nie został otwarty");
            }
        }

        public bool resetCOM()
        {
            int czasOd;
            int D = 0;
            byte[] baju = new byte[1];
            byte[] lista = new byte[1];

            setCOM(9600, 8, Parity.None, StopBits.One);
            cleanCOM();
            lista[0] = 0xF0;
            sendCOM(lista);
            czasOd = returnTime() + 50;

            do
            {
                RxDataCOM(baju, 1, D);
            }
            while ((D == 1) | czasOd < returnTime());
            if (D == 1)
             return (baju[0] != 0xF0);
            return true;
        }

    #endregion

}

}

这是我的应用程序的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using COMAPI;

namespace temp_3
{
class Program
{
    static private COMutils util = new COMutils();


    static void Main(string[] args)
    {
        int TH,TL;
        int TEMP_READ;
        double TEMP;
        util.openCOM(1);
        byte[] lista = new byte[1];
        bool czy = util.resetCOM();
        lista[0] = 0xCC;
        czy = util.sendCOM(lista);
        lista[0] = 0x44;
        czy = util.sendCOM(lista);
        Thread.Sleep(750);
        czy = util.resetCOM();
        lista[0] = 0xCC;
        czy = util.sendCOM(lista);
        lista[0] = 0xBE;
        czy = util.sendCOM(lista);

        TL = util.sendByte(0xFF);
        Console.WriteLine(TL);
        TH = util.sendByte(0xFF);
        Console.WriteLine(TH);

        czy = util.resetCOM();
        Console.WriteLine(czy);

        TEMP_READ = TL + 256 * TH;
        TEMP = TEMP_READ / 16.0;
        Console.WriteLine(TEMP);
        Console.WriteLine(czy);

        Console.ReadKey();
    }
}

}

不幸的是,根据这段代码,它读取的温度超过了 8000 摄氏度。有人能指出错误在哪里吗?任何提示将不胜感激。下面是用 Delphi 编写的函数:

  function Reset_COM:boolean;
  var B:Byte;
  D,time:DWord;
  begin
  Result := False;
  //ustawienie portu RS232
  Ustaw_COM(9600,8,NOPARITY,ONESTOPBIT);
 //czyszczenie RS232
  Result := Czysc_COM;
  TransmitCommChar(hCom,Chr($F0));
  time:=GetTickCount+50;
  repeat
    ReadFile(hCom,B,1,D,nil)
    until (D=1) or (time<GetTickCount);
  if D=1 then
  Result:=(B<>$F0);
  end;

  function send_Bajt(X:Byte):Byte;
     var
     n:Integer;
     B:Byte;
     D,time:DWord;
  begin
     Result:=$FF;
     Ustaw_Com(115200,8,NOPARITY,ONESTOPBIT);
     Czysc_COM;
     time:=GetTickCount+50;
     for n:=1 to 8 do
     begin
     if Odd(X) then TransmitCommChar(hCom,Chr($FF)) else TransmitCommChar(hCom,Chr($00));
      X:=X shr 1;
      repeat ReadFile(hCom,B,1,D,nil)
      until (D=1) or (time<GetTickCount);
      if D<>1 then exit;
      if Odd(B) then X:=X or $80;
      if Odd(B xor CRC)
      then CRC:=((CRC xor $18) shr 1) or $80
      else CRC:=CRC shr 1;
      end;
      Result:=X;
      end;

     function Odczytaj_TEMP:real;
       var TH,TL:Byte;
       TEMP_READ: Smallint;
       Temp: double;

       begin
        Resetuj_COM;
        send_Bajt($CC); //Skip ROM
        send_Bajt($44); //Start T Convert
        Sleep(750);

        Resetuj_COM;
        send_Bajt($CC); //Skip ROM
        send_Bajt($BE); //Read Scratchpad

        TL:=send_Bajt($FF);
        TH:=send_Bajt($FF);

        Resetuj_COM;

        TEMP_READ := TL + 256 * TH;
        Temp := TEMP_READ / 16.0;
         Result := Temp;
        end;
4

0 回答 0