TI Cotex M3/4单片机关于寄存器操作详解

2023-05-16

TI Cotex M3/4单片机关于寄存器操作详解

  • 前备知识
    • 寄存器与偏移量
    • 位带操作、位带区
  • TI单片机寄存器操作详解
    • 快速在TI的手册里面确认某外设某寄存器的确切地址
    • 寄存器操作介绍
    • 本文参考

前备知识

  当前单片机的开发方式多种多样,寄存器,库函数,图形化编程等等,可以说是越发的方便,开发速度也是越来越快,库函数开发固好,但是了解一些寄存器操作也绝不是一件多余的事情,因为有很多库函数其底层其实就是寄存器操作编写而成的,能够看懂、理解寄存器操作,对于库函数也会有更深入的理解,有时候也能更快更好地解决一些你以前认为很无厘头的bug。

寄存器与偏移量

  在学习单片机过程中我们不可避免的要接触了解一点寄存器的内容,初学者刚刚听到这个名字往往有些不知所云,脑子里对寄存器没有一个具象的概念,所以我们就先从寄存器介绍开始吧。
  什么是寄存器?
  给有特定功能的内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。给一个我们不能直观理解的数字(这里指地址)一个名字,就会让我们在进行操作时更快更省力的完成任务。
  偏移地址以及如何计算:
  偏移地址是微控制器里的内存分段后,在段内某一地址相对于段首地址(段地址)的偏移量。偏移地址也成为偏移量。最后硬件电路山所应用的物理地址,是由相应段地址加上偏移地址组成的,在单片机中即为:物理地址=寄存器首位地址+偏移量。

  计算方法:物理地址 = 基地址+偏移量。

  关于单片机寄存器地址的计算实际上是非常简单的,举个例子就可以明白:关于MSP432E401Y单片机来说GPIO_PORTA的寄存器的值=0x40058000H,我们认为这就是基地址。RCGCGPIO Register的偏移地址是是0x608H。

GPIO Port A (AHB): 0x40058000 (ending address of 0x40058FFF)
RCGCGPIO Register (Offset = 0x608) [reset = 0x00]

  我们如果想操作GPIO_PORTA的RCGCGPIO这个寄存器的话,我们就可以算出:
  GPIO_PORTA的RCGCGPIO的物理地址=0x40058000H+0x608H=0x4005 8608H

位带操作、位带区

  位带操作这个概念很早就存在了,要说其起始那还要说到51 单片机的位寻址操作。为了控制篇幅,在此就不再过多介绍其中渊源,我们当前只需了解CortexM3/4 就是将位寻址操作能力进化,就得到了威力大幅加强的位带操作。
  概念明析:
  位寻址操作: 许多嵌入式使用者的第一块单片机都是51单片机,这是大家非常熟悉的。51单片机中,假设P1.5的IO口上挂了一个LED,那么你单独对LED的操作就是P1.5 = 0或P1.5 = 1,在51单片机中你可以单独的对P1端的第5个IO口进行操作,这种操作就叫位寻址操作。然而在像STM32、MSP432等等资源量更大的单片机中是不允许这样做的,那么为了像51单片机一样能够单独的对某个端的某一个IO单独操作,就引入了位带操作这样的概念,简而言之,就是为了去单独操作更大资源量单片机里面某个GPIO_PORT口中的某一个IO口(当然也支持同时操作几个),所以就有了位带这样的操作机制。
  位带操作: 就是指可以使用普通的加载/存储指令来对单一的比特(bit)来进行读写。打个比喻,就相当于是为位带区的每一位都起了一个别名,或者说是为为带区的每一位新建了一个快捷方式,通过对指定别名的访问来代替对指定位的访问。说明:指定位与别名之间的映射过程是由内核完成的,无需人工干预。
  位带区: 支持位带操作的地址范围,在CortexM4中有两个位置实现了位带操作,一个是SRAM的最低1MB范围,另一个是片内外设区的最低1MB范围。这两个区中的地址除了可以像普通的RAM 一样使用外,它们还都在“位带别名区”有自己的位带别名,位带别名区把每个比特膨胀成一个32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。为了能使用普通指令来加载和存储那么这个别名肯定得膨胀成32位(一个字),不过这个32位只有低位有效。所以这样就可以通过对别名的访问来代替对位带区指定位的访问了。
  位带别名区: 对别名地址的访问最终会作用到位带区对应位,注意这个过程中有一个地址映射的过程。
  
