如何将.a文件导程序如何写入单片机机中?

最近用团队的帐号发了一篇文章,初衷是但愿给你们传递一些可能没有接触过的知识,其中某些知识可能也超出了前端的范畴,本质是但愿给你们提供一些扫盲的思路。可是文章的评论使我意识到你们对于这个文章的抵触心情很是大。我有很认真的看你们的每一条评论,而后可能过多的解释也没有什么用。我本身也反思可能文章就不该该以面试为标题进行传播,由于面试的话它就意味着跟职位以及工做息息相关,更况且我仍是以团队的名义去发这个文章。在这里,先跟这些读完文章体验不是很好的同窗道个歉。javascript

之前写文章感受都很开心,写完发完感受都能给你们带来一些新的输入。可是这一次,我感受挺难受的,也确实反思了不少,感受本身以这样的方式传播可能有些问题,主要以下:html

  • 题目取的不对,不该该拿面试做为标题,题目就应该是“脚撕专有钉钉前端面试题”
  • 若是做为面试题,其中某些问题问的太大,范围太广,确实不适合面试者进行回答
  • 若是做为面试题,其中某些问题问的不够专业,甚至是有歧义
  • 给出了面试题,就应该给出面试题的答案,这样才是真正帮助到你们扫盲

这里再也不过多解释和纠结面试题的问题了,由于我感受无论在评论中作什么解释,不承认的同窗仍是会一如既往的怼上来(挺好的,若是怼完感受本身还能释放一些小压力,或许还能适当的给子弈增长一些苍白解释的动力)。固然我也很开心不少同窗在评论中求答案,接下来我会好好认真作一期答案,但愿可以给你们带来一些新的输入,固然答案不可能一会儿作完,也不必定全面或者让你们感受满意,或许你们此次的评论又能给我带来一些学习的机会。前端

舒适提示:这里尽可能多给出一些知识点,因此不会针对问题进行机械式的回答,可能更多的须要你们自行理解和抽象。其中大部分面试题可能会已文章连接的形式出现,或许是我本身之前写过的文章,或者是我以为别人写的不错的文章。java

基础知识主要包含如下几个方面:node

  • 基础:计算机原理、编译原理、数据结构、算法、设计模式、编程范式等基本知识了解
  • 工程:编译工具、格式工具、Git、NPM、单元测试、Nginx、PM二、CI / CD 了解和使用
  • 性能:编译性能、监控、白屏检测、SEO、Service Worker 等了解
  • 后端:Redis 缓存、数据库、Graphql、SSR、模板引擎等了解和使用

现代计算机以存储器为中心,主要由 CPU、I / O 设备以及主存储器三大部分组成。各个部分之间经过总线进行链接通讯,具体以下图所示: 上图是一种多总线结构的示意图,CPU、主存以及 I / O 设备之间的全部数据都是经过总线进行并行传输,使用局部总线是为了提升 CPU 的吞吐量(CPU 不须要直接跟 I / O 设备通讯),而使用高速总线(更贴近 CPU)和 DMA 总线则是为了提高高速 I / O 设备(外设存储器、局域网以及多媒体等)的执行效率。ios

主存包括随机存储器 RAM 和只读存储器 ROM,其中 ROM 又能够分为 MROM(一次性)、PROM、EPROM、EEPROM 。ROM 中存储的程序(例如启动程序、固化程序)和数据(例如常量数据)在断电后不会丢失。RAM 主要分为静态 RAM(SRAM) 和动态 RAM(DRAM) 两种类型(DRAM 种类不少,包括 SDRAM、RDRAM、CDRAM 等),断电后数据会丢失,主要用于存储临时程序或者临时变量数据。 DRAM 通常访问速度相对较慢。因为现代 CPU 读取速度要求相对较高,所以在 CPU 内核中都会设计 L一、L2 以及 L3 级别的多级高速缓存,这些缓存基本是由 SRAM 构成,通常访问速度较快。git

高级程序设计语言不能直接被计算机理解并执行,须要经过翻译程序将其转换成特定处理器上可执行的指令,计算机 CPU 的简单工做原理以下所示: CPU 主要由控制单元、运算单元和存储单元组成(注意忽略了中断系统),各自的做用以下:程序员

  • 控制单元:在节拍脉冲的做用下,将程序计数器(Program Counter,PC)指向的主存或者多级高速缓存中的指令地址送到地址总线,接着获取指令地址所对应的指令并放入指令寄存器 (Instruction Register,IR)中,而后经过指令译码器(Instruction Decoder,ID)分析指令须要进行的操做,最后经过操做控制器(Operation Controller,OC)向其余设备发出微操做控制信号。
  • 运算单元:若是控制单元发出的控制信号存在算术运算(加、减、乘、除、增 一、减 一、取反等)或者逻辑运算(与、或、非、异或),那么须要经过运算单元获取存储单元的计算数据进行处理。
  • 存储单元:包括片内缓存和寄存器组,是 CPU 中临时数据的存储地方。CPU 直接访问主存数据大概须要花费数百个机器周期,而访问寄存器或者片内缓存只须要若干个或者几十个机器周期,所以会使用内部寄存器或缓存来存储和获取临时数据(即将被运算或者运算以后的数据),从而提升 CPU 的运行效率。

除此以外,计算机系统执行程序指令时须要花费时间,其中取出一条指令并执行这条指令的时间叫指令周期。指令周期能够分为若干个阶段(取指周期、间址周期、执行周期和中断周期),每一个阶段主要完成一项基本操做,完成基本操做的时间叫机器周期。机器周期是时钟周期的分频,例如最经典的 8051 单片机的机器周期为 12 个时钟周期。时钟周期是 CPU 工做的基本时间单位,也能够称为节拍脉冲或 T 周期(CPU 主频的倒数) 。假设 CPU 的主频是 1 GHz(1 Hz 表示每秒运行 1 次),那么表示时钟周期为 1 / 109 s。理论上 CPU 的主频越高,程序指令执行的速度越快。es6

上图右侧主存中的指令是 CPU 能够支持的处理命令,通常包含算术指令(加和减)、逻辑指令(与、或和非)、数据指令(移动、输入、删除、加载和存储)、流程控制指令以及程序结束指令等,因为 CPU 只能识别二进制码,所以指令是由二进制码组成。除此以外,指令的集合称为指令集(例如汇编语言就是指令集的一种表现形式),常见的指令集有精简指令集(ARM)和复杂指令集(Inter X86)。通常指令集决定了 CPU 处理器的硬件架构,规定了处理器的相应操做。github

早期的计算机只有机器语言时,程序设计必须用二进制数(0 和 1)来编写程序,而且要求程序员对计算机硬件和指令集很是了解,编程的难度较大,操做极易出错。为了解决机器语言的编程问题,慢慢开始出现了符号式的汇编语言(采用 ADD、SUB、MUL、DIV 等符号表明加减乘除)。为了使得计算机能够识别汇编语言,须要将汇编语言翻译成机器可以识别的机器语言(处理器的指令集): 因为每一种机器的指令系统不一样,须要不一样的汇编语言程序与之匹配,所以程序员每每须要针对不一样的机器了解其硬件结构和指令系统。为了能够抹平不一样机器的指令系统,使得程序员能够更加关注程序设计自己,前后出现了各类面向问题的高级程序设计语言,例如 BASIC 和 C,具体过程以下图所示: 高级程序语言会先翻译成汇编语言或者其余中间语言,而后再根据不一样的机器翻译成机器语言进行执行。除此以外,汇编语言虚拟机和机器语言机器之间还存在一层操做系统虚拟机,主要用于控制和管理操做系统的所有硬件和软件资源(随着超大规模集成电路技术的不断发展,一些操做系统的软件功能逐步由硬件来替换,例如目前的操做系统已经实现了部分程序的固化,简称固件,将程序永久性的存储在 ROM 中)。机器语言机器还能够继续分解成微程序机器,将每一条机器指令翻译成一组微指令(微程序)进行执行。

上述虚拟机所提供的语言转换程序被称为编译器,主要做用是将某种语言编写的源程序转换成一个等价的机器语言程序,编译器的做用以下图所示: 例如 C 语言,能够先经过 gcc 编译器生成 Linux 和 Windows 下的目标 .o 和 .obj 文件(object 文件,即目标文件),而后将目标文件与底层系统库文件、应用程序库文件以及启动文件连接成可执行文件在目标机器上执行。

舒适提示:感兴趣的同窗能够了解一下 ARM 芯片的程序运行原理,包括使用 IDE 进行程序的编译(IDE 内置编译器,主流编译器包含 ARMCC、IAR 以及 GCC FOR ARM 等,其中一些编译器仅仅随着 IDE 进行捆绑发布,不提供独立使用的能力,而一些编译器则随着 IDE 进行发布的同时,还提供命令行接口的独立使用方式)、经过串口进行程序下载(下载到芯片的代码区初始启动地址映射的存储空间地址)、启动的存储空间地址映射(包括系统存储器、闪存 FLASH、内置 SRAM 等)、芯片的程序启动模式引脚 BOOT 的设置(例如调试代码时经常选择内置 SRAM、真正程序运行的时候选择闪存 FLASH)等。

