C# đọc dữ liệu cổng UART

huyphuc92

Trứng gà
Theo loạt clip học C# của PIF, mình có làm theo để đọc chuỗi string ở cổng UART của kit TM4C129. Khi mình dùng hercules để kiểm tra thì chuỗi string gửi đi đúng, nhưng khi mình test bằng đoạn code C# thì chuỗi nhận về bị sai, nó hiển thị ra cái gì ấy.

Code C#
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
 
namespace Auto_detect_Com
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            LBStatus.Text = "Disconnect";
            BTConnect.Text = "Connect";
        }
        int intlen = 0;
        private void timer1_Tick(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();           
            if (intlen != ports.Length)
            {
                intlen = ports.Length;
                CBSelecCOM.Items.Clear();
                for (int j = 0; j < intlen; j++)
                {
                    CBSelecCOM.Items.Add(ports[j]);
                }
            }
        }
 
        private void BTConnect_Click(object sender, EventArgs e)
        {
            if (LBStatus.Text == "Disconnect")
            {
                Com.PortName = CBSelecCOM.Text;
                Com.Open();
                LBStatus.Text = "Connect";
                BTConnect.Text = "Disconnect";
            }
            else
            {
                Com.Close();
                LBStatus.Text = "Disconnect";
                BTConnect.Text = "Connect";
            }
        }
 
        private void BTSend_Click(object sender, EventArgs e)
        {
            string s;
            if (LBStatus.Text == "Connect")
            {
                s = TxtSend.Text;
                Com.Write(s);
            }
        }
 
        private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string s;
            s = Com.ReadExisting();
            Display(s);
        }
        private delegate void DlDisplay(string s);
        private void Display (string s)
        {
            if (TxtReceive.InvokeRequired)
            {
                DlDisplay sd = new DlDisplay(Display);
                TxtReceive.Invoke(sd, new object[] { s });
            }
            else
            {
                TxtReceive.Text = s;
            }
        }
    }
}
Còn code cho kit TM4C129 thì giống code UART của PIF luôn.
 

Fujiko

Thành Viên PIF
Bạn đã set thuộc tính số byte nhận để sinh ra ngắt của cổng Com chưa?
 

Fujiko

Thành Viên PIF
Nó nằm trong phần properties của cổng com.

Ví dụ chuỗi bạn gửi lên "PIF" thì nó có 4 byte (thêm 1 byte của ký tự kết thúc chuỗi \0), khi đó bạn sẽ đặt số byte sinh ra ngắt là 4 byte.
Còn nếu bạn để nó là 1 byte, và lại dùng thêm hàm ReadExisting thì mỗi lần nó chỉ hiển thị 1 kí tự, và kí tự cuối cùng bạn thấy là \0.
Cách khác, bạn vẫn có thể để là 1 byte, nhưng trong GUI bạn sẽ phải nhận từng kí tự, khi nào gặp \0 thì dừng và lúc đó mới cho hiển thị chuỗi. Cách này thì không cần quy định trước số byte truyền nhận.
 

Phạm Thành Danh

Thành Viên PIF
Nếu bạn chỉnh RecivedBytes thì sẽ gặp một rắc rối là nếu mình gửi những string có độ dài chuỗi khác nhau sẽ khó khăn trong việc nhận dữ liệu về. Ở đây là một đoạn code mình hay sử dụng, bạn có thể tham khảo, tùy mục đích nhận dữ liệu về để làm gì thì bạn có thể dùng RecivedBytes hoặc dùng theo cách của mình :1cool_byebye:
Code:
private void Display(string s)
        {
            if (txt_rev.InvokeRequired)
            {
                DIDisplay sd = new DIDisplay(Display);
                txt_rev.Invoke(sd, new object[] { s });
            }
            else
            {
                txt_rev.Text += s;
                //txt_rev.Text = "\n";
            }
        }
 

Lee

Cố Vấn CLB
Staff member
@huyphuc92: Welcome bạn đến với forum (như mình đã nói, forum lun hỗ trợ bạn). Bạn có thể tham khảo ý kiến cũng như share lại kiến thức với mọi người tại forum.

Về vấn đề của bạn, nếu code đã đúng hết nhưng vẫn chưa chạy thành công, thì có thể là đoạn string bạn gửi có các ký tự đặc biệt như \r,\n,\0 ; hoặc encoding bị sai. Nên dùng UTF8 để encode hơn là ASCII (range của ASCII chỉ chạy từ 0 đến 127).

Về vấn đề hiện thị, đoạn code của Phạm Thành Danh mục đích là để tránh crossthread call.
 

huyphuc92