在这里插入图片描述
MSP432E401Y数据手册中对CotexM4中的位带操作的介绍

图 1-MSP432E401Y数据手册中对CotexM4中的位带操作的介绍

  其实TI的手册是及其详尽的,缺点就是它对英文不太好的朋友不是很友好。对于位带的这部分内容上面手册中讲解的这部分内容就很直观清楚了,我谨在下进行少量的内容总结与补充。

  在CotexM4中支持位带操作的两个内存区的范围是:
  SRAM区最低的1M:从 0x2000.0000 到 0x2006.FFFF
  片上外设区的最低1M:从 0x4000.0000 到 0x400F.FFFF

  对于SRAM位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
  AliasAddr = 0x2200.0000+((A-0x2000.0000)*8+n)*4=0x2200.0000+(A-0x2000.0000)*32+n*4
  对于片上外设位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
  AliasAddr = 0x4200.0000+((A-0x4000.0000)*8+n)*4=0x4200.0000+(A-0x4000.0000)*32+n*4
  上式中,“*4”表示为一个字4个字节,“*8”表示为一个字节中有8个比特。
本部分内容到此结束,如果实在看不懂也请不要放弃,看起来复杂,你只需要会用就可以,接下来本文将进入实操内容,会对如何进行实际操作进行尽可能详细的介绍。

TI单片机寄存器操作详解

快速在TI的手册里面确认某外设某寄存器的确切地址

  首先我们手里要确保有一本你正在使用的单片机型号相相对应的手册,TI各系列单片机的手册均可在官网下载得到,在此不赘述。
  (以下以寻找MSP432E401Y单片机GPIO_PORTA的GPIODIR寄存器为例)
1.从目录找到对应外设的寄存器内容描述部分,获得基地址GPIO Port A (AHB): 0x40058000 (ending address of 0x40058FFF)。
在这里插入图片描述

图 2-获取基地址

2.根据手册中的寄存器表,找到GPIODIR寄存器,详细查看。
在这里插入图片描述

图 3-找到GPIODIR寄存器

3.了解该寄存器的偏移量及其功能。
在这里插入图片描述

图 4-了解该寄存器的偏移量及其功能

我们就可以知道GPIO_PORTA的GPIODIR的首地址为: 0x40058000 + 0x400 = 0x40058400 。

寄存器操作介绍

  以下内容适用于目前大多数TI单片机。本文均以MSP432E401Y单片机为例。

//*****************************************************************************
//
// types.h - Macros used when accessing the comparator hardware.
// Copyright (c) 2017 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
//*****************************************************************************
#ifndef __TYPES_H__
#define __TYPES_H__

//*****************************************************************************
//
// Macros for hardware access, both direct and via the bit-band region.
//
//*****************************************************************************
#define HWREG(x)//HWREG 就是用来取外设寄存器地址                           	  \
        (*((volatile uint32_t *)(x)))
#define HWREGH(x)                                                             \
        (*((volatile uint16_t *)(x)))
#define HWREGB(x)                                                             \
        (*((volatile uint8_t *)(x)))
