实验五 Flash在线编程实验

2023-05-16

一.实验目的

(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发送擦除、写入、读取命令及参数:

思路分析:

  1. 通过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。
  2. 通过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

思路分析:

  1. 查询数据传的位置的本质,其实就是给组帧添加一种查找的格式。
  2. 查找算法:先获取起始扇区,并将其值存到sect变量中,当其值小于结束扇区号时,初始化偏移量为0,偏移量从0开始增加到1024-count(待查询字节数),然后在循环中将字符串与查找到的字符串进行一一对比,如果相同则向串口发送FOUND,否则发送NOTFOUND
  3. R:[4]查询起始扇区号+[5]查询结束扇区号+[6]查询字节数m+[7]~[(6+m)]查询字符串内容
  4. 设计Q的数据格式:
  5. 根据钱一个实验已经明确了原程序的组帧格式,我将帧格式的第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,取出之后,解析字符串没有成功,所以这里只写出分析思路和部分实现代码。

思路分析:

  1. 连接数据库之后,点击按钮,将数据库的数据获取之后,存到DataSet;
  2. 将DataSet中的数据显示在dataGridView1上;
  3. 点击存入按钮,获取数据,将DataSet数据转化为json格式的字符串,将该字符串分为若干份,分别发送至flash并存到flash相邻的扇区,并想C#程序返回字符串长度;
  4. 在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 <= 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版)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实验五 Flash在线编程实验 的相关文章