若是某种高级语言或者应用语言(例如用于人工智能的计算机设计语言)转换的目标语言不是特定计算机的汇编语言,而是面向另外一种高级程序语言(不少研究性的编译器将 C 做为目标语言),那么还须要将目标高级程序语言再进行一次额外的编译才能获得最终的目标程序,这种编译器可称为源到源的转换器。

除此以外,有些程序设计语言将编译的过程和最终转换成目标程序进行执行的过程混合在一块儿,这种语言转换程序一般被称为解释器,主要做用是将某种语言编写的源程序做为输入,将该源程序执行的结果做为输出,解释器的做用以下图所示:

解释器和编译器有不少类似之处,都须要对源程序进行分析,并转换成目标机器可识别的机器语言进行执行。只是解释器是在转换源程序的同时立马执行对应的机器语言(转换和执行的过程不分离),而编译器得先把源程序所有转换成机器语言并产生目标文件,而后将目标文件写入相应的程序存储器进行执行(转换和执行的过程分离)。例如 Perl、Scheme、APL 使用解释器进行转换, C、C++ 则使用编译器进行转换,而 Java 和 JavaScript 的转换既包含了编译过程,也包含了解释过程。

JavaScript 中的数组存储大体须要分为两种状况:

  • 同种类型数据的数组分配连续的内存空间
  • 存在非同种类型数据的数组使用哈希映射分配内存空间

舒适提示:能够想象一下连续的内存空间只须要根据索引(指针)直接计算存储位置便可。若是是哈希映射那么首先须要计算索引值,而后若是索引值有冲突的场景下还须要进行二次查找(须要知道哈希的存储方式)。

编译器的设计是一个很是庞大和复杂的软件系统设计,在真正设计的时候须要解决两个相对重要的问题:

  • 如何分析不一样高级程序语言设计的源程序
  • 如何将源程序的功能等价映射到不一样指令系统的目标机器

为了解决上述两项问题,编译器的设计最终被分解成前端(注意这里所说的不是 Web 前端)和后端两个编译阶段,前端用于解决第一个问题,然后端用于解决第二个问题,具体以下图所示: 上图中的中间表示(Intermediate Representation,IR)是程序结构的一种表现方式,它会比 AST(后续讲解)更加接近汇编语言或者指令集,同时也会保留源程序中的一些高级信息,除此以外 ,它的种类不少,包括、以及基于栈的 IR 等,具体做用包括:

  • 靠近前端部分主要适配不一样的源程序,靠近后端部分主要适配不一样的指令集,更易于编译器的错误调试,容易识别是 IR 以前仍是以后出问题
  • 以下左图所示,若是没有 IR,那么源程序到指令集之间须要进行一一适配,而有了中间表示,则可使得编译器的职责更加分离,源程序的编译更多关注如何转换成 IR,而不是去适配不一样的指令集
  • IR 自己能够作到多趟迭代从而优化源程序,在每一趟迭代的过程当中能够研究代码并记录优化的细节,方便后续的迭代查找并利用这些优化信息,最终能够高效输出更优的目标程序

因为 IR 能够进行多趟迭代进行程序优化,所以在编译器中可插入一个新的优化阶段,以下图所示: 优化器能够对 IR 处理一遍或者多遍,从而生成更快执行速度(例如找到循环中不变的计算并对其进行优化从而减小运算次数)或者更小体积的目标程序,也可能用于产生更少异常或者更低功耗的目标程序。除此以外,前端和后端内部还能够细分为多个处理步骤,具体以下图所示: 优化器中的每一遍优化处理均可以使用一个或多个优化技术来改进代码,每一趟处理最终都是读写 IR 的操做,这样不只仅可使得优化能够更加高效,同时也能够下降优化的复杂度,还提升了优化的灵活性,可使得编译器配置不一样的优化选项,达到组合优化的效果。

观察者模式和发布/订阅模式

编程范式(Programming paradigm)是指计算机编程的基本风格或者典型模式,能够简单理解为编程学科中实践出来的具备哲学和理论依据的一些经典原型。常见的编程范式有:

阅读连接::若是你对于编程范式的定义相对模糊,能够继续阅读 了解更多。

不一样的语言能够支持多种不一样的编程范式,例如 C 语言支持 POP 范式,C++ 和 Java 语言支持 OOP 范式,Swift 语言则能够支持 FP 范式,而 Web 前端中的 JavaScript 能够支持上述列出的全部编程范式。

顾名思义,函数式编程是使用函数来进行高效处理数据或数据流的一种编程方式。在数学中,函数的三要素是定义域、值域和**对应关系。假设 A、B 是非空数集,对于集合 A 中的任意一个数 x,在集合 B 中都有惟一肯定的数 f(x) 和它对应,那么能够将 f 称为从 A 到 B 的一个函数,记做:y = f(x)。在函数式编程中函数的概念和数学函数的概念相似,主要是描述形参 x 和返回值 y 之间的对应关系,**以下图所示:

舒适提示:图片来自于。

在实际的编程中,能够将各类明确对应关系的函数进行传递、组合从而达处处理数据的最终目的。在此过程当中,咱们的关注点不在于如何去实现**对应关系,**而在于如何将各类已有的对应关系进行高效联动,从而可快速进行数据转换,达到最终的数据处理目的,提供开发效率。

尽管你对函数式编程的概念有所了解,可是你仍然不知道函数式编程到底有什么特色。这里咱们仍然拿 OOP 编程范式来举例,假设但愿经过 OOP 编程来解决数学的加减乘除问题:

以上程序计算的结果是 8,彻底符合预期。咱们知道了 addmultiply 两个函数的实际对应关系,经过将对应关系进行有效的组合和传递,达到了最终的计算结果。除此以外,这两个函数还能够根据数学定律得出更优雅的组合方式:

咱们彻底不须要追踪相似于 OOP 编程范式中可能存在的内部状态数据,事实上对于数学定律中的结合律、交换律、同一概以及分配律,上述的函数式编程代码足能够胜任。

经过上述简单的例子能够发现,要实现高可复用的函数**(对应关系)**,必定要遵循某些特定的原则,不然在使用的时候可能没法进行高效的传递和组合,例如

若是你以前常常进行无原则性的代码设计,那么在设计过程当中可能会出现各类出乎意料的问题(这是为何新手总是出现一些稀奇古怪问题的主要缘由)。函数式编程能够有效的经过一些原则性的约束使你设计出更加健壮和优雅的代码,而且在不断的实践过程当中进行经验式叠加,从而提升开发效率。

虽然咱们在使用函数的过程当中更多的再也不关注函数如何实现(对应关系),可是真正在使用和设计函数的时候须要注意如下一些特色:

咱们之前设计的代码一般是命令式编程方式,这种编程方式每每注重具体的实现的过程(对应关系),而函数式编程则采用声明式的编程方式,每每注重如何去组合已有的**对应关系。**简单举个例子:

 
命令式代码一步一步的告诉计算机须要执行哪些语句,须要关心变量的实例化状况、循环的具体过程以及跟踪变量状态的变化过程。声明式代码更多的再也不关心代码的具体执行过程,而是采用表达式的组合变换去处理问题,再也不强调怎么作,而是指明**作什么。**声明式编程方式能够将咱们设计代码的关注点完全从过程式解放出来,从而提升开发效率。

在 JavaScript 中,函数的使用很是灵活,例如能够对函数进行如下操做:
经过以上示例能够看出,函数继承至对象并拥有对象的特性。在 JavaScript 中能够对函数进行参数传递、变量赋值或数组操做等等,所以把函数称为一等公民。函数式编程的核心就是对函数进行组合或传递,JavaScript 中函数这种灵活的特性是知足函数式编程的重要条件。

纯函数是是指在相同的参数调用下,函数的返回值惟一不变。这跟数学中函数的映射关系相似,一样的 x 不可能映射多个不一样的 y。使用函数式编程会使得函数的调用很是稳定,从而下降 Bug 产生的机率。固然要实现纯函数的这种特性,须要函数不能包含如下一些反作用:
  • 可变数据(包括在函数内部改变输入参数)
 
从以上常见的一些反作用能够看出,纯函数的实现须要遵循最小意外原则,为了确保函数的稳定惟一的输入和输出,尽可能应该避免与函数外部的环境进行任何交互行为,从而防止外部环境对函数内部产生没法预料的影响。纯函数的实现应该自给自足,举几个例子:
 
 
纯函数的特性使得函数式编程具有如下特性:
 
可缓存性和可测试性基于纯函数输入输出惟一不变的特性,可移植性则主要基于纯函数不依赖外部环境的特性。这里举一个可缓存的例子:

在函数式编程的简单示例中已经能够清晰的感觉到函数式编程绝对不能依赖内部状态,而在纯函数中则说明了函数式编程不能依赖外部的环境或状态,由于一旦依赖的状态变化,不能保证函数根据对应关系所计算的返回值由于状态的变化仍然保持不变。
这里单独讲解一下数据不可变,在 JavaScript 中有不少数组操做的方法,举个例子:
这里的 slice 方法屡次调用都不会改变原有数组,且会产生相同的输出。而 splice 每次调用都在修改原数组,且产生的输出也不相同。 在函数式编程中,这种会改变原有数据的函数已经再也不是纯函数,应该尽可能避免使用。

