Thông báo

Collapse
No announcement yet.

Serial Port - lập trình giao tiếp nối tiếp

Collapse
This topic is closed.
X
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #16
    Sorry, đánh máy nhầm cái R và S: nó đây này
    Private Sub Setup_Com()
    On Error Resume Next
    MSComm1.CommPort = COMPORT
    If MSComm1.PortOpen = True Then
    MSComm1.PortOpen = False
    End If
    MSComm1.RThreshold = MAX_LEN
    MSComm1.PortOpen = True
    End Sub

    Bác cứ xoáy sâu vào cái đó của em.. hehe..
    Vấn đề trễ 1ms trong WIN ko như bạn nói đâu, với VDK thì đơn giản, chứ với VB trên PC thì cực khó. Ko tin bạn thử xem. Windows chứ ko phải MCU. Ý em muốn nói là ko phải là tốc độ của bus hay bộ đệm mà là tốc độ xử lý thời gian thực của PC.

    Ko phải em ko đọc bài của bác, mà cái về giao tiếp qua cổng COM này em làm từ năm thứ 3 nên thấy bài hướng dẫn của bác rất có ích với mọi.
    Việc đặt:
    MSComm1.RThreshold = 1
    Nếu truyền tốc độ cao thì PC liên tục nhảy vào hàm phục vụ ngắt, và thậm chí nếu đọc theo ngắt thì có khi ko chỉ một byte mà là >1 byte. Bạn nào thử đọc tốc độ >=115.200 kbps thì biết ngay. Vì khi báo ngắt thì rất có thể trong bộ đệm đã >1 byte rồi:
    tmp=MScomm1.input thi nó đọc sạch sành sanh trong bộ đệm nhận chứ ko phải đọc chỉ 1 byte.


    Byte start và stop là mình trích nguyên văn của VTCBKa, ý nói là các byte nhận dạng ở đầu và cuối mỗi khung truyền. Bit start và stop thì ai cũng biết, nói làm gì.
    Last edited by CHIBANG; 17-12-2005, 11:48.
    -------------------

    Comment


    • #17
      Vấn đề nữa là MSComm ko giải quyết được vấn dêd tui nói ở trên, mà phải dùng API loằng ngoằng rắm rối lắm. Bác nào có trình độ nói rõ cái này thì hay. Ví dụ: timerout = API, ví dụ thời gian nghỉ giữa 2 byte = API....
      -------------------

      Comment


      • #18
        Thôi ko bàn cãi nữa nhé, hẹn lần sau khi tìm hiểu kỹ về cách sử dụng hàm API, mình sẽ post lên so sánh với thằng MScomm1 của bạn Bắc, để mọi người có thể lựa chọn cho mình cách phù hợp hơn trong từng ứng dụng.
        Đề nghị bạn Bắc tiếp tục.
        -------------------

        Comment


        • #19
          Lập trình trên VB:

          OK cảm ơn ChiBang. Thực ra tôi lập trình cũng sử dụng hàm API mà bạn.
          Do hôm qua luyện chưởng sai nên không làm xong theo kế hoạch để anh em chiêm ngưỡng. Có lẽ mai hoặc ngày kia luyện công xong đã.
          To CHIBANG: có thể thiết lập thời gian truyền mỗi byte và thời gian truyền mỗi bít đó bạn ạ. Với lại sau khi truyền xong một byte thì có thể dùng trễ để truyền hết byte đó cho vdk nhận xong lại truyền tiếp. ở dây dùng timeout. CHIBANG và mọi người đọc bài dưới đây nha.
          Các bạn có thể biết được các hàm API về cách khai báo và một số hằng số nữa. Theo hướng dẫn hình dưới và mở trình API Text Viewer đó lên, vào file mở load file win32api.txt rồi các bạn sẽ đọc được các kiểu khai báo ở đây.
          Trước hết, trong ứng dụng này sử dụng 2 điều khiển Timer là tên là tmrTransferInterval và tmrTimeout , và 2 ActiveX là Microsoft Comm Control 6.0 và Microsoft Common Dialog 6.0 .
          Trước hết tôi xin phân tích một vài điều:
          * Tìm cổng:
          Ứng dụng dùng MSComm không phải biết bất cứ điều gì về cổng giao tiếp mà nó sử dụng ngoại trừ tên của cổng đó, như là COM1, COM2,.. Trong nhiều trường hợp ứng dụng không phảỉ biết địa chỉ của cổng hoặc đường IRQ bởi vì MSComm tự làm chi tiết hết cả. Nhưng ứng dụng cũng cần phải biết là có những cổng nào tồn tài trên máy tính của bạn chứ, khi đó nó sẽ cho người dùng lựa chọn cổng để giao tiếp.
          Có 2 cách để tìm các cổng này:
          +Hàm FindPorts phát hiện cổng = cách thử mở tất cả các cổng từ COM1 đến COM16( vì chỉ có tối đa bằng này cổng thôi). Nếu cổng đã được mở hoặc trả về lỗi “Port In Use” ( lỗi 8005) thì tức là cổng này có tồn tại và thêm vào mảng CommPort.

          Code:
          Public Sub FindPorts()
          'Find Comm ports by trying to open each.
          'Each port must support the current settings (bit rate, etc.).
          Dim Count As Integer
          Dim NumberOfPorts As Integer
          Dim SavedPortNumber As Integer
          Dim SaveCurrentPort As Boolean
          ReDim CommPorts(1 To 16)
          On Error Resume Next
          SaveCurrentPort = False
          NumberOfPorts = 0
          'If a port is already open, reopen it on exiting.
          If frmMain.MSComm1.PortOpen = True Then
                  frmMain.MSComm1.PortOpen = False
                  SavedPortNumber = PortNumber
                  SaveCurrentPort = True
          End If
          For Count = 1 To 16
              frmMain.MSComm1.CommPort = Count
              frmMain.MSComm1.PortOpen = True
              If Err.Number = 8005 Then
                  'The port is already open
                  'The port exists, so add it to the list.
                  NumberOfPorts = NumberOfPorts + 1
                  CommPorts(NumberOfPorts) = "COM" & CStr(Count)
              ElseIf frmMain.MSComm1.PortOpen = True Then
                  'If the port opens, it exists.
                  'Close it and add to the list.
                  frmMain.MSComm1.PortOpen = False
                  NumberOfPorts = NumberOfPorts + 1
                  CommPorts(NumberOfPorts) = "COM" & CStr(Count)
              Err.Clear
              End If
          Next Count
          'Disable the error handler
          On Error GoTo 0
          ReDim Preserve CommPorts(1 To NumberOfPorts)
          If SaveCurrentPort = True Then
              PortNumber = SavedPortNumber
              frmMain.MSComm1.CommPort = PortNumber
              frmMain.MSComm1.PortOpen = True
          End If
          End Sub
          ‘ ------------------
          + Hàm fncGetHeighestComPortNumber dùng theo cách khác là gọi hàm API EscapeComFunction để tìm chỉ số lớn nhất tên của cổng ở trong máy của bạn.
          Code:
          ===============
          Public Function fncGetHighestComPortNumber() As Integer
          'Returns the number of the system's highest Com port.
          'Also shows how to use the EscapeCommFunction API call.
          Dim ClosePortOnExit As Boolean
          Dim PortCount As Long
          Dim handle As Long
          'The API call requires a CommID of an open port.
          If frmMain.MSComm1.PortOpen = False Then
              frmMain.MSComm1.PortOpen = True
              ClosePortOnExit = True
          Else
              ClosePortOnExit = False
          End If
          handle = frmMain.MSComm1.CommID
          PortCount = GETMAXCOM
          'Add 1 because EscapeCommFunction begins counting at 0.
          fncGetHighestComPortNumber = _
              EscapeCommFunction(handle, PortCount) + 1
          If ClosePortOnExit = True Then
              frmMain.MSComm1.PortOpen = False
          End If
          End Function
          -----------------------
          * việc dùng trễ:
          - Ứng dụng dùng MSComm có thể dùng nhiều hàm trễ sau để quyết định khi nào quá trình truyền nhận là kết thúc và khi nào thì thoát khỏi trạng thái chờ một đáp ứng từ một máy tính khác.
          + Hàm Delay có tham số dạng mili giây, dùng hàm API timeGetTime trong thư việc .dll. Hàm này tạo trễ có giá trị là từng mili giây do hàm timeGetTime trả về số giây mà hệ điều hành bắt đầu khởi động. Và nó bị tràn sau 24 ngày nếu các bạn cứ để PC của bạn cú chạy suốt. Nếu chạy suốt thì sau 24 ngày phải kiểm tra lại các thông số này không có sai thì chết.
          Code:
          ------------------------
          Public Sub Delay(DelayInMilliseconds As Single)
          'Delay timer with approximately 1-msec. resolution.
          'Uses the API function timeGetTime.
          'Rolls over 24 days after the last Windows startup.
          Dim Timeout As Single
          Timeout = DelayInMilliseconds + timeGetTime()
          Do Until timeGetTime() >= Timeout
              DoEvents
          Loop
          End Sub
          -----------------------------
          +Hàm LowResDelay dùng thời gian của hệ thống để gây trễ. Thời gian này có chu kì hoạt động là 18 chu kì/ giây nên trễ mỗi chu kì khoảng 55 mili giây. Dùng hàm Timer, hàm này trả về số mili giây tính từ nửa đêm hay nói cách khác tính như giờ hiện hành trên máy của bạn nhưng đổi ra mili giây.
          Code:
          ---------------
          Public Sub LowResDelay(DelayInMilliseconds As Single)
          'Uses the system timer, with resolution of about 56 milliseconds.
          Dim Timeout As Single
          'Add the delay to the current time.
          Timeout = Timer + DelayInMilliseconds / 1000
          If Timeout > 86399 Then
              'If the end of the delay spans midnight,
              'subtract 24 hrs. from the Timeout count:
              Timeout = Timeout - 86399
              'and wait for midnight:
              Do Until Timer < 100
                  DoEvents
              Loop
          End If
          'Wait for the Timeout count.
          Do Until Timer >= Timeout
              DoEvents
          Loop
          End Sub
          ------------------------
          + Trễ 1 byte hàm fncOneByteDelay tính toán thời gian để truyền hết 1 byte. Nó có ích cho một vài liên kết kiểu halp-duplex, nơi mà máy tính phải chuyển hướng truyền sau khi gửi dữ liệu để cho máy tính khác tiếp tục truyền. Trễ này để cho chắc chắc mọi bít trong byte truyền được hết. Hàm vbSetCommTimeouts dùng hàm này.( nhân đây gửi ChiBang là câu hỏi thứ 4 của bạn có thể thực hiện được).
          Code:
          ---------------------------
          Public Function fncOneByteDelay(BitRate As Long) As Single
          'Calculate the time in milliseconds to transmit
          '8 bits + 1 Start & 1 Stop bit.
          Dim DelayTime As Integer
          DelayTime = 10000 / BitRate
          fncOneByteDelay = DelayTime
          End Function
          ---------------------------
          - Timeout: hàm api SetCommTimeouts quyết định thời gian thiết bị giao tiếp của Windows hoàn thành việc truyền nhận dữ liệu. Giá trị mặc định là 5 giây với mỗi việc này. Khi có 1 timeout xảy ra thì thì công việc sẽ bị huỷ bỏ, cái này xảy ra khi ứng dụng có thể chưa hoàn thành công việc nào cả( truyền hoặc nhận) hoặc chưa biết lỗi xảy ra ở đâu trong việc truyền, nhận. Dữ liệu nhận vẫn còn trong bộ đệm cho đến khi ứng dụng đọc nó nhưng bên truyền bộ đệm bị xoá khi xảy ra timeouts.
          Để chống lại timeout dùng SetCommTimeouts đê thiết lập thông số cho thời gian ứng dụng hoàn thành việc truyền nhận dữ liệu.
          Bắt tay phần cứng có thể chậm hơn bên truyền đữ liệu. Ví dụ liên kết với vđk thì cần phải có thời gian để cho vdk nhận biết được tín hiệu bắt tay do đó cần phải thêm thời gian này vào timeout.
          Khi dùng thuộc tính Input hoặc Output để đọc, truyền dữ liệu thì nếu ứng dụng truyền một block nhở và bên nhận không cần trễ để bắt tay dài thì giá trị timeout mặc định là 5 giây sẽ không gây ra lỗi gì cả.
          Trong chiều nhận, bạn có thể chống lại timeout bằng cách kiểm tra InBufferCount và dùng Input để đọc đữ liệu ngay khi dữ liệu bắt đầu đến. Đó là cách rất hay vì VB sẽ trả lại một lỗi khi mà ứng dụng đọc bộ đệm rỗng.
          Để vô hiệu hoá timeóut , thì thiết lập mọi giá trị = 0.
          Last edited by ngohaibac; 29-12-2005, 16:18.
          Technical sale at WT Microelectronics S'pore
          Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
          Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

          Comment


          • #20
            Mình đã tìm được một chương trình của bọn lvr.com
            Đây là chương trình phải nói là rất là hay dùng chuẩn RS-485 với 1 master là PC và các có thêm 7 node khác là slave. Nó cũng cho phép hiển thị tất cả các cổng com có trong PC của bạn. Do tôi không có phần cứng thử nghiệm nên không test được.
            Các bạn hoàn toàn có thể download về và lấy một phần đoạn mã để làm với ứng dụng của mình.
            Tôi sẽ hoàn thành viết cho RS-232 sau.
            Chương trình có hướng dẫn cụ thể có lẽ tôi chẳng cần phải hướng dẫn gì đâu. bạn nào có thắc mắc thì xin cho ý kiến. Tourial này có thể nói là đã gần hoàn thành rồi các bạn ạ. Dựa vào các kiến thức tôi đã đưa ra ở trên việc hiểu chương trình không còn là vấn đề gì nữa.
            Chương trình này có dùng một số delay. Các bạn đọc kỹ nhé.
            Hi vọng chương trình này sẽ làm cho các bạn cảm thấy hứng thú.
            Technical sale at WT Microelectronics S'pore
            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

            Comment


            • #21
              Phân tích code

              Có lẽ mọi người đã có được chương trình rồi. Việc làm tiếp trên RS232 chẳng có gì là khó cả bạn ạ.
              Do tôi đang rất bận, làm nhiều thứ. Nên tôi chỉ phân tích các hàm cho các bạn để các bạn dễ hiểu có thể làm cho mình những ứng dụng thực tế khác.
              Còn về chương trình qua RS232 xin khất các bạn sau. Tôi đang phải làm viết cái đó trên VC++.
              Trên đây tôi đã giới thiệu một vài hàm. Bây giờ tôi xin giới thiệu chi tiết một các hàm, các điều khiển dùng trong mỗi form:
              - Trong file serport.bas : file thư viện
              + Gồm các hằng số lấy từ file win32api.txt như ở trên bao gồm: Parity, Stop bits, Error, CommEventMark bit, Escape Comm Function value,Bit rates, DTR Control Flow Values, RTS Control flow values, DCB Bits values. Chi tiết các bạn xem trong file gửi ở dưới. Tôi lấy một vài ví dụ các hằng số này như số bít stop:
              Code:
               
              'Stop bits
              Global Const ONESTOPBIT = 0
              Global Const ONE5STOPBITS = 1
              Global Const TWOSTOPBITS = 2
              … …
              Các hằng số này có trong file win32api.txt.
              + Định nghia các kiểu dữ liệu làm tham số cho các hàm api: dcbType, COMMTIMEOUTS:
              Code:
              'define type COMMTIMEOUTS
              Public Type COMMTIMEOUTS
                   ReadIntervalTimeout As Long
                  ReadTotalTimoutMultiplier As Long
                  ReadTotalTimeoutConstant As Long
                  WriteTotalTimeoutMultiplier As Long
                  WriteTotalTimeoutConstant As Long
              End Type
              
              'define type dcbType
              Public Type dcbType
                      DCBlength As Long
                      BaudRate As Long
                      Bits1 As Long
                      wReserved As Integer
                      XonLim As Integer
                      XoffLim As Integer
                      ByteSize As Byte
                      Parity As Byte
                      StopBits As Byte
                      XonChar As Byte
                      XoffChar As Byte
                      ErrorChar As Byte
                      EofChar As Byte
                      EvtChar As Byte
                      wReserved2 As Integer
              End Type
              + Các biến và hằng toàn cục dùng chung cho ứng dụng( rất quan trong xuyên suốt cả ứng dụng này)
              Code:
              Public Const ProjectName = "SerialPortComplete"
              
              Public BitRate As Long  ‘ tần số bus
              Public Buffer As Variant  ‘ bộ đệm 
              Public CommDCB As dcbType  ‘
              Public CommPorts() As String  ‘ mảng để lưu trữ các cổng có trong PC
              Public OneByteDelay As Single ‘ thời gian trễ khi truyền 1 byte
              Public PortExists As Boolean ‘ Port tồn tại
              Public PortInUse As Boolean ‘ port đang sử dụng
              Public PortNumber As Integer ‘ số thứ tự của cổng 
              Public PortOpen As Boolean ‘ 
              Public SaveDataInFile As Boolean ‘
              Public TimedOut As Boolean  ‘ Có xảy ra timeouts hay không
              Public ValidPort As Boolean ‘ Cổng có thực
              + Tiếp theo là khai báo một số hàm api và ý nghĩa của nó tôi sẽ nói trong khi dùng nó để các bạn biết rõ:
              Code:
              Public Declare Function apiGetCommState _
                  Lib "kernel32"   Alias "GetCommState"   (ByVal nCid As Long, _
                  lpDCB As dcbType)   As Long
              Public Declare Function apiSetCommState    Lib "kernel32" 
                  Alias "SetCommState"   (ByVal hCommDev As Long, _
                  lpDCB As dcbType)   As Long
              Public Declare Function EscapeCommFunction  Lib "kernel32" _
                  (ByVal nCid As Long,   ByVal nFunc As Long)   As Long
              Public Declare Function GetCommTimeouts    Lib "kernel32" _
                  (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) _
                  As Long
              Public Declare Function SetCommTimeouts  Lib "kernel32" _
                  (ByVal hFile As Long, _
                  lpCommTimeouts As COMMTIMEOUTS)   As Long
              Public Declare Function timeGetTime  Lib "winmm.dll" () As Long
              Public Declare Function TransmitCommChar  Lib "kernel32" _
                  (ByVal nCid As Long,    ByVal cChar As Byte)    As Long
              + Việc khai báo các hàm API đã xong bây giờ phải viết một vài chương trình chung cho cả ứng dụng:
              ++ Hàm fncByteToAsciiHex: chuyển đổi một byte thành 2 xâu bao gồm 2 kí tự ASCII HEX như 165 -> “A5”
              Code:
              Public Function fncByteToAsciiHex _
                  (ByteToConvert As Byte) _
                  As String
              'Converts a byte to a 2-character ASCII Hex string
              Dim AsciiHex As String
              AsciiHex = Hex$(ByteToConvert) ‘ dùng hàm Hex$ để chuyển đổi.
              If Len(AsciiHex) = 1 Then ‘ nếu chỉ là một kí tự thì thêm ‘0’ vào trước
                  AsciiHex = "0" & AsciiHex
              End If
              fncByteToAsciiHex = AsciiHex ‘ return 
              End Function
              -----------------------------------
              ++ Hàm fncDisplayDataAndFile không tham số dùng chuyển đổi giở hệ thống ra thành kiểu dạng : ngày – thòi gian
              Code:
              Public Function fncDisplayDateAndTime() As String
              'Date and time formatting.
              fncDisplayDateAndTime = _
                  CStr(Format(Date, "General Date")) & ", " & _
                  (Format(Time, "Long Time"))
              End Function
              ------------------------
              Last edited by ngohaibac; 29-12-2005, 16:21.
              Technical sale at WT Microelectronics S'pore
              Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
              Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

              Comment


              • #22
                Phân tích code( tiếp)

                ++ hàm fncGetHighestComPortNumber
                Code:
                Public Function fncGetHighestComPortNumber() As Integer
                'trả vê chỉ số lớn nhất của cổng trong hệ thống
                ‘Dùng hàm API: EscapeCommFunction cần dùng 2 tham số là CommID của đối tượng MSComm và hằng số dùng cho hàm ở trên GETMAXCOM = 9.
                Dim ClosePortOnExit As Boolean ‘ biến này dùng để biết là cổng giao tiếp đã mở chưa, hay đóng: true : cổng chưa mở, false: đã mở
                Dim PortCount As Long 
                Dim handle As Long
                'The API call requires a CommID of an open port.
                ‘ nếu chưa mở thì mở cổng và lưu trữ trạng thái trong ClosePortOnExit
                If frmMain.MSComm1.PortOpen = False Then
                    frmMain.MSComm1.PortOpen = True
                    ClosePortOnExit = True
                Else
                    ClosePortOnExit = False
                End If
                ‘ phải mở cổng thì mới lấy được CommID
                handle = frmMain.MSComm1.CommID ‘ lấy CommID của điều khiển ‘MSComm.
                PortCount = GETMAXCOM
                'Thêm vào 1 bởi vì hàm EscapeCommFunction bắt đầu tính từ 0.
                fncGetHighestComPortNumber = _
                    EscapeCommFunction(handle, PortCount) + 1
                ‘ nếu cổng vừa mở thì đóng lại để trả lại trạng thái ban đầu.
                If ClosePortOnExit = True Then
                    frmMain.MSComm1.PortOpen = False
                End If
                End Function
                ------------------------
                ++ Hàm fncVerifyChecksum:
                Code:
                Public Function fncVerifyChecksum(UserString As String) As Boolean
                'Kiểm tra dữ liệu bằng cách so sánh checksum nhận được với giá trị được tính toán
                'UserString là một loạt các byte kiểu Ascii Hex format,
                'Kết thúc cho vào cuối  a checksum.
                Dim Count As Integer
                Dim Sum As Long
                Dim Checksum As Byte
                Dim ChecksumAsAsciiHex As String
                ‘Sum là tổng của các cắp số trong UserString.
                For Count = 1 To Len(UserString) - 3 Step 2
                    Sum = Sum + Val("&h" & Mid(UserString, Count, 2))
                Next Count
                'checksum byte thấp của Sum
                Checksum = Sum - (CInt(Sum / 256)) * 256
                ‘chuyển sang kiểu xâu
                ChecksumAsAsciiHex = fncByteToAsciiHex(Checksum) 
                'So sánh với checksum vừa tính toàn với checksum nhận được: 2 byte cuối của UserSetting
                If Checksum = Val("&h" & (Right(UserString, 2))) Then
                    fncVerifyChecksum = True ‘ nếu đúng thì trả lại True và ngược lại
                Else
                    fncVerifyChecksum = False
                End If
                End Function
                -------------
                ++ Hàm trễ với thời gian cho vào là kiểu mili giây
                Code:
                Public Sub Delay(DelayInMilliseconds As Single)
                'hàm trễ từng mili giây một
                ‘ dùng hàm API timeGetTime.
                'sẽ bị tràn sau 24 ngày sau khi hệ thống bắt đầu khởi động.
                Dim Timeout As Single 
                Timeout = DelayInMilliseconds + timeGetTime() ‘ Timeout = thời gian hiện tại  + thòi gian trễ
                ‘ trễ nếu thời gian của hệ thống không nhỏ hơn thì không làm gì cả
                Do Until timeGetTime() >= Timeout
                    DoEvents ‘ chẳng làm gì cả, trạng thái nghỉ.
                Loop
                End Sub
                --------------
                ++ hàm EditDCB :
                Code:
                Public Sub EditDCB()
                'Enables changes to a port's DCB.
                'The port must be open.
                Dim Success As Boolean
                Dim PortID As Long
                PortID = frmMain.MSComm1.CommID
                Success = apiGetCommState(PortID, CommDCB)
                
                'To change a value, uncomment and revise the appropriate line:
                'CommDCB.BaudRate = 2400
                'CommDCB.Bits1 = &H11
                'CommDCB.XonLim = 64
                'CommDCB.XoffLim = 64
                'CommDCB.ByteSize = 8
                'CommDCB.Parity = 0
                'CommDCB.StopBits = 0
                'CommDCB.XonChar = &H12
                'CommDCB.XoffChar = &H13
                'CommDCB.ErrorChar = 0
                'CommDCB.EofChar = &H1A
                'CommDCB.EvtChar = 0
                
                'Write the values to the DCB.
                Success = apiSetCommState(PortID, CommDCB)
                
                'Read the values back to verify changes.
                Success = apiGetCommState(PortID, CommDCB)
                
                Debug.Print "DCBlength: ", Hex$(CommDCB.DCBlength)
                Debug.Print "BaudRate: ", CommDCB.BaudRate
                Debug.Print "Bits1: ", Hex$(CommDCB.Bits1); "h"
                Debug.Print "wReserved: ", Hex$(CommDCB.wReserved)
                Debug.Print "XonLim: ", CommDCB.XonLim
                Debug.Print "XoffLim: ", CommDCB.XoffLim
                Debug.Print "ByteSize: ", CommDCB.ByteSize
                Debug.Print "Parity: ", CommDCB.Parity
                Debug.Print "StopBits: ", CommDCB.StopBits
                Debug.Print "XonChar: ", Hex$(CommDCB.XonChar); "h"
                Debug.Print "XoffChar: ", Hex$(CommDCB.XoffChar); "h"
                Debug.Print "ErrorChar: ", Hex$(CommDCB.ErrorChar); "h"
                Debug.Print "EofChar: ", Hex$(CommDCB.EofChar); "h"
                Debug.Print "EvtChar: ", Hex$(CommDCB.EvtChar); "h"
                Debug.Print "wReserved2: ", Hex$(CommDCB.wReserved2)
                
                End Sub
                ++ Hàm findPorts: giới thiệu rồi
                ++ Lấy thiết lập mới từ lựa chọn của người dùng từ frmPortSetting. Để hiểu nó các bạn đọc tiếp các phàn sau:
                Code:
                Public Sub GetNewSettings()
                'Read and store user changes in the Setup menu.
                BitRate = Val(frmPortSettings.cboBitRate.Text)
                PortNumber = Val(Right(frmPortSettings.cboPort.Text, 1))
                ‘ gọi hàm khởi tạo cho cổng 
                Call frmMain.fncInitializeComPort(BitRate, PortNumber)
                End Sub
                ++  Lấy thông số ban đầu: 
                Public Sub GetSettings()
                'Get user settings from last time.
                BitRate = GetSetting(ProjectName, "Startup", "BitRate", 1200)
                PortNumber = GetSetting(ProjectName, "Startup", "PortNumber", 1)
                'Defaults in case values retrieved are invalid:
                If BitRate < 300 Then BitRate = 9600
                If PortNumber < 1 Then PortNumber = 1
                End Sub
                ++ ImmediateTransmit truyền trực tiếp các byte.
                Code:
                Sub ImmediateTransmit(ByteToSend As Byte)
                'Places a byte at the top of the transmit buffer
                'for immediate sending.
                Dim Success As Boolean 
                Success = TransmitCommChar(frmMain.MSComm1.CommID, ByteToSend)
                End Sub
                Last edited by ngohaibac; 29-12-2005, 16:22.
                Technical sale at WT Microelectronics S'pore
                Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                Comment


                • #23
                  Lập trình giao tiếp nối tiếp bằng Visual C++

                  Chào các bạn.

                  Trong thời gian qua tôi hơi bận nên chưa tiếp tục chủ đề này được. Có lẽ phần mềm Visual Basic mọi người khá thông thạo thì không phải bàn cãi gì nữa. Tôi xin gửi cho mọi người chương trình khá đơn giản để gửi kí tự mình đánh từ bàn phím qua RS232 đến vi điều khiển:
                  http://luckytoki.com/haibac/download...SerialPort.rar

                  Tôi xin tiếp tục hướng dẫn các bạn làm việc với Visual C++ , công cụ khá mạnh mà nếu các bạn học qua C,C++ thì làm việc với Visual C++ lại khá là đơn giản.

                  Ở đây tôi cũng dùng điều khiển ActiveX là Microsoft Communication 6.0 của bọn Microsoft. Và thiết lập thông số hoàn toàn tương tự với dùng với VB. Các bạn nên đọc qua các bài viết của tôi ở trên để nắm được hướng làm việc, cách thiết lập thông số.

                  Giới thiệu thế thôi. Mai viết tiếp.
                  Technical sale at WT Microelectronics S'pore
                  Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                  Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                  Comment


                  • #24
                    Visualc và Serial port

                    Tôi rất thích giao tiếp với vi điều khiển thông qua Visual C 6, nhưng việc khai báo để sử dụng cổng com trong mscomm class vẫn chưa thực hiện được. Nay đến với diễn đàn tôi thực sự cảm thấy rất vui khi biết được có người sẵn sàng giúp đỡ.
                    Hiện tại tôi đang rất cần các bước khai báo cũng như việc gọi các hàm, và một ví dụ đơn giản nhất để có thể xuất được dữ liệu đi và nhận về. Với cổng LPT thì khá đơn giản nhưng với com thì tôi làm chưa được. Tôi rất mong nhận được sự giúp đỡ từ phí các bạn.
                    Email tôi đang dùng: tanhiep_jav@yahoo.com
                    Cảm ơn nhiều !

                    Comment


                    • #25
                      Có ai lập trình .NET kô thế
                      Vẫn biết mỗi lần xa là một lần về lại...

                      Comment


                      • #26
                        Giới thiệu điều khiển MSComm trong VC++

                        Chào các bạn. Cách lập trình giao tiếp cổng Com có hơi khác với dùng VB một chút thôi. Chỉ cần các bạn có kiến thức đầy đủ về C,C++ lập trình hướng đối tượng như lớp Class, Thừa kế( lớp cơ sở, lớp dẫn suất),.. là các bạn có thể hoàn toàn có thể lập trình được ngon lành rồi.

                        Trước hết tôi xin giới thiệu các bạn cách lấy điều khiển MSComm cho vào list của bạn để dùng:


                        Bước 1:

                        Bạn vào Project -> Add to Project ->Components Control...

                        Bước 2:
                        Tiếp theo các bạn chọn như hình vẽ:





                        Khi đó nó sẽ định nghĩa cho chúng ta một lớp có tên là MSComm được định nghĩa trong 2 file :
                        - Header file: MSComm.h
                        - Source file: MSComm.c



                        Khi đó bạn gắp thả vào trong điều khiển của mình bình thường như các điều khiển khác:
                        Technical sale at WT Microelectronics S'pore
                        Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                        Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                        Comment


                        • #27
                          Kích chuột phải chọn Properties khi đó sẽ hiện lên một số các thuộc tính của điều khiển như tên ID, Setting ban đầu. Những cái này các bạn xem qua chắc hẳn thấy rất giống với trong VB đúng không? Những cái này hoàn toàn lập trình được chúng ta sẽ làm sau:







                          Để có thể lập trình với điều khiển này. Các bạn ấn Ctr- W để sau đó thêm một biến điều khiển để lập trình. Biến này là biến Control , kiểu CMSComm.

                          Quên không mang theo hình vẽ nên không cho các bạn xem được.
                          Technical sale at WT Microelectronics S'pore
                          Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                          Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                          Comment


                          • #28
                            Giới thiệu lớp MSComm

                            Các bạn mở file MSComm.h thì các bạn sẽ biết được các hàm được định nghĩa đối với lớp MSComm. Còn chi tiết nó thực hiện như thế nào thì xem trong file MSComm.c

                            Tất cả các hàm này đều không được nói rõ trong MSDN có lẽ là do sự tương tự với bản thân nó trong VB.

                            Tôi xin giới thiệu cho các bạn lớp này: Các điều khiển trong VC toàn thừa kế từ lớp CWnd do đó các bạn có thể dùng các hàm trong lớp CWnd như GetDlgItemText(..) , GetDlgItem( .... ),...

                            ----------------------------
                            Code:
                            class CMSComm : public CWnd
                            {
                            protected:
                            	DECLARE_DYNCREATE(CMSComm)
                            public:
                            	CLSID const& GetClsid()
                            	{
                            		static CLSID const clsid
                            			= { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } };
                            		return clsid;
                            	}
                            	virtual BOOL Create(LPCTSTR lpszClassName,
                            		LPCTSTR lpszWindowName, DWORD dwStyle,
                            		const RECT& rect,
                            		CWnd* pParentWnd, UINT nID,
                            		CCreateContext* pContext = NULL)
                            	{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }
                            
                                BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,
                            		const RECT& rect, CWnd* pParentWnd, UINT nID,
                            		CFile* pPersist = NULL, BOOL bStorage = FALSE,
                            		BSTR bstrLicKey = NULL)
                            	{ return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
                            		pPersist, bStorage, bstrLicKey); }
                            
                            // Attributes
                            public:
                            
                            // Operations
                            public:
                            	void SetCDHolding(BOOL bNewValue);
                            	BOOL GetCDHolding();
                            	void SetCommID(long nNewValue);
                            	long GetCommID();
                            	void SetCommPort(short nNewValue);
                            	short GetCommPort();
                            	void SetCTSHolding(BOOL bNewValue);
                            	BOOL GetCTSHolding();
                            	void SetDSRHolding(BOOL bNewValue);
                            	BOOL GetDSRHolding();
                            	void SetDTREnable(BOOL bNewValue);
                            	BOOL GetDTREnable();
                            	void SetHandshaking(long nNewValue);
                            	long GetHandshaking();
                            	void SetInBufferSize(short nNewValue);
                            	short GetInBufferSize();
                            	void SetInBufferCount(short nNewValue);
                            	short GetInBufferCount();
                            	void SetBreak(BOOL bNewValue);
                            	BOOL GetBreak();
                            	void SetInputLen(short nNewValue);
                            	short GetInputLen();
                            	void SetNullDiscard(BOOL bNewValue);
                            	BOOL GetNullDiscard();
                            	void SetOutBufferSize(short nNewValue);
                            	short GetOutBufferSize();
                            	void SetOutBufferCount(short nNewValue);
                            	short GetOutBufferCount();
                            	void SetParityReplace(LPCTSTR lpszNewValue);
                            	CString GetParityReplace();
                            	void SetPortOpen(BOOL bNewValue);
                            	BOOL GetPortOpen();
                            	void SetRThreshold(short nNewValue);
                            	short GetRThreshold();
                            	void SetRTSEnable(BOOL bNewValue);
                            	BOOL GetRTSEnable();
                            	void SetSettings(LPCTSTR lpszNewValue);
                            	CString GetSettings();
                            	void SetSThreshold(short nNewValue);
                            	short GetSThreshold();
                            	void SetOutput(const VARIANT& newValue);
                            	VARIANT GetOutput();
                            	void SetInput(const VARIANT& newValue);
                            	VARIANT GetInput();
                            	void SetCommEvent(short nNewValue);
                            	short GetCommEvent();
                            	void SetEOFEnable(BOOL bNewValue);
                            	BOOL GetEOFEnable();
                            	void SetInputMode(long nNewValue);
                            	long GetInputMode();
                            };
                            -----------------------------------

                            Khi đó chắc bạn đã biết về cách thiết lập trong VC đúng không?

                            Sự tương tự là với một thuộc tính nào đó như InputLen thì nếu lấy giá trị này thì gọi :
                            Code:
                            CMSComm a;
                            int b = a.GetInputLen();    // lấy giá trị 
                            a.SetInputLen(1); //  thiết lập thuộc tính
                            Các thiết lập khác cũng tương tự.

                            Các bạn lại nhìn lại các hàm SetOutput:

                            Code:
                            void SetOutput(const VARIANT& newValue);
                            Biến ở đây là biến hằng tham chiếu đến kiểu VARIANT. Đây là một cấu trúc do đó bạn không thể nào trực tiếp chuyển đối kiểu nó từ kiểu CString mà bạn phải làm như sau: Thông qua một lớp COleVariant
                            Code:
                            if (m_mscomm1.GetPortOpen()) 
                              m_mscomm1.SetOutput(COleVariant(m_dToSend));

                            // còn chiều nhận lại trả về kiểu VARIANT bạn phải làm sao để chuyển sang kiểu CString để dùng.

                            Code:
                            VARIANT data = m_mscomm1.GetInput(); 
                              m_dReceive = (CString) data.bstrVal; // ép chuyển đổi kiểu
                            Chúc các bạn thành công.
                            Technical sale at WT Microelectronics S'pore
                            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                            Comment


                            • #29
                              Dùng ngắt OnComm

                              Các bạn đã biết cho điều khiển activeX vào rồi. Hẳn các bạn cũng tự hỏi là mình sẽ lập trình với điều khiển này thế nào để nó làm theo ý muốn như trong VB. Ví dụ như hàm ngắt OnComm , dùng thế nào,làm sao biết ngắt nào là ngắt nhận, truyền,.. Tôi sẽ giới thiệu cho các bạn từ từ.

                              Trước hết tôi xin đưa ra các tham số cần thiết lập ban đầu cho điều khiển MSComm của các bạn. Tôi cho đây là tối ưu nhất cho việc nhận dữ liệu và truyền dữ liệu. Các tham số này trong ứng dụng đơn giản bạn nên đặt vào trong hàm OnInitDialog() ( các bạn làm việc với VC++ đều biết cái này nằm ở đâu nên tôi không cần nói nữa).

                              Tôi ví dụ bạn đã đặt tên cho biến điều khiển của MSComm1 là m_mscomm1.

                              Code:
                              	// Thiết lập cho mscomm
                              	m_mscomm1.SetCommPort(1);// chọn cổng COM1
                              	m_mscomm1.SetHandshaking(0); // không chọn bắt tay
                                      m_mscomm1.SetSettings("9600,N,8,1");  
                              
                              	// thiết lập cho bên truyền
                              	m_mscomm1.SetInBufferSize(1024); // bộ đệm nhận
                              	m_mscomm1.SetInputLen(1);  // mỗi lần đọc 1 kí tự
                              	m_mscomm1.SetRThreshold(1); // dùng sự kiện comEvReceive
                              	m_mscomm1.SetInputMode(0); // Text Mode 
                              	m_mscomm1.SetOutBufferSize(512);
                              	//m_mscomm1.SetSThreshold(0);// don't use comEvSend
                              Thế là các bạn đã thiết lập xong.

                              Bây giờ bạn kích đúp chuột vào điều khiển MSComm1 nó sẽ gợi ý cho bạn đặt tên hàm là : OnOnCommMscomm1 . Bạn đồng ý luôn.

                              Khi bạn dùng ngắt thì giá trị trả về của m_mscomm1.GetCommEvent() cho ta biết là đang có ngắt nào. Giá trị đó chính là số thứ tự của các ngắt trong thuộc tính ComEvent của VB tôi đã giới thiệu trên ( trong MSDN).

                              Do đó hàm đơn giản như sau( trong OnOnCommMscomm1()):

                              Code:
                               
                                   UpdateData(true);
                                   switch( m_mscomm1.GetCommEvent()){
                              	case 1: // comEvSend
                                              // làm gì thì làm
                              		break;
                              	case 2://  comEvReceive
                              		VARIANT data = m_mscomm1.GetInput();
                                              CString dataReceive = (CString) data.bstrVal;
                              		break;
                              	case 3:// comEvCTS
                              		break;
                              	case 4://comEvDSR
                              		break;
                              	case 5: //comEvCD
                              		break;
                              	case 6://comEvRing
                              		break;
                              	case 7: //comEvEOF
                              		break;
                              	};
                                  UpdateData(false);
                              Hi vọng các bạn làm việc với điều khiển ngon lành.

                              Coi như đây là quà đầu năm mới chúc mọi người sức khỏe tôt( để còn cầy).

                              Chúc bạn, bạn của bạn, người yêu của bạn sức khỏe tốt, hạnh phúc,.. thích gì được lấy.
                              Technical sale at WT Microelectronics S'pore
                              Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                              Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                              Comment


                              • #30
                                hay wa..........
                                quả là bác có kiến thức thật uyên thâm về lĩnh vực này.Nhưng lần sau bác nên gửi sang dạng file đính kèm thì mọi người thấy thú vị hơn đấy.
                                chúc bác sang năm mới mạnh khỏe và thành đạt, chúc bác có nhiều bài viết hay để cho anh em cung học hỏi.

                                Comment

                                Về tác giả

                                Collapse

                                ngohaibac Tìm hiểu thêm về ngohaibac

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X