嵌入式产品一般出场前要经过参数设定、参数校准、终端号设置等操作,单片机上面没有太多的设置接口,一般而言,只有一个串口可以使用,我尝试使用VS2019+WinForm,C#开发开发一款串口调试工具,用于配置产品的参数。
1、建立好工厂后,布局,给控件命名
2、编写代码
2.1 实现端口号扫描
private void ReflashPortToComboBox(SerialPort serialPort, ComboBox comboBox)
{
if (!serialPort.IsOpen)
{//串口处于关闭状态
comboBox.Items.Clear();
string[] str = SerialPort.GetPortNames();
if (str == null)
{
MessageBox.Show("本机没有串口!", "Error");
return;
}
//添加串口
foreach (string s in str)
{
comboBox.Items.Add(s);
Console.WriteLine(s);
}
}
else
{
MessageBox.Show("串口处于打开状态下,不能刷新串口列表", "Error");
}
}
2.2 打开串口按钮代码
private void btn_open_com_Click(object sender, EventArgs e)
{
Int32 ibaudrate = Convert.ToInt32(cb_select_baudrate.SelectedItem.ToString());
serialPort1.PortName = cb_select_com.SelectedItem.ToString();
serialPort1.BaudRate = ibaudrate;
serialPort1.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cb_select_check_bit.Text);
serialPort1.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cb_select_stop_bit.Text);
serialPort1.DataBits = Convert.ToInt16(cb_select_data_bits.Text);
//添加串口事件处理
serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(ReceiveData);
try
{
serialPort1.Open();
btn_open_com.Enabled = false;
btn_close_com.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show("串口打开失败"+ex, "Error");
}
}
2.3 串口接收事件代码
//串口接收事件
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
string content = serialPort1.ReadExisting(); //从串口中读取输入流,返回string
ShowData(content);
}
private void ShowData(string text)
{
string receiveText = text;
//更新接收数据计数
recv_cntr += (UInt32)receiveText.Length;
lab_recv_cntr.Text = recv_cntr.ToString();
textBox_debug.AppendText("接收到了"+ receiveText.Length.ToString()+ "个数据: "+ text+"\r\n");
if (rbtn_recv_hex.Checked)
{//按HEX模式 展示接收到的内容
byte[] recData = System.Text.Encoding.Default.GetBytes(receiveText);// 将接受到的字符串据转化成数组;
foreach (byte str in recData)
{
textBox_recv.AppendText(string.Format("{0:X2} ", str));
}
}
else
{//按ASCII模式 展示接收到的内容
textBox_recv.AppendText(text); //将收到的字符串追加展示出来
}
}
2.4 发送按钮代码
private void btn_send_Click(object sender, EventArgs e)
{
//串口打开的情况下,才能进行下一步操作
if (!serialPort1.IsOpen) return;
//发送内容不能为空
if ("" == textBox_send.Text) return;
string sendData = textBox_send.Text; //复制发送数据
if (true == rbtn_send_ascii.Checked)
{//字符模式
try
{
serialPort1.Write( sendData );
//更新发送数据计数
send_cntr += (UInt32)sendData.Length;
lab_send_cntr.Text = send_cntr.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "串口数据发送错误");
serialPort1.Close();
btn_open_com.Enabled = true;
btn_close_com.Enabled = false;
}
}
else
{//HEX模式
try
{
sendData.Replace("0x", ""); //去掉0x
sendData.Replace("0X", ""); //去掉0X
string[] strArray = sendData.Split(new char[] { ',', ',', '\r', '\n', ' ', '\t' });
byte[] sendBuffer = new byte[strArray.Length]; //发送数据缓冲区
int decNum = 0,i = 0;
foreach (string str in strArray)
{
try
{
decNum = Convert.ToInt16(str, 16);
sendBuffer[i] = Convert.ToByte(decNum);
i++;
}
catch
{
//MessageBox.Show("字节越界,请逐个字节输入!", "Error");
}
}
serialPort1.Write(sendBuffer, 0, sendBuffer.Length);
//更新发送数据计数
send_cntr += (UInt32)sendBuffer.Length;
lab_send_cntr.Text = send_cntr.ToString();
}
catch
{
MessageBox.Show("当前为16进制发送模式,请输入16进制数据");
}
}
}
离线
3、测试
工程跑起来后,插入CH340G,将TX RX短接,
(1)设置为ascii模式,收发一切正常。
(2)设置为HEX模式,发送0x01、0x02 、0x99等不带字母的十六进制数,正常。
但是发送0xA0,这样带字母的十六进制数,就会出现以下情况。
(为了调试方便,我加入了日志打印区。在发生接收事件时,做2件事情,①在接收区显示收到的数据,②在日志区显示收到了多长的数据)
[1]第一次发送0xA0,触发了接收事件,①显示区没有任何显示;②数据长度是0
[2]第二次发送0xA0,触发了接收事件,①显示区显示了2个A0;②数据长度是1
结果是,数据长度对不上。。。请问有没有大神懂这是什么原因呢?
附上工程:uart_tool_base_v001_20221128.zip
外链免费下载:uart_tool_base_v001_20221128.zip
最近编辑记录 LinjieGuo (2022-11-28 13:51:02)
离线
虽然我没搞过C#,但很明显 textBox_debug应该要像textBox_recv那样AppendText时要区分HEX和ASCII
嗯嗯,你说的这一点也是对的。
不过问题不是出在这个地方,问题是:数据内容接收到了,但是出现读取到的长度却不一致的情况。
后来在@周正的指导下,解决这个问题。
(1)使用ReadExisting()这个方法从串口接收中取数据,适用于字符串,可能不太适合面向字节流的数据。
(2)所以,接收代码修改为:
//串口接收事件
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
byte[] datas = new byte[serialPort1.BytesToRead];
int len = serialPort1.Read(datas, 0, datas.Length);
//数据写入环形缓冲区
recv_lp.write_data(datas, len);
show_recv_data(datas, len);
/*
string content = serialPort1.ReadExisting(); //从串口中读取输入流,返回string
ShowData(content);
*/
}
private void show_recv_data(byte[] data, int len)
{
//更新接收数据计数
recv_cntr += (UInt32)len;
lab_recv_cntr.Text = recv_cntr.ToString();
if (rbtn_recv_hex.Checked)
{//按HEX模式 展示接收到的内容
for (int i = 0; i < len; i++)
{
textBox_recv.AppendText(string.Format("{0:X2} ", data[i]));
}
}
else
{//按ASCII模式 展示接收到的内容
string str = System.Text.Encoding.Default.GetString(data);
textBox_recv.AppendText(str);
}
}
最近编辑记录 LinjieGuo (2022-11-29 21:50:26)
离线