阅读连接:若是想要了解更深刻的函数式编程知识点,能够额外阅读。

 
 
响应式编程是一种基于观察者(发布 / 订阅)模式而且面向异步(Asynchronous)数据流(Data Stream)和变化传播的声明式编程范式。响应式编程主要适用的场景包含:
  • 用户和系统发起的连续事件处理,例如鼠标的点击、键盘的按键或者通讯设备发起的信号等
  • 非可靠的网络或者通讯处理(例如 HTTP 网络的请求重试)
  • 连续的异步 IO 处理
  • 复杂的继发事务处理(例如一次事件涉及到多个继发的网络请求)
  • 高并发的消息处理(例如 IM 聊天)
 
 
 
 
 



这里列出一些我经常使用的 API:
 

在 JavaScript 中利用(Event Loop)能够在单线程中实现非阻塞式、异步的操做。例如
 
咱们重点来看一下经常使用的几种编程方式(Callback、Promise、Generator、Async)在语法糖上带来的优劣对比。

Callback(回调函数)是在 Web 前端开发中常常会使用的编程方式。这里举一个经常使用的定时器示例:
回调函数常常会由于调用环境的变化而致使 this 的指向性变化。除此以外,使用回调函数来处理多个继发的异步任务时容易致使回调地狱(Callback Hell):
回调函数不能经过 return 返回数据,好比咱们但愿调用带有回调参数的函数并返回异步执行的结果时,只能经过再次回调的方式进行参数传递:
 

上述示例讲述的都是 JavaScript 中标准的异步 API ,若是使用一些三方的异步 API 而且提供了回调能力时,这些 API 多是非受信的,在真正使用的时候会由于执行反转(回调函数的执行权在三方库中)致使如下一些问题:
  • 使用者的回调函数设计没有进行错误捕获,而偏偏三方库进行了错误捕获却没有抛出错误处理信息,此时使用者很难感知到本身设计的回调函数是否有错误
  • 使用者难以感知到三方库的回调时机和回调次数,这个回调函数执行的权利控制在三方库手中
  • 使用者没法更改三方库提供的回调参数,回调参数可能没法知足使用者的诉求
 


Callback 的异步操做形式除了会形成回调地狱,还会形成难以测试的问题。ES6 中的 Promise (基于 规范的异步编程解决方案)利用的原理来解决异步的处理问题,Promise 对象提供了统一的异步编程 API,它的特色以下:
  • Promise 对象的执行状态不受外界影响。Promise 对象的异步操做有三种状态: pending(进行中)、 fulfilled(已成功)和 rejected(已失败) ,只有 Promise 对象自己的异步操做结果能够决定当前的执行状态,任何其余的操做没法改变状态的结果
 

舒适提示:有限状态机提供了一种优雅的解决方式,异步的处理自己能够经过异步状态的变化来触发相应的操做,这会比回调函数在逻辑上的处理更加合理,也能够下降代码的复杂度。

 
Promise 对象的执行状态不可变示例以下:
假设要实现两个继发的 HTTP 请求,第一个请求接口返回的数据是第二个请求接口的参数,使用回调函数的实现方式以下所示(这里使用 setTimeout 来指代异步请求):
 
 
 

舒适提示:继发请求的依赖关系很是常见,例如人员基本信息管理系统的开发中,常常须要先展现组织树结构,并默认加载第一个组织下的人员列表信息。

 
若是采用 Promise 的处理方式则能够规避上述常见的回调地狱问题:

首先 Promise 能够注册多个 then(放在一个执行队列里),而且这些 then 会根据上一次返回值的结果依次执行。除此以外,各个 Promise 的 then 执行互不干扰。 咱们将示例进行简单的变换:
上述例子中的执行结果是由于 then 的执行会返回一个新的 Promise 对象,而且若是 then 执行后返回的仍然是 Promise 对象,那么下一个 then 的链式调用会等待该 Promise 对象的状态发生变化后才会调用(能获得这个 Promise 处理的结果)。接下来重点看下 Promise
从上述示例能够看出 Promise 的错误不会影响其余代码的执行,只会影响 Promise 内部的代码自己,由于Promise 会在内部对错误进行异常捕获,从而保证总体代码执行的稳定性。Promise 还提供了其余的一些 API 方便多任务的执行,包括
  • Promise.all:适合多个异步任务并发执行但不容许其中任何一个任务失败
  • Promise.race :适合多个异步任务抢占式执行
  • Promise.allSettled :适合多个异步任务并发执行但容许某些任务失败
 
Promise 相对于 Callback 对于异步的处理更加优雅,而且能力也更增强大, 可是也存在一些自身的缺点:
  • 状态单一,每次决断只能产生一种状态结果,须要不停的进行链式调用
 

舒适提示:手写 Promise 是面试官很是喜欢的一道笔试题,本质是但愿面试者可以经过底层的设计正确了解 Promise 的使用方式,若是你对 Promise 的设计原理不熟悉,能够深刻了解一下或者手动设计一个。

 

Promise 解决了 Callback 的回调地狱问题,但也形成了代码冗余,若是一些异步任务不支持 Promise 语法,就须要进行一层 Promise 封装。Generator 将 JavaScript 的异步编程带入了一个全新的阶段,它使得异步代码的设计和执行看起来和同步代码一致。Generator 使用的简单示例以下:
经过上述代码,能够看出 Generator 相对于 Promise 具备如下优点:
  • 丰富了状态类型,Generator 经过 next 能够产生不一样的状态信息,也能够经过 return 结束函数的执行状态,相对于 Promise 的 resolve 不可变状态更加丰富 
  • Generator 函数内部的异步代码执行看起来和同步代码执行一致,很是利于代码的维护
  • Generator 函数内部的执行逻辑和相应的状态变化逻辑解耦,下降了代码的复杂度
 
next 能够不停的改变状态使得 yield 得以继续执行的代码能够变得很是有规律,例如从上述的手动执行 Generator 函数能够看出,彻底能够将其封装成一个自动执行的执行器,具体以下所示:

舒适提示:设计了一个 Generator 自动执行器 ,使用 Co 的前提是 yield  命令后必须是 Promise 对象或者 Thunk 函数。Co 还能够支持并发的异步处理,具体可查看官方的 。

 
须要注意的是 Generator 函数的返回值是一个 Iterator 遍历器对象,具体以下所示:
Generator 函数的错误处理相对复杂一些,极端状况下须要对执行和 Generator 函数进行双重错误捕获,具体以下所示:
在使用 g.throw 的时候还须要注意如下一些事项:
  • 若是 Generator 函数自己没有捕获错误,那么 Generator 函数内部抛出的错误能够在执行处进行错误捕获
  • 若是 Generator 函数内部和执行处都没有进行错误捕获,则终止进程并抛出错误信息
  • 若是没有执行过 g.next,则 g.throw 不会在 Gererator 函数中被捕获(由于执行指针没有启动 Generator 函数的执行),此时能够在执行处进行执行错误捕获
 

  • 内置执行器:Generator 函数须要设计手动执行器或者通用执行器(例如 Co 执行器)进行执行,Async 语法则内置了自动执行器,设计代码时无须关心执行步骤
 

经过上述示例能够看出,async 函数的特性以下:
  • 调用 async 函数后返回的 Promise 对象必须等待内部全部 await 对应的 Promise 执行完(这使得 async 函数多是阻塞式执行)后才会发生状态变化,除非中途遇到了 return 语句
  • await 命令后若是是 Promise 对象,则返回 Promise 对象处理后的结果,若是是原始数据类型,则直接返回原始数据类型
 
上述代码是阻塞式执行,nextPromise 须要等待 firstPromise 执行完成后才能继续执行,若是但愿二者可以并发执行,则能够进行下述设计:
除了使用 Promise 自带的并发执行 API,也能够经过让全部的 Promise 提早并发执行来处理:
Async 的错误处理相对于 Generator 会更加简单,具体示例以下所示:
async 函数内部抛出的错误,会致使函数返回的 Promise 对象变为 rejected 状态,从而能够经过 catch 捕获, 上述代码只是一个粗粒度的容错处理,若是但愿 firstPromise 错误后能够继续执行
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
业务思考更多的是结合基础知识的广度和深度进行的具体业务实践,主要包含如下几个方面:
  • 通用性:脚手架、SDK、组件库等框架设计
  • 低代码:通用表单设计、通用布局设计、通用页面设计、JSON Schema 协议设计等
  • 测试:E2E 测试、单元测试、测试覆盖率、测试报告等
  • 业务:数据、体验、复杂度、监控
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
笔试更多的是考验应聘者的逻辑思惟能力和代码书写风格,主要包含如下几个方面:
 
 
 
 
 
 
 
 
 
}

1. C语言和汇编语言在开发单片机时各有哪些优缺点?

答:汇编语言是一种用文字助记符来表示机器指令的符号语言,是最接近机器码的一种语言。其主要优点是占用资源少、程序执行效率高。但是不同的CPU,其汇编语言可能有所差异,所以不易移植。

