1. 目标说明
实现的目标如下图:
编写一个上图的界面,实现:
- 串口数据交互功能;
- 文件流的读取;
- 升级过程的实时展示;
2. 开始
2.1 串口部分
放置GroupBOX,命名为SerialConfig
内部放置:串口号的comboBox、波特率的comboBox、串口开关按钮open和close,串口号刷新按钮refresh;
在Form_Load中加上串口初始化的内容:
private void Form1_Load(object sender, EventArgs e)
{
//获取本地串口号
RegistryKey keyCom = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");
string[] sSubKeys = keyCom.GetValueNames();
foreach (var sValue in sSubKeys)
{
string PortName = (string)keyCom.GetValue(sValue);
comboBox2.Items.Add(PortName);
}
//配置串口 115200
serialPort1.PortName = comboBox2.Text.ToString();
serialPort1.BaudRate = int.Parse(comboBox1.Text);
serialPort1.DataBits = 8;
serialPort1.StopBits = StopBits.One;
serialPort1.Parity = Parity.None;
/* 模式数组数据定义结束 */
//
button2.Enabled = false; //启动时串口关闭按钮失能
label5.BackColor = Color.Transparent;
label5.TextAlign = ContentAlignment.MiddleRight;
}
串口开关按钮控制打开和关闭串口功能:
open_button
private void button1_Click(object sender, EventArgs e)
{
try
{
//serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
//开启串口按钮按下
serialPort1.PortName = comboBox2.Text.ToString();
serialPort1.BaudRate = int.Parse(comboBox1.Text);
//如果串口处于开启状态则关闭
if (serialPort1.IsOpen)
{
serialPort1.Close(); //关闭
}
serialPort1.Open(); //打开
button2.Enabled = true; //失能开启按钮
button1.Enabled = false; //启动时关闭按钮使能
}
catch
{
MessageBox.Show("please check the current serial-port state!");
}
}
close_button
try
{
//serialPort1.DataReceived -= new SerialDataReceivedEventHandler(serialPort1_DataReceived);
//Thread.Sleep(10);
if (serialPort1.IsOpen)
{
serialPort1.DiscardInBuffer(); // ??????
serialPort1.DiscardOutBuffer(); // ??????
}
serialPort1.Close();
if (serialPort1.IsOpen)
{
serialPort1.Close(); //??
}
button2.Enabled = false; //??????
button1.Enabled = true; //?????????
Serial_C_F = false;
}
catch
{
MessageBox.Show("please check the current serial-port state!");
}
refresh
private void button3_Click(object sender, EventArgs e)
{
comboBox2.Items.Clear(); //清除combox中的数据重新赋值
//获取串口号
RegistryKey keyCom = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");
string[] sSubKeys = keyCom.GetValueNames();
foreach (var sValue in sSubKeys)
{
string PortName = (string)keyCom.GetValue(sValue);
comboBox2.Items.Add(PortName);
}
}
串口接收数据处理:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] recv = new byte[serialPort1.BytesToRead]; //接收数据加入缓存区
serialPort1.Read(recv, 0, recv.Length);
string str = Encoding.GetEncoding("gb2312").GetString(recv); //接收数据格式转换
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ssss"); // 获取时间戳
richTextBox1.Text += "[" + timestamp + "]" + "?" + "<-" + " " + str; //富文本框打印信息加时间戳
//
if (str.EndsWith("\r\n")) // 判断接收数据尾
{
if (str.StartsWith("CRC_REEOR")) //判断接收数据头
{
MessageBox.Show("BOX CRC ERROR!");
crc_error_flag = true;
Console.WriteLine("BOX CRC ERROR");
}
else if (str.StartsWith("UPDATE_READY")) //判断数据头
{
star_update_flag = true;
//recv_update_flag = true;
consoler_page = 0;
is_final_page[0] = 0;
have_send_data_len = 0;
have_send_page = 0;
Console.WriteLine("UPDATE_READY");
}
else if (str.StartsWith("DATA_WRITE")) //判断数据头
{
recv_update_flag = true;
Console.WriteLine("DATA_WRITE");
}
}
}
2.2 数据流部分
private void button4_Click(object sender, EventArgs e)
{
crc_bit[0] = 0x00;
hexData = null;
OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)//选中确定后
{
textBox1.Text = dlg.FileName; //加入地址栏
string filetosplit = @dlg.FileName;
fsr = new FileStream(filetosplit, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fsr);
hexData = br.ReadBytes((int)fsr.Length);
Console.WriteLine(fsr.Length); //打印bin文件长度
fsr.Close();
bagNumber = (hexData.Length % 1024) == 0 ? hexData.Length / 1024 : hexData.Length / 1024 + 1; //分包数量
textBox2.Text = bagNumber.ToString();
fsr_flag = true;
progressBar1.Maximum = bagNumber; //赋值进度条最大长度信息
}
}
3. 其他
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
//富文本框永远保持在底部
richTextBox1.Focus();
richTextBox1.Select(richTextBox1.Text.Length, 0);
richTextBox1.ScrollToCaret();
}