#define HWREGBITW(x, b)                                                       \
        HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                     \
              (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITH(x, b)                                                       \
        HWREGH(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \
               (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))
#define HWREGBITB(x, b)                                                       \
        HWREGB(((uint32_t)(x) & 0xF0000000) | 0x02000000 |                    \
               (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))

#endif // __TYPES_H__

  在MSP432E401Y(TIVA系列同)的开发过程当中,使用的SDK开发都是库函数操作,即只需要调用相关的函数,确定相应的入口参数就可以实现特定功能。但是库函数归根结底的功能是操作寄存器中的相关位,通过一层一层的调用关系,而归结到最底层,凡是对硬件的操作最终都会以上几条语句。
  前面3句是直接的取寄存器操作,后面三句是通过“位带操作”取寄存器。
  位带操作最主要是理解位带区和未带别名区的对应关系。接下来是对HWREGBITW()操作进行解析:

 HWREG(((uint32_t)(x) & 0xF0000000) | 0x02000000 |  (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2))  :
 bit_word_offset = (byte_offset x 32) + (bit_number x 4)
 bit_word_addr = bit_band_base + bit_word_offset
 
 其中:
 bit_word_offset-在位带区中的目标位的位置。
 (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)
 bit_word_addr-在别名区中与目标位映射的字的地址。
 (((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)
 bit_band_base-别名区的起始地址  
 ((uint32_t)(x) & 0xF0000000) | 0x02000000
 byte_offset-字节在包含目标位的位带区中的编号
 ((uint32_t)(x) & 0x000FFFFF)

 bit_number-目标位的位置,0-7

  接下来是直接操作寄存器位的C语言语句: (*((volatile uint8_t *)
  1、(volatile uint32_t )(x)表示将X强制转化为uint32-t型指针;
  2、
((volatile uint32_t )(x)),设(volatile uint32_t )(x)=P,则表达式为P,我们可以对P进行取值和赋值。
  3、volatile是告诉编译器这段代码不要优化,也就是每次取值,都是从内存里面取,而不是从寄存器里面直接取。

  最后我们现在再来看一下GPIODirModeSet()这个函数的原型,相信各位已经可以看懂了。

//Sets the direction and mode of the specified pin(s).
//设置具体的引脚的方向与模式
void
GPIODirModeSet(uint32_t ui32Port, uint8_t ui8Pins, uint32_t ui32PinIO)
{
    //
    // Check the arguments.
    //
    ASSERT(_GPIOBaseValid(ui32Port));
    ASSERT((ui32PinIO == GPIO_DIR_MODE_IN) ||
           (ui32PinIO == GPIO_DIR_MODE_OUT) ||
           (ui32PinIO == GPIO_DIR_MODE_HW));

    //
    // Set the pin direction and mode.
    //
    HWREG(ui32Port + GPIO_O_DIR) = ((ui32PinIO & 1) ?
                                    (HWREG(ui32Port + GPIO_O_DIR) | ui8Pins) :
                                    (HWREG(ui32Port + GPIO_O_DIR) & ~(ui8Pins)));
    HWREG(ui32Port + GPIO_O_AFSEL) = ((ui32PinIO & 2) ?
                                      (HWREG(ui32Port + GPIO_O_AFSEL) |
                                       ui8Pins) :
                                      (HWREG(ui32Port + GPIO_O_AFSEL) &
                                       ~(ui8Pins)));
}

本文参考

[1]: 《MSP432E4 SimpleLink™ 微控制器技术参考手册》
[2]: “ti\simplelink_msp432e4_sdk_4_20_00_12\source\ti\devices\msp432e4\driverlib\types.h”

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

TI Cotex M3/4单片机关于寄存器操作详解 的相关文章

  • android -- 蓝牙 bluetooth (四)OPP文件传输

    在前面android 蓝牙 bluetooth xff08 一 xff09 入门文章结尾中提到了会按四个方面来写这系列的文章 xff0c 前面已写了蓝牙打开和蓝牙搜索 xff0c 这次一起来看下蓝牙文件分享的流程 xff0c 也就是蓝牙应用
  • Hadoop综合项目——二手房统计分析(MapReduce篇)

    Hadoop综合项目 二手房统计分析 MapReduce篇 文章目录 Hadoop综合项目 二手房统计分析 MapReduce篇 0 写在前面 1 MapReduce统计分析 1 1 统计四大一线城市房价的最值 1 2 按照城市分区统计二手
  • Hadoop综合项目——二手房统计分析(Hive篇)

    Hadoop综合项目 二手房统计分析 Hive篇 文章目录 Hadoop综合项目 二手房统计分析 Hive篇 0 写在前面 1 Hive统计分析 1 1 本地数据 HDFS数据导入到Hive 1 2 楼龄超过20年的二手房比例 1 3 四大
  • Hadoop综合项目——二手房统计分析(可视化篇)

    Hadoop综合项目 二手房统计分析 可视化篇 文章目录 Hadoop综合项目 二手房统计分析 可视化篇 0 写在前面 1 数据可视化 1 1 二手房四大一线城市总价Top5 1 2 统计各个楼龄段的二手房比例 1 3 统计各个城市二手房标
  • Git Bash Here和RStudio软件的问题解决

    Git Bash Here和RStudio软件的问题解决 文章目录 Git Bash Here和RStudio软件的问题解决0 写在前面1 Git软件在任务栏图标空白2 RStudio软件2 1 警告信息InormalizePath pat
  • 算法的复杂性分析

    算法的复杂性分析 文章目录 算法的复杂性分析0 算法评价的基本原则1 影响程序运行时间的因素2 算法复杂度2 1 算法的时间复杂度2 2 渐进表示法2 2 1 运行时间的上界2 2 运行时间的下界2 2 3 运行时间的准确界 3 总结4 参
  • 整数划分问题(Java递归)

    整数划分问题 xff08 Java递归 xff09 文章目录 整数划分问题 xff08 Java递归 xff09 0 问题描述1 递归式2 代码3 参考 0 问题描述 整数划分问题 将正整数n表示成一系列正整数之和 xff1a n 61 n
  • 快速排序(Java分治法)

    快速排序 xff08 Java分治法 xff09 文章目录 快速排序 xff08 Java分治法 xff09 0 分治策略1 思路步骤2 代码3 复杂度分析3 1 最好情况3 2 最坏情况3 3 平均情况3 4 性能影响因素 4 合并排序V
  • 动态规划算法

    动态规划算法 文章目录 动态规划算法0 动态规划的思想方法1 动态规划法的设计思想2 动态规划基本步骤3 动态规划算法设计步骤3 1 动态规划算法的基本要素 4 两种实现的比较5 备忘录方法6 备忘录方法与动态规划比较7 参考 0 动态规划
  • 最长公共子序列(LCS)

    最长公共子序列 xff08 LCS xff09 文章目录 最长公共子序列 xff08 LCS xff09 0 写在前面1 问题描述2 最长公共子序列的结构3 子问题的递归结构4 计算最优值5 算法的改进6 参考 0 写在前面 本文文字大都来
  • 贪心算法(Java)

    贪心算法 文章目录 贪心算法0 写在前面1 贪心算法的基本要素1 1 贪心选择性质1 2 最优子结构性质1 3 贪心算法与动态规划算法的差异 2 贪心算法的特点3 贪心法的正确性证明4 活动安排问题4 1 问题描述4 2 贪心法的设计思想4
  • android -- 蓝牙 bluetooth (五)接电话与听音乐

    前段时间似乎所有的事情都赶在一起 xff0c 回家 集体出游 出差 xff0c 折腾了近一个月 xff0c 终于算暂时清静了 xff0c 但清静只是暂时 xff0c 估计马上又要出差了 xff0c 所以赶紧把蓝牙这一部分的文章了结下 xff
  • 保研/考研复试-数据结构

    数据结构 1 时间复杂度 xff1a 是一个描述算法性能的函数 xff0c 可以定性的描述算法的运行时间 是评价算法优劣的重要指标 2 快速找到第K个数 1 xff09 可以使用快排的思想 xff0c 因为快排每次可以找到一个第i位置的数
  • Github高效搜索方式

    Github高效搜索方式 文章目录 Github高效搜索方式0 写在前面1 常用的搜索功能1 1 直接搜索1 2 寻找指定用户 大小的仓库1 3 搜索仓库1 4 查找特定star范围的仓库1 5 查找指定主题1 6 查找仓库语言1 7 搜索
  • 电子游戏销售之缺失值检测与处理

    电子游戏销售之缺失值检测与处理 文章目录 电子游戏销售之缺失值检测与处理 0 写在前面 1 数据缺失值预处理 1 1 表的形状 1 2 原始数据每个特征缺失和非缺失的数目 1 3 每个特征缺失的率 1 4 处理后各特征缺失值的数目 1 5
  • 电子游戏销售之回归模型与数据可视化

    电子游戏销售之回归模型与数据可视化 文章目录 电子游戏销售之回归模型与数据可视化0 写在前面1 回归模型1 1 模型建立准备1 2 建立模型1 3 模型分析 2 数据可视化3 参考资料 0 写在前面 该篇文章的任务包括以下3个方面 检测与处
  • 基于R的Bilibili视频数据建模及分析——预处理篇

    基于R的Bilibili视频数据建模及分析 预处理篇 文章目录 基于R的Bilibili视频数据建模及分析 预处理篇0 写在前面1 项目介绍1 1 项目背景1 2 数据来源1 3 数据集展示 2 数据预处理2 1 删除空数据2 2 增加id
  • 基于R的Bilibili视频数据建模及分析——变量相关性分析篇

    基于R的Bilibili视频数据建模及分析 变量相关性分析篇 文章目录 基于R的Bilibili视频数据建模及分析 变量相关性分析篇 0 写在前面 1 数据分析 1 1 变量相关性分析 1 2 单元数据直观展示 1 3 多元数据直观展示 2
  • 基于R的Bilibili视频数据建模及分析——聚类分析篇

    基于R的Bilibili视频数据建模及分析 聚类分析篇 文章目录 基于R的Bilibili视频数据建模及分析 聚类分析篇 0 写在前面 1 数据分析 1 1 聚类分析 1 2 聚类统计 1 3 系统聚类 1 4 Kmeans与主成分分析 2
  • 基于R的Bilibili视频数据建模及分析——建模-因子分析篇

    基于R的Bilibili视频数据建模及分析 建模 因子分析篇 文章目录 基于R的Bilibili视频数据建模及分析 建模 因子分析篇 0 写在前面 1 数据分析 1 1 建模 因子分析 1 2 对数线性模型 1 3 主成分分析 1 4 因子

随机推荐

  • 大数据技术之Maxwell基础知识

    大数据技术之Maxwell基础知识 文章目录 大数据技术之Maxwell基础知识0 写在前面1 Maxwell 概述1 1 Maxwell 定义1 2 Maxwell 工作原理1 2 1 MySQL 主从复制过程1 2 2 Maxwell
  • 大数据技术之Maxwell入门案例学习

    大数据技术之Maxwell入门案例学习 文章目录 大数据技术之Maxwell入门案例学习1 写在前面2 Maxwell 使用2 1 Maxwell 安装部署2 2 Maxwell 入门案例2 2 1 监控 Mysql 数据并在控制台打印2
  • Canal实时监控案例

    Canal实时监控案例 文章目录 Canal实时监控案例0 写在前面1 TCP 模式测试1 1 IDEA创建项目canal module 1 2 通用监视类 CanalClient1 2 1 Canal 封装的数据结构1 2 2 在 can
  • unity笔记--Transform.SetSibling

    transform SetAsLastSibling 将变换移动到本地变换列表的末尾 即设置为同级索引中的最后一项 transform SetAsFirstSibling 将变换移动到本地变换列表的开头 即设置为同级索引中的第一项 tran
  • 大数据技术之Canal入门篇

    大数据技术之Canal入门篇 文章目录 大数据技术之Canal入门篇写在前面第 1 章 Canal 入门1 1 什么是 Canal1 2 MySQL 的Binlog1 2 1 什么是 Binlog1 2 2 Binlog 的分类 1 3 C
  • Doris集成Spark读写的简单示例

    Doris集成Spark读写的简单示例 文章目录 Doris集成Spark读写的简单示例0 写在前面1 Spark Doris Connector介绍2 基本示例2 1 提前准备表和数据2 2 新建项目2 3 使用SQL方式进行读写2 3
  • Linux用户与用户组介绍

    Linux用户与用户组介绍 文章目录 Linux用户与用户组介绍0 写在前面1 group1 1 什么是组 xff1f 1 2 groupadd1 2 groupmod1 3 groupdel1 4 gpasswd1 5 相关文件说明 2
  • Linux安装Oracle数据库

    Linux安装Oracle数据库 文章目录 Linux安装Oracle数据库0 写在前面1 Oracle 数据库1 1 简介1 2 Oracle 与 MySQL 的SQL 区别 2 前置准备2 1 安装依赖包2 2 配置用户组2 3 上传安
  • DataX与DB2导入导出案例

    DataX与DB2导入导出案例 文章目录 DataX与DB2导入导出案例0 写在前面1 DB2介绍2 DB2数据库对象关系3 安装前的准备3 1 安装依赖3 2 修改配置文件 sysctl conf3 3 修改配置文件 limits con
  • Doris集成其他系统——ODBC外部表

    Doris集成其他系统 ODBC外部表 文章目录 Doris集成其他系统 ODBC外部表0 写在前面1 正文1 1 ODBC外部表介绍1 2 使用方式 2 使用 ODBC 的 MySQL 外表2 1 前置芝士2 2 安装 unixODBC2
  • Linux安装ElasticSearch

    Linux安装ElasticSearch 文章目录 Linux安装ElasticSearch0 写在前面1 环境准备2 ES安装2 1ES解压2 2 新增普通用户2 3 给新创建的普通用户授权2 4 给新创建的普通用户设置sudo权限2 5
  • Hadoop入门学习——简介篇

    Hadoop入门学习 简介篇 文章目录 Hadoop入门学习 简介篇1 大数据概论1 1 分布式 并行 1 2 大数据特点 xff08 4V xff09 1 2 1 Volume xff08 大量 xff09 1 2 2 Velocity
  • Hadoop之分布式技术

    Hadoop之分布式技术 文章目录 Hadoop之分布式技术1 我们为什么需要分布式1 1 计算问题1 2 存储问题 2 分布式系统概述3 分布式实现方案4 分布式系统5 集群6 负载均衡7 弹性8 故障转移 1 我们为什么需要分布式 1
  • 认识DataX及简单入门

    认识DataX及简单入门 文章目录 认识DataX及简单入门1 DataX的概述1 1 什么是DataX1 2 DataX 的设计1 3 支持的数据源1 3 支持的数据源1 4 框架设计1 5 运行原理1 6 DataX和Sqoop的对比
  • Nginx 反向代理及https配置

    参考代码 在server中添加 location api proxy set header Host host proxy set header X Real IP remote addr proxy set header X Forwar
  • DataX使用之基础案例

    DataX使用之基础案例 文章目录 DataX使用之基础案例0 写在前面1 从stream 流读取数据并打印到控制台2 读取 MySQL 中的数据存放到 HDFS2 1 查看官方模板2 1 1 mysqlreader 参数解析 xff1a
  • DataX和Oracle使用案例

    DataX和Oracle使用案例 文章目录 DataX和Oracle使用案例0 写在前面1 从 Oracle 中读取数据存到 MySQL1 1 MySQL 中创建表1 2 编写 Datax 配置文件1 3 执行命令 2 读取 Oracle
  • MongoDB初认识

    MongoDB初认识 文章目录 MongoDB初认识0 写在前面1 MongoDB是什么2 MongoDB的优缺点3 基础概念解析4 安装4 1 下载地址4 2 安装MongoDB4 3 pgrep使用4 4 进入 shell 交互页面 0
  • DataX和MongoDB之间的数据导入导出案例

    DataX和MongoDB之间的数据导入导出案例 文章目录 DataX和MongoDB之间的数据导入导出案例0 写在前面1 MongoDB前置知识1 1 基础概念详解1 1 1 数据库1 1 2 集合1 1 3 文档 xff08 Docum
  • TI Cotex M3/4单片机关于寄存器操作详解

    TI Cotex M3 4单片机关于寄存器操作详解 前备知识寄存器与偏移量位带操作 位带区 TI单片机寄存器操作详解快速在TI的手册里面确认某外设某寄存器的确切地址寄存器操作介绍本文参考 前备知识 当前单片机的开发方式多种多样 xff0c