3

I have built an adapter DS9097E and connected to it DS18B20 digital thermometer. On the internet you can find examples of applications in Delphi and C that reads the temperature from this device. I'm trying to write it in C#. At the beginning I was relying on .NET but it didn't work. I had problems with RESET AND PRESENCE PULSES, so I tried with kernel32.dll. Yesterday I found this library: OpenNETCF. Unfortunately there is no documentation for it. In the meantime, I tried to write my own library:

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

}

}

This is code of my application:

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();
    }
}

}

Unfortunately, based on this code, it reads the temperature of over 8000 degrees Celsius. Could someone point out where is the mistake? Any hint will be appreciated. Here are functions wrote in 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;
szakal
  • 31
  • 1
  • 5

0 Answers0