随机推荐

  • RS485接收数据后发送乱码

    序 最近调块板子上面有几路485 xff0c 控制芯片STM32F407VE 转换芯片ADM2587 xff0c 使用485转换器连接电脑 xff0c 发现串口助手向板子发送数据后会收到乱码 xff0c 经软硬件联合调试排除bug 一 问题
  • python urllib.parse

    urlparse span class token keyword from span urllib span class token punctuation span parse span class token keyword impo
  • HTTP学习(5)--demo编写(1)

    一个基于Java的HTTP服务器demo 前面几篇博客 xff0c 大致介绍了几个方面的例子 xff0c 例如报文解析 报文组装等 现在打算将这些东西集合起来 xff0c 编写一个小HTTP服务器demo 期间遇到了很多问题 xff0c 也
  • 用Python写一个监督你刷李永乐考研题目的简单小程序

    import datetime import xlwings import math month 61 datetime datetime now strftime 39 m 39 date 61 datetime datetime now
  • 对于遗传算法,谈谈个人看法

    最近在学习遗传算法 xff0c 小有体会 这个用数学方法来模拟生物学过程的算法实在是有很多值得玩味的地方 遗传算法要干什么 xff1f 比如Z 61 f x y 我们要找到他在x 0 1 y 0 1 区间上的最大值 我们就先随机在x 0 1
  • AD(altium designer)软件的基础使用(硬件的一些总结,写的有些乱,高手请略过)

    1 快捷键 xff1a Ctrl 43 R 复制并重复粘贴 Shift 43 c 取消选择 Space 逆时针旋转对象 Shift 43 space 顺时针旋转对象 X 水平翻转对象 Y 垂直翻转对象 G切换捕捉栅格 V F View中的F
  • C++字节转换 (byte转int 互转)(BCD和HEX转换)

    2个字节short int 高低位转化 short int y 61 0x7f21 y 61 y amp 0xff00 gt gt 8 y amp 0x00ff lt lt 8 printf 34 x 34 y 用short型变量储存 xf
  • 王者荣耀-数模论文分享(虽然结果我自己都不信)

    基于基础数据的王者荣耀英雄强度评估及英雄设计 摘要 王者荣耀是当下很火爆的一款手机游戏 xff0c 如何基于当下的双方阵容选择合适的英雄来获得胜利 xff0c 是一个值得探讨的问题 xff0c 现基于游戏数据对于各个英雄的强度进行建模评估
  • 用蚁群算法求解TSP问题

    TSP是什么 xff1f TSP全称Travelling salesman problem 中文名 xff1a 旅行商问题 就是模拟退火中讲到的14个城市之间巡回旅行 xff0c 求路径最短的问题 为什么偏偏找他呢 xff1f 因为这是一个
  • python 语法小进阶1

    1 filter 是通过生成 True 和 False 组成的迭代器将可迭代对象中不符合条件的元素过滤掉 xff1b 而 map 返回的则是 True 和 False 组成的迭代器 gt gt gt res1 61 map lambda n
  • 焊接的技巧与方法

    手工焊接操作的基本步骤 1 清洁焊接对象的表面 xff0c 这一步是必须的 xff0c 就算你再赶时间也不能偷懒 用小刀或者砂纸把焊点打磨光亮 xff0c 露出铜的光泽 铜表面的氧化物会阻碍焊锡与之形成合金 xff0c 这一步做得不到位的话
  • 计算机网络体系结构

    计算机网络体系结构 一 计算机网络概述计算机网络的概念 组成与功能概念 xff1a 计算机网络 功能 xff1a 数据通信 连通性 资源共享分布式处理 信息综合处理 提高可靠性 负载均衡 发展的三个阶段组成 xff1a 物理组成 xff1a
  • 嵌入式技术基础与实践(第4版)

    1 5 2020 开放权限 在此之前 xff0c 防报告查重 嵌入式系统概述 嵌入式系统常用术语 嵌入式系统常用的C语言基本语法概要 M0 43 体系结构与指令系统简介 存储映象 中断源 硬件最小系统 GPIO及基本打通原理 程序的基本调试
  • 串行通信基础知识与UART驱动构件使用方法

    串行通信基础 串行通信接口 异步串行通信 UART 常称为 串口 或SCI xff0c 在USB未普及之前 xff0c 是PC机必备通信接口之一 通信方式为单字节通信 xff0c 是最简单的串行通信方式 RS232 RS485 接线简单 x
  • ARM Cortex-M0+中断机制与中断编程步骤

    中断基础知识 为什么需要使用中断 xff1f 如果通过查询接收标志查看一个字节是否收到 xff0c 则需要时刻花费CPU等资源 但中断机制能够在收到一个字节后 xff0c 通知CPU把收到的字节取走 异常 xff1a CPU强行从正常运行的
  • 计算机网络体系结构

    一 计算机网络概述 计算机网络的概念 组成与功能 概念 功能 组成 工作方式 分类 计算机网络的标准化工作及相关组织 标准分类 计算机网络的标准化工作 相关组织 二 计算机网络体系结构与参考模型 计算机网络分层结构 计算机网络体系结构 为什
  • KL25嵌入式实验考核

    KL25嵌入式实验考核 xff08 6 43 xff09 404 页面找不到 说明资源在审核中 1 利用 KL25 小板实现 控制红色 LED 灯每隔 2 秒钟亮暗变换的同时 在 PC 机上显示 MCU 的计时时间 xff0c MCU 的初
  • 自制PMW3901光流模块

    PMW3901光流Sensor体积小 功耗低 精度高 xff0c 效果非常好 xff0c 自己做了一个光流小模块带TOF测距 xff0c 使用Pixracer 43 PX4固件 xff0c 测试效果还不错 测试视频 xff1a https
  • 模数转换ADC模块

    通用基础知识 ADC模块是嵌入式应用中重要的组成部分 xff0c 是嵌入式系统与外界连接的纽带 xff0c 是在测控系统中的重要内容 ADC模块 xff1a 即模数转换模块 AD转换模块 xff0c 功能是将电压信号转换为相应的数字信号 实
  • 实验五 Flash在线编程实验

    一 xff0e 实验目的 xff08 1 xff09 掌握 Flash 存储器在线编程的基本概念 xff08 2 xff09 熟悉 Flash 存储器的在线编程擦除和写入的步骤 xff08 3 xff09 进一步深入理解 MCU 和 C 串