C语言是一种结构化的高级语言。其优点是可读性好,移植容易,是普遍使用的一种计算机语言。缺点是占用资源较多,执行效率没有汇编高。

对于目前普遍使用的RISC架构的8bit MCU来说,其内部ROM、RAM、STACK等资源都有限,如果使用C语言编写,一条C语言指令编译后,会变成很多条机器码,很容易出现ROM空间不够、堆栈溢出等问题。而且一些单片机厂家也不一定能提供C编译器。而汇编语言,一条指令就对应一个机器码,每一步执行什幺动作都很清楚,并且程序大小和堆栈调用情况都容易控制,调试起来也比较方便。所以在单片机开发中,我们还是建议采用汇编语言比较好。

如果对单片机C语言有兴趣,HOLTEK的单片机就有提供C编译器,可以到HOLTEK的网站免费下载使用。

2. C或汇编语言可以用于单片机,C++能吗?

答:在单片机开发中,主要是汇编和C,没有用C++的。

3. 搞单片机开发,一定要会C吗?

答:汇编语言是一种用文字助记符来表示机器指令的符号语言,是最接近机器码的一种语言。其主要优点是占用资源少、程序执行效率高。但是不同的CPU,其汇编语言可能有所差异,所以不易移植。

对于目前普遍使用的RISC架构的8bit MCU来说,其内部ROM、RAM、STACK等资源都有限,如果使用C语言编写,一条C语言指令编译后,会变成很多条机器码,很容易出现ROM空间不够、堆栈溢出等问题。而且一些单片机厂家也不一定能提供C编译器。而汇编语言,一条指令就对应一个机器码,每一步执行什么动作都很清楚,并且程序大小和堆栈调用情况都容易控制,调试起来也比较方便。所以在资源较少单片机开发中,我们还是建议采用汇编语言比较好。

而C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。C语言有功能丰富的库函数、运算速度快、编译效率高、有良好的可移植性,而且可以直接实现对系统硬件的控制。C语言是一种结构化程序设计语言,它支持当前程序设计中广泛采用的由顶向下结构化程序设计技术。此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。因此,使用C语言进行程序设计已成为软件开发的一个主流。用C语言来编写目标系统软件,会大大缩短开发周期,且明显地增加软件的可读性,便于改进和扩充,从而研制出规模更大、性能更完备的系统。

综上所述,用C语言进行单片机程序设计是单片机开发与应用的必然趋势。所以作为一个技术全面并涉足较大规模的软件系统开发的单片机开发人员最好能够掌握基本的C语言编程。

4. 当开发一个较复杂而又开发时间短的项目时,用C还是用汇编开发好?

答:对于复杂而开发时间紧的项目时,可以采用C语言,但前提是要求对该MCU系统的C语言和C编译器非常熟悉,特别要注意该C编译系统所能支持的数据类型和算法。虽然C语言是最普遍的一种高级语言,但不同的MCU厂家其C语言编译系统是有所差别的,特别是在一些特殊功能模块的操作上。如果对这些特性不了解,那调试起来就有的烦了,到头来可能还不如用汇编来的快。

5. 在教学中要用到8088和196芯片单片机教材,请问那里可以找到关于这方面的书或资料?

答:有关这方面的教材,大学里常用的一本是《IBM-PC汇编语言程序设计》清华大学出版社出版的,在网上以及书店都是可以找到的,另外网上还可以搜索到很多其他的教材如:《微机原理及汇编语言教程》(杨延双 张晓冬 等编著 )和《16/32 位微机原理、汇编语言及接口技术》(作者: 钟晓捷 陈涛 ,机械工业出版社 出版)等,可以在较大型的科技书店里查找或者直接从网上订购。

6. 初学者到底是应该先学C还是汇编?

答:对于单片机的初学者来说,应该从汇编学起。因为汇编语言是最接近机器码的一种语言,可以加深初学者对单片机各个功能模块的了解,从而打好扎实的基础。

7. 我是一名武汉大学电子科技大3的学生,学了电子线路、数字逻辑、汇编和接口、C语言,但是总是感觉很迷茫,觉好象什么都不会。怎么办?

答:大学过程是一个理论过程,实践的机会比较少,往往会造成理论与实践相脱节,这是国内大学教育系统的通病,不过对于学生来说切不可好高骛远。一般从大三会开始接触到一些专业课程,电子相关专业会开设相关的单片机应用课程并且会有简单的实验项目,那么要充分把握实验课的机会,多多地实际上机操作练习。平时可以多看看相关的电子技术杂志网站,看看别人的开发经验,硬件设计方案以及他人的软件设计经验。有可能的话,还可以参加一些电子设计大赛,借此机会2--3个人合作做一个完整系统,会更有帮助。到了大四毕业设计阶段,也可以选择相关的课题作些实际案例增长经验。做什么事情都有个经验的积累过程,循序渐进。

8. 请问作为学生,如何学好单片机?

答:学习好单片机,最主要的是实践,在实践中增长经验。在校学生的话,实践机会的确会比较少,但是有机会的话,可以毕业实习选择相关的课题,这样就可以接触到实际的项目。而且如果单片机微机原理是一门主课的话,相信学校会安排比较多的实践上机机会。有能力的话,可以找一些相关兼职工作做做,会更有帮助。而且单片机开发应用需要软硬件结合,所以不能只满足于编程技巧如何完美,平时也要注意硬件知识的积累,多上上电子论坛网站,买一些相关杂志。可能的话,可以到电子市场去买一些小零件,自己搭一个小系统让它工作起来。

HOTLEK的单片机是RISC结构的8位单片机,它可以广泛应用在家用电器、安全系统、掌上游戏等方面。大概来说可以分成I/O型单片机、LCD型单片机、A/D型单片机、A/D with LCD型单片机等等。

9. 如何才能才为单片机的高手啊?

答:要成为单片机高手,应该多实践,时常关注单片机的发展趋势;经常上一些相关网站,从那里可以找到许多有用的资料。

12. 8位机还能延续多久!

答:以现在MCU产品主力还是在8位领域,主要应用于汽车应用、消费性电子、电脑及PC周边、电信与通讯、办公室自动化、工业控制等六大市场,其中车用市场多在欧、美地区,而亚太地区则以消费性电子为主, 并以量大低单价为产品主流,目前16位MCU与8位产品,还有相当幅度的价差,新的应用领域也仍在开发,业界预计,至少在2005年前8位的MCU仍是MCU产品的主流。[page]

13. 学习ARM及嵌入式系统是否比学习其它一般单片机更有使用前景?对于一个初学者应当具备哪些相关知识?

答:一般在8位单片机与ARM方面的嵌入式系统是有层次上的差别,ARM适用于系统复杂度较大的高级产品,如PDA、手机等应用。而8位单片机因架构简单,硬件资源相对较少,适用于一般的工业控制、消费性家电等等。对于一个单片机方面的软件编程初学者,应以HOLTEK系列或8051等8位单片机来做入门练习。而初学者应当具备软件编程相关知识,单片机一般软件编程是以汇编语言为主,各家有各家的语法,但大都以RISC的MCU架构为主,其中 RISC (Reduced Instruction Set Computer) 代表MCU的所有指令。都是利用一些简单的指令组成的,简单的指令代表 MCU 的线路可以尽量做到最佳化,而提高执行速率。另外初学者要具备单片机I/O接口的应用知识,这在于周边应用电路及各种元器件的使用,须配合自己所学的电子学及电路学等。

15. 请介绍一下MCU的测试方法。

答: MCU从生产出来到封装出货的每个不同的阶段会有不同的测试方法,其中主要会有两种:中测和成测。

所谓中测即是WAFER的测试,它会包含产品的功能验证及AC、DC的测试。项目相当繁多,以HOLTEK产品为例最主要的几项如下:

接续性测试:检测每一根I/OPIN内接的保护用二极管是否功能无误。

功能测试:以产品设计者所提供测试资料(TEST PATTERN)灌入IC,检查其结果是否与当时SIMULATION时状态一样。

STANDBY电流测试:测量IC处于HALT模式时即每一个接点(PAD)在1态0态或Z态保持不变时的漏电流是否符合最低之规格。

耗电测试:整颗IC的静态耗电与动态耗电。

输入电压测试:测量每个输入接脚的输入电压反应特性。

输出电压测试:测量每个输出接脚的输出电压位准。

相关频率特性(AC)测试,也是通过外灌一定频率,从I/O口来看输出是否与之匹配。

为了保证IC生产的长期且稳定品质,还会做产品的可靠性测试,这些测试包括ESD测试,LATCH UP测试,温度循环测试,高温贮存测试,湿度贮存测试等。

成测则是产品封装好后的测试,即PACKAGE测试。即是所有通过中测的产品封装后的测试,方法主要是机台自动测试,但测试项目仍与WAFER TEST相同。PACKAGE TEST的目的是在确定IC在封装过程中是否有任何损坏。

16. 能否利用单片来检测手机电池的充放电时间及充放电时的电压电流变化,并利用一个I/O端口使检测结果在电脑上显示出来?

