Thông báo

Collapse
No announcement yet.

Giúp mình gửi một số integer lên máy tính qua UART

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

  • Giúp mình gửi một số integer lên máy tính qua UART

    Xin chào tất cả mọi người.
    Mình mới tập viết chương trình cho AVR, trong lúc truyền nhận qua UART mình có một vấn đề là mình không biết truyền một số integer bằng một hàm lên máy tính như thế nào, mình chỉ biết truyền một char (character) thôi. Mong các mọi người giúp mình.
    Chân thành cám ơn.

  • #2
    bạn có thể chuyển đổi dạng int sang char rồi truyền.
    tham khảo hàm itoa() trong stdlib.h

    Comment


    • #3
      Nguyên văn bởi tnn1510 Xem bài viết
      Xin chào tất cả mọi người.
      Mình mới tập viết chương trình cho AVR, trong lúc truyền nhận qua UART mình có một vấn đề là mình không biết truyền một số integer bằng một hàm lên máy tính như thế nào, mình chỉ biết truyền một char (character) thôi. Mong các mọi người giúp mình.
      Chân thành cám ơn.
      Biết cách truyền một character rồi thì truyền 1 xâu ký tự dễ mà.
      Cách đơn giản để truyền một integer thì chuyển nó thành xâu ký tự rồi gửi lên máy tính.
      Sử dụng hàm sprintf(str, format,....) để chuyển đổi integer thành string.

      Comment


      • #4
        Nguyên văn bởi tnn1510 Xem bài viết
        Xin chào tất cả mọi người.
        Mình mới tập viết chương trình cho AVR, trong lúc truyền nhận qua UART mình có một vấn đề là mình không biết truyền một số integer bằng một hàm lên máy tính như thế nào, mình chỉ biết truyền một char (character) thôi. Mong các mọi người giúp mình.
        Chân thành cám ơn.
        Nếu lập trình giao diện bằng C# thì hơi khó đây. C# chỉ nhận và truyền ký tự ko truyền số Hex. Ở VĐK bạn phải đổi số int thành từ ký tự (chứ ko phải số) rồi dùng hàm gửi ký tự truyền lên máy tính. Chỗ nhận mã trên C# cũng hơi khó, phải khai báo cho phép chạy đa luồng thì mới được, còn ko là nó báo lỗi khi nhận.
        Nếu lập trình giao diện bằng VB6.0 thì dễ, VB6.0 cho phép truyền và nhận số Hex. Đổi số int thành byte rồi truyền. Viết hàm nhận dữ liệu trong MScomm.

        Comment


        • #5
          @ Open Door.
          Mình có vài ý kiến mong trao đổi với bạn:
          1. Mình vẫn viết hàm đọc và ghi dữ liệu kiểu Byte (Hex) ra Com với C#:
          Đọc: port.ReadByte();
          Ghi 1 byte , mình dùng 1 void:
          private void writeByte(byte b)
          {
          byte[] buffer = new byte[1];
          buffer[0] = b;
          try
          {
          this.port.Write(buffer, 0, 1);
          }
          catch { }
          }
          2. Nhưng đúng là khi nhận mã thì khó, vì nếu dùng hàm DataReceived thì mình chưa biết cách truyền dữ liệu nhận đến phần chính, nên mình vẫn phải làm theo cách thông thường là gửi dữ liệu, trễ, rồi đọc cổng (dùng hàm đọc riêng, ko dùng DataReceived), kiểm tra dữ liệu nhận -> cách này không hay lắm vì nếu ko biết chính xác dung lượng dữ liệu nhận thì khó thiết lập trễ.
          Bạn có nhắc đến giải pháp: cho phép chạy đa luồng? Mong bạn giải thích kỹ hơn.
          Cảm ơn Open Door nhiều nhé.

          Comment


          • #6
            Chỉ một việc đơn giản là truyền số 16bit mà sao rối như canh hẹ vậy?
            Ở phần vdk thì tách ra làm hai lần phát, lần thứ nhất lấy 8bit cao, lần sau lấy 8bit thấp. Bên PC cứ nhận đủ 2 byte thì cộng lại ByteH*256+ByteL là xong chứ gì
            Đã bỏ nghề về quê chăn gà...

            Comment


            • #7
              chỉ là giao thức truyền thôi mà, bạn truyền được 1byte thì bạn sẽ dựa bvaof đó để truyền byte tiếp,tùy theo cách của bạn, có thể truyền từng byte hay cũng có thể lấy 1 byte nhân v 1 số nao đó, khi lên máy tính lại nhân lại
              tom and jery !!!!!!!

              Comment


              • #8
                Nguyên văn bởi vqsktdt Xem bài viết
                @ Open Door.
                Mình có vài ý kiến mong trao đổi với bạn:
                1. Mình vẫn viết hàm đọc và ghi dữ liệu kiểu Byte (Hex) ra Com với C#:
                Đọc: port.ReadByte();
                Ghi 1 byte , mình dùng 1 void:
                private void writeByte(byte b)
                {
                byte[] buffer = new byte[1];
                buffer[0] = b;
                try
                {
                this.port.Write(buffer, 0, 1);
                }
                catch { }
                }
                2. Nhưng đúng là khi nhận mã thì khó, vì nếu dùng hàm DataReceived thì mình chưa biết cách truyền dữ liệu nhận đến phần chính, nên mình vẫn phải làm theo cách thông thường là gửi dữ liệu, trễ, rồi đọc cổng (dùng hàm đọc riêng, ko dùng DataReceived), kiểm tra dữ liệu nhận -> cách này không hay lắm vì nếu ko biết chính xác dung lượng dữ liệu nhận thì khó thiết lập trễ.
                Bạn có nhắc đến giải pháp: cho phép chạy đa luồng? Mong bạn giải thích kỹ hơn.
                Cảm ơn Open Door nhiều nhé.
                Mình gửi lên đây 1 đoạn code truyền và nhận dữ liệu bằng C#. Hy vọng giúp được bạn.

                using System;
                using System.Collections.Generic;
                using System.ComponentModel;
                using System.Data;
                using System.Drawing;
                using System.Text;
                using System.Windows.Forms;
                using System.IO.Ports;
                using System.IO;

                namespace Dem_so_nguoi_o_tram_xang
                {
                public partial class form1 : Form
                {
                string dulieu;
                private SerialPort ComPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);

                public form1()
                {
                InitializeComponent();
                ComPort.DataReceived += new SerialDataReceivedEventHandler(datareceived); //Khoi tao su kien nhan data tu ComPort;
                Control.CheckForIllegalCrossThreadCalls = false; //Cho phep xu li du lieu o luong khac khi nhan data tu ComPort;
                //Mo Comport
                try
                {
                ComPort.Open();
                }
                catch
                {
                MessageBox.Show("Đã xảy ra lỗi khi mở cổng COM !", "Note");
                this.ComPort.DtrEnable = false;
                this.ComPort.RtsEnable = false;
                }
                }

                private void datareceived(object sender, SerialDataReceivedEventArgs e)
                {
                //Nhan du lieu
                dulieu += ComPort.ReadExisting();
                }
                }

                Comment


                • #9
                  Nguyên văn bởi OpenDoor Xem bài viết
                  Nếu lập trình giao diện bằng C# thì hơi khó đây. C# chỉ nhận và truyền ký tự ko truyền số Hex. Ở VĐK bạn phải đổi số int thành từ ký tự (chứ ko phải số) rồi dùng hàm gửi ký tự truyền lên máy tính. Chỗ nhận mã trên C# cũng hơi khó, phải khai báo cho phép chạy đa luồng thì mới được, còn ko là nó báo lỗi khi nhận.
                  Nếu lập trình giao diện bằng VB6.0 thì dễ, VB6.0 cho phép truyền và nhận số Hex. Đổi số int thành byte rồi truyền. Viết hàm nhận dữ liệu trong MScomm.
                  Cơ bản thì đúng nhưng cũng ko hẳn là Ở VĐK bạn phải đổi số int thành từ ký tự
                  C# cũng ko phải là nhận kí tự, mà nhận Byte. Chúng ta đừng nên nghĩ nó quá phức tạp lên, tất cả xử lý đều truyện nhận là 1 byte, Char hay ACSII cũng chỉ là Byte.
                  Nếu ta hiểu cái này bạn sẽ code 1 cách linh hoạt.
                  Ví dụ tôi gửi 1 số là 12 thuộc kiểu byte (uint8, char, ASCII) thì trên C# cũng chỉ nhận đó là byte, và trên đó bạn sẽ tùy biến nó.
                  Thân.
                  My Face :

                  Comment


                  • #10
                    Nguyên văn bởi hienclubvn Xem bài viết
                    Cơ bản thì đúng nhưng cũng ko hẳn là Ở VĐK bạn phải đổi số int thành từ ký tự
                    C# cũng ko phải là nhận kí tự, mà nhận Byte. Chúng ta đừng nên nghĩ nó quá phức tạp lên, tất cả xử lý đều truyện nhận là 1 byte, Char hay ACSII cũng chỉ là Byte.
                    Nếu ta hiểu cái này bạn sẽ code 1 cách linh hoạt.
                    Ví dụ tôi gửi 1 số là 12 thuộc kiểu byte (uint8, char, ASCII) thì trên C# cũng chỉ nhận đó là byte, và trên đó bạn sẽ tùy biến nó.
                    Thân.
                    Uhm bạn nói đúng đó. Phần rắc rối chỉ ở chỗ nhận dữ liệu trên C#.
                    Last edited by OpenDoor; 18-10-2011, 19:27.

                    Comment


                    • #11
                      hì, với C# mà khó ??
                      mình nghĩ với C# thì thật là dễ dàng, mình chơi Labview mới là khó nè :P
                      Vì sao lại nói khó ? Bởi vì Labview nhận byte là chuyển qua ASCII ngay, mình phải xử lý ASCII sau đó bóc tách gì đó, rồi chuyển lại thành byte, rồi ghép lại thành biến.
                      Với C# thì khi sử dụng ReadByte thì còn ý nghĩa gì nữa đâu ? - Bởi vì nó quá đơn giản.
                      Tôi ví dụ cho bạn 1 cách đơn giản nhất có thể.
                      Tôi gửi 1 biến kiểu int16 chẳng hạn : bien = 1234
                      à, biến này có 4 số, mà 1 byte là từ 0 -255, vậy là OK, chúng ta sẽ dùng 2 byte để truyền
                      Byte1 = 12, Byte2 = 34
                      Bây giờ bạn tiến hành truyền 2 byte này lên theo thứ tự array[0] = Byte1 và array[0] = Byte2
                      Trên C# sẽ nhận được 2 byte này, chúng ta tiến hành ghép nó lại = 12X1000 + 34 = 1234.
                      Lưu ý : Gửi dưới VĐK nên truyền theo kiểu FIFO, mà có định khung để trên C# biết đâu là byte đầu.
                      Cái này phải tìm hiểu kỹ thì chơi sẽ rất linh hoạt.
                      Nhưng có 1 cái truyền nữa, rất dể, làm chủ hơn rs232. Code với cái gì cũng dể đó là giao thức USB
                      Nó truyền từng khối, nên ko lo lạc giữ liệu đi đâu cả, truyền mảng 64 Byte thì PC nhận đc Mảng 64 Byte
                      Công việc cuối chỉ việc ghép lại thôi,
                      hịc, mệt quá, ko viết nữa.
                      My Face :

                      Comment


                      • #12
                        Có thể bạn có cách học hay, nhận thức nhanh, có năng khiếu nên mọi thứ trở nên dễ dàng. Còn đối với những bạn khác thì khó trăm bề, khi bế tắc chẳng biết hỏi ai. Nhớ lại lúc bắt đầu học C# nên mình cũng gặp khó khăn khi nhận dữ liệu trên C# nên mới nói việc nhận dữ liệu trên C# ko phải dễ, mặc dù chỉ thêm 1 câu lệnh là giải quyết được vấn đề nhưng nhiều người mới học đâu có biết. Một khi đã truyền nhận được rồi thì truyền bao nhiêu byte chẳng được, xử lý dữ liệu thế nào tùy mình thôi.

                        Comment


                        • #13
                          Đó giờ minh chỉ xài kiểu này:

                          So16bit=0xABCD
                          so8bit_low=sobit16 (= CD)
                          so8bit_hi = so16bit>>8 (=AB)

                          Truyền lên máy tính từng biến sau đó tổng hợp lại so16bit = so8bit_hi*256 + so8bit_low

                          Comment


                          • #14
                            1 cái đơn giản nhất là gì sử dụng kiểu biến union lúc đó nó như sau:
                            union bien{
                            int So;
                            unsigned char H;
                            unsigned char L;
                            };
                            khi khai báo:bien so16bit;
                            việc gửi đi byte cao và thấp tương ứng với so16bit.H và so16bit.L.
                            cái này trên C.Kô biết c# có cái trò này kô.
                            , , ,

                            Comment


                            • #15
                              Thực sự trong quá trình mình làm thực nghiệm, việc truyền 1 số int (16bit) => qua UART, mình tách làm 2 bytes, mỗi byte 8 bit (vì chuẩn truyền UART cho pic theo mình biết chỉ giới hạn ở 8bit). Cách 1: để truyền 1 số 5000 (>8bit), ta có thể tách làm 2 số:, số thứ nhất: 50, và số tiếp theo: 00. Sau đó bên nhận sẽ làm 1 thuật toán đơn giản là gộp 2 byte lại.
                              Cách 2: có thể bạn sử dụng việc tách theo kiểu dịch bit, vd số: 5000 (int) = 10011 | 10001000, các bạn có thể truyền byte cao trước: 10011, sau đó truyền byte thấp sau: 10001000. Để có được phép toán tách đó, ta sẽ sử dụng hàm dịch bít trong C (<< hoặc >>). Các bạn mới học có thể tìm hiểu thêm trên Google. Và bên nhận cũng dùng dịch bit theo chiều ngược lại để nhận.

                              Vấn đề còn tồn đọng ở đây, là nếu tốc độ baudrate cao, việc truyền dẫn phát sinh lỗi. Vd như bạn truyền liên tục các số đã được chia làm 2 byte trên chân Tx của UART là: high-low -- high-low -- high-low -- . Bên nhận sẽ không nhận theo cặp --high-low-- như vậy, mà nhận theo kiểu -- low-high-- low-high... Do đó, giá trị bên nhận sẽ nhận sai hoàn toàn bên gửi.Ta nói bên nhận bị "trượt byte"
                              Lỗi này thường nằm ở chỗ bên gửi đã gửi rùi mà bên nhận không nhận ngay từ đầu, bân nhận bắt đầu ngắt UART không phải từ thời điểm bên gửi bắt đầu gửi. Do đó dẫn đến trượt byte. Solution trong trường hợp này là trước khi gửi data, thì bên gửi gửi 1 cờ wa, để báo cho bên nhận bắt đầu nhận. Cờ đó có thể là byte bất kì quy định trước của master/slave.
                              Hope to help s.o new to UART.

                              Comment

                              Về tác giả

                              Collapse

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

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

                              Collapse

                              Đang tải...
                              X