├── .vs
└── win-iap-ymodem
│ └── v15
│ └── .suo
├── README.md
├── win-iap-ymodem.sln
└── win-iap-ymodem
├── Crc16Ccitt.cs
├── Form1.Designer.cs
├── Form1.cs
├── Form1.resx
├── HexToBin.cs
├── Program.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── bin
└── Debug
│ ├── win-iap-ymodem.exe
│ └── win-iap-ymodem.pdb
├── obj
└── Debug
│ ├── CoreCompileInputs.cache
│ ├── DesignTimeResolveAssemblyReferences.cache
│ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ ├── win-iap-ymodem.csproj.FileListAbsolute.txt
│ ├── win-iap-ymodem.csproj.GenerateResource.Cache
│ ├── win-iap-ymodem.csprojResolveAssemblyReference.cache
│ ├── win-iap-ymodem.exe
│ ├── win-iap-ymodem.pdb
│ ├── win_iap_ymodem.Form1.resources
│ └── win_iap_ymodem.Properties.Resources.resources
└── win-iap-ymodem.csproj
/.vs/win-iap-ymodem/v15/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/.vs/win-iap-ymodem/v15/.suo
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## STM32串口IAP的上位机工具部分使用说明
3 |
4 | > 终于我们来到这一篇,现在我们来简单说一下上位机工具的基本配置及使用。
5 |
6 | 1. 该项目实现通过PC的串口对STM32系列MCU进行IAP。
7 |
8 | 2. 该项目包含三个部分(三套代码):
9 |
10 | - 运行在STM32平台的Boot;
11 | - 运行在STM32平台的App(我做了两个,一个是支持usmart的重量版,另一个是很简洁的轻量版);
12 | - 运行在Windows平台的上位机操作工具。
13 |
14 | 3. 本篇是属于运行在windows平台的上位机工具部分,另外两篇介绍请参阅:
15 |
16 | - [STM32平台的bootloader](https://github.com/havenxie/stm32-iap-uart-boot)
17 | - [STM32平台的App(usmart版)](https://github.com/havenxie/stm32-iap-uart-app)
18 | - 或[STM32平台的App(轻量版)](https://github.com/havenxie/stm32-iap-uart-app_lite)
19 |
20 | 4. 这套代码使用C#基于.net4.0开发。我用的是vs2017.
21 |
22 | *****
23 |
24 | ## 工具使用方法:
25 |
26 | 1. 通过jlink或者其他工具将与你的硬件相对应的boot烧入你的片子。
27 |
28 | 2. 运行该上位机工具
29 |
30 | 3. 通过串口将硬件和PC进行连接
31 |
32 | 4. 选择对应的串口
33 |
34 | 5. 波特率选择115200
35 |
36 | 6. 打开串口
37 |
38 | 7. 选择你待升级的app固件
39 |
40 | 8. 包长度随你选
41 |
42 | 9. 点击"更新固件Update"按钮后固件将会自动烧录到你的片子。
43 |
44 | 10. 烧完之后自动运行app。
45 |
46 | ### 其他
47 |
48 | - "读取固件Upload"按钮将会把芯片内的固件读出来(这个功能还没有做)
49 |
50 | - "擦除固件Erase"按钮将会把App部分的固件擦除,之后运行boot的菜单。
51 |
52 | - "进入IAP菜单"按钮将会软件自动复位硬件,然后运行boot的菜单。
53 |
54 | - "运行App"按钮将会软件自动复位硬件,然后跳转到app部分去执行。
55 |
56 | - "清除窗口"按钮将会把信息视窗的内容清空。
57 |
58 | - 除了这些按钮你还可以通过在信息视窗输入相应的指令并回车以完成不同的操作,这里就不过多讲解了,你可以自己试一试。
59 |
60 | 注:boot部分只需要烧录一次即可,之后所有操作都通过上位机工具完成。
61 |
62 |
63 | *****
64 |
65 | ## 版本说明:
66 | - 用户使用master版本即可。
67 |
68 |
69 |
--------------------------------------------------------------------------------
/win-iap-ymodem.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26430.6
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "win-iap-ymodem", "win-iap-ymodem\win-iap-ymodem.csproj", "{04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Crc16Ccitt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace win_iap_ymodem
6 | {
7 | public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }
8 |
9 | public class Crc16Ccitt
10 | {
11 | const ushort poly = 0x1021;
12 | ushort[] table = new ushort[256];
13 | ushort initialValue = 0;
14 |
15 | public ushort ComputeChecksum(byte[] bytes)
16 | {
17 | ushort crc = this.initialValue;
18 | for (int i = 0; i < bytes.Length; i++)
19 | {
20 | crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
21 | }
22 | return crc;
23 | }
24 |
25 | public byte[] ComputeChecksumBytes(byte[] bytes)
26 | {
27 | ushort crc = ComputeChecksum(bytes);
28 | return new byte[] { (byte)(crc >> 8), (byte)(crc & 0x00ff) };
29 | }
30 |
31 | public Crc16Ccitt(InitialCrcValue initialValue)
32 | {
33 | this.initialValue = (ushort)initialValue;
34 | ushort temp, a;
35 | for (int i = 0; i < table.Length; i++)
36 | {
37 | temp = 0;
38 | a = (ushort)(i << 8);
39 | for (int j = 0; j < 8; j++)
40 | {
41 | if (((temp ^ a) & 0x8000) != 0)
42 | {
43 | temp = (ushort)((temp << 1) ^ poly);
44 | }
45 | else
46 | {
47 | temp <<= 1;
48 | }
49 | a <<= 1;
50 | }
51 | table[i] = temp;
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace win_iap_ymodem
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// 必需的设计器变量。
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// 清理所有正在使用的资源。
12 | ///
13 | /// 如果应释放托管资源,为 true;否则为 false。
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows 窗体设计器生成的代码
24 |
25 | ///
26 | /// 设计器支持所需的方法 - 不要修改
27 | /// 使用代码编辑器修改此方法的内容。
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | this.btn_Port = new System.Windows.Forms.Button();
33 | this.lbl_Port = new System.Windows.Forms.Label();
34 | this.progressBar1 = new System.Windows.Forms.ProgressBar();
35 | this.serialPort1 = new System.IO.Ports.SerialPort(this.components);
36 | this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
37 | this.lbl_Bps = new System.Windows.Forms.Label();
38 | this.lbl_Pass = new System.Windows.Forms.Label();
39 | this.cbx_Port = new System.Windows.Forms.ComboBox();
40 | this.cbx_Baud = new System.Windows.Forms.ComboBox();
41 | this.txb_FilePath = new System.Windows.Forms.TextBox();
42 | this.btn_SelectFile = new System.Windows.Forms.Button();
43 | this.groupBox1 = new System.Windows.Forms.GroupBox();
44 | this.groupBox2 = new System.Windows.Forms.GroupBox();
45 | this.btn_Clear = new System.Windows.Forms.Button();
46 | this.tbx_show = new System.Windows.Forms.TextBox();
47 | this.btn_Erase = new System.Windows.Forms.Button();
48 | this.btn_Upload = new System.Windows.Forms.Button();
49 | this.btn_RunApp = new System.Windows.Forms.Button();
50 | this.btn_Update = new System.Windows.Forms.Button();
51 | this.btn_IAPMenu = new System.Windows.Forms.Button();
52 | this.groupBox3 = new System.Windows.Forms.GroupBox();
53 | this.cbx_PageSize = new System.Windows.Forms.ComboBox();
54 | this.label1 = new System.Windows.Forms.Label();
55 | this.groupBox1.SuspendLayout();
56 | this.groupBox2.SuspendLayout();
57 | this.groupBox3.SuspendLayout();
58 | this.SuspendLayout();
59 | //
60 | // btn_Port
61 | //
62 | this.btn_Port.Location = new System.Drawing.Point(22, 120);
63 | this.btn_Port.Name = "btn_Port";
64 | this.btn_Port.Size = new System.Drawing.Size(155, 32);
65 | this.btn_Port.TabIndex = 0;
66 | this.btn_Port.Text = "打开";
67 | this.btn_Port.UseVisualStyleBackColor = true;
68 | this.btn_Port.Click += new System.EventHandler(this.btn_Port_Click);
69 | //
70 | // lbl_Port
71 | //
72 | this.lbl_Port.AutoSize = true;
73 | this.lbl_Port.Location = new System.Drawing.Point(20, 41);
74 | this.lbl_Port.Name = "lbl_Port";
75 | this.lbl_Port.Size = new System.Drawing.Size(53, 12);
76 | this.lbl_Port.TabIndex = 1;
77 | this.lbl_Port.Text = "串口号:";
78 | //
79 | // progressBar1
80 | //
81 | this.progressBar1.BackColor = System.Drawing.SystemColors.ControlLight;
82 | this.progressBar1.Location = new System.Drawing.Point(12, 381);
83 | this.progressBar1.Name = "progressBar1";
84 | this.progressBar1.Size = new System.Drawing.Size(715, 22);
85 | this.progressBar1.TabIndex = 2;
86 | //
87 | // serialPort1
88 | //
89 | this.serialPort1.BaudRate = 115200;
90 | this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
91 | //
92 | // openFileDialog1
93 | //
94 | this.openFileDialog1.Filter = "bin文件(*.bin)|*.bin|hex文件(*.hex)|*.hex";
95 | this.openFileDialog1.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog1_FileOk);
96 | //
97 | // lbl_Bps
98 | //
99 | this.lbl_Bps.AutoSize = true;
100 | this.lbl_Bps.Location = new System.Drawing.Point(20, 81);
101 | this.lbl_Bps.Name = "lbl_Bps";
102 | this.lbl_Bps.Size = new System.Drawing.Size(53, 12);
103 | this.lbl_Bps.TabIndex = 3;
104 | this.lbl_Bps.Text = "波特率:";
105 | //
106 | // lbl_Pass
107 | //
108 | this.lbl_Pass.AutoSize = true;
109 | this.lbl_Pass.Location = new System.Drawing.Point(19, 30);
110 | this.lbl_Pass.Name = "lbl_Pass";
111 | this.lbl_Pass.Size = new System.Drawing.Size(65, 12);
112 | this.lbl_Pass.TabIndex = 4;
113 | this.lbl_Pass.Text = "文件路径:";
114 | //
115 | // cbx_Port
116 | //
117 | this.cbx_Port.FormattingEnabled = true;
118 | this.cbx_Port.Location = new System.Drawing.Point(79, 38);
119 | this.cbx_Port.Name = "cbx_Port";
120 | this.cbx_Port.Size = new System.Drawing.Size(98, 20);
121 | this.cbx_Port.TabIndex = 5;
122 | this.cbx_Port.DropDown += new System.EventHandler(this.cbx_Port_DropDown);
123 | //
124 | // cbx_Baud
125 | //
126 | this.cbx_Baud.FormattingEnabled = true;
127 | this.cbx_Baud.Items.AddRange(new object[] {
128 | "Custom",
129 | "110",
130 | "300",
131 | "600",
132 | "1200",
133 | "2400",
134 | "4800",
135 | "9600",
136 | "14400",
137 | "19200",
138 | "38400",
139 | "56000",
140 | "57600",
141 | "115200",
142 | "128000",
143 | "256000"});
144 | this.cbx_Baud.Location = new System.Drawing.Point(79, 78);
145 | this.cbx_Baud.Name = "cbx_Baud";
146 | this.cbx_Baud.Size = new System.Drawing.Size(98, 20);
147 | this.cbx_Baud.TabIndex = 6;
148 | //
149 | // txb_FilePath
150 | //
151 | this.txb_FilePath.BackColor = System.Drawing.SystemColors.Window;
152 | this.txb_FilePath.Location = new System.Drawing.Point(21, 54);
153 | this.txb_FilePath.Name = "txb_FilePath";
154 | this.txb_FilePath.Size = new System.Drawing.Size(155, 21);
155 | this.txb_FilePath.TabIndex = 7;
156 | //
157 | // btn_SelectFile
158 | //
159 | this.btn_SelectFile.Location = new System.Drawing.Point(112, 25);
160 | this.btn_SelectFile.Name = "btn_SelectFile";
161 | this.btn_SelectFile.Size = new System.Drawing.Size(64, 23);
162 | this.btn_SelectFile.TabIndex = 8;
163 | this.btn_SelectFile.Text = "选择文件";
164 | this.btn_SelectFile.UseVisualStyleBackColor = true;
165 | this.btn_SelectFile.Click += new System.EventHandler(this.btn_SelectFile_Click);
166 | //
167 | // groupBox1
168 | //
169 | this.groupBox1.Controls.Add(this.btn_Port);
170 | this.groupBox1.Controls.Add(this.lbl_Bps);
171 | this.groupBox1.Controls.Add(this.lbl_Port);
172 | this.groupBox1.Controls.Add(this.cbx_Port);
173 | this.groupBox1.Controls.Add(this.cbx_Baud);
174 | this.groupBox1.Location = new System.Drawing.Point(12, 12);
175 | this.groupBox1.Name = "groupBox1";
176 | this.groupBox1.Size = new System.Drawing.Size(191, 173);
177 | this.groupBox1.TabIndex = 10;
178 | this.groupBox1.TabStop = false;
179 | this.groupBox1.Text = "端口操作";
180 | //
181 | // groupBox2
182 | //
183 | this.groupBox2.Controls.Add(this.btn_Clear);
184 | this.groupBox2.Controls.Add(this.tbx_show);
185 | this.groupBox2.Location = new System.Drawing.Point(220, 12);
186 | this.groupBox2.Name = "groupBox2";
187 | this.groupBox2.Size = new System.Drawing.Size(507, 306);
188 | this.groupBox2.TabIndex = 11;
189 | this.groupBox2.TabStop = false;
190 | this.groupBox2.Text = "信息视窗";
191 | //
192 | // btn_Clear
193 | //
194 | this.btn_Clear.Location = new System.Drawing.Point(0, 276);
195 | this.btn_Clear.Name = "btn_Clear";
196 | this.btn_Clear.Size = new System.Drawing.Size(75, 23);
197 | this.btn_Clear.TabIndex = 16;
198 | this.btn_Clear.Text = "清除窗口";
199 | this.btn_Clear.UseVisualStyleBackColor = true;
200 | this.btn_Clear.Click += new System.EventHandler(this.btn_Clear_Click);
201 | //
202 | // tbx_show
203 | //
204 | this.tbx_show.BackColor = System.Drawing.SystemColors.HighlightText;
205 | this.tbx_show.Location = new System.Drawing.Point(1, 20);
206 | this.tbx_show.Multiline = true;
207 | this.tbx_show.Name = "tbx_show";
208 | this.tbx_show.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
209 | this.tbx_show.Size = new System.Drawing.Size(506, 255);
210 | this.tbx_show.TabIndex = 9;
211 | this.tbx_show.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.tbx_show_KeyPress);
212 | //
213 | // btn_Erase
214 | //
215 | this.btn_Erase.Location = new System.Drawing.Point(429, 336);
216 | this.btn_Erase.Name = "btn_Erase";
217 | this.btn_Erase.Size = new System.Drawing.Size(94, 28);
218 | this.btn_Erase.TabIndex = 12;
219 | this.btn_Erase.Text = "擦除固件Erase";
220 | this.btn_Erase.UseVisualStyleBackColor = true;
221 | this.btn_Erase.Click += new System.EventHandler(this.btn_Erase_Click);
222 | //
223 | // btn_Upload
224 | //
225 | this.btn_Upload.Location = new System.Drawing.Point(324, 336);
226 | this.btn_Upload.Name = "btn_Upload";
227 | this.btn_Upload.Size = new System.Drawing.Size(99, 28);
228 | this.btn_Upload.TabIndex = 13;
229 | this.btn_Upload.Text = "读取固件UpLoad";
230 | this.btn_Upload.UseVisualStyleBackColor = true;
231 | this.btn_Upload.Click += new System.EventHandler(this.btn_Upload_Click);
232 | //
233 | // btn_RunApp
234 | //
235 | this.btn_RunApp.Location = new System.Drawing.Point(631, 336);
236 | this.btn_RunApp.Name = "btn_RunApp";
237 | this.btn_RunApp.Size = new System.Drawing.Size(96, 28);
238 | this.btn_RunApp.TabIndex = 14;
239 | this.btn_RunApp.Text = "运行App";
240 | this.btn_RunApp.UseVisualStyleBackColor = true;
241 | this.btn_RunApp.Click += new System.EventHandler(this.btn_RunApp_Click);
242 | //
243 | // btn_Update
244 | //
245 | this.btn_Update.BackColor = System.Drawing.SystemColors.ControlLight;
246 | this.btn_Update.ForeColor = System.Drawing.SystemColors.Desktop;
247 | this.btn_Update.Location = new System.Drawing.Point(220, 336);
248 | this.btn_Update.Name = "btn_Update";
249 | this.btn_Update.Size = new System.Drawing.Size(98, 28);
250 | this.btn_Update.TabIndex = 15;
251 | this.btn_Update.Text = "更新固件UpDate";
252 | this.btn_Update.UseVisualStyleBackColor = false;
253 | this.btn_Update.Click += new System.EventHandler(this.btn_Update_Click);
254 | //
255 | // btn_IAPMenu
256 | //
257 | this.btn_IAPMenu.Location = new System.Drawing.Point(529, 336);
258 | this.btn_IAPMenu.Name = "btn_IAPMenu";
259 | this.btn_IAPMenu.Size = new System.Drawing.Size(96, 28);
260 | this.btn_IAPMenu.TabIndex = 16;
261 | this.btn_IAPMenu.Text = "进入IAP菜单";
262 | this.btn_IAPMenu.UseVisualStyleBackColor = true;
263 | this.btn_IAPMenu.Click += new System.EventHandler(this.btn_IAPMenu_Click);
264 | //
265 | // groupBox3
266 | //
267 | this.groupBox3.Controls.Add(this.cbx_PageSize);
268 | this.groupBox3.Controls.Add(this.label1);
269 | this.groupBox3.Controls.Add(this.lbl_Pass);
270 | this.groupBox3.Controls.Add(this.btn_SelectFile);
271 | this.groupBox3.Controls.Add(this.txb_FilePath);
272 | this.groupBox3.Location = new System.Drawing.Point(13, 191);
273 | this.groupBox3.Name = "groupBox3";
274 | this.groupBox3.Size = new System.Drawing.Size(190, 173);
275 | this.groupBox3.TabIndex = 17;
276 | this.groupBox3.TabStop = false;
277 | this.groupBox3.Text = "文件设置";
278 | //
279 | // cbx_PageSize
280 | //
281 | this.cbx_PageSize.FormattingEnabled = true;
282 | this.cbx_PageSize.Items.AddRange(new object[] {
283 | "32",
284 | "64",
285 | "128",
286 | "256",
287 | "512",
288 | "1024"});
289 | this.cbx_PageSize.Location = new System.Drawing.Point(78, 99);
290 | this.cbx_PageSize.Name = "cbx_PageSize";
291 | this.cbx_PageSize.Size = new System.Drawing.Size(98, 20);
292 | this.cbx_PageSize.TabIndex = 10;
293 | //
294 | // label1
295 | //
296 | this.label1.AutoSize = true;
297 | this.label1.Location = new System.Drawing.Point(19, 102);
298 | this.label1.Name = "label1";
299 | this.label1.Size = new System.Drawing.Size(53, 12);
300 | this.label1.TabIndex = 9;
301 | this.label1.Text = "包长度:";
302 | //
303 | // Form1
304 | //
305 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
306 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
307 | this.BackColor = System.Drawing.SystemColors.ControlLightLight;
308 | this.ClientSize = new System.Drawing.Size(743, 416);
309 | this.Controls.Add(this.groupBox3);
310 | this.Controls.Add(this.btn_IAPMenu);
311 | this.Controls.Add(this.btn_RunApp);
312 | this.Controls.Add(this.btn_Upload);
313 | this.Controls.Add(this.btn_Erase);
314 | this.Controls.Add(this.btn_Update);
315 | this.Controls.Add(this.groupBox2);
316 | this.Controls.Add(this.groupBox1);
317 | this.Controls.Add(this.progressBar1);
318 | this.Name = "Form1";
319 | this.Text = "STM32-IAP上位机操作工具";
320 | this.Load += new System.EventHandler(this.Form1_Load);
321 | this.groupBox1.ResumeLayout(false);
322 | this.groupBox1.PerformLayout();
323 | this.groupBox2.ResumeLayout(false);
324 | this.groupBox2.PerformLayout();
325 | this.groupBox3.ResumeLayout(false);
326 | this.groupBox3.PerformLayout();
327 | this.ResumeLayout(false);
328 |
329 | }
330 |
331 | #endregion
332 |
333 | private System.Windows.Forms.Button btn_Port;
334 | private System.Windows.Forms.Label lbl_Port;
335 | private System.Windows.Forms.ProgressBar progressBar1;
336 | private System.IO.Ports.SerialPort serialPort1;
337 | private System.Windows.Forms.OpenFileDialog openFileDialog1;
338 | private System.Windows.Forms.Label lbl_Bps;
339 | private System.Windows.Forms.Label lbl_Pass;
340 | private System.Windows.Forms.ComboBox cbx_Port;
341 | private System.Windows.Forms.ComboBox cbx_Baud;
342 | private System.Windows.Forms.TextBox txb_FilePath;
343 | private System.Windows.Forms.Button btn_SelectFile;
344 | private System.Windows.Forms.GroupBox groupBox1;
345 | private System.Windows.Forms.GroupBox groupBox2;
346 | private System.Windows.Forms.Button btn_Erase;
347 | private System.Windows.Forms.Button btn_Upload;
348 | private System.Windows.Forms.Button btn_RunApp;
349 | private System.Windows.Forms.TextBox tbx_show;
350 | private System.Windows.Forms.Button btn_Update;
351 | private System.Windows.Forms.Button btn_Clear;
352 | private System.Windows.Forms.Button btn_IAPMenu;
353 | private System.Windows.Forms.GroupBox groupBox3;
354 | private System.Windows.Forms.ComboBox cbx_PageSize;
355 | private System.Windows.Forms.Label label1;
356 | }
357 | }
358 |
359 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using System.Globalization;
10 | using System.IO;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using Microsoft.Win32;
14 |
15 | namespace win_iap_ymodem
16 | {
17 | public partial class Form1 : Form
18 | {
19 | private bool hasOpenPort = false;
20 | public bool HasOpenPort
21 | {
22 | get { return hasOpenPort; }
23 | set
24 | {
25 | hasOpenPort = value;
26 | if (hasOpenPort && hasSelectBin)
27 | openControlBtn();
28 | else
29 | closeControlBtn();
30 | }
31 | }
32 | private bool hasSelectBin = false;
33 | public bool HasSelectBin
34 | {
35 | get { return hasSelectBin; }
36 | set
37 | {
38 | hasSelectBin = value;
39 | if (hasOpenPort && hasSelectBin)
40 | openControlBtn();
41 | else
42 | closeControlBtn();
43 | }
44 | }
45 |
46 | public static string filePath = "";
47 | string sendCmd = "";
48 | int fsLen = 0;
49 |
50 | /* packet define */
51 | const byte C = 67; // capital letter C
52 | byte STX = 2; // Start Of Text
53 | //const byte PACKET_SEQNO_INDEX = 1;
54 | //const byte PACKET_SEQNO_COMP_INDEX = 2;
55 | //const byte PACKET_HEADER = 3;
56 | //const byte PACKET_TRAILER = 2;
57 | //const byte PACKET_OVERHEAD = 2 + 3;
58 |
59 | const int FILE_NAME_LENGTH = 256;
60 | const byte FILE_SIZE_LENGTH = 16;
61 |
62 | public Form1()
63 | {
64 | InitializeComponent();
65 | }
66 |
67 | private void Form1_Load(object sender, EventArgs e)
68 | {
69 | closeControlBtn();
70 | EnumComportfromReg(cbx_Port);
71 | serialPort1.Encoding = Encoding.GetEncoding("gb2312");//串口接收编码GB2312码
72 | System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//忽略程序跨越线程运行导致的错误.没有此句将会产生错误
73 | cbx_Baud.SelectedIndex = 13;
74 | cbx_PageSize.SelectedIndex = 4;
75 | }
76 |
77 |
78 | ///
79 | /// enabled all button
80 | ///
81 | private void openControlBtn()
82 | {
83 | btn_Update.Enabled = true;
84 | btn_Upload.Enabled = true;
85 | //btn_Erase.Enabled = true;
86 | btn_IAPMenu.Enabled = true;
87 | btn_RunApp.Enabled = true;
88 | }
89 |
90 |
91 | ///
92 | /// disabled all button
93 | ///
94 | private void closeControlBtn()
95 | {
96 | btn_Update.Enabled = false;
97 | btn_Upload.Enabled = false;
98 | //btn_Erase.Enabled = false;
99 | btn_IAPMenu.Enabled = false;
100 | btn_RunApp.Enabled = false;
101 |
102 | }
103 |
104 |
105 | ///
106 | /// the button for select bin file or hex file.
107 | ///
108 | ///
109 | ///
110 | private void btn_SelectFile_Click(object sender, EventArgs e)
111 | {
112 | openFileDialog1.ShowDialog();
113 | }
114 |
115 |
116 | ///
117 | /// has been selected the right file.
118 | ///
119 | ///
120 | ///
121 | private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
122 | {
123 | filePath = openFileDialog1.FileName;
124 | //Get the extension of the file
125 | string extName = Path.GetExtension(filePath);
126 | if (extName == ".hex")
127 | {
128 | //we shoule convert the hex file to bin file.
129 | if (HexToBin.convertHexToBin(filePath))
130 | {
131 | tbx_show.AppendText("> 文件转换完成!\r\n");
132 | }
133 | else
134 | {
135 | tbx_show.AppendText("> 文件转换失败!\r\n");
136 | }
137 | }
138 |
139 | txb_FilePath.Text = filePath;
140 |
141 | HasSelectBin = true;//flag has been select file.
142 |
143 | FileStream fileStream = new FileStream(@filePath, FileMode.Open, FileAccess.Read);
144 | fsLen = (int)fileStream.Length;
145 | tbx_show.AppendText("文件大小: " + fsLen.ToString() + "\r\n");
146 | }
147 |
148 |
149 | ///
150 | /// get all port and add to cbx_Port.
151 | ///
152 | ///
153 | ///
154 | private void cbx_Port_DropDown(object sender, EventArgs e)
155 | {
156 | if (!HasOpenPort)
157 | {
158 | EnumComportfromReg(cbx_Port);
159 | }
160 | }
161 |
162 |
163 | ///
164 | /// open or close port.
165 | ///
166 | ///
167 | ///
168 | private void btn_Port_Click(object sender, EventArgs e)
169 | {
170 | if (serialPort1.IsOpen)//try to close
171 | {
172 | try
173 | {
174 | serialPort1.Close();
175 | btn_Port.Text = "打开";
176 | HasOpenPort = false;
177 | }
178 | catch (Exception ex)
179 | {
180 | MessageBox.Show("关闭失败");
181 | return;
182 | }
183 | }
184 | else //try to open
185 | {
186 | if (cbx_Port.Items.Count == 0)
187 | return;
188 | int baud = int.Parse(cbx_Baud.Text);
189 | serialPort1.PortName = cbx_Port.Text;
190 | serialPort1.BaudRate = baud;
191 | try
192 | {
193 | serialPort1.Open();
194 | btn_Port.Text = "关闭";
195 | HasOpenPort = true;
196 | }
197 | catch (Exception ex)
198 | {
199 | MessageBox.Show("打开失败");
200 | return;
201 | }
202 | }
203 | }
204 |
205 |
206 | ///
207 | /// Get the port list from the registry
208 | ///
209 | ///
210 | private void EnumComportfromReg(ComboBox Combobox)
211 | {
212 | Combobox.Items.Clear();
213 | ///定义注册表子Path
214 | string strRegPath = @"Hardware\\DeviceMap\\SerialComm";
215 | ///创建两个RegistryKey类,一个将指向Root Path,另一个将指向子Path
216 | RegistryKey regRootKey;
217 | RegistryKey regSubKey;
218 | ///定义Root指向注册表HKEY_LOCAL_MACHINE节点
219 | regRootKey = Registry.LocalMachine;
220 | regSubKey = regRootKey.OpenSubKey(strRegPath);
221 | if (regSubKey.GetValueNames() == null)
222 | {
223 | MessageBox.Show("获取串口设备失败");
224 | return;
225 | }
226 | string[] strCommList = regSubKey.GetValueNames();
227 | foreach (string VName in strCommList)
228 | {
229 | //向listbox1中添加字符串的名称和数据,数据是从rk对象中的GetValue(it)方法中得来的
230 | Combobox.Items.Add(regSubKey.GetValue(VName));
231 | }
232 | if (Combobox.Items.Count > 0)
233 | {
234 | Combobox.SelectedIndex = 0;
235 | }
236 | else
237 | {
238 | Combobox.Text = "";
239 | }
240 | regSubKey.Close();
241 | regRootKey.Close();
242 | }
243 |
244 |
245 | ///
246 | /// once has date in. we should show it on the txb.(找到了bug的原因,就是有数据来了之后首先主动去读取了一次数据,然后又通过这个服务去被动读取了一次,所以会出现问题。)
247 | ///
248 | ///
249 | ///
250 | private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
251 | {
252 | try
253 | {
254 | string revData = serialPort1.ReadExisting();
255 | tbx_show.AppendText(revData);
256 | }
257 | catch
258 | {
259 | MessageBox.Show("串口出现故障");
260 | }
261 | }
262 |
263 |
264 | ///
265 | /// A thread to update firmware.
266 | ///
267 | private void updateFileThread()
268 | {
269 | YmodemUpdateFile(txb_FilePath.Text);
270 | }
271 |
272 |
273 | ///
274 | /// upload the firmware when the app is runing.
275 | ///
276 | ///
277 | ///
278 | private void btn_Update_Click(object sender, EventArgs e)
279 | {
280 | if ( !File.Exists(@txb_FilePath.Text) || (Path.GetExtension(@txb_FilePath.Text) != ".bin"))
281 | {
282 | MessageBox.Show("请选择有效的bin文件", "提示");
283 | return;
284 | }
285 |
286 | progressBar1.Value = 0;
287 | this.serialPort1.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
288 | serialPort1.Write("update\r\n");//发送更新命令
289 | serialPort1.ReadTimeout = 1000;
290 | try
291 | {
292 | string rec = serialPort1.ReadTo("C");
293 | Thread UploadThread = new Thread(updateFileThread);
294 | UploadThread.Start();
295 | }
296 | catch
297 | {
298 | MessageBox.Show("后台下载失败");
299 | }
300 | finally
301 | {
302 | this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
303 | }
304 | }
305 |
306 |
307 | ///
308 | /// erase all flash when the button has checked.
309 | ///
310 | ///
311 | ///
312 | private void btn_Erase_Click(object sender, EventArgs e)
313 | {
314 | progressBar1.Value = 0;
315 | this.serialPort1.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
316 |
317 | serialPort1.Write("erase\r\n");
318 | serialPort1.ReadTimeout = 1000;
319 | try
320 | {
321 | string rec = serialPort1.ReadTo("@");
322 | rec = serialPort1.ReadTo("@");
323 | progressBar1.Maximum = Convert.ToInt32(rec);
324 | tbx_show.AppendText("\r\n\n> 需要擦除 " + rec + " 页:\r\n");
325 | while (true)
326 | {
327 | rec = serialPort1.ReadTo("@");
328 | if (rec != "")
329 | {
330 | int val = Convert.ToInt32(rec);
331 | if (val < progressBar1.Maximum)
332 | {
333 | progressBar1.Value = val;
334 | tbx_show.AppendText("> 正在擦除 " + val + " 页.\r\n");
335 | }
336 | else
337 | {
338 | progressBar1.Value = progressBar1.Maximum;
339 | tbx_show.AppendText("> 正在擦除 " + val + " 页.\r\n");
340 | tbx_show.AppendText("> 擦除完成.\r\n");
341 | break;
342 | }
343 | }
344 | }
345 | }
346 | catch (TimeoutException)
347 | {
348 | tbx_show.AppendText("> 响应超时.\r\n");
349 | }
350 | finally {
351 | this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
352 | }
353 | }
354 |
355 |
356 | ///
357 | /// upload the app file form stm32 to PC.
358 | ///
359 | ///
360 | ///
361 | private void btn_Upload_Click(object sender, EventArgs e)
362 | {
363 | //to do.
364 | MessageBox.Show("不好意思,这个功能还没有做。");
365 | }
366 |
367 |
368 | ///
369 | /// into iap menu
370 | ///
371 | ///
372 | ///
373 | private void btn_IAPMenu_Click(object sender, EventArgs e)
374 | {
375 | serialPort1.Write("menu\r\n");
376 | }
377 |
378 |
379 | private void btn_RunApp_Click(object sender, EventArgs e)
380 | {
381 | serialPort1.Write("runapp\r\n");
382 | }
383 |
384 | ///
385 | /// reset the stm32 when the button has been checkde.
386 | ///
387 | ///
388 | ///
389 | private void btn_Reset_Click(object sender, EventArgs e)
390 | {
391 | serialPort1.Write("reset\r\n");
392 | }
393 |
394 |
395 | ///
396 | /// clear tbx_show window when the button has been checked.
397 | ///
398 | ///
399 | ///
400 | private void btn_Clear_Click(object sender, EventArgs e)
401 | {
402 | tbx_show.Text = "";
403 | }
404 |
405 |
406 |
407 | ///
408 | /// when user is input the key on the tbx_show, it should be send to stm32.
409 | ///
410 | ///
411 | ///
412 | private void tbx_show_KeyPress(object sender, KeyPressEventArgs e)
413 | {
414 | if (e.KeyChar == (char)Keys.Enter)
415 | {
416 | //tbx_show.AppendText("\r\n" + sendCmd + "\r\n");
417 | switch (sendCmd)
418 | {
419 | case "update":
420 | btn_Update_Click(null, null);
421 | break;
422 | case "upload":
423 | btn_Upload_Click(null, null);
424 | break;
425 | case "erase":
426 | btn_Erase_Click(null, null);
427 | break;
428 | case "menu":
429 | btn_IAPMenu_Click(null, null);
430 | break;
431 | case "runapp":
432 | btn_RunApp_Click(null, null);
433 | break;
434 | default:
435 | serialPort1.Write(sendCmd + "\r\n");
436 | break;
437 | }
438 | sendCmd = "";
439 | }
440 | else if (e.KeyChar == (char)Keys.Back)
441 | {
442 | if(sendCmd.Length > 0)
443 | sendCmd = sendCmd.Substring(0, sendCmd.Length - 1);
444 | }
445 | else
446 | {
447 | sendCmd += e.KeyChar.ToString();
448 | }
449 | }
450 |
451 |
452 | private byte getPageHead(string text)
453 | {
454 | switch (Convert.ToInt32(text))
455 | {
456 | //case 8:
457 | // return 0xA1;
458 | //case 16:
459 | // return 0xA2;
460 | case 32:
461 | return 0xA3;
462 | case 64:
463 | return 0xA4;
464 | case 128:
465 | return 0xA5;
466 | case 256:
467 | return 0xA6;
468 | case 512:
469 | return 0xA7;
470 | case 1024:
471 | return 0xA8;
472 | //case 2048:
473 | // return 0xA9;
474 | default:
475 | return 2;
476 | }
477 | }
478 | private bool YmodemUpdateFile(string filePath)
479 | {
480 | const byte SOH = 1; // Start Of Head
481 |
482 | const byte EOT = 4; // End Of Transmission
483 | const byte ACK = 6; // Positive ACknowledgement
484 | const int crcSize = 2;
485 |
486 | //byte HEAD = 0;
487 | // int dataSize = 1024;
488 | int dataSize = Convert.ToInt32(cbx_PageSize.Text);
489 | STX = getPageHead(cbx_PageSize.Text);
490 |
491 | /* header: 3 bytes */
492 | int proprassVal = 0;
493 | int packetNumber = 0;
494 | int invertedPacketNumber = 255;
495 | /* data: 1024 bytes */
496 | byte[] data = new byte[dataSize];
497 | /* footer: 2 bytes */
498 | byte[] CRC = new byte[crcSize];
499 |
500 | /* get the file */
501 | FileStream fileStream = new FileStream(@filePath, FileMode.Open, FileAccess.Read);
502 | int packetCnt = (fileStream.Length % dataSize) == 0 ? (int)(fileStream.Length / dataSize) : (int)(fileStream.Length / dataSize) + 1;
503 | progressBar1.Maximum = packetCnt;
504 |
505 | try
506 | {
507 | if (!sendYmodemInitialPacket(STX, packetNumber, invertedPacketNumber, data, dataSize, filePath, fileStream, CRC, crcSize)) return false;
508 |
509 | if (serialPort1.ReadByte() != ACK)
510 | {
511 | Console.WriteLine("Can't send the initial packet.");
512 | return false;
513 | }
514 |
515 | if (serialPort1.ReadByte() != C)
516 | return false;
517 |
518 | /* send packets with a cycle until we send the last byte */
519 | int fileReadCount;
520 | do
521 | {
522 | /* if this is the last packet fill the remaining bytes with 0 */
523 | fileReadCount = fileStream.Read(data, 0, dataSize);
524 | if (fileReadCount == 0) break;
525 | if (fileReadCount != dataSize)
526 | for (int i = fileReadCount; i < dataSize; i++)
527 | data[i] = 0;
528 |
529 | /* calculate packetNumber */
530 | packetNumber++;
531 | if (packetNumber > 255)
532 | packetNumber -= 256;
533 | Console.WriteLine(packetNumber);
534 |
535 | /* calculate invertedPacketNumber */
536 | invertedPacketNumber = 255 - packetNumber;
537 |
538 | /* calculate CRC */
539 | Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.Zeros);
540 | CRC = crc16Ccitt.ComputeChecksumBytes(data);
541 |
542 | /* send the packet */
543 | if (!sendYmodemPacket(STX, packetNumber, invertedPacketNumber, data, dataSize, CRC, crcSize)) return false;
544 | progressBar1.Value = ++proprassVal;
545 | /* wait for ACK */
546 | if (serialPort1.ReadByte() != ACK)
547 | {
548 | Console.WriteLine("Couldn't send a packet.");
549 | return false;
550 | }
551 | } while (dataSize == fileReadCount);
552 |
553 | /* send EOT (tell the downloader we are finished) */
554 | serialPort1.Write(new byte[] { EOT }, 0, 1);
555 | /* send closing packet */
556 | packetNumber = 0;
557 | invertedPacketNumber = 255;
558 | data = new byte[dataSize];
559 | CRC = new byte[crcSize];
560 | if (!sendYmodemClosingPacket(STX, packetNumber, invertedPacketNumber, data, dataSize, CRC, crcSize)) return false;
561 | /* get ACK (downloader acknowledge the EOT) */
562 | if (serialPort1.ReadByte() != ACK)
563 | {
564 | Console.WriteLine("Can't complete the transfer.");
565 | return false;
566 | }
567 | }
568 | catch (TimeoutException)
569 | {
570 | progressBar1.Value = 0;
571 | MessageBox.Show("数据传输超时");
572 | }
573 | catch (InvalidOperationException)
574 | {
575 | progressBar1.Value = 0;
576 | MessageBox.Show("端口打开失败");
577 | }
578 | catch (IOException)
579 | {
580 | progressBar1.Value = 0;
581 | MessageBox.Show("端口被中断,请检查连接");
582 | }
583 | finally
584 | {
585 | fileStream.Close();
586 | }
587 |
588 | Console.WriteLine("File transfer is succesful");
589 | return true;
590 | }
591 |
592 |
593 | private bool sendYmodemPacket(byte STX, int packetNumber, int invertedPacketNumber, byte[] data, int dataSize, byte[] CRC, int crcSize)
594 | {
595 | try
596 | {
597 | serialPort1.Write(new byte[] { STX }, 0, 1);
598 | serialPort1.Write(new byte[] { (byte)packetNumber }, 0, 1);
599 | serialPort1.Write(new byte[] { (byte)invertedPacketNumber }, 0, 1);
600 | serialPort1.Write(data, 0, dataSize);
601 | serialPort1.Write(CRC, 0, crcSize);
602 | return true;
603 | }
604 | catch (InvalidOperationException)
605 | {
606 | MessageBox.Show("端口打开失败");
607 | return false;
608 | }
609 | catch (TimeoutException)
610 | {
611 | MessageBox.Show("数据传输超时");
612 | return false;
613 | }
614 | catch (IOException)
615 | {
616 | MessageBox.Show("端口被中断,请检查连接");
617 | return false;
618 | }
619 |
620 | }
621 |
622 |
623 | private bool sendYmodemInitialPacket(byte STX, int packetNumber, int invertedPacketNumber, byte[] data, int dataSize, string path, FileStream fileStream, byte[] CRC, int crcSize)
624 | {
625 | string fileName = System.IO.Path.GetFileName(path);
626 | string fileSize = fileStream.Length.ToString();
627 |
628 |
629 | /* add filename to data */
630 | int i;
631 | for (i = 0; i < fileName.Length && (fileName.ToCharArray()[i] != 0); i++)
632 | {
633 | data[i] = (byte)fileName.ToCharArray()[i];
634 | }
635 | data[i] = 0;
636 |
637 | /* add filesize to data */
638 | int j;
639 | for (j = 0; j < fileSize.Length && (fileSize.ToCharArray()[j] != 0); j++)
640 | {
641 | data[(i + 1) + j] = (byte)fileSize.ToCharArray()[j];
642 | }
643 | data[(i + 1) + j] = 0;
644 |
645 | /* fill the remaining data bytes with 0 */
646 | for (int k = ((i + 1) + j) + 1; k < dataSize; k++)
647 | {
648 | data[k] = 0;
649 | }
650 |
651 | /* calculate CRC */
652 | Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.Zeros);
653 | CRC = crc16Ccitt.ComputeChecksumBytes(data);
654 |
655 | /* send the packet */
656 | if (!sendYmodemPacket(STX, packetNumber, invertedPacketNumber, data, dataSize, CRC, crcSize)) return false;
657 | return true;
658 | }
659 |
660 |
661 | private bool sendYmodemClosingPacket(byte STX, int packetNumber, int invertedPacketNumber, byte[] data, int dataSize, byte[] CRC, int crcSize)
662 | {
663 | /* calculate CRC */
664 | Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.Zeros);
665 | CRC = crc16Ccitt.ComputeChecksumBytes(data);
666 |
667 | /* send the packet */
668 | if (!sendYmodemPacket(STX, packetNumber, invertedPacketNumber, data, dataSize, CRC, crcSize)) return false;
669 |
670 | return true;
671 | }
672 |
673 |
674 | }
675 | }
676 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 131, 17
125 |
126 |
127 | 46
128 |
129 |
--------------------------------------------------------------------------------
/win-iap-ymodem/HexToBin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using System.Globalization;
10 | using System.IO;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using Microsoft.Win32;
14 |
15 | namespace win_iap_ymodem
16 | {
17 | public class HexToBin
18 | {
19 | public static bool convertHexToBin(string szHexPath)
20 | {
21 | Int32 i = 0;
22 | Int32 j = 0;
23 | Int32 maxAddr = 0; //HEX文件的最大地址
24 | Int32 segAddr = 0; //段地址
25 | Int32 first = 0;
26 | Int32 row = 0;
27 | Int32 sum = 0;
28 | try
29 | {
30 | String szLine = "";
31 | String szHex = "";
32 | if (szHexPath == "")
33 | {
34 | MessageBox.Show("请选择需要转换的目标文件! ", "提示");
35 | return false;
36 | }
37 | StreamReader HexReader = new StreamReader(szHexPath);
38 | //先找出HEX文件的最大地址
39 | while (true)
40 | {
41 | szLine = HexReader.ReadLine(); //读取一行数据
42 | i++;
43 | if (szLine == null) break;
44 | if (szLine.Substring(0, 1) == ":") //判断第1字符是否是:
45 | {
46 | if (szLine.Substring(1, 8) == "00000001")//数据结束
47 | {
48 | break;
49 | }
50 | if (szLine.Substring(7, 2) == "04")
51 | {
52 | segAddr = Int32.Parse(szLine.Substring(9, 4), NumberStyles.HexNumber); //800
53 | segAddr *= 16;
54 | }
55 | else if (szLine.Substring(7, 2) == "00")
56 | {
57 | int len_row = szLine.Length;
58 | Int32 tmpAddr = Int32.Parse(szLine.Substring(3, 4), NumberStyles.HexNumber);
59 | tmpAddr += UInt16.Parse(szLine.Substring(1, 2), NumberStyles.HexNumber);
60 | tmpAddr += segAddr;
61 | row++;
62 | sum = row * 16;
63 | if (len_row < 42)
64 | sum -= Int32.Parse(szLine.Substring(1, 2), NumberStyles.HexNumber);
65 |
66 | if (tmpAddr > maxAddr)
67 | maxAddr = tmpAddr;
68 | }
69 | }
70 | else
71 | {
72 | MessageBox.Show("错误:不是标准的hex文件!");
73 | return false;
74 | }
75 | }
76 | //新建一个二进制文件
77 | byte[] szBin = new byte[sum];
78 |
79 | ////返回文件开头
80 | HexReader.BaseStream.Seek(0, SeekOrigin.Begin);
81 | HexReader.DiscardBufferedData();//不加这句不能正确返回开头
82 | segAddr = 0;
83 |
84 | //根据hex文件地址,填充bin文件
85 | while (true)
86 | {
87 | szLine = HexReader.ReadLine(); //读取一行数据
88 | if (szLine == null) //读完所有行
89 | {
90 | break;
91 | }
92 | if (szLine.Substring(0, 1) == ":") //判断第1字符是否是:
93 | {
94 | if (szLine.Substring(1, 8) == "00000001")//数据结束
95 | {
96 | break;
97 | }
98 | if (szLine.Substring(7, 2) == "04")
99 | {
100 | segAddr = Int32.Parse(szLine.Substring(9, 4), NumberStyles.HexNumber);
101 | segAddr *= 16;
102 | }
103 | if (szLine.Substring(7, 2) == "00")
104 | {
105 | int tmpAddr = Int32.Parse(szLine.Substring(3, 4), NumberStyles.HexNumber);
106 | int num = Int16.Parse(szLine.Substring(1, 2), NumberStyles.HexNumber);
107 | tmpAddr += segAddr;
108 | j = 0;
109 | for (i = 0; i < num; i++)
110 | {
111 | szBin[first++] = (byte)Int16.Parse(szLine.Substring(j + 9, 2), NumberStyles.HexNumber);
112 | j += 2;
113 | }
114 | }
115 | }
116 | }
117 |
118 | HexReader.Close(); //关闭目标文件
119 | Form1.filePath = Path.ChangeExtension(szHexPath, "bin");
120 | //tbBinPath.Text = szBinPath;
121 | FileStream fs = new FileStream(Form1.filePath, FileMode.Create);
122 |
123 | //将byte数组写入文件中
124 | fs.Write(szBin, 0, szBin.Length);
125 | fs.Close();
126 |
127 | return true;
128 | //Form1.tbx_show.AppendText("> 文件转换完成!\r\n");
129 | //tbx_show.AppendText("> 文件大小: " + sum.ToString() + " 字节\r\n");
130 | }
131 | catch (Exception ex)
132 | {
133 | MessageBox.Show(ex.ToString());
134 | return false;
135 | }
136 | }
137 |
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace win_iap_ymodem
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// 应用程序的主入口点。
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | Application.Run(new Form1());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("win-iap-ymodem")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("win-iap-ymodem")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("04c7b13d-0399-4722-beb7-dd6a6d3e2ded")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace win_iap_ymodem.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("win_iap_ymodem.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace win_iap_ymodem.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/win-iap-ymodem/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/win-iap-ymodem/bin/Debug/win-iap-ymodem.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/bin/Debug/win-iap-ymodem.exe
--------------------------------------------------------------------------------
/win-iap-ymodem/bin/Debug/win-iap-ymodem.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/bin/Debug/win-iap-ymodem.pdb
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/CoreCompileInputs.cache:
--------------------------------------------------------------------------------
1 | e208185a35486ed372e74771f1834b1bff1b4e88
2 |
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/DesignTimeResolveAssemblyReferences.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/DesignTimeResolveAssemblyReferences.cache
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win-iap-ymodem.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\bin\Debug\win-iap-ymodem.exe
2 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\bin\Debug\win-iap-ymodem.pdb
3 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.csprojResolveAssemblyReference.cache
4 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win_iap_ymodem.Form1.resources
5 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win_iap_ymodem.Properties.Resources.resources
6 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.csproj.GenerateResource.Cache
7 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.exe
8 | C:\Users\Haven\Desktop\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.pdb
9 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\bin\Debug\win-iap-ymodem.exe
10 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\bin\Debug\win-iap-ymodem.pdb
11 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.csprojResolveAssemblyReference.cache
12 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win_iap_ymodem.Form1.resources
13 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win_iap_ymodem.Properties.Resources.resources
14 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.csproj.GenerateResource.Cache
15 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.exe
16 | F:\IAP\winapp-iap-ymodem\win-iap-ymodem\obj\Debug\win-iap-ymodem.pdb
17 |
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win-iap-ymodem.csproj.GenerateResource.Cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win-iap-ymodem.csproj.GenerateResource.Cache
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win-iap-ymodem.csprojResolveAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win-iap-ymodem.csprojResolveAssemblyReference.cache
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win-iap-ymodem.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win-iap-ymodem.exe
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win-iap-ymodem.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win-iap-ymodem.pdb
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win_iap_ymodem.Form1.resources:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win_iap_ymodem.Form1.resources
--------------------------------------------------------------------------------
/win-iap-ymodem/obj/Debug/win_iap_ymodem.Properties.Resources.resources:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/havenxie/winapp-iap-uart/f30e493661136cc8cbf6386b692979d76c1f2939/win-iap-ymodem/obj/Debug/win_iap_ymodem.Properties.Resources.resources
--------------------------------------------------------------------------------
/win-iap-ymodem/win-iap-ymodem.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {04C7B13D-0399-4722-BEB7-DD6A6D3E2DED}
8 | WinExe
9 | win_iap_ymodem
10 | win-iap-ymodem
11 | v4.0
12 | 512
13 |
14 |
15 | AnyCPU
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | AnyCPU
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Form
49 |
50 |
51 | Form1.cs
52 |
53 |
54 |
55 |
56 |
57 | Form1.cs
58 |
59 |
60 | ResXFileCodeGenerator
61 | Resources.Designer.cs
62 | Designer
63 |
64 |
65 | True
66 | Resources.resx
67 |
68 |
69 | SettingsSingleFileGenerator
70 | Settings.Designer.cs
71 |
72 |
73 | True
74 | Settings.settings
75 | True
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------