答:目前市场上的各类智能充电器,大部分都采用MCU进行充电电流和电压的控制。至于要在电脑上显示,好象并不实用,可能只有在一些专门的电池检测仪器中才会用到;对于一般的手机用户来说,谁会在充电时还需要用一台电脑来做显示呢?要实现单片机与电脑的连接,最简单的方式就是采用串口通讯,但需要加一颗RS-232芯片。

17. 在ARM编程中又应当如何?

答:就以嵌入式系统观念为例,一般嵌入式处理器可以分为三类:嵌入式微处理器、嵌入式微控制器、嵌入式DSP(Digital Signal Processor)。

嵌入式微处理器就是和通用计算机的微处理器对应的CPU。在应用中,一般是将微处理器装配在专门设计的电路板上,在母板上只保留和嵌入式相关的功能即可,这样可以满足嵌入式系统体积小和功耗低的要求。目前的嵌入式处理器主要包括:PowerPC、Motorola 68000、ARM系列等等。

嵌入式微控制器又称为单片机,它将CPU、存储器(少量的RAM、ROM或两者都有)和其它接口I/O封装在同一片集成电路里。常见的有HOLTEK MCU系列、Microchip MCU系列及8051等。

嵌入式DSP专门用来处理对离散时间信号进行极快的处理计算,提高编译效率和执行速度。在数字滤波、FFT(Fast Fourier Transform)、频谱分析、图像处理的分析等领域,DSP正在大量进入嵌入式市场。

18. MCU在射频控制时,MCU的时钟(晶振)、数据线会辐射基频或基频的倍频,被低噪放LNA放大后进入混频,出现带内的Spur,无法滤除。除了用layout、选择低辐射MCU的方法可以减少一些以外,还有什么别的方**

答:在设计高频电路用电路板有许多注意事项,尤其是GHz等级的高频电路,更需要注意各电子组件pad与印刷pattern的长度对电路特性所造成的影响。最近几年高频电路与数位电路共享相同电路板,构成所谓的混载电路系统似乎有增加的趋势,类似如此的设计经常会造成数位电路动作时,高频电路却发生动作不稳定等现象,其中原因之一是数位电路产生的噪讯,影响高频电路正常动作所致。为了避免上述问题除了设法分割两电路block之外,设计电路板之前充分检讨设计构想,才是根本应有的手法,基本上设计高频电路用电路板必需掌握下列三大原则:

以下是设计高频电路板的一些建议:

(1)印刷pattern的长度会影响电路特性。尤其是传输速度为GHz高速数位电路的传输线路,通常会使用strip line,同时藉由调整配线长度补正传输延迟时间,其实这也意味着电子组件的设置位置对电路特性具有绝对性的影响。

(2)Ground作大better。铜箔面整体设置ground层,而连接via的better ground则是高频电路板与高速数位电路板共同的特征,此外高频电路板最忌讳使用幅宽细窄的印刷pattern描绘ground。

(2)电子组件的ground端子,以最短的长度与电路板的ground连接。具体方法是在电子组件的ground端子pad附近设置via,使电子组件能以最短的长度与电路板的ground连接。

(3)信号线作短配线设计。不可任意加大配线长度,尽量缩短配线长度。

(4)减少电路之间的结合。尤其是filter与amplifier输出入之间作电路分割非常重要,它相当于audio电路的cross talk对策。

(5)MCU回路Layout考量:震荡电路仅可能接近IC震荡脚位;震荡电路与VDD & VSS保持足够的距离;震荡频率大于1MHz时不需加 osc1 & osc2 电容;电源与地间要最短位置并尽量拉等宽与等距的线,于节点位置加上104/103/102等陶瓷电容。

答:一个即时系统的软体由即时操作系统加上应用程序构成。应用程序与作业系统的接口通过系统调用来实现。用80C196KB作业系统的MCU,只能用内部RAM作为TCB和所有系统记忆体(含各种控制表)以及各个任务的工作和资料单元。因此一定要注意以下几点:

(1)对各个任务分配各自的堆迭区,该堆迭区既作为任务的工作单元,也作为任务控制块的保护单元。

(2)系统的任务控制块只存放各任务的堆迭指标,而任务的状态均存放于任务椎栈中。在一个任务退出运行时,通过中断把它的状态进栈,然后把它的堆迭指标保存于系统的TCB中;再根据优先取出优先顺序最高的已就绪任务的堆迭指标SP映象值送入SP中;最后执行中断返回指令转去执行新任务。

(3)各任务的资料和工作单元尽量用堆迭实现,这样可以允许各任务使用同一个子程序。使用堆迭实现参数传递并作为工作单元,而不使用绝对地址的RAM,可实现可重入子程序。该子程序既可为各个任务所调用,也可实现递回调用。

20. 在demo板上采样电压时,不稳定,采样结果有波动,如何消除?

答:一般来说,仿真器都是工作在一个稳压的环境(通常为5V)。如果用仿真器的A/D时,要注意其A/D参考电压是由仿真器内部给出,还是需要外部提供。A/D转换需要一个连续的时钟周期,所以在仿真时不能用单步调试的方法,否则会造成A/D采样值不准。至于A/D采样不稳定,可以在A/D输入口加一电容,起到滤波作用;在软件处理时采用中值滤波的方法。

21. 在车载DVD系统中,如何设计电子防震系统?

答:在车载DVD系统,最好选择高档DVD机,因为高档DVD机都采用电子防震系统(ADVANCEDESP),当记忆缓冲区内的读数降低,先进的电子防震设计会以双速读数系统,做出比正常速度快两倍的读数速率,以减低噪声,即使连续震荡仍可避免跳线情况出现,现在就说说什幺叫电子防震。简单地说:电子防震就是一个信号的储存--释放过程,首先CD要先把信号进行提前读取,也就是我们见到机子的加速,再把信号储存在RAM中,而我们在开防震的时候所听到的就是经过RAM的声音,这样就是它的过程。当没有防震时是由于信号是1比1读取的,所以当受到冲击后,就会出现跳音。而当开了防震时,机子受到冲击后,由RAM释放出来的声音使音乐不停地播放,而与此同时,光头迅速进行复位检索,当检索到信号后立即补充,所以不会出现跳音。大概的情况就是这样。但是这样还没有满足用家的要求,由于这种的方法带来的时间短,通常只有3秒,所以跳音的机会还是蛮高,如果增大RAM又带来造价的增高因为RAM这东西价格较贵,尤其是质量好的。

22. 在电子防震技术中,有那些IC或器件可供选择?

答:在电子防震技术中,最重要的技术之一要数是RAM技术,而一直以来都是因为它的成本问题,所以防震时间都一直不能增加,也就是说RAM本身就有限制,RAM的容量越大,造价就越高。而许多厂家就如何在RAM的限制里得到最大限度的记忆时间展开了开发研究。

23. 如何进行编程可以减少程序的bug?

答:在此提供一些建议,因系统中实际运行的参数都是有范围的。系统运行中要考虑的超范围管理参数有:

物理参数。这些参数主要是系统的输入参数,它包括激励参数、采集处理中的运行参数和处理结束的结果参数。合理设定这些边界,将超出边界的参数都视为非正常激励或非正常回应进行出错处理。

资源参数。这些参数主要是系统中的电路、器件、功能单元的资源,如记忆体容量、存储单元长度、堆迭深度。在程序设计中,对资源参数不允许超范围使用。

应用参数。这些应用参数常表现为一些单片机、功能单元的应用条件。如E2PROM的擦写次数与资料存储时间等应用参数界限。

过程参数。指系统运行中的有序变化的参数。

在上述参数群对一程序编写者而言,须养成良好习惯,在程序的开头,有顺序的用自己喜欢文字参数对应列表来替代,然后用自己定义的文字参数来编写程序,这样在做程序的修改及维护时只在程序的开头做变动即可,不用修改到程序段,才比较容易且不会出错。

24. 有人认为单片机将被ARM等系列结构的嵌入式系统所取代。单片机的生命期还有多长?

答:因为8位单片机与嵌入式系统的ARM在功能结构和单价的差异,故应用层次上就有很大的不同。 ARM适用于系统复杂度较大的高级产品,如PDA、手机等应用。 而8位单片机因架构简单,硬件资源相对较少,适用于一般的工业控制,消费性家电……等等。评估单片机近期是否会给ARM取代,要观察两个因素:

因ARM的工作频率较高,电路较庞大,所需的芯片制造工艺要求在0。25U以上,成本较高。8位单片机工作频率相对较低,电路较小,所需的芯片制造工艺在0。5U 即可,成本较低。

ARM的功能较单片机强,但两者定位不同。就如现阶段不会有人用ARM去作一个简单的工业定时开关。当然,如果两者单价相同也无不可,但现实是有很大的单价差距。

至于将来,因芯片制造成本会不断下降,上述的成本差异影响愈来愈少!但我估计在往后5年单片机仍有价格优势,仍能存活!但ARM是否会精简架构,降低成本,抢夺低阶市场?我想可能性不大,ARM应该会向上发展。同样,单片机也只能向上发展,如16位,高功能……等。 原因就是因为芯片制造工艺进步太快。压迫芯片设计往高集成发展。

