实验五 Flash在线编程实验 | 您所在的位置:网站首页 › flash广告设计实验结果及分析怎么写 › 实验五 Flash在线编程实验 |
一.实验目的
(1)掌握 Flash 存储器在线编程的基本概念。。 (2)熟悉 Flash 存储器的在线编程擦除和写入的步骤。 (3)进一步深入理解 MCU 和 C#串口通信的编程方法。 二.实验内容1.验证性实验 1)验证样例程序(ch09-Flash)中(Flash),主要功能是实现通过串口输入命令 “?”可获得帮助; E:擦除第 50 扇区;R:从 50 扇区 0 字节开始的地址读取 30 字节长度字符串;A:从全局变量 watchGlobalVar 地址直接读取该变量;W:向 50 扇区 0 字节开始的地址写入 30 字节长度字符串;P:保护 50 扇区(实际保护 48,49,50,51 四个对齐扇区)。 实验步骤如下: (1)将样例 Flash 程序下载至目标板; (2)将“TTL-USB 串口线”的“USB 端口”接 PC 机的 USB 口,串口线的串口接开发板上的串口 2(3 根,RX 接蓝线,TX 接白线,GND 接黑线); (3)打开串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”进行串口通信测试,观察实验现象。 (4)分析理解 main.c 程序和中断服务例程 isr.c。 2.设计性实验 (1)复制样例程序(ch09-Flash)中(Flash),利用该程序框架实现:通过串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”发送擦除、写入、读取命令及其参数,参数能够设置扇区号(0-127)、写入/读取扇区内部偏移地址(0~1020,要求为 0,4,8,12,......);写入/读取字节数目(4~1024,要求为 4,8,12,......)和数据。 请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句。 (2)复制样例程序(ch09-Flash)中(Flash),利用该程序框架实现:通过串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”发送查询 Flash 相应扇区的数据串,(如:50 100 Hello,查找扇区 50 至扇区 100 中的字符串 Hello),如果找到发送 Found 给串口,如果未找到发送 Not Found 给串口。 请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句。 3.进阶实验★ (1)复制样例程序(ch09-Flash)中(Flash),利用该程序框架实现:通过 C#程序发送擦除、写入、读取命令及其参数,参数能够设置扇区号(0-127)、写入/读取扇区内部偏移地址(0~1020,要求为 0,4,8,12,......);写入/读取字节数目(4~1024,要求为 4,8,12,......)和数据。C#界面设计如如图 1 所示。 请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句和 C#方主要程序段。 图 1 C#界面设计 (2)复制样例程序(ch09-Flash)中(Flash),利用该程序框架实现:通过 C#程序访问数据库中的表,读取表中存放的数据列表并显示(表中字段如:学号,姓名,成绩),通过发送按钮将数据列表保存至 Flash 中;通过 C#程序界面输入读取的数据列表的条数,从 Flash中读取相应的数据后显示。 请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句和 C#方主要程序段。 (3)复制样例程序(ch09-Flash)中(Flash),利用该程序框架实现:通过 C#程序打开一副图片(比如自己的一寸电子照片),通过串口将图片数据发送至 MCU 并保存 Flash 中;通过 C#程序可以将 MCU 的 Flash 中保存的图片读取并显示。 请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句和 C#方主要程序段。 三.实验步骤和结果1.验证性实验 组帧格式分析: 组帧:[0]P+[1]数据字节数n+数据+[n+2]C 数据部分:[2]握手或数据命令(C-握手/D-flash操作)+[3]flash操作类型(R:按逻辑地址读取;A:按物理地址读取;W:写入操作;E:擦除操作;P:保护操作;)+该操作类型的数据 R:[4]扇区号+[5]偏移量高字节+[6]偏移量低字节+[7]读取字节数 A:[4]地址高位+[5]地址第二高位+[6]地址第二低位+[7]地址低位+[8]读取字节数 W:[4]扇区号+[5]偏移量高字节+[6]偏移量低字节+[7]写入字节数m+写入数据 E:[4]扇区号 P:[4]保护区域号 2.设计性实验 (1)通过串口调试助手,向flash发送擦除、写入、读取命令及参数: 思路分析: 通过C#串口调试工具向串口发送擦除指令:50 03 44 45 32 43(擦除50号扇区),正确返回结果:4D 21 43 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 55。通过C#串口调试工具向串口发送写入指令:50,0C,44,57,32,00,00,06,41,42,43,44,45,46,43(向50号扇区00偏移量写ABCDEF),正确返回结果:4D 07 43 41 42 43 44 45 46 55 3.通过C#串口调试工具向串口发送读出指令:50 06 44 52 32 00 00 0A 43(从50号扇区00偏移量读ABCDEF),正确返回结果:4D 07 43 41 42 43 44 45 46 55 。 流程图: 串口流程图
Main函数流程图:
具体代码如下: 串口程序: void UART2_IRQHandler(void) { uint_8 i,flag; DISABLE_INTERRUPTS; //关总中断 //----------------------------------------------------------------------- i=uart_re1(UART_2, &flag); //接收一个字节 if (1 == flag) { uart_send1(UART_2, i); } //调用内部函数CreateFrame进行组帧 if(CreateFrame(i,g_uart_recvBuf)!=0) //组帧成功 { //g_uart_recvBuf[2]是命令字节 if(g_uart_recvBuf[2] == 'C') //握手命令 { g_uart_sentBuf[0]=(uint_8)'M'; // g_uart_sentBuf[1]=5; // g_uart_sentBuf[2] = (uint_8)'C'; // g_uart_sentBuf[3] = (uint_8)'K'; //"PCNode" g_uart_sentBuf[4] = (uint_8)'L'; g_uart_sentBuf[5] = (uint_8)'2'; g_uart_sentBuf[6] = (uint_8)'5'; g_uart_sentBuf[7] = (uint_8)'U'; // uart_sendN(UART_2,8,g_uart_sentBuf); framestate=1;//握手命令帧 } // else //其他情况,置“串口0接收完整数据帧事件位(EVENT_UART0_RE)”,触发task_uart0_re任务处理 { framestate=0;//非握手命令帧 } } //----------------------------------------------------------------------- ENABLE_INTERRUPTS; //开总中断 }(2)在flash查找存入数据,如果找到想串口发送FOUND,否则发送NOTFOUND 思路分析: 查询数据传的位置的本质,其实就是给组帧添加一种查找的格式。查找算法:先获取起始扇区,并将其值存到sect变量中,当其值小于结束扇区号时,初始化偏移量为0,偏移量从0开始增加到1024-count(待查询字节数),然后在循环中将字符串与查找到的字符串进行一一对比,如果相同则向串口发送FOUND,否则发送NOTFOUNDR:[4]查询起始扇区号+[5]查询结束扇区号+[6]查询字节数m+[7]~[(6+m)]查询字符串内容设计Q的数据格式:根据钱一个实验已经明确了原程序的组帧格式,我将帧格式的第4位,即[3]flash操作类型增加一种查询类型Q流程图:
具体代码如下: case 'Q': offset = 0; //偏移地址 uint_8 sect = g_uart_recvBuf[4]; uint_8 i = 0; count = g_uart_recvBuf[6]; //存取字节数 uint_8 g_query[count]; uint_8 flag = 0; while (sect < g_uart_recvBuf[5]) { offset = 0; //偏移地址 for (offset; offset < 1024 - count; offset++) { flash_read_logic(&g_query[0], sect, offset, count); for (; i < count; i++) { if (g_query[i] == g_uart_recvBuf[i + 7]) { if (i >= count - 1) { g_uart_sentBuf[0] = (uint_8) 'M'; //帧头 g_uart_sentBuf[1] = 7; //内容数(内容count+C) g_uart_sentBuf[2] = (uint_8) 'C'; //内容起始帧 g_uart_sentBuf[3] = (uint_8) 'F'; g_uart_sentBuf[4] = (uint_8) 'O'; g_uart_sentBuf[5] = (uint_8) 'U'; g_uart_sentBuf[6] = (uint_8) 'N'; g_uart_sentBuf[7] = (uint_8) 'D'; g_uart_sentBuf[8] = (uint_8) 'U'; //帧尾 uart_sendN(UART_2, 9,&g_uart_sentBuf[0]); flag = 1; } } else { i = 0; break; } } if (flag) break; } if (flag) break; sect++; } if (!flag) { g_uart_sentBuf[0] = (uint_8) 'M'; //帧头 g_uart_sentBuf[1] = 9; //内容数(内容count+C) g_uart_sentBuf[2] = (uint_8) 'C'; //内容起始帧 g_uart_sentBuf[3] = (uint_8) 'N'; g_uart_sentBuf[4] = (uint_8) 'O'; g_uart_sentBuf[5] = (uint_8) 'T'; g_uart_sentBuf[6] = (uint_8) 'F'; g_uart_sentBuf[7] = (uint_8) 'O'; g_uart_sentBuf[8] = (uint_8) 'U'; g_uart_sentBuf[9] = (uint_8) 'N'; g_uart_sentBuf[10] = (uint_8) 'D'; g_uart_sentBuf[11] = (uint_8) 'U'; //帧尾 uart_sendN(UART_2, 12, &g_uart_sentBuf[0]); } break;3.进阶实验★ (1)通过C#程序实现对flash的存、取和擦除等功能 由于已有完整的C#程序,我便通过此程序实验了一些flash基本操作,并且仔细阅读同时理解了具体实现代码。 (2)通过C#程序访问数据库中的表,读取表中的存放的数据并显示通过发送按钮发送并保存到flash中,通过C#程序读取数据并显示。 由于此次实验过程并不是很顺利,将数据库中的数据以字符串的形式存入flash,取出之后,解析字符串没有成功,所以这里只写出分析思路和部分实现代码。 思路分析: 连接数据库之后,点击按钮,将数据库的数据获取之后,存到DataSet;将DataSet中的数据显示在dataGridView1上;点击存入按钮,获取数据,将DataSet数据转化为json格式的字符串,将该字符串分为若干份,分别发送至flash并存到flash相邻的扇区,并想C#程序返回字符串长度;在C#界面输入查询的起始扇区和字符串长度,点击查询按钮,从先前存放数据的几个扇区中取出json数据,并将json转换为DataSet数据,并显示到dataGridView2上。主要代码: C#端: //读取数据库 private void button1_Click(object sender, EventArgs e) { // sql a = new sql(); //a.Select(); MySqlConnection myconn = null; MySqlCommand mycom = null; // MySqlDataAdapter myrec = null; myconn = new MySqlConnection("server=localhost;user id=root;password=admin;database=armcortex"); // Host =localhost;Database=student;Username=lemon;Password=123 myconn.Open(); mycom = myconn.CreateCommand(); mycom.CommandText = "SELECT *FROM stuinfo"; MySqlDataAdapter adap = new MySqlDataAdapter(mycom); DataSet ds = new DataSet(); adap.Fill(ds); dataGridView1.DataSource = ds.Tables[0].DefaultView; myconn.Close(); } //将数据库存入flash private void button2_Click(object sender, EventArgs e) { // 1. 临时变量声明 byte sector; //扇区号 int offset; //偏移量 byte n; //写入字节数 int i; byte len; //获取数据库数据 MySqlConnection myconn = null; MySqlCommand mycom = null; //MySqlDataAdapter myrec = null; myconn = new MySqlConnection("server=localhost;user id=root;password=admin;database=armcortex"); // Host =localhost;Database=student;Username=lemon;Password=123 myconn.Open(); mycom = myconn.CreateCommand(); mycom.CommandText = "SELECT *FROM stuinfo"; MySqlDataAdapter adap = new MySqlDataAdapter(mycom); DataSet ds = new DataSet(); adap.Fill(ds); //dataGridView1.DataSource = ds.Tables[0].DefaultView; byte[] writeDataArray = System.Text.Encoding.Default.GetBytes(DatasetToJson(ds)); //String转化为Byte[] // 2. 临时变量赋值 sector = Convert.ToByte(tbSector2.Text); // 将TextBox中的Text转换为Byte类型 offset = Convert.ToInt32(tbOffset2.Text); // 将TextBox中的Text转换为Byte类型 n = (byte)writeDataArray.Length; byte j = 0,k=0,l=0,m=0; if (n > 56) { if (n % 56 != 0) { l = (byte)(n % 56); j = (byte)(n / 56 + 1); } else { j = (byte)(n / 56); l = 56; } //n = (byte)(n + 6); for (; k < j; k++) { if (k == j - 1) { len = (byte)(l + 6); m = l; } else { len = (byte)(56 + 6); m = 56; } byte[] SendByteArray = new byte[len + 3]; this.Txt_recv1.Text = ""; this.Txt_recv2.Text = ""; this.Txt_recv1.Refresh(); this.Txt_recv2.Refresh(); this.tb_statue.Text = "运行状态:" + "单击“KL25 Flash 写测试”按钮..."; this.tb_statue.Refresh(); try { SendByteArray[0] = (byte)'P'; //帧头 SendByteArray[1] = len; //帧长 SendByteArray[2] = (byte)'D'; //FLASH操作命令 SendByteArray[3] = (byte)'W'; //FLASH写操作 SendByteArray[4] = (byte)(sector+(byte)k); //扇区号 SendByteArray[5] = (byte)(offset / 256); //偏移量高字节 SendByteArray[6] = (byte)(offset % 256); //偏移量低字节 SendByteArray[7] = m; //字节数 for (i = 8; i > 8); byte j = 0, k = 0, l = 0, m = 0; if (count > 56) { if (count % 56 != 0) { l = (byte)(count % 56); j = (byte)(count / 56 + 1); } else { j = (byte)(count / 56); l = 56; } //n = (byte)(n + 6); for (; k < j; k++) { if (k == j - 1) { m = l; } else { m = 56; } this.Txt_recv1.Text = ""; this.Txt_recv2.Text = ""; this.Txt_recv1.Refresh(); this.Txt_recv2.Refresh(); this.tb_statue.Text = "运行状态:" + "单击“KL25 Flash 按逻辑地址读测试”按钮..."; this.tb_statue.Refresh(); try { SendByteArray[0] = (byte)'P'; //帧头 SendByteArray[1] = 0x06; //帧长 SendByteArray[2] = (byte)'D'; //FLASH操作命令 SendByteArray[3] = (byte)'R'; //FLASH读操作 SendByteArray[4] = (byte)(sector + (byte)k); //第几页 SendByteArray[5] = offset_high; //偏移量高字节 SendByteArray[6] = offset_low; //偏移量低字节 SendByteArray[7] = m; //读取字节数 SendByteArray[8] = (byte)'C'; //帧尾 //发送、接收、显示 //str += sendRecvDB(SendByteArray, 2, 100); sb.Append(sendRecvDB(SendByteArray, 2, 100)); } catch { this.Txt_recv1.Text = "KL25 Flash第"+(k+1)+"读取操作失败!"; } } if (sb != null&& !sb.Equals("")) { DataSet ds = (DataSet)JsonToDataSet(sb.ToString()); dataGridView2.DataSource = ds.Tables[0].DefaultView; }else { this.Txt_recv1.Text = "KL25 Flash读取操作失败!"; } } else { } } 四.实验总结(需加入心得体会)通过本次实验,我掌握了flash在线编程的基本概念,熟悉了flash擦除、写入和读取的基本操作。但是在具体实验的过程中还是遇到许多难题,其中有一些解决了,但是还有一些没有得到完全解决。在后面的时间,我会继续寻找这些问题的解决方法,让自己获得更大的提升。 嵌入式技术基础与实践(第4版) |
CopyRight 2018-2019 实验室设备网 版权所有 |