Trứng gà
Chưa ổn!
Nói chung thế này. Bên kit TI, mình làm y chang hướng dẫn UART, cũng test bằng hercules, khi gửi 1 hoặc nhiều ký tự thì nhận được ký tự trả về giống hệt. Mấy ký tự \r,\n,\0 mình gửi đi cũng nhận về được.
Còn bên C#, mình cũng chỉnh thử số byte xảy ra ngắt (gì gì đó :D) rồi cũng thử đoạn code của bạn Danh, nhưng nhận về toàn ??? hoặc rất nhiều ??? :D
Nói thật các bạn nói gì mình chưa hiểu, để xem lại mấy clip C# cơ bản trên learnvisualstudio đã. :)
 

Phạm Thành Danh

Thành Viên PIF
Chưa ổn!
Nói chung thế này. Bên kit TI, mình làm y chang hướng dẫn UART, cũng test bằng hercules, khi gửi 1 hoặc nhiều ký tự thì nhận được ký tự trả về giống hệt. Mấy ký tự \r,\n,\0 mình gửi đi cũng nhận về được.
Còn bên C#, mình cũng chỉnh thử số byte xảy ra ngắt (gì gì đó :D) rồi cũng thử đoạn code của bạn Danh, nhưng nhận về toàn ??? hoặc rất nhiều ??? :D
Nói thật các bạn nói gì mình chưa hiểu, để xem lại mấy clip C# cơ bản trên learnvisualstudio đã. :)
bạn xem lại tốc độ Baud xem sao, chứ mình vẫn dùng bình thường mà :gach
 

huyphuc92

Trứng gà
Vấn đề mới đây. Nó nằm ở phần MCU.
1/
Trong phần ngắt UART, có đoạn code:

Code:
UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE));
Khi mình test mới một vài ký tự thì không sao, nhưng khi Send một chuỗi dài (ví dụ: Test UART, Enter something char), thì chuỗi nhận về bị thiếu(nhận về:Test UART, Enter s), đã test bằng hercule.

Tại sao nhỉ?

2/
Vô tình đang mở hercule thì mình cũng kết nối GUI C# với kit, kết quả là VS báo lỗi ngay hàm Com.Open() (mình đặt tên cổng COM là com). Có hàm nào kiểm tra trạng thái rỗi của cổng COM trước khi kết nối không nhỉ?

Cảm ơn tất cả. Chúc ngủ ngon =))
 

gochit

Cố Vấn CLB
Bạn có thể dùng câu lệnh Com.Open() theo cách:
try { câu lệnh } catch (Exception) { xử lý với trường hợp lỗi} để có thể xử lý những lỗi kiểu như vậy :D
 

LeeTruHee

Thành Viên PIF
Nếu bạn chỉnh RecivedBytes thì sẽ gặp một rắc rối là nếu mình gửi những string có độ dài chuỗi khác nhau sẽ khó khăn trong việc nhận dữ liệu về. Ở đây là một đoạn code mình hay sử dụng, bạn có thể tham khảo, tùy mục đích nhận dữ liệu về để làm gì thì bạn có thể dùng RecivedBytes hoặc dùng theo cách của mình :1cool_byebye:
Code:
private void Display(string s)
        {
            if (txt_rev.InvokeRequired)
            {
                DIDisplay sd = new DIDisplay(Display);
                txt_rev.Invoke(sd, new object[] { s });
            }
            else
            {
                txt_rev.Text += s;
                //txt_rev.Text = "\n";
            }
        }
anh ơi, mình muốn tách dữ liệu từ một chuỗi liên tiếp đó thì làm thế nào ạ? vì cộng dồn như vậy không biết được dữ liệu nào là của cái nào
 

huyphuc92

Trứng gà
Dữ liệu TM4C nhận được là mã ASCII, làm sao để tách ra thành số hay ký tự riêng rẽ nhỉ?

Ý tưởng rất đơn giản, C# gửi 1 số 1234 xuống TM4C để lưu vào một biến nào đó. Mình phải làm như thế nào?
 

huyphuc92

Trứng gà
Hiện tại mình đã thử gửi 1 mảng byte xuống kit TM4C129 để bật tắt LED, điều khiển linh tinh được 1 số thứ. Nhưng còn 1 số vấn đề vẫn đang tìm hiểu.
1/ Làm sao để gửi nhiều hơn 1 byte. Giả sử mình gửi một biến dạng long hay float thì sao? Cả gửi lên và gửi xuống.
2/ Ý tưởng truyền như thế này nữa: chuẩn bị truyền-nội dung truyền-kết thúc. Có bạn nào làm chưa, cho mình ỳ tưởng giải quyết với :)
 
Top