25. 在单片机C编成时,如何才能使生成的代码具有和汇编一样的效率?

答:如果是使用C语言编程时,不太可能生成的代码具有1:1和汇编一样的效率。

C语言命令要被硬件识别并执行,必须通过编译器编译。编译器分为前端、中端、后端。前端与各种计算机语言写的程序打交道,后端与处理器的基本指令集接轨。所以如果使用C编程时,要达到最高的效率,最好能够很了解所使用的C编译器。先试验一下每条C语言编译以后对应的汇编语言的语句行数,这样就可以很明确的知道效率。在今后编程的时候,使用编译效率最高的语句,这样就能确保单片机C编程的时候同样的功能不同的C程序,编译效率最高。但是各家的C编译器都会有一定的差异,优秀的嵌入式系统C编译器代码长度和执行时间仅比以汇编语言编写的同样功能程度长5-20%,所以不同厂家的C编译器的编译效率也会有所不同。

26. ARM单片机和哪种内核的单片机比较接近?

答:严格的说,ARM不是单片机,是一个嵌入式的实时操作系统。ARM(Advanced RISC Machines)是微处理器行业的一家知名企业,设计了大量高性能、廉价、耗能低的RISC处理器、相关技术及软件。ARM将其技术授权给世界上许多着名的半导体、软件和OEM厂商,每个厂商得到的都是一套独一无二的ARM相关技术及服务。所以市场上像Intel、IBM、LG半导体、NEC、SONY、菲利浦和国半这样的大公司都有ARM系列,现在不存在什幺ARM单片机和哪种内核的单片机比较接近的问题。而且由于厂家购买内核后会根据自己芯片应用方向的不同,自行添加不同的外挂功能模块,所以,同样内核的芯片其提供的功能是不同的。

答:从51转到ARM,其实编程之类的原理都是一样的,但是要注意的是ARM是一个RISC的架构,在ARM的应用开放源代码的程序很多,要想提高自己,就要多看别人的程序,linux,uc/os-II等等这些都是很好的源码。

28. 我学过MCS51单片机教材,很有兴趣,但缺乏实践经验,手头没有任何道具可供演练,资金又有限,请问该怎么办?

答:在没有任何条件进行实践时,如果真的有兴趣,可以下载一些具有软件仿真功能仿真软件进行一些编程,像一些做得比较好的51仿真软件应该具有这种功能。HOLTEK的仿真软件HT-IDE3000也具有相应的功能,同时它还具有LCD软件仿真,周边电路的软件仿真。

29. 如果已经有了针对某MCU的C实现的某个算法,保持框架不变,对核心的部分用汇编优化,有没有一些比较通用的原则?

答:每个人的编程都有自己的风格与习惯,如果要利用别人的程序,在其中修修改改,如果他的程序并没有很好的模块化的话,建议最好不要这幺做,否则本来预期达到事倍功半,说不定反而事半功倍了。要参考他人的程序当然可以,但是首要是要看懂并理解他人程序的算法精髓,而不是在他的基础上打补丁。而关于算法方面的优化,可以购买一些数据结构的书籍,上面有比较详细的说明。

30. 如果准备估计一个算法的MIPS,有什么好的途径?

答:算法的运行时间是指一个算法在计算机上运算所花费的时间。它大致等于计算机执行简单操作(如赋值操作,比较操作等)所需要的时间与算法中进行简单操作次数的乘积。通常把算法中包含简单操作次数的多少叫做算法的时间复杂性。它是一个算法运行时间的相对量度,一般用数量级的形式给出。度量一个程序的执行时间通常有两种方法:

一种是事后统计的方法。因为很多计算机内部都有计时功能,不同算法的程序可通过一组或若干组相同的统计数据以分辨优劣。但这种方法有两个缺陷:一是必须先运行依据算法编制的程序;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优劣。因此人们常常采用另一种事前分析估算的方法。

一种是事前分析估算的方法。一个程序在计算机上运行时所消耗的时间取决于下列因素:

(1)依据的算法选用何种策略;

(2)问题的规模。例如求100以内还是1000以内的素数;

(3)书写程序的语言。对于同一个算法,实现语言的级别越高,执行效率就越低;

(4)编译程序所产生的机器代码的质量。这个跟编译器有关;

(5)机器执行指令的速度。

显然,同一个算法用不同的语言实现,或者用不同的编译程序进行编译,或者在不同的计算机上运行时,效率均不相同。这表明使用绝对的时间单位衡量算法的效率是不合适的。撇开这些与计算机硬件、软件有关的因素,可以认为一个特定算法"运行工作量"的大小,只依赖于问题的规模(通常用整数量n表示),或者说,它是问题规模的函数。

一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。为了便于比较同一问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本运算的原操作,以该基本操作重复执行的次数作为算法的时间度量。

算法的MIPS有专门的一门学问,可以去好好参考相关的数据结构书籍。

31. 遥控的编*思路和设计流程是怎样的?

答:一般来说完整的遥控码分为头码、地址码、数据码和校验码四个组成部分。头码根据不同的厂家各不相同,地址码和数据码都由逻辑“1”和逻辑“0”组成。编码的设计目的,就是按照编码规则发送不同的码值。我们最常见的码型有SONY、松下、NEC等厂家型号。遥控编码芯片最常用的是在空调、DVD、车库门等遥控器上。

设计编码程序可以分为三个部分。

第一部分是了*型的特性。遥控码的头码和地址码(也称为客户码)是固定不变的,数据码和校验码根据不同的键值而改变。

第二部分是计算发码时间。遥控码大部分都是由逻辑“1”和逻辑“0”组成,也就是由一串固定占空比、固定周期的方波所组成。通常这些方波的周期是毫秒甚至微秒等级,需要在时间上计算的比较精确。所以选择发码单片机型号的时候,就要考虑到单片机的运行速度是不是够快,以及程序运行时间够不够。

第三部分就是程序的编写。选定单片机型号之后,开始设计程序流程。一般来说我们使用I/O口就可以做发码的输出端口。发码程序一般由几个子程序组成,头码子程序、逻辑1子程序,逻辑0子程序以及校验码的算法子程序。一旦我们得到要发送码的命令后,首先调用头码子程序,然后根据客户码和键值调用逻辑1子程序或者逻辑0子程序,最后调用校验码算法子程序输出校验码。

HOLTEK公司的HT48CA0/HT48RA0、HT48CA3/HT48RA3和HT48CA6是专为遥控器设计的单片机,它们具有专门红外输出口,可以实现绝大部分发码的要求。

设计*程序也可以分为三部分。

第一部分了解编码波形特性。从分析编码的高、低脉冲宽度入手,了解逻辑“1”和逻辑“0”的波形占空比、周期。了解头码的特性。

第二部分确定接收方式。一般我们可以用I/O口查询方法或者INT口中断响应方法来接收编码。这两者的区别是I/O口查询方式比较耗费单片机的运行时间资源,需要不断的去侦测I/O的电平变化,以免漏掉有效的码值;而INT口中断接收方式则比较节省资源,当外部有电平变化时,单片机才需要去处理,不需要时刻进行侦测。但是INT口中断接收方式不能辨别相同周期不同占空比的波形特性,当编码所携带的逻辑“1”和逻辑“0”具有这种特性时,就无法通过INT口中断接收方式来辨别了,因为INT中断只是在上升沿或者下降沿的时候才触发。

第三部分将接收的码值存储并分析执行。根据判断高低电平的宽度(定时器或者延时),可以得到码值,也就是我们所说的*。一般我们连续收到3个相同的完整码值,就确认此码的确被发出,并接收成功。当*结束,根据码值我们可以判断出是哪个按键被按下,由此去执行相对的按键功能。

HOLTEK公司的HT48以及HT49(带LCD)系列单片机,都可以符合大多数*的任务。

32. 在学习单片机的过程中,如何理解预分频,12时钟模式(6时钟模型)等概念?

答:预分频器的英文是prescaler。它就是将输入的频率信号分频,然后再输出。HOLTEK公司有一款最基本的8位I/O型单片机HT48R05A-1,我们就以这款单片机为例说明。HT48R05A-1有一个8位向上计数的定时器Counter。系统时钟Fsys(4MHz)进入八阶预分频器(8-stage Prescaler)进行分频,再进入定时计数器Counter计数。根据软件设置,预分频器可以将Fsys进行2的n次方分频(n=1~8)。举例来说,如果软件设置为预分频器2分频,那幺预分频器输出的频率就是Fsys/2=2MHz,这个2MHz信号再进入定时计数器Counter。

12时钟模式(6时钟模型)应该就是在MCS51系列中,12个系统时钟为一个机器周期,2个系统时钟为一个状态,即一个机器周期有6个状态。

33. A/D、D/A的采样速率与其它单片机相比有什么优势?

至于D/A,一般是指PWM输出,HOLTEK A/D Type MCU都带有8bit的PWM输出,但HOLTEK PWM的特点是其输出频率由系统频率决定(既系统频率选定后,PWM频率也就定了),其占空比通过对[PWM]寄存器赋值进行控制,不需要占用定时/计数器资源。

