├── .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 | --------------------------------------------------------------------------------