单片机BootLoader上位机简介
BootLoader上位机开发语言为C#,选择uart通信,需要用到几个常用的串口控件:串口号,波特率,数据位和打开串口按钮。另外需要一个打开HEX的按钮,一个保存bin文件的按钮。打开一个BLE.HEX文件,上位机对hex文件进行解析,然后显示在窗口,最后也可以保存成bin文件,再来就是一个下载按钮,点击按钮则开始下载程序。
上位机界面
HEX文件解析工作
打开hex文件
保存bin文件
hex与bin文件比较,hex文件会有跳存储地址情况,则在空的地址填补十六进制 FF。这样既可生成完整的bin。
左hex和右bin文件比较
C# 程序部分代码览阅
using System;
using System.Collections.Generic;
using System.ComponentModel;
一、bin文件的打开方式 具体有以下两种打开方法:1、下载后如扩展名为BIN,MDF,ISO等,必须使用DAEMON TOOLS等虚拟光驱安装,DAEMON TOOLS 对于BIN和MDF等装入的时候,应该选择*.*才行。光盘镜像格式主要有:Bin,mds, ccd, 。
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
using System.IO.Ports;
using System.Threading;
namespace Boot
{
public partial class Bootloader : Form
{
bool ReceiveByte_Busy = false;
bool serialPort_Closing = false;//串口正在关闭标志
Int32 ReceiveByte_Cnt = 0;//串口操作,接收字节计数
Int32 SendByte_Cnt = 0;//串口操作,发送字节计数
public List<byte> BufferData = new List<byte>();//串口数据数据帧识别缓存空间
// public FormTM tmfrm = null;//new FormTM();
public Thread thrd = null;
public FileStream writefile = null;
byte[] buffer = new byte[1024 * 1024 * 5]; // 打开文件hex to bin缓存
int bufferAdr; // 打开文件hex to bin缓存指针
public Bootloader()
{
InitializeComponent();
}
private void Form1_Load(object sender,EventArgs e)
{
#region 串口设置初始状态
try
{
foreach (string com in System.IO.Ports.SerialPort.GetPortNames())//自动获取串口号名称
{
this.cmbboxCom.Items.Add(com);
}
cmbboxCom.SelectedIndex = 0;
//默认串口设置显示
cmbBaudRate.Items.Add("1200");
cmbBaudRate.Items.Add("2400");
cmbBaudRate.Items.Add("4800");
cmbBaudRate.Items.Add("9600");
cmbBaudRate.Items.Add("19200");
cmbBaudRate.Items.Add("38400");
cmbBaudRate.Items.Add("115200");
cmbBaudRate.SelectedIndex = 3;
cmbDataBit.SelectedIndex = 0;
}
catch
{
MessageBox.Show("找不到串口连接!","Error");
}
#endregion
}
private void btnOpen_Click(object sender,EventArgs e)
{
#region 串口点击设置
if (!serialPort1.IsOpen)
{
string sComNum = cmbboxCom.Text;
string sBaudRate = cmbBaudRate.Text;
string sDataBit = cmbDataBit.Text;
try
{
serialPort1.PortName = sComNum;
serialPort1.BaudRate = Int32.Parse(sBaudRate);
serialPort1.DataBits = Int32.Parse(sDataBit);
serialPort1.ReadTimeout = 500;
serialPort1.WriteTimeout = 500;
serialPort1.Open();
if (serialPort1.IsOpen)
{
btnOpen.Text = "关闭";
cmbboxCom.Enabled = false;
cmbBaudRate.Enabled = false;
cmbDataBit.Enabled = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
try
{
serialPort1.Close();
if (!serialPort1.IsOpen) // 如果已经关闭串口
{
btnOpen.Text = "打开";
cmbboxCom.Enabled = true;
cmbBaudRate.Enabled = true;
cmbDataBit.Enabled = true;
this.cmbboxCom.Items.Clear();
foreach (string com in System.IO.Ports.SerialPort.GetPortNames()) //重新自动获取串口号名称
{
this.cmbboxCom.Items.Add(com);
}
}
bin文件打开方法如下:1、首先打开此电脑,点击查看,勾选文件扩展名。2、右键点击bin文件,选择重命名,修改文件后缀,尝试txt、jpg、zip、pdf等常见格式。3、系统提示改变扩展名可能导致文件不可用,点击是,然后打开文件,。
}
catch { }
}
#endregion
}
private void serialPort1_DataReceived(object sender,System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (serialPort_Closing == true)//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
{
return;
}
try
{
ReceiveByte_Busy = true;//串口接收忙碌标志
int ReceiveNums = serialPort1.BytesToRead;//记录缓存数量
ReceiveByte_Cnt += ReceiveNums;
this.Invoke((EventHandler)(delegate
{
txtbRcvArea.Text = ReceiveByte_Cnt.ToString("D");
if (chkbHexDisplay.CheckState == CheckState.Checked)
{
byte[] buf = new byte[ReceiveNums];//
serialPort1.Read(buf,0,ReceiveNums);//读取缓冲数据
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadSavDat),buf);
int idx = 0;
for (; idx < BufferData.Count - 3; idx++)
{
if (BufferData[idx] == 0x39 && BufferData[idx + 1] == 0xD7 && BufferData[idx + 2] == 0x11)
{
if (BufferData.Count - idx >= 33)
{
byte[] tmb = new byte[33];
BufferData.CopyTo(idx,tmb,0,tmb.Length);
}
else
{
break;
}
}
}
BufferData.RemoveRange(0,idx);
string tempstr = string.Empty;
for (int i = 0; i < ReceiveNums; i++)
{
tempstr += buf[i].ToString("X2") + " ";
}
if (chkbPauDisp.CheckState == CheckState.Unchecked)
{
txtbRcvArea.AppendText(tempstr);//追加到接收数据显示框中
bin文件打开方法如下:1、首先打开此电脑,点击查看,勾选文件扩展名。2、右键点击bin文件,选择重命名,修改文件后缀,尝试txt、jpg、zip、pdf等常见格式。3、系统提示改变扩展名可能导致文件不可用,点击是,然后打开文件,。
}
}
else
{
serialPort1.Encoding = System.Text.Encoding.GetEncoding("GB2312");//解决乱码问题,国标2312编码格式
if (chkbPauDisp.CheckState == CheckState.Unchecked)
{
txtbRcvArea.AppendText(serialPort1.ReadExisting());
}
}
// ledRcvStat.LEDSwitch = true;
// ledRcvStat.Invalidate();
// stat_timer.Enabled = true;
}));
ReceiveByte_Busy = false;
}
catch (Exception er)
{
}
}
void ThreadSavDat(object o)
{
byte[] buf = o as byte[];
if (writefile != null && writefile.CanWrite)
{
writefile.Write(buf,0,buf.Length);
}
}
private void button1_Click(object sender,EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "请选择要打开的文本文件";
ofd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
ofd.Multiselect = true;
ofd.Filter = "HEX文件|*.hex|文本文件|*.txt|所有文件|*.*";
ofd.ShowDialog();
string path = ofd.FileName; //获得用户选中的文件的路径
//list.Add(path);//将文件的全路径存储到泛型集合中
string fileName = Path.GetFileName(path);//获得了用户打开文件的文件名
//listBox1.Items.Add(fileName);//将文件名放到ListBox中
tbHexPath.Text = fileName;
if (path == "")
{
return;
}
FileStream fsRead = new FileStream(path,FileMode.OpenOrCreate,FileAccess.Read);
string szLine;
int startAdr;
int endAdr;
endAdr = 0;
bufferAdr = 0;
txtbRcvArea.Text = "";
while (true)
{
szLine = HexReader.ReadLine(); //读取Hex中一行
if (szLine == null) { break; } //读取完毕,退出
if (szLine.Substring(0,1) == ":") //判断首字符是”:”
{
if (szLine.Substring(1,8) == "00000001") { break; } //文件结束标识
if ((szLine.Substring(8,1) == "0") || (szLine.Substring(8,1) == "1"))//直接解析数据类型标识为 : 00 和 01 的格式
{
int lineLenth;
string hexString;
hexString = szLine.Substring(1,2);
lineLenth = Int32.Parse(hexString,System.Globalization.NumberStyles.HexNumber); // 获取一行的数据个数值
hexString = szLine.Substring(3,4);
startAdr = Int32.Parse(hexString,System.Globalization.NumberStyles.HexNumber); // 获取地址值
for (int i = 0; i < startAdr - endAdr; i++) // 补空位置
{
hexString = "FF";
buffer[bufferAdr] = value;
bufferAdr++;
}
for (int i = 0; i < lineLenth; i++) // hex转换为byte
{
hexString = szLine.Substring(i * 2 + 9,2);
byte value = byte.Parse(hexString,System.Globalization.NumberStyles.HexNumber);
buffer[bufferAdr] = value;
bufferAdr++;
}
endAdr = startAdr + lineLenth;
}
}
}
txtbRcvArea.Text = byteToHexStr(buffer,bufferAdr);
}
private void button3_Click(object sender,EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @"C:\Users\SpringRain\Desktop";
sfd.Title = "请选择要保存的文件路径";
sfd.Filter = "BIN文件|*.bin|文本文件|*.txt|所有文件|*.*";
sfd.ShowDialog();
//获得用户要保存的文件的路径
string path = sfd.FileName;
//获得了用户打开文件的文件名
string fileName = Path.GetFileName(path);
rbHexPath.Text = fileName;
if (path == "")
{
return;
}
FileStream fsWrite = new FileStream(path,FileMode.OpenOrCreate,FileAccess.Write);
// byte[] buffer = Encoding.Default.GetBytes(txtbRcvArea.Text);
fsWrite.Write(buffer,0,bufferAdr);
MessageBox.Show("保存成功");
}
//字节数组转16进制字符串
public static string byteToHexStr(byte[] bytes,int len)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < len; i++)
{
returnStr += bytes[i].ToString("X2");
}
bin文件是PE光盘镜像文件。打开bin格式文件的方法如下:1、首先下载一个叫做软媒魔方的工具,然后在软媒魔方主界面找到【应用大全】,点击打开。2、在【磁盘文件】下找到虚拟光驱,点击打开。3、弹出“软媒虚拟光驱”窗口,点击。
}
return returnStr;
}
private void button4_Click(object sender,EventArgs e)
{
txtbRcvArea.Text = "";
}
}
}