实验五 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發送擦除、寫入、讀取命令及參數:
思路分析:
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
思路分析:
流程圖:
?
具體代碼如下:
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,取出之后,解析字符串沒有成功,所以這里只寫出分析思路和部分實現代碼。
思路分析:
主要代碼:
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=123myconn.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();}//將數據庫存入flashprivate 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=123myconn.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 <= 7 + m; i++){SendByteArray[i] = writeDataArray[k* 56 + i - 8];}SendByteArray[len + 2] = (byte)'C'; ??????//幀尾//發送、接收、顯示sendRecv(SendByteArray, 2, 100);}catch{this.Txt_recv1.Text = "KL25 Flash第"+(k+1)+"次寫入操作失敗!";}}}this.textBox4.Text = n + "字節";?????????}//修改讀出程序private string sendRecvDB(byte[] SendByteArray, int cnt, int time){string result="";// string str="";byte[] recvData;int i;this.tb_statue.Text += "正在發送...";this.tb_statue.Refresh();recvData = pcNode1.PCNodeSendReturn(SendByteArray, cnt, time);if (recvData.Length <= 0){this.tb_statue.Text += "無數據返回";this.tb_statue.Refresh();}else{this.tb_statue.Text += "有數據返回";this.tb_statue.Refresh();this.Txt_recv1.Text = string.Empty;for (i = 0; i < recvData.Length; i++)this.Txt_recv1.Text += recvData[i].ToString("X2").ToUpper() + " ";this.tbhead.Text = "" + (char)recvData[0];//幀頭this.tblen.Text = "" + ((char)recvData[1] - 1);//長度-1(內容起始幀C)this.tbfirst.Text = "" + (char)recvData[2];//內容起始幀C//this.Txt_recv2.Text = "幀頭:" + (char)recvData[0] + " 接收長度:" + (recvData[1]-1) + " 接收起始字符幀:" + (char)recvData[2] + " 接收內容:";for (i = 3; i < recvData.Length - 1; i++){//可顯示字符予以顯示,不可顯示的ASCII碼顯示為空if (recvData[i] > 31 && recvData[i] < 127){this.Txt_recv2.Text += (char)recvData[i];}else{this.Txt_recv2.Text += " ";}}this.tbtail.Text = "" + (char)recvData[i];//幀尾result = System.Text.Encoding.Default.GetString (recvData);result = result.Substring(1, result.Length - 1);result = result.Substring(1, result.Length - 1);result = result.Substring(1, result.Length - 1);return result.Substring(0, result.Length - 2);// str = result;//return result;}return result;???????????}//查詢獲取flash中數據庫的數據private void button3_Click(object sender, EventArgs e){??????????// 1. 臨時變量聲明byte sector; ??????????// 扇區號int offset; ???????????// 偏移量byte count; ???????????// 讀取字節數StringBuilder sb = new StringBuilder();byte[] SendByteArray = new byte[9]; ????????// 定義發送緩沖區byte offset_high, offset_low; ??????????????// 定義偏移地址的高低字節// 2. 臨時變量賦值sector = Convert.ToByte(tbSector1.Text); ???// 將TextBox中的Text轉換為Byte類型offset = Convert.ToInt32(tbOffset1.Text); ?// 將TextBox中的Text轉換為Byte類型count = Convert.ToByte(tbCount1.Text);// 計算偏移地址高低位offset_low = (byte)(0xff & offset);offset_high = (byte)((0xff00 & offset) >> 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版)
總結
以上是生活随笔為你收集整理的实验五 Flash在线编程实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gitbook 插件 图片查看
- 下一篇: 数据结构1800试题(第3章)