Beruflich Dokumente
Kultur Dokumente
Interface
Many consumers use digital thermometers every day and due to their usefulness they
have become cheap and readily available. Most users only need to know if they have a
temperature or are running a fever and so a one time use and read system is preferable. In this
case outputting the result to an LCD is easier and gives the user immediate results. However,
what if the user wants to keep track of their results digitally? In a situation such as this you
would want to be able to store temperatures in a file on a computer. This presents a problem
as most digital thermometers available today are meant for independent use. That is, they are
not designed to transmit their data anywhere outside the device itself.
4 10uF capacitor
2 1 kohm resistor
1 10 kohm resistor
1 1.5 kohm resistor
1 22 ohm resistor
1 27 ohm resistor
2 Digital Thermometers with 100K ohm Thermistors
For Informationon our PIC18F4520, MAX232, and LM324 chips please see the links
in the sources section of this document.
Understanding how a Digital thermometer works will allow us to think about how we
wish to implement one in terms of components. A useful resource for this can be found via a
lab from the UCL department of Physics and Astronomy in the United Kingdom (found here
http://www.cmmp.ucl.ac.uk/~nts/teachinglabs/3c40-e5.pdf) .
We know that a thermistor will allow us to measure a resistance value that can correspond to a
temperature after some testing and formula extraction. We also know that to transmit data
over serial we are going to need the MAX232 line driver/receiver and a digital signal to
transmit. This digital signal will be the temperature value we wish to be read by our computer
program. However, we need some way to change the resistance value into a voltage signal to
be changed into a transmittable digital signal. From the document I linked to above we find
the following flow chart which gives us a clue as to how to proceed.
Figure 1: Logical flow for a traditional “Off the Shelf” Thermometer (from lab 3C40-e5)
As the image above shows, we can utilize an op-amp to generate a voltage signal. We
will change the signal through use of the thermistor. We can use the resistance value of the
thermistor to change the gain equation for the output of our operational amplifier. With our
analog voltage signal we can pass through an ADC, converting our value into a binary output.
Normally, a commercial unit would then convert that binary voltage value into a binary
temperature value using conversion hardware, then that value would be output to a LCD
display. However, we will only be using the first three units in Figure one, as we wish only to
send that digital voltage signal over RS232. This has the added benefit of reducing the amount
of hardware that we need since we can convert the ADC output to a temperature within our
GUI program itself.
For now we are concerned with what will be done once we have an analog signal. As
figure 1 demonstrates, this value will be converted into a digital signal and we need to get that
value over to our GUI.. To do this we will use our PIC and our MAX232 chips. The
advantage to the PIC18F4520 is that it has a built in 10-bit ADC and can make use of
software handshaking to transmit and receive serial signals with the help of the MAX232. For
a good tutorial on how to construct this part of the circuit we can use a pair of ECE480 labs
from Michigan State University available at
http://www.egr.msu.edu/classes/ece480/goodman/ForMiniprojects/Lab4.pdf and
http://www.egr.msu.edu/classes/ece480/goodman/ForMiniprojects/Lab3.pdf. These lab
explain how to construct a few PIC based circuits including a circuit capable of transmitting a
converted analog voltage signal to a GUI. From these two labs I have designed a circuit
schematic for the circuit that we will need to use. Please see the schematic below and
construct it on a proto-board.
Figure 3: Thermometer Schematic (See Appendix A for full-sized schematic Pg. 14)
Section B: Programming your PIC Microprocessor
Now that we have built our circuit we are ready to program the PIC microcontroller to
handle our data and output the correct digital voltage value to our MAX232 Chip. Below is
the code from the .c file we will be using to program the PIC. We will use MPLAB to
program our PIC along with a Microchip MPLAB ICD 2 PIC programmer. (More
information can be found on this product here
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDoc
Name=en010046)
For instruction on programming you PIC please use the MSU LAB 3 pdf file, linked
to here http://www.egr.msu.edu/classes/ece480/goodman/ForMiniprojects/Lab3.pdf.
information on programming the PIC18F4520 can be found in the first section. Please use the
code below. (Simply copy and paste)
#include <p18cxxx.h>
#include <usart.h>
#include <ADC.h>
#pragma config LVP=OFF
#pragma config WDT=OFF
void rx_handler (void); //Declare the ISR function
unsigned char data;
char data2[6] = {'S', 'c', 'h', 'e', 'e', 'l'};
long int count;
int dloop, dloop2, altflash, adc_result;
void main()
{
OpenUSART (USART_TX_INT_OFF & USART_RX_INT_ON &
USART_ASYNCH_MODE & USART_EIGHT_BIT &
USART_CONT_RX & USART_BRGH_LOW, 63);
RCONbits.IPEN = 1; /* Enable interrupt priority */
IPR1bits.RCIP = 1; /* Make receive interrupt high priority */
INTCONbits.GIEH = 1; /* Enable all high priority interrupts */
OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD,
ADC_CH0 & ADC_INT_OFF, 0); //open adc port for reading
SetChanADC(ADC_CH1); //Set ADC to Pin 3
ADCON1 =0x00; //set VREF+ to VDD and VREF- to GND (VSS)
TRISD = 0x04;
PORTDbits.RD0 = 0;
PORTDbits.RD3 = 0;
PORTDbits.RD1 = 0;
altflash = 1;
dloop = 0;
dloop2 = 0;
while(1)
{
}
}
//Lets the compiler know the location of the ISR
#pragma code rx_interrupt = 0x8
void rx_int (void)
{
_asm goto rx_handler _endasm
}
#pragma code
//Lets the compiler know that this function is the ISR
#pragma interrupt rx_handler
void rx_handler (void)
{
unsigned char c;
altflash = !altflash;
c = getcUSART(); //get a single character off the USART line
while(BusyUSART());
if (c == 'e')
{
ConvertADC(); //perform ADC conversion
while(BusyADC()); //wait for result
adc_result = ReadADC(); //get ADC result
data = adc_result >> 2;
putcUSART (data); //put a single character on the USART line
}
PIR1bits.RCIF = 0; //reset the ISR flag.
}
After you have entered the code and built the project please program your PIC and
make sure it runs. If you have errors please go back and repeat the steps listed in ECE 480
Lab 3. Your MPLAB screen should look like the one below.
To view the the data on our computer we will need to design a simple graphical user
interface for a user to manipulate. For simplicity we will be using Visual Basic.NET, however
you can use which ever programming language you wish. You will however need a class of
some sort to handle communications over RS232. A Sample class for visual basic can be
found in Appendix C. The code for our form can found below and should be added to a form
called Form1.vb. This form should appear under your solution explorer pane in Visual
Studio.NET as seen in figure 5 below. Note that CRs232.vb is our RS232 driver located in
Appendix B (Pg. 15) of this tutorial.
If you need additional guidance please consult MSU Lab 4 found here
http://www.egr.msu.edu/classes/ece480/goodman/ForMiniprojects/Lab4.pdf. Please also use
the help function within Visual Studio to answer questions on how to create a new VB
project.
After you have your file structure setup please proceed to add the following code to your
Form1.vb file to create a GUI we can use.
Public Class Form1
Inherits System.Windows.Forms.Form
Dim setRs232 As New Rs232
Dim serial_in As String
Dim x As Integer
Dim sf As String
Dim sr As String
Dim sleepf As Integer
Dim sample As Integer
Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal
dwMilliseconds As Long)
End Sub
End Sub
#End Region
End Sub
Please compile your code and make sure that your GUI runs correctly. The program,
as it currently runs, will generate a voltage value passed from the MCU instead of a
temperature value. We do this so that we can calibrate our thermistor and find the relationship
between voltage and temperature. We will change the code after we are done calibrating our
thermistor in the following section.
Section D: Calibrating Your Thermistor
After you have built your circuit you are ready to find the formula necessary for
converting your voltage value into a temperature value. This part of the process is quite
simple and straight forward. The simplest way to find your relationship is through testing.
You will need the following items to run your test.
Equipment:
1 - Cup filled with ice
1- Cup filled with hot water
1- Thermometer or temperature probe
1 - 5V power supply
Your finished and operational circuit
To measure the relationship between voltage and temperature follow the following steps.
temperature
in F vdc
104.4 4.12
97.3 3.9025
97.4 3.9028
96.1 3.8955
95 3.8886
92.9 3.88
91.1 3.8753
91.5 3.55
96.5 3.8907
97 3.8947
97.7 3.897
98.2 3.8985
97.8 3.992
97.9 3.8963
Figure 6: Example Table of recorded Data
*Note: This data will vary from experiment to experiment depending on what resistance value
your thermistor operates at and the temperature of the water you are using/time between
measurements.
With this data you can graph the relationship and find a curve using the tools within
the given program. For more information on graphing in MS Excel please use the following
link(http://chemed.chem.purdue.edu/genchem/lab/datareports/excel/plotting.html) After the
data has been plotted goto chart->add trend line and select exponential. This should give you
a formula for the best fit line of your data.
4.2
4.1
y = 3.125e0.0045x
4
)Voltage )VDC
3.9
Series1
Expon. (Series1)
3.8
3.7
3.6
3.5
Temperature in degrees
Fahrenheit
From figure 7 we can see that our general formula is y = 3.125.0045x with y equaling the
voltage and x equaling the temperature in degrees Fahrenheit. From this we can derive the
following equation to determine the temperature based on a given voltage value in decimal
form (which is what we get in from our circuit). The resulting equation is
Temperature = ln(voltage/3.125)/-0.0045. Lucky for us the natural log function can be used
in Visual Basic. Net with the command Math.Log(). Your GUI code should be modified to
display your new temperature result. By changing the following lines of code in Form1.vb.
Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button7.Click
setRs232.Write("e")
setRs232.Read(1)
serial_in = setRs232.InputStreamString
x = AscW(CChar(serial_in))
TextBox1.Text = x * 0.0156'modify adc_result to reflect voltage
interms of vref
End Sub
Now that we have calibrated our thermistor and made the correct changes to the code
in our GUI we are ready to hook everything up and run our circuit.
Steps
Congratulations! Your Screen should look like the one shown in figure 8 below.
Conclusion:
Through this note we have designed and built a digital thermometer that can be used
with a windows computer. The applications for such a device are wide ranging including, but
not limited to, medical thermometers and temperature sensors for a detection system. We have
designed this thermometer to be accurate to within 0.1 degree F, which should work for even
medical applications. Your results will vary depending on the resistance value of your
thermistor and the sensitivity/tolerance of the thermistor itself. This may vary from
commercial product to commercial product. Other possible changes to this device include
programming the GUI in a language such as Qt for cross platform support, however this will
require a RS232 support class. Such classes can be found on the Internet, an example of one
such class can be found at http://qextserialport.sourceforge.net/. One might also use an API to
save the recorded data to a database file for future reference and comparison. This can also be
accomplished in Qt. This product is meant as a starting point for work with digital
thermometers and hopefully you have gained some insight into how such products function.
Appendix A: Circuit Schematic
•
Appendix B: Serial Driver Code
This code has been extracted from the files accompanying Michigan State University
ECE 480 Lab 4. Please see above links or the links in the reference Section (Pg.40) of
this note.
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Threading
Imports System.ComponentModel
Imports System.IO
#Region "RS232"
Public Class Rs232 : Implements IDisposable
'===================================================
'
' Module : Rs232
' Description : Class for handling RS232 comunication with
VB.Net
' Created : 10/08/2001 - 8:45:25
' Author : Corrado Cavalli
(corrado@mvps.org)
'WebSite : www.codeworks.it/net/index.htm
'
' Notes :
'-----------------------------------------------------------------------
------------------------
'
* Revisions *
'
' 02/12/2000 First internal alpha version built on
framework beta1
'
' 1st Public release Beta2 (10/08/2001)
'
' Rev.1 (28.02.2002)
' 1. Added ResetDev, SetBreak and ClearBreak to the
EscapeCommFunction constants
' 2. Added the overloaded Open routine.
' 3. Added the modem status routines, properties and enum.
' 4. If a read times out, it now returns a EndOfStreamException
(instead of a simple Exception).
' 5.Compiled with VS.Net final
'===================================================
'// Class Members
Private mhRS As IntPtr = New IntPtr(0) '// Handle to Com Port
#Region "Enums"
'// Parity Data
Public Enum DataParity
Parity_None = 0
Parity_Odd
Parity_Even
Parity_Mark
End Enum
'// StopBit Data
Public Enum DataStopBit
StopBit_1 = 1
StopBit_2
End Enum
<Flags()> Public Enum PurgeBuffers
RXAbort = &H2
RXClear = &H8
TxAbort = &H1
TxClear = &H4
End Enum
Private Enum Lines
SetRts = 3
ClearRts = 4
SetDtr = 5
ClearDtr = 6
ResetDev = 7 ' // Reset device if possible
SetBreak = 8 ' // Set the device break line.
ClearBreak = 9 ' // Clear the device break line.
End Enum
'// Modem Status
<Flags()> Public Enum ModemStatusBits
ClearToSendOn = &H10
DataSetReadyOn = &H20
RingIndicatorOn = &H40
CarrierDetect = &H80
End Enum
'// Working mode
Public Enum Mode
NonOverlapped
Overlapped
End Enum
'// Comm Masks
<Flags()> Public Enum EventMasks
RxChar = &H1
RXFlag = &H2
TxBufferEmpty = &H4
ClearToSend = &H8
DataSetReady = &H10
CarrierDetect = &H20
Break = &H40
StatusError = &H80
Ring = &H100
End Enum
#End Region
#Region "Structures"
<StructLayout(LayoutKind.Sequential, Pack:=1)> Private Structure DCB
Public DCBlength As Int32
Public BaudRate As Int32
Public Bits1 As Int32
Public wReserved As Int16
Public XonLim As Int16
Public XoffLim As Int16
Public ByteSize As Byte
Public Parity As Byte
Public StopBits As Byte
Public XonChar As Char
Public XoffChar As Char
Public ErrorChar As Char
Public EofChar As Char
Public EvtChar As Char
Public wReserved2 As Int16
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=1)> Private Structure
COMMTIMEOUTS
Public ReadIntervalTimeout As Int32
Public ReadTotalTimeoutMultiplier As Int32
Public ReadTotalTimeoutConstant As Int32
Public WriteTotalTimeoutMultiplier As Int32
Public WriteTotalTimeoutConstant As Int32
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=8)> Private Structure
COMMCONFIG
Public dwSize As Int32
Public wVersion As Int16
Public wReserved As Int16
Public dcbx As DCB
Public dwProviderSubType As Int32
Public dwProviderOffset As Int32
Public dwProviderSize As Int32
Public wcProviderData As Int16
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=1)> Public Structure
OVERLAPPED
Public Internal As Int32
Public InternalHigh As Int32
Public Offset As Int32
Public OffsetHigh As Int32
Public hEvent As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=1)> Private Structure
COMSTAT
Dim fBitFields As Int32
Dim cbInQue As Int32
Dim cbOutQue As Int32
End Structure
#End Region
#Region "Constants"
Private Const PURGE_RXABORT As Integer = &H2
Private Const PURGE_RXCLEAR As Integer = &H8
Private Const PURGE_TXABORT As Integer = &H1
Private Const PURGE_TXCLEAR As Integer = &H4
Private Const GENERIC_READ As Integer = &H80000000
Private Const GENERIC_WRITE As Integer = &H40000000
Private Const OPEN_EXISTING As Integer = 3
Private Const INVALID_HANDLE_VALUE As Integer = -1
Private Const IO_BUFFER_SIZE As Integer = 1024
Private Const FILE_FLAG_OVERLAPPED As Int32 = &H40000000
Private Const ERROR_IO_PENDING As Int32 = 997
Private Const WAIT_OBJECT_0 As Int32 = 0
Private Const ERROR_IO_INCOMPLETE As Int32 = 996
Private Const WAIT_TIMEOUT As Int32 = &H102&
Private Const INFINITE As Int32 = &HFFFFFFFF
#End Region
#Region "Win32API"
'// Win32 API
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetCommState(ByVal hCommDev As IntPtr, ByRef lpDCB As DCB) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
GetCommState(ByVal hCommDev As IntPtr, ByRef lpDCB As DCB) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function BuildCommDCB(ByVal lpDef As String, ByRef lpDCB As
DCB) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetupComm(ByVal hFile As IntPtr, ByVal dwInQueue As Int32, ByVal dwOutQueue
As Int32) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetCommTimeouts(ByVal hFile As IntPtr, ByRef lpCommTimeouts As
COMMTIMEOUTS) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
GetCommTimeouts(ByVal hFile As IntPtr, ByRef lpCommTimeouts As
COMMTIMEOUTS) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
ClearCommError(ByVal hFile As IntPtr, ByRef lpErrors As Int32, ByRef
lpComStat As COMSTAT) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
PurgeComm(ByVal hFile As IntPtr, ByVal dwFlags As Int32) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
EscapeCommFunction(ByVal hFile As IntPtr, ByVal ifunc As Int32) As Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
WaitCommEvent(ByVal hFile As IntPtr, ByRef Mask As EventMasks, ByRef
lpOverlap As OVERLAPPED) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
WriteFile(ByVal hFile As IntPtr, ByVal Buffer As Byte(), ByVal
nNumberOfBytesToWrite As Integer, ByRef lpNumberOfBytesWritten As Integer,
ByRef lpOverlapped As OVERLAPPED) As Integer
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
ReadFile(ByVal hFile As IntPtr, <Out()> ByVal Buffer As Byte(), ByVal
nNumberOfBytesToRead As Integer, ByRef lpNumberOfBytesRead As Integer,
ByRef lpOverlapped As OVERLAPPED) As Integer
End Function
<DllImport("kernel32.dll", SetlastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function CreateFile(ByVal lpFileName As String, ByVal
dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal
lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer,
ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As Integer) As
IntPtr
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
CloseHandle(ByVal hObject As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Public Shared Function
GetCommModemStatus(ByVal hFile As IntPtr, ByRef lpModemStatus As Int32) As
Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetEvent(ByVal hEvent As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function CreateEvent(ByVal lpEventAttributes As IntPtr,
ByVal bManualReset As Int32, ByVal bInitialState As Int32, ByVal lpName As
String) As IntPtr
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
WaitForSingleObject(ByVal hHandle As IntPtr, ByVal dwMilliseconds As Int32)
As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
GetOverlappedResult(ByVal hFile As IntPtr, ByRef lpOverlapped As
OVERLAPPED, ByRef lpNumberOfBytesTransferred As Int32, ByVal bWait As
Int32) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetCommMask(ByVal hFile As IntPtr, ByVal lpEvtMask As Int32) As Int32
End Function
<DllImport("kernel32.dll", SetlastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function GetDefaultCommConfig(ByVal lpszName As String,
ByRef lpCC As COMMCONFIG, ByRef lpdwSize As Integer) As Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
SetCommBreak(ByVal hFile As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetlastError:=True)> Private Shared Function
ClearCommBreak(ByVal hFile As IntPtr) As Boolean
End Function
#End Region
#Region "Events"
Public Event CommEvent As CommEventHandler
#End Region
#Region "Delegates"
Public Delegate Sub CommEventHandler(ByVal source As Rs232, ByVal
Mask As EventMasks)
#End Region
End Sub
Public ReadOnly Property InBufferCount() As Int32
'===================================================
'
©2003 www.codeworks.it All rights reserved
'
' Description : Returns the number of bytes inside Rx buffer
' Created : 20/04/05 - 10:02:57
' Author : Corrado Cavalli/Jean-Pierre
ZANIER
'
'
'===================================================
Get
Dim comStat As COMSTAT
Dim lpErrCode As Int32
Dim iRc As Int32
comStat.cbInQue = 0
If mhRS.ToInt32 > 0 Then
iRc = ClearCommError(mhRS, lpErrCode, comStat)
Return comStat.cbInQue
End If
Return 0
End Get
End Property
#Region "Finalize"
Protected Overrides Sub Finalize()
'===================================================
'
' Description : Closes COM port if object is garbage
collected and still owns
' COM port reosurces
'
' Created : 27/05/2002 - 19:05:56
'
' *Parameters Info*
'
' Notes :
'===================================================
Try
If Not mbDisposed Then
If mbEnableEvents Then Me.DisableEvents()
Close()
End If
Finally
MyBase.Finalize()
End Try
End Sub
#End Region
End Sub
Private Sub pEventsWatcher()
'===================================================
'
©2003 www.codeworks.it All rights reserved
'
' Description : Watches for all events raising events when
they arrive to the port
' Created : 15/07/03 - 11:45:13
' Author : Corrado Cavalli
'
' *Parameters Info*
'
' Notes :
'===================================================
'// Events to watch
Dim lMask As EventMasks = EventMasks.Break Or
EventMasks.CarrierDetect Or EventMasks.ClearToSend Or _
EventMasks.DataSetReady Or EventMasks.Ring Or EventMasks.RxChar Or
EventMasks.RXFlag Or _
EventMasks.StatusError
Dim lRetMask As EventMasks, iBytesRead, iTotBytes, iErrMask As
Int32, iRc As Int32, aBuf As New ArrayList
Dim uComStat As COMSTAT
'-----------------------------------
'// Creates Event
muOvlE = New Overlapped
Dim hOvlE As GCHandle = GCHandle.Alloc(muOvlE, GCHandleType.Pinned)
muOvlE.hEvent = CreateEvent(Nothing, 1, 0, Nothing)
If muOvlE.hEvent.ToInt32 = 0 Then Throw New
ApplicationException("Error creating event for overlapped reading")
'// Set mask
SetCommMask(mhRS, lMask)
'// Looks for RxChar
While mbEnableEvents = True
WaitCommEvent(mhRS, lMask, muOvlE)
Select Case WaitForSingleObject(muOvlE.hEvent, INFINITE)
Case WAIT_OBJECT_0
'// Event (or abort) detected
If mbEnableEvents = False Then Exit While
If (lMask And EventMasks.RxChar) > 0 Then
'// Read incoming data
ClearCommError(mhRS, iErrMask, uComStat)
If iErrMask = 0 Then
Dim ovl As New Overlapped
Dim hOvl As GCHandle = GCHandle.Alloc(ovl,
GCHandleType.Pinned)
ReDim mabtRxBuf(uComStat.cbInQue - 1)
If ReadFile(mhRS, mabtRxBuf, uComStat.cbInQue,
iBytesRead, ovl) > 0 Then
If iBytesRead > 0 Then
'// Some bytes read, fills temporary
buffer
If iTotBytes < miBufThreshold Then
aBuf.AddRange(mabtRxBuf)
iTotBytes += iBytesRead
End If
'// Threshold reached?, raises event
If iTotBytes >= miBufThreshold Then
'//Copies temp buffer into Rx
buffer
ReDim mabtRxBuf(iTotBytes - 1)
aBuf.CopyTo(mabtRxBuf)
'// Raises event
Try
Me.OnCommEventReceived(Me,
lMask)
Finally
iTotBytes = 0
aBuf.Clear()
End Try
End If
End If
End If
If (hOvl.IsAllocated) Then hOvl.Free()
End If
Else
'// Simply raises OnCommEventHandler event
Me.OnCommEventReceived(Me, lMask)
End If
Case Else
Dim sErr As String = New Win32Exception().Message
Throw New ApplicationException(sErr)
End Select
End While
'// Release Event Handle
CloseHandle(muOvlE.hEvent)
muOvlE.hEvent = IntPtr.Zero
If (hOvlE.IsAllocated) Then hOvlE.Free()
muOvlE = Nothing
End Sub
#End Region
End Class
#End Region
#Region "Exceptions"
Public Class CIOChannelException : Inherits ApplicationException
'===================================================
'
' Module : CChannellException
' Description: Customized Channell Exception
' Created : 17/10/2001 - 10:32:37
'
' Notes : This exception is
raised when NACK error found
'===================================================
Sub New(ByVal Message As String)
MyBase.New(Message)
End Sub
Sub New(ByVal Message As String, ByVal InnerException As Exception)
MyBase.New(Message, InnerException)
End Sub
End Class
Public Class IOTimeoutException : Inherits CIOChannelException
'===================================================
'
' Description : Timeout customized exception
' Created : 28/02/2002 - 10:43:43
'
' *Parameters Info*
'
' Notes :
'===================================================
Sub New(ByVal Message As String)
MyBase.New(Message)
End Sub
Sub New(ByVal Message As String, ByVal InnerException As Exception)
MyBase.New(Message, InnerException)
End Sub
End Class
#End Region
Sources: