Thông báo

Collapse
No announcement yet.

Làm sao để C# nhận đủ dữ liệu từ Vi xử lý lên cổng COM?

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Làm sao để C# nhận đủ dữ liệu từ Vi xử lý lên cổng COM?

    Tình hình là em đã truyền dât từ vi xử lý lên C# được rồi nhưng không hiểu sao mà khi nhấn nút đọc kết quả thì có lúc nó nhận đủ data có khi nó nhận không đủ data đã gửi. Ví dụ dưới vi xử lý gửi là 13523 mà trên C# có khi nhận đủ 13523 cũng có khi nó chỉ nhận là 3 hoặc là 23 hoặc là 523 có khi không có gì. Em đã tìm nhiều cách rồi mà không làm sao cho C# nhận đủ data hết. Mong các Pro giúp em với.
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.IO.Ports;
    using System.Xml;
    
    namespace Giao_tiep
    {
        public partial class Form1 : Form
        {
    
            SerialPort P = new SerialPort(); // Khai báo 1 Object SerialPort mới.
            string InputData = String.Empty; // Khai báo string buff dùng cho hiển thị dữ liệu sau này.
            delegate void SetTextCallback(string text); // Khai bao delegate SetTextCallBack voi tham so string
            public Form1()
            {
                InitializeComponent();
                string[] ports = SerialPort.GetPortNames();
                // Thêm toàn bộ các COM đã tìm được vào combox cbCom
                cbCom.Items.AddRange(ports); // Sử dụng AddRange thay vì dùng foreach
                P.ReadTimeout = 500;
            }
    
            private void panel1_Paint(object sender, PaintEventArgs e)
            {
    
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
            }
    
            private void ngat_Click(object sender, EventArgs e)
            {
                P.Close();
                status.Text = "Đã Ngắt Kết Nối                        ";
                cbCom.Enabled = true;
                ngat.Visible = false;
                ketnoi.Visible = true;
                dockq.Visible = false;
                thoat.Visible = true;
                timer2.Stop();
                data = "";
                kq.Text = "- - - - - ";
            }
    
            private void ketnoi_Click(object sender, EventArgs e)
            {
                try
                {
                    P.BaudRate = 9600;
                    P.DataBits = 8;
                    P.Parity = Parity.None;
                    P.StopBits = StopBits.One;
                    P.Handshake = Handshake.None;
                    ngat.Visible = true;
                    ketnoi.Visible = false;
                    cbCom.Enabled = false;
                    dockq.Visible = true;
                    P.Open();
                    status.Text = "Đang kết nối với cổng " + cbCom.SelectedItem.ToString() + ".";
                    status.ForeColor = Color.Black;
                }
                catch (Exception ex)
                {
                    thoat.Visible = true;
                    dockq.Visible = false;
                    ketnoi.Visible = true;
                    ngat.Visible = false;
                    cbCom.Enabled = true;
                    MessageBox.Show("Không kết nối được.", "Thử lại", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
    
            private void thoat_Click(object sender, EventArgs e)
            {
                this.Close();
            }
    
            private void cbCom_SelectedIndexChanged(object sender, EventArgs e)
            {
                if (P.IsOpen)
                {
                    P.Close(); // Nếu đang mở Port thì phải đóng lại
                }
                P.PortName = cbCom.SelectedItem.ToString(); // Gán PortName bằng COM đã chọn
            }
    
            
            private void dockq_Click(object sender, EventArgs e)
            {
                timer2.Interval = 500;
                timer2.Enabled = true;
                timer2.Start();
            }
    
            private void kq_Click(object sender, EventArgs e)
            {
    
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                thoigian.Text= DateTime.Now.ToString("hh:mm:ss");
            }
    
            private void label1_Click(object sender, EventArgs e)
            {
    
            }
    
            private void statusStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
            {
    
            }
    
            private void thoigian_Click(object sender, EventArgs e)
            {
                
            }
    
            string data;
            private void timer2_Tick(object sender, EventArgs e)
            {
                data = P.ReadExisting();
                thoat.Visible = false;
                if (data != String.Empty)
                {
                    kq.Text = data;
                }
            }            
        }
    }

  • #2
    Trước khi truyền hay nhận dữ liệu, chúng ta có nhiều cách để chắc chẵn rằng:
    - Dữ liệu đó đã truyền/nhận đủ
    - Dữ liệu đó đẫ truyền/nhận sai

    Muốn vậy, cách đơn giản mà tôi chỉ cho bạn đó là:

    Mã mở đầu + Nội dụng + mã kết thúc.

    Ví dụ: @+12345 + 0x1F
    Nếu nhận được mã @ đúng là dữ liệu của mình cần thì nhận cho đến khi nào gặp 0x1F thì dừng, như vậy đảm bảo luôn luôn nhận đủ và nhận đúng

    Comment


    • #3
      Nguyên văn bởi eKhanhHoa Xem bài viết
      Trước khi truyền hay nhận dữ liệu, chúng ta có nhiều cách để chắc chẵn rằng:
      - Dữ liệu đó đã truyền/nhận đủ
      - Dữ liệu đó đẫ truyền/nhận sai

      Muốn vậy, cách đơn giản mà tôi chỉ cho bạn đó là:

      Mã mở đầu + Nội dụng + mã kết thúc.

      Ví dụ: @+12345 + 0x1F
      Nếu nhận được mã @ đúng là dữ liệu của mình cần thì nhận cho đến khi nào gặp 0x1F thì dừng, như vậy đảm bảo luôn luôn nhận đủ và nhận đúng
      Nhưng mà khi truyền lên C# thì làm sao nó loại bỏ được @ và 0x1F để lấy được data anh?

      Comment


      • #4
        giúp em với

        Comment


        • #5
          Em cũng bị cái lỗi giống bác welcomto97. Chỉ đơn thuần là nhận là lưu vào 1 file trên máy tính. Em dùng 1 biến tầm 6kbyte lưu dữ liệu. Sau khi nhận đủ mới lưu vô file. Em dùng vb.net. Việc đóng khung dữ liệu rồi tính checksum khi gửi theo em chỉ giúp nhận chính xác dữ liệu, với những khung bị mất 1 vài byte sẽ loại bỏ không xử lý. Mà đôi khi ta lại quan trọng việc nhận đủ dữ liệu. Để giảm tác động của dây dẫn em đã giảm tốc độ truyền và giảm chiều dài dây dẫn xuống 9600 và 1 m nhưng vẫn không khắc phục hết. Vẫn lỗi nhiều. Bác nào có cao kiến xin chỉ giúp.

          Giải pháp điện tử của bạn

          Comment


          • #6
            Nguyên văn bởi welcometo97 Xem bài viết
            Nhưng mà khi truyền lên C# thì làm sao nó loại bỏ được @ và 0x1F để lấy được data anh?
            Để tách lấy thông tin bác cứ làm như với vi điều khiển. Set thông số để chỉ cần 1 byte trong bộ đệm nhận là phát sinh sự kiện (như kiểu ngắt). Rồi kiểm tra, nếu ok tiến hành nhận, tương tự như với ký tự kết thúc. Chú ý ký tự bắt đầu và kết thúc không được xuất hiện trong dữ liệu. Như em hay làm thì thường chỉ kiểm tra điều kiện bắt đầu khung, rồi áp dụng cách đóng khung kiểm tra dữ liệu như modbus. Điều kiện bắt đầu khung càng đặc biệt càng tốt, ví dụ 0xFF,0xFF. Bác thử theo cách đó xem.

            Giải pháp điện tử của bạn

            Comment


            • #7
              Nguyên văn bởi vuxuansyhut Xem bài viết
              Để tách lấy thông tin bác cứ làm như với vi điều khiển. Set thông số để chỉ cần 1 byte trong bộ đệm nhận là phát sinh sự kiện (như kiểu ngắt). Rồi kiểm tra, nếu ok tiến hành nhận, tương tự như với ký tự kết thúc. Chú ý ký tự bắt đầu và kết thúc không được xuất hiện trong dữ liệu. Như em hay làm thì thường chỉ kiểm tra điều kiện bắt đầu khung, rồi áp dụng cách đóng khung kiểm tra dữ liệu như modbus. Điều kiện bắt đầu khung càng đặc biệt càng tốt, ví dụ 0xFF,0xFF. Bác thử theo cách đó xem.
              Cảm ơn bạn để mình thử xem.
              Ah mà bạn dùng ngắt nào để nhận dữ liệu từ cổng COM? Timer hay serial port

              Comment


              • #8
                Nguyên văn bởi welcometo97 Xem bài viết
                Cảm ơn bạn để mình thử xem.
                Ah mà bạn dùng ngắt nào để nhận dữ liệu từ cổng COM? Timer hay serial port
                Em viết bằng vb.net. Nếu dùng điều khiển mscomm thì là sự kiện oncomm còn nếu dùng serial port thì là sự kiện data recv

                Giải pháp điện tử của bạn

                Comment


                • #9
                  Nguyên văn bởi vuxuansyhut Xem bài viết
                  Em viết bằng vb.net. Nếu dùng điều khiển mscomm thì là sự kiện oncomm còn nếu dùng serial port thì là sự kiện data recv
                  Ah còn cái này nữa.
                  Khi nhận dự liệu Vd: @12345#@12345#@12345# bạn có thuật toán nào để loại bỏ @ và # để lấy 12345 không?

                  Comment


                  • #10
                    Cái này giống trên mà bác. Khi nhận được @ bác bắt đầu lưu, khi nhận được # bác kết thúc lưu. Chuỗi lưu của bác là chuỗi cần lấy.

                    Giải pháp điện tử của bạn

                    Comment


                    • #11
                      chào bạn welcometo97

                      Mình đã gặp phải lỗi như bạn và đã biết cách khắc phục, mình đọc đoạn code của bạn không hiểu tại sao câu lệnh kq.Text = data; trong khối time2 sao không gặp lỗi vì nó bị xung đột dữ liệu, đây là đoạn code của mình bạn tham khảo nhé, project của mình là hiển thị nhiệt độ lên pc băng C#

                      private void timer2_Tick(object sender, EventArgs e)
                      {
                      if (serialPort1.IsOpen)
                      {
                      string s;
                      s = serialPort1.ReadExisting();

                      if (s != "")
                      {
                      Display(s); // ham nay se mo ta sau
                      }
                      // khong the gan box_sent = s duoc vi se bao loi
                      }
                      }
                      private delegate void DlDisplay(string s);
                      private void Display(string abc)
                      {
                      if (name.InvokeRequired)
                      {
                      DlDisplay sd = new DlDisplay(Display);
                      name.Invoke(sd, new object[] { abc });
                      }
                      else
                      {

                      name.Text = abc;
                      }

                      }
                      nếu vẫn nhận thiểu dữ liệu thì bạn đổi time2 thay vì 100ms thành 200ms nhé, còn 1 điều nữa là khi nhận dữ liệu có thế nó sẽ xống dòng hay nó hiện 2 lần j đó thì cái name.text là bạn cho button nhé điều chỉnh cái button đó để đúng theo khuân mẫu mà mình hiển thị thôi, nếu bạn vẫn chưa làm được thì bạn liên hệ với mình qua mail: tdtruong91@gmail.com nhé.

                      Comment

                      Về tác giả

                      Collapse

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

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

                      Collapse

                      Đang tải...
                      X