34. 采用AT89S51时,出现了按了复位按钮,RAM中的数据被修改了。这是怎么回事?注:数据放在特殊寄存器之外。

答:如果是RESET脚的复位按钮:一般MCU的RESET复位,其特殊寄存器会被重新初始化,而通用寄存器的值保持不变。

如果复位按钮是电源复位:那就是MCU的上电复位,其特殊寄存器会被初始化,而通用寄存器的值是随机数。

35. 将P2.7用来驱动一个NPN三极管,中间串接了一个1K的电阻。问题是:当我尝试向P2.7写’1’时,发现管脚只能输出大约0.5V的一个电平。这个电路的使用得妥当么?如何正确的使用IO功能?

答:是在仿真时遇到的问题,还是烧录芯片后遇到的问题?

可以先将P2.7的外部电路断开,测量输出电压是否正常。如果断开后输出电压正常,那就说明P2.7的驱动能力不够,不能驱动NPN三极管,应该改用PNP三极管(一般在MCU应用中,都采用PNP方式驱动)。如果断开后输出电压还不正常,那有可能是仿真器(或芯片)已经损坏。

答:你所说的PWM是通过定时/计数器来控制其频率和占空比的,所以要提高频率,必然会降低精度。如果要提高PWM的频率,只能通过提高系统振荡频率来解决。

37. 汽车电子用的单片机是8位多,还是32位?如何看待单片机在汽车电子市场中的前景?

答:现今汽车制造也是一个进步很快的工业,特别是电子应用于汽车上,令多种新功能得以实现。

总的来说,汽车电子应用分三部份。

汽车发动机控制:限速控制,涡轮增压,燃料喷注控制等。

汽车舒适装置:遥控防盗系统,自动空调系统,影音播放系统,卫星导航系统等。

汽车操控和制动:刹车防抱死系统(ABS),循迹系统(TCS),防滑系统(ASR),电子稳定系统(ESP)等。

汽车上的各系统繁多,且日新月异,故利用何种单片机是依各系统规格,要求不一,但有一样可肯定是该单片机要符工业规格,才能忍受汽车应用的恶劣环境,高温,电源干扰,可靠度要求。不同档次的汽车其功能配置相对亦有差别,故8位单片机在较低阶的系统如机械控制,遥控防盗等应该还有空间,但高阶的系统如影音、导航及将来的无人驾驶,就非一般单片机能实现。

因汽车工业现阶段由欧美日数个大集团所把持,相关的汽车电子配件各集团会挑选单片机大厂合作, 故汽车内置的电子系统亦由单片机大厂把持,市场只剩外置系统如遥控防盗,影音导航供小厂开发。

答:您是需要三个外部counter还是需要三个定时器?如果是三个定时器标志的话,可以取这三个定时最基本的时基作为timer的基础计数,然后以这个时基来计算这三个需要的计数标志的flag,在程序中只需要查询flag是否到,再采取动作。

如果要3个外部脉冲计数的话,这个有一定的难度,如果外部脉冲不是很频繁,可以考虑通过外部中断进行,但是这个方法必须是外部脉冲的频率与MCU执行速度有一定的数量级差,否则mcu可能无法处理其它程序,一直在处理外部中断。

39. 在芯片集成技术日益进步的今天,单片机的集成技术发展也很迅速,在传统的40引脚的基础上,飞利浦公司推出20引脚的单片机系列,使很多的引脚可以复用,这种复用技术的使用在实际应用中会不会影响其功能的执行?

答:现在有很多品牌的单片机都有引脚复用功能,不止飞利浦一家,应该说这个方式前几年就已经有了。在实际应用中不会影响其功能的执行,但是要注意的是,有的MCU如果采用复用引脚的话,该引脚会有一些应用上的限制,这在相应的datasheet里面都会有描述,所以在系统规划的时候都要予以注意。

答:Delta-Sigma原理一般应用在ADC应用中。具体来说,Delta-Sigma ADC的工作原理是由差动器、积分器和比较器构成调制器,它们一起构成一个反馈环路。调制器以大大高于模拟输入信号带宽的速率运行,以便提供过采样。模拟输入与反馈信号(误差信号)进行差动 (delta)比较。该比较产生的差动输出馈送到积分器(sigma)中。然后将积分器的输出馈送到比较器中。比较器的输出同时将反馈信号(误差信号)传送到差动器,而自身被馈送到数字滤波器中。这种反馈环路的目的是使反馈信号(误差信号)趋于零。比较器输出的结果就是1/0 流。该流如果1密度较高,则意味着模拟输入电压较高;反之,0密度较高,则意味着模拟输入电压较低。接着将1/0流馈送到数字滤波器中,该滤波器通过过采样与抽样,将1/0流从高速率、低精度位流转换成低速率、高精度数字输出。

简而言之,Delta就是差动,Sigma就是积分的意思。Delta-Sigma软件测试,我的理解应该是通过软件模拟差动积分的过程。具体来说,就是侦测外部输入的电压(或者电流)信号变化,然后通过软件积分运算,得出外部信号随时间变化的基本状况。

41. 通常采用什么方法来测试单片机系统的可靠性?

答:单片机系统可以分为软件和硬件两个方面,我们要保证单片机系统可靠性就必须从这两方面入手。

首先在设计单片机系统时,就应该充分考虑到外部的各种各样可能干扰,尽量利用单片机提供的一切手段去割断或者解决不良外部干扰造成的影响。我们以HOLTEK最基本的I/O单片机HT48R05A-1为例,它内部提供了看门狗定时器WDT防止单片机内部程序乱跑出错;提供了低电压复位系统LVR,当电压低于某个允许值时,单片机会自动RESET防止芯片被锁死;HOLTEK也提供了最佳的外围电路连接方案,最大可能的避免外部干扰对芯片的影响。

当一个单片机系统设计完成,对于不同的单片机系统产品会有不同的测试项目和方法,但是有一些是必须测试的:

测试单片机软件功能的完善性。 这是针对所有单片机系统功能的测试,测试软件是否写的正确完整。

上电掉电测试。在使用中用户必然会遇到上电和掉电的情况,可以进行多次开关电源,测试单片机系统的可靠性。

老化测试。测试长时间工作情况下,单片机系统的可靠性。必要的话可以放置在高温,高压以及强电磁干扰的环境下测试。

ESD和EFT等测试。可以使用各种干扰模拟器来测试单片机系统的可靠性。例如使用静电模拟器测试单片机系统的抗静电ESD能力;使用突波杂讯模拟器进行快速脉冲抗干扰EFT测试等等。

当然如果没有此类条件,可以模拟人为使用中,可能发生的破坏情况。例如用人体或者衣服织物故意摩擦单片机系统的接触端口,由此测试抗静电的能力。用大功率电钻靠近单片机系统工作,由此测试抗电磁干扰能力等。

42. 在开发单片机的系统时,具体有那些是衡量系统的稳定性的标准?

答:从工业的角度来看,衡量系统稳定性的标准有很多,也针对不同的产品标准不同。下面我们大概介绍单片机系统最常用的标准。

本试验目的为测试试件承受直接来自操作者及相对对象所产生之静电放电效应的程度。

空间辐射耐受试验(RS)

本试验为验证试件对射频产生器透过空间散射之噪声耐受程度。

快速脉冲抗扰测试(EFT/B)

本试验目的为验证试件之电源线,信号线(控制线)遭受重复出现之快速瞬时丛讯时之耐受程度。

本试验为针对试件在操作状态下,承受对于开关或雷击瞬时之过电压/电流产生突波之耐受程度。

传导抗扰耐受性(CS)

本试验为验证试件对射频产生器透过电源线传导之噪声耐受程度。

脉冲经由耦合注入电源线或控制线所作的杂抗扰性试验。

43. 在设计软体时,大多单片机都设有看门狗,需要在软体适当的位置去喂狗,以防止软体复位和软体进入死循环,如何适当的喂狗,即如何精确判定软体的运行时间?

答:大多数单片机都有看门狗定时器功能(WDT,Watch Dog Timer)以避免程序跑错。HOLTEK有一款基本I/O型单片机--HT48R05A-1,我们就以它为例做个说明吧。

首先了解一下WDT的基本结构,它其实是一个定时器,所谓的喂狗是指将此定时器清零。喂狗分为软件和硬件两种方法。软件喂狗就是用指令来清除WDT,即CLR WDT;硬件喂狗就是硬件复位RESET。当定时器溢出时,会造成WDT复位,也就是我们常说的看门狗起作用了。在程序正常执行时,我们并不希望WDT复位,所以要在看门狗溢出之前使用软件指令喂狗,也就是要计算WDT相隔多久时间会溢出一次。HT48R05A-1的WDT溢出时间计算公式是:256*Div*Tclock。其中Div是指wdt预分频数1~128,Tclock是指时钟来源周期。如果使用内部RC振荡作为WDT的时钟来源(RC时钟周期为65us/5V),最大的WDT溢出时间为2.1秒。

当我们得到了WDT溢出时间Twdt后,一般选择在Twdt/2左右的时间进行喂狗,以保证看门狗不会溢出,同时喂狗次数不会过多。

