串口代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace BXHSerialPort
{
public partial class frmSerialPort : Form
{
private SerialPort ComDevice = new SerialPort();
private Timer timer1 = new Timer();
private int i = 0;
public frmSerialPort()
{
InitializeComponent();
this.init();
timer1.Enabled = true;
timer1.Interval = 1000;
}
//获取串口号的端口
public void init()
{
btnSend.Enabled = false;
cbbComList.Items.AddRange(SerialPort.GetPortNames());
if (cbbComList.Items.Count > 0)
{
cbbComList.SelectedIndex = 0;
}
cbbBaudRate.SelectedIndex = 5;
cbbDataBits.SelectedIndex = 0;
cbbParity.SelectedIndex = 0;
cbbStopBits.SelectedIndex = 0;
pictureBox1.BackgroundImage = Properties.Resources.red;
ComDevice.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);//绑定事件
}
/// <summary>
/// 打开串口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnOpen_Click(object sender, EventArgs e)
{
if (cbbComList.Items.Count <= 0)
{
MessageBox.Show("没有发现串口,请检查线路!");
return;
}
if (ComDevice.IsOpen == false)
{
ComDevice.PortName = cbbComList.SelectedItem.ToString();
ComDevice.BaudRate = Convert.ToInt32(cbbBaudRate.SelectedItem.ToString());
ComDevice.Parity = (Parity)Convert.ToInt32(cbbParity.SelectedIndex.ToString());
ComDevice.DataBits = Convert.ToInt32(cbbDataBits.SelectedItem.ToString());
ComDevice.StopBits = (StopBits)Convert.ToInt32(cbbStopBits.SelectedItem.ToString());
try
{
ComDevice.Open();
btnSend.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
btnOpen.Text = "关闭串口";
pictureBox1.BackgroundImage = Properties.Resources.green;
}
else
{
try
{
ComDevice.Close();
btnSend.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
btnOpen.Text = "打开串口";
pictureBox1.BackgroundImage = Properties.Resources.red;
}
cbbComList.Enabled = !ComDevice.IsOpen;
cbbBaudRate.Enabled = !ComDevice.IsOpen;
cbbParity.Enabled = !ComDevice.IsOpen;
cbbDataBits.Enabled = !ComDevice.IsOpen;
cbbStopBits.Enabled = !ComDevice.IsOpen;
}
/// <summary>
/// 关闭串口
/// </summary>
public void ClearSelf()
{
if (ComDevice.IsOpen)
{
ComDevice.Close();
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sender"></param>
/// <param name="data"></param>
public bool SendData(byte[] data)
{
if (ComDevice.IsOpen)
{
try
{
ComDevice.Write(data, 0, data.Length);//发送数据
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("串口未打开", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return false;
}
private void timer1_Tick(object sender, EventArgs e)
{
i++;
if (i == 10)
{
timer1.Stop();
if (MessageBox.Show("是否请求关灯!", "", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
{
DataTurn();
MessageBox.Show("灯关闭了");
}
else
{
MessageBox.Show("灯还在开着");
timer1.Start();
}
}
}
/// <summary>
/// 发送数据button事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
if (MessageBox.Show("是否请求开灯!","",MessageBoxButtons.YesNo,MessageBoxIcon.Information)==DialogResult.Yes)
{
Data();
if (lblSendCount.Text==null)
{
MessageBox.Show("你的发送区为空,请重新发送");
return;
}
else if (txtShowData.Text=="97")
{
MessageBox.Show("灯已经打开了");
timer1.Tick += new EventHandler(timer1_Tick);
txtSendData.Text = "";
}
else
{
MessageBox.Show("灯是没有打开");
return;
}
}
else
{
MessageBox.Show("灯没有打开,请发送对的信息");
return;
}
}
byte[] sendData;
/// <summary>
/// 选择某种传输模式
/// </summary>
public void Data()
{
sendData = null;
if (rbtnSendHex.Checked)
{
sendData = strToHexByte(txtSendData.Text.Trim());
}
else if (rbtnSendASCII.Checked)
{
sendData = Encoding.ASCII.GetBytes(txtSendData.Text.Trim());
}
else if (rbtnSendUTF8.Checked)
{
sendData = Encoding.UTF8.GetBytes(txtSendData.Text.Trim());
}
else if (rbtnSendUnicode.Checked)
{
sendData = Encoding.Unicode.GetBytes(txtSendData.Text.Trim());
}
else
{
sendData =Encoding.ASCII.GetBytes(txtSendData.Text.Trim());
}
if (this.SendData(sendData))//发送数据成功计数
{
lblSendCount.Invoke(new MethodInvoker(delegate
{
lblSendCount.Text = (int.Parse(lblSendCount.Text) + txtSendData.Text.Length).ToString();
}));
}
else
{
}
}
/// <summary>
/// 关灯
/// </summary>
public void DataTurn()
{
sendData = null;
if (rbtnSendHex.Checked)
{
sendData = strToHexByte("0x00");
}
else if (rbtnSendASCII.Checked)
{
sendData = Encoding.ASCII.GetBytes("1#*");
}
else if (rbtnSendUTF8.Checked)
{
sendData = Encoding.UTF8.GetBytes("1#*");
}
else if (rbtnSendUnicode.Checked)
{
sendData = Encoding.Unicode.GetBytes("1#*");
}
else
{
sendData = Encoding.ASCII.GetBytes("1#*");
}
if (this.SendData(sendData))//发送数据成功计数
{
//lblSendCount.Invoke(new MethodInvoker(delegate
//{
// lblSendCount.Text = (int.Parse(lblSendCount.Text) + txtSendData.Text.Length).ToString();
//}));
//txtShowData.AppendText("\r\n");
}
else
{
}
}
/// <summary>
/// 字符串转换16进制字节数组
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
private byte[] strToHexByte(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0) hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ",""), 16);
return returnBytes;
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] ReDatas = new byte[ComDevice.BytesToRead];
ComDevice.Read(ReDatas, 0, ReDatas.Length);//读取数据
this.AddData(ReDatas);//输出数据
}
/// <summary>
/// 添加数据
/// </summary>
/// <param name="data">字节数组</param>
public void AddData(byte[] data)
{
if (rbtnHex.Checked)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.AppendFormat("{0:x2}" + " ", data[i]);
}
AddContent(sb.ToString().ToUpper());
}
else if (rbtnASCII.Checked)
{
AddContent(new ASCIIEncoding().GetString(data));
}
else if (rbtnUTF8.Checked)
{
AddContent(new UTF8Encoding().GetString(data));
}
else if (rbtnUnicode.Checked)
{
AddContent(new UnicodeEncoding().GetString(data));
}
else
{}
lblRevCount.Invoke(new MethodInvoker(delegate
{
lblRevCount.Text = (int.Parse(lblRevCount.Text) + data.Length).ToString();
}));
}
/// <summary>
/// 输入到显示区域
/// </summary>
/// <param name="content"></param>
private void AddContent(string content)
{
this.BeginInvoke(new MethodInvoker(delegate
{
if(chkAutoLine.Checked && txtShowData.Text.Length>0)
{
txtShowData.AppendText("\r\n");
}
txtShowData.AppendText(content);
}));
}
/// <summary>
/// 关闭灯
/// </summary>
private void AddTurn()
{
string connect = "1#*";
this.BeginInvoke(new MethodInvoker(delegate
{
if (chkAutoLine.Checked && txtShowData.Text.Length > 0)
{
txtShowData.AppendText("\r\n");
}
txtShowData.AppendText(connect);
}));
}
/// <summary>
/// 清空接收区
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClearRev_Click(object sender, EventArgs e)
{
txtShowData.Clear();
}
/// <summary>
/// 清空发送区
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnClearSend_Click(object sender, EventArgs e)
{
txtSendData.Clear();
}
}
项目描述:
界面:
上位机(数据发送区)给单片机发送信息,单片机返回信息给数据接收区文本框,上位机给单片机发送a#*,单片机返回上位机的数据接收区文本框一个数字97,对97数字进行判断?
第一次接收信息区弹出的提示
第二次接收信息区接收弹出的提示框
我想向大佬们求教一下,为什么第一次发送信息a#*返回97数字,判断不能触发定时器,我在网上说是数据丢失的原因,求大佬指点.....
不知道我的经验能不能给你参考:以前项目上用到过一种电子秤,也是通过电子秤的串口读取重量信息,但是这玩意有点很坑爹,软件通过串口连接上后,就会一直不间断的发数据过来,只要一段时间不去读串口数据,就会累积很长一段。不过还好它这玩意的数据报文是有指定格式的,只要定时去读,并且按照报文解析,把不需要的残缺数据丢弃不管就行了。
比如说他的报文是以#开头,!结尾,报文总长度固定18位。我的读取方式就是等待一段时间(我设置的大概是200-300ms),然后读一次串口,按照报文开头结尾和指定长度去分析这段串口数据(找出完整的报文,剔除缺损的报文)。这样虽然会得到好几组报文,但我至少能拿到我想要的数据。
方法比较拉稀,但我觉得应该能解决数据丢失的情况。