软件运行时间是根据不同的运行路线来决定的,如果可以预见软件运行的路线,那么可以根据T=n*T1来计算软件的运行时间。n是指运行的机器周期数,T1是指机器周期。HOLTEK单片机是RISC结构,大部分指令由一个机器周期组成,只需要知道软件运行了多少条指令,就可以算出运行时间了。HOLTEK的编译软件HT-IDE3000中,就有计算运行时间的工具。但是对于CISC结构的单片机,一条指令可以由若干个机器周期组成,那么就需要根据具体执行的指令来计算了。

我们是一家开发数控系统的专业厂,利用各种单片机和CPU开发了很多产品,在软件开发上也采用了很多通用的抗干扰技术,如:软件陷阱、指令允余、看门狗和数字滤波等等,但实际运用中还是很不可靠,如:经常莫名其妙地死机、程序跳段、I/O数据错误等,并且故障的重复性很不确定,也不是周期性地重复。往往用户使用中出现故障,但又无法重现,很让人头痛。反复检查硬件也设查出原因,所以对软件的可靠性很是怀疑。怎么办?

答:防止干扰最有效的方法是去除干扰源、隔断干扰路径,但往往很难做到,所以只能看单片机抗干扰能力够不够强了。单片机干扰最常见的现象就是复位;至于程序跑飞,其实也可以用软件陷阱和看门狗将程序拉回到复位状态;所以单片机软件抗干扰最重要的是处理好复位状态。

一般单片机都会有一些标志寄存器,可以用来判断复位原因;另外也可以自己在RAM中埋一些标志。在每次程序复位时,通过判断这些标志,可以判断出不同的复位原因;还可以根据不同的标志直接跳到相应的程序。这样可以使程序运行有连续性,用户在使用时也不会察觉到程序被重新复位过。

可以在定时中断里面设置一些暂存器累加,然后加到预先设定的值(一个比较长的时间),SET标志位,这些动作都在中断程序里面。而主程序只需要查询标志位就好了,但是注意标志位使用后,记得清除,还有中断里面的时基累加器使用以后也要记得清除。

}

软件类型:国产软件 授权方式:共享软件 界面语言:简体中文 软件大小:0.14 MB 文件类型:.zip 演示网址:http:// 下载次数:

每一年的这个时候我都会将前一年的实验收获总结一遍,并重新打造这个mini 系列。

快三年了,主体线路图并未有过太大改变,依然保持着简洁的特点,变化最大的则是PCB的排版及布线技术。

回顾一下第一版的mini吧,不知道可否有朋友记得它?可曾记得可爱的扫帚标志?

这个是我第一款成功的MINI系列DAC,本坛的老朋友应该都见过。
它还有3个后续开发的附件

受网络的影响,我也曾经菜菜过,以为加一个时钟就能换取性能的提高,但后来事实证明,
这个时钟并不是那么简单实用的。它带来的高频失真倒是个不小的麻烦。

记得9X年的时候,某某报刊书籍都有说DAC并联提高精度之类的云云,我也是从那些书籍的指导中成长起来的,
因此也曾对此深信不疑,并制造了这个东西。

在我讲它接上去的瞬间,哇塞!好猛烈的低频啊……我不由得被自己的聪明创造所感动!兴奋的拿去给朋友们欣赏,
当时大家对DAC的认识都还比较肤浅,也都异常的兴奋,但……兴奋过后,
慢慢的我发现这一切只是强烈感官刺激后所带来的幻觉,低频的量感是强了,却失去了弹性,没了活力,
死气沉沉,毫无生气,高频暗淡无光,像是黑夜中被乌云遮去的月色一般……越听越难受,
于是我放弃了这个并联架构,使它成为了寿命最短的附件。

嫁接在mini TDA1541 DAC OS上的一个庞然大物,通过CPLD芯片修改数据及时序,
将7220输出的信号送给TDA1540这个古老的14bit芯片做DA转换,让这枚老爷车级别的芯片重新焕发青春,
唱响新时代的乐章。个人觉得这个是我设计得最好的一个附件,至少在国内互联网上,
它应该是唯一……声音表现尚可,唯独低噪偏大,这个是因为架构的问题导致的,比较遗憾,
这也凸显了升级接口设计的重要性。

从这一个版本开始,我深刻的体会到了PCB布线的重要性,通过改良走线,带来的听感上的改变是出乎意料的,
和换元件带来的听感变化不同,这种改变是很有趣的。

也是从这一版本开始,我开始对音响设备有了新的认识,也更多的花时间去了解音乐去听,去欣赏,去接受各种不同烧友给我提出的意见,在这些过程中,慢慢的,我进化了,我的DAC也进化了,我开始明白音乐是什么,设备和音乐的关系又是什么。从那时起,设备突然开始有了灵性,而我则化为了塑造这种灵性的操手。

MINI TDA1541 DAC OS 2在过去的一年里,随我游历了多位烧友的听音室,在不同的设备环境下进行了回放的测试,也参加了多次烧友聚会,每次活动之后都收获到了宝贵的改进资料,并在这段过程中不断的改进器件的选用和搭配,甚至切割线路板……仅为提高那一点点的性能。

最终它累了,走到了尽头,无法再进行改动了,拖着残破的身体,回到了它应有的归宿(一个崭新的机壳),成为了一台将永久保留在我设备架上的机器。 

这是它现在最终的样子,很龊,但很优秀!很残,但也挺美。讨了个55VA的牛媳妇,住在黑匣子里,挺乐~

BTW:这台随身的机器进行了多次修改,背面已满是伤痕,性能已不是它诞生时可比了,尽管它已经降级成连A标都没有的最普通的TDA1541。

当OS 2已成往事,那谁来接替扫帚MINI TDA1541 DAC的旗帜?我一直在想。

随着年龄的增长,经验的积累,以及心态的变化,我越发感觉到应该纠正过往设计的缺陷和错误,应该尽自己所能将mini TDA1541 DAC发挥得更好,这种想法一直在脑子里回荡。

终于……OS 3的实体摆在了我的面前。

这个板子延续了“OS 2 改”的声音风格,趋向于平衡、更自然地听感,而不再一味的突出1541的中频优势,高频顺滑,低频则扎实。
主体电路依然没有改变,调整了一下稳压电路及PCB布线,PCB的尺寸和它前两代时一样的,这也是我一贯的设计作风,通过改良线路来提高性能。

以上就是过往设计过的mini TDA1541 DAC,哦 对了还少了一份,就是由个附属品的mini 尺寸也一样。但仅仅做了几套的板子。

这是我迄今为止唯一的一台有配套外壳mini TDA1541 DAC

嗯 秀完了,该回到正题,OS 3。

目前正在调整测试阶段,一会上测试资料吧

困了 未完 待续。。。。

篇外话:mini的 前世今生

既然发帖子了,索性就继续写下去。

时间是2004年末,我对1541的了解是从论坛的第一版1541DAC开始的。

当年小钳子友情赠送了一套PCB给我,(至今仍然非常感激,遗憾的是没装完。。。 ),

那一年我还在大学校园里傻楞傻楞的……稀里糊涂的遇到了我的第一个PCB老师——创梦站长(C-Dream),于是开始的我的创造之路。。。。。

时间:2005年,这个是我们第一个版本的TDA1541……它还算不上mini,设计和布局还有些幼稚,很DIY的感觉。

当时我还不会使用PCB制图软件,所以这个板子是由我的老师代笔完成的。

线路结构大体和论坛早期的类似,NOS结构、二级稳压LM317+TL431,增加了时钟电路,信号输入选择电路,电阻IV+一阶LPF+运放放大输出。很搞笑的是当年选的制版厂不怎么好,居然搞出了几个短路点,一上电这个板子就烟花了……

而当年的形而上学,未真正了解电路,因此造出的机器稳定性不佳,TL431的应用在此成为了败笔。

随后我们还出了这个改进的版本。。。相比之前的是稳定得多了。声音表现也还行。

遗憾的是没有更多的照片留底,随着计算机硬盘的报废而报废了。。。仅得几张。

时间过得很快……我的学习也慢慢进步到可以自己绘制线路板的阶段了。在这个时期,我是疯狂的,妄想的,自以为是的。

其实并不像某些人说我只会做小板子,只会追求性价比之类的说法。实际上我一开始就是一个烧坏脑子的疯子。我第一张作品就是大板,而且很奢侈的找了一家为摩托罗拉代工的厂家帮打造了电路板,贵。。。。很贵。。。。把我的压岁钱挥霍掉了大半。 而且还疯狂的收集TDA1541的芯片,各个年代,不同产地,从最早的1541到双皇冠,我统统都买了回来,现在回头想想,够疯狂,够神经,一个人怎么去玩那几百片的芯片呢?狂晕自己!

见图吧,这个是我个人真正的第一套独立设计的PCB,很不幸。。它有bug。。。 

 实际上很想重新做这第一套板子,但……无奈已经没有了动力。)

这个板子在这个世界上仅有5套,现在一套都不在我身边。。。有些想召回它们。

}

我要回帖

更多关于 程序如何写入单片机 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信