【知乎用户的回答(52票)】:
知乎上问具体专业问题果然不是好选择。前面的回答不能说是错的,至少也是不准确的。
不知道题主学过数字电路没有,学过就比较好理解了。
我们写的软件经过这几个步骤 高级语言-->汇编语言--->机器语言。机器语言是二进制的,每一种指令操作都有对应的二进制编码,比如我们执行 ADD R1,R2 指令, ADD有一个唯一的二进制编码假设为编码1 ,R1 R2是CPU寄存器地址也有唯一的编码设为编码2 编码3.这些编码的具体格式和数值是根据指令格式和具体cpu架构确定的。比如arm的指令字长就固定为32位,特定的位代表着条件码操作码等。arm的指令可参考《arm 体系结构与编程》杜春雷编
我们的程序就是以这种二进制编码格式存储在cpu的存储器里。
有了这几个唯一编码之后呢?cpu就开始译码操作,进行一些数字电路的组合运算,假设编码1是 0x10(只是假设,实际各个指令集编号不同),当译码电路发现指令的操作码是0x10时就知道是进行加法运算,此时会输出一个有效信号选通加法器;同时也对编码2和编码3进行译码,选通对应的寄存器(哪一个是源寄存器哪一个是目标寄存器是由指令集格式规定的),然后就将寄存器输出的数据通过CPU内部的数据线送入加法器进行加法运算,运算的结果送入目标寄存器。这就运行了一个加法运算。
直接回答题主的问题,当你在程序中对IO管脚的寄存器写0时,单片机将通过类似上述的步骤对指令进行译码,然后将0这个数据写入到IO管脚寄存器中。寄存器的数值如何送到对应的IO管脚?一般是通过D 触发器(如图):
在单片机内部IO寄存器的数据口连接到D触发器的D管脚(实际上还有其他电路,用来增大驱动能力等),D管脚下面有小三角的管脚是时钟信号管脚,当时钟信号上升沿来临时,D触发器D端口的数据将输出到Q端口,Q端口是连接着外部的管脚的。所以只要IO寄存器不改变,Q管脚将一直保持着高电平或者低电平,即你程序表现出来的写0就使管脚输出低电平。
更多CPU指令操作内容可浏览我的一个回答
http://www.zhihu.com/question/20388579/answer/14985333
总结一下:你的程序编写完后通过编译器将变成一堆二进制的机器编码----->单片机对这些编码进行译码,知道你要对哪一个寄存器进行什么样的操作----->对应的寄存器被写入正确的值,如果是IO管脚的话将根据时钟将寄存器的值输出到外部IO管脚。所以实际上单片机也就是一堆数字电路的组合,只不过我们人为的规定什么样的编码要进行什么样的操作而已。
【随风的回答(19票)】:
我怎么发现得票数最多的没有真正回答问题呢....
下面是我的答案:
先说代码:
我们是用电脑的键盘来输入的指令,每一个指令都对应一个ASCII码,而这里的ASCII码就是有序的电压的高低(或电流的有无,下面只提电压的高低),即我们输入的是电压的高低,你所看到代码是这些电压的高低控制显示器所显示的图像,其实电脑也不知道它是什么,只知道这样显示。
结论:代码其实就是存储在存储器(内存、硬盘或者闪存等等)中有序的电压的高低。
再说编译:
编译是一个有序的电压的高低向另一种有序的电压高低的一种转换过程,下面以52单片机为例,我们编译是从表示ASCII码的那种有序电压高低转换为52单片机能够识别的另一种规定好的有序电压高低,即表示HEX文件的电压高低。
结论:编译出的结果还是电脑中存储的有序电压高低。
到单片机烧录:
接下俩就是烧录,理解了上面两点就很容易理解下面的内容,烧录就是电脑中的有序电压高低通过数据线传输到单片机中的ROM中。
接下来ROM就可以释放其中的电压来控制外围的电路。
总结:从代码的编辑到最后对电路的控制都是电压在起作用,只是为了方面我们而给我们展现的形式不一样而已,而其本质都是电压,这样也就不存在转换。
理解这句话:世界上没有软件,软件只是对硬件的一种反映,就像意识是对世界的一种反映是一样的!
相信这样就很容易理解了。
看到有人赞同了我的观点,很开心,针对题目我再补充一点:
只要你提到0/1,提到软件,这个问题就没法理解...因为软件
【包括0/1】和硬件始终存在一道无法跨越的鸿沟;
你说你在单片机中写0,请问你是如何写0的?在键盘上敲个0?实际还是电平
【和我们理解的数字没关系】,那个0只是你在电脑显示器上电平的呈现形式,那个所谓的0
【实质是电平】可以传输到单片机中的ROM中,电平控制电平没什么疑问吧,这样就输出低电平了...
有错误欢迎指出。
【知乎用户的回答(4票)】:
非专业人士,以自己对于问题的理解来回答这个问题。抛砖引玉,欢迎专业人士指正。
先从电子技术讲起。
电子技术中有个叫做脉冲触发器的东西专门用来产生开闭信号,也就是你说的1、0。这个信号用来控制电路的导通与关闭,导通的电路参与到整个电路的运作中,关闭的电路不参与运作。与之对应的有很多各种各样的触发器,这些触发器的组合可以形成逻辑里的最基本的两种逻辑:与、非。与非两种逻辑又可以构成或、且、异或等。这就构成了基本的逻辑。
再说说纺织机。
为什么要说纺织机,其实现在的CPU的运行原理和纺织机是一样的。所以你的个人电脑也好手机也好都可以看做是一个高级的纺织机。
纺织衣服的时候有两种状态,一种状态是线在上面,另一种是线在下面。通过这种综合交错的上上下下的线,衣服上就形成了图案。我们把线在上面记做1,线在下面记做0。把整个衣服看做是在一个xy平面上进行纺织的。那么纺衣服的过程就可以以如下步骤进行(以(0,0)点为例):
1.该点是否选X线(绿线、蓝线等等)
2.X线是否在上面
循环这个步骤就可以纺织出衣服了。
如果再细分,选线这个步骤也可以细分为很多个由是否组成的问题,其他问题同理。也就是说,纺织机的原理其实就是把纺织这整套过程细分,分为一个个只有是非两种选项的问题。
这其实就是计算机的原理。
这回轮到说单片机了。
代码其实就是一整套是非指令的集合。CPU的厂商把一些常用的处理过程(是非指令的集合)比如说:移动、增加、减少编制成代码,你运行一次代码,就相当于完成了很多步的是非指令。这些指令的作用结果就是你可以看到的单片机的各种动作。最简单的就是算数了。前段时间有人问数学有什么用,这里就体现出来了数学的作用。正是有了数学这个工具,我们现在的处理器才能给我们展示如此丰富多彩的多媒体技术,你听到的声音、图像都是由1、0这样最基本的形式经过各种数学运算所展现出来的。
最后推荐一个小游戏:Akinator,链接:http://en.akinator.com。这个小游戏很好的展示了怎么通过一系列的是否问题来完成猜人名这个过程。玩儿完了你就会对整个计算机的运算过程有个初步的了解。
【饮悦的回答(6票)】:
推荐一本书《编码的奥秘》,你会很明白的
【知乎用户的回答(3票)】:
既然楼主提到“低电平”,看来对数字电路是有一点了解的。
那么,翻开数字电路相关教材,最前面几页。
一般它都会告诉你,三极管/场效应管类似继电器(一种通过线圈产生磁场、然后用磁场控制物理开关的通断与否的设备);在它一个管脚上输入/切断电压信号,另一个管脚就会出现高/低电平。
这东西,就是数字电路的基础。
你敲入的任何东西,最终就是通过类似的东西/机制储存的;所谓“指令”,其实就是“某个命令码“(一般叫机器码),这个”命令码”会改变CPU内部一堆“开关”的状态,以激活不同的电路;然后数据(前面提到过,它也是用三极管/场效应管的导通与否“记忆”的)利用类似的机制,被送入这个被“指令”激活的电路——这些电路是工程师们利用最最基础的三极管控制原理,用一大堆三极管组合出来的:当数据(某种高低电平的组合)经过这些电路后,就会变成另外一组高低电平的组合:这个组合刚好和“指令”代表的功能所应该给出的结果一致。
这段话可能有点难以理解。那么,看下最简单的与门吧:数据有两个,分别通过两条不同的线路进入与门;输出只有一个,必须给它输入两个高电平,它才会输出高电平;否则就输出低电平(这一般简化表述为:只有输入两个1,它才输出1,否则输出0)。
——这就是所谓的“与”逻辑;一组这样的“与”逻辑就与计算机指令/高级语言里的“按位与”直接对应。
——而按位与这个指令,意思就是选择一组线路,把数据导通到这组“与”逻辑电路之上;然后这组与逻辑电路就会输出两组数据的按位与的结果。
——类似的,二进制加法,1+1=0(同时进位);1+0=1;0+1=1;0+0=0:这可以用一个异或电路来模拟(因为异或电路的规则就是1+1=0、1+0=1、0+1=1、0+0=0);但这样(同时进位)这个说明就会丢失了,所以需要同时用一个与门模拟高位进位(前面说过,与门就是只有两个1才会输出1,其它输出0;综合异或的说明:这是不是就和二进制加法的规则刚好一致了呢?)
然后更高一位就成了两根输入线上的数据相加、再加上进位数据……依此类推:这就是用开关做加法的思路。而这样堆起来的一组开关,就叫加法器。
——add指令呢,就是选中上面做的那一堆用来做加法的开关们;然后给它们输入数据(不要忘了,两组高低电平而已),这些数据就驱动着构成加法器的那些开关们,噼里啪啦一阵乱响之后(嗯,如果是老掉牙的继电器计算机的话:还记得BUG的故事吗?),电路就稳定在某个状态了:此时,加法器的输出,恰恰就是输入数据的和(当然是这样了。前面讲过,我们是刻意用异或门和与门精心组合,让它们刚好和加法的效果一致)。
——其它种种指令,莫不大同小异(更复杂/高级的时钟、流水线啥的……暂时就无视吧)
你可以翻翻课本。上面讲过加法器的实现。
而加法器和另外一些逻辑电路加起来,就是所谓的ALU(算术逻辑单元,一下子就高大上了有木有)。
简而言之,代码在计算机内部,本身就是一组特定的高低电平组合;而计算机是精心设计的、海量的、用高低电平控制通断的开关组;当给这个开关组输入不同的电平组合时,就会导致它内部出现复杂的开关动作,最终产生另外一组高低电平的组合作为输出;这些开关动作经过精心设计,使得它的行为是可解释、可预测的——解释/预测的规则,就是CPU的指令集。
——换言之,在机器内部,一切本来就是高低电平,不存在转换问题。
——反而是键盘/鼠标/mic的输入要经过模数转换;而视频、音频之类的输出,要经过数模转换
————————————————————————————————
我知道,很多人困惑的,可能并不是开关的原理;而是:如果CPU不过是一堆开关的话,它为什么能“听懂”类似“加法”“do...while”这类高大上的复杂指令、甚至做出office、photoshop甚至人工智能这样神奇的东西呢?
这就不得不说说图灵的贡献了。
还是从最小儿科的题目开始。假设你从来没听说过乘法表;那么,你怎么算8×9呢?
我们知道,A x B就是B个A相加或A个B相加的意思。那么,要算8×9,我们只要把8个9加起来就够了:8次加法而已。
换句话说,这里有个很好的思想,即: 很多“高级”数学计算(如乘法),其实用“低级”方法(如加法)一样是可以算的。
图灵的贡献就是,他证明了,如果一台机器,可以接受一系列的输入、并按输入指示完成运算;那么,当这台机器满足“图灵完备”的要求时,它就可以模拟任何其它数学/逻辑运算!
换句话说,要搞出一台“无所不能”的计算机器,并不需要穷尽一切可能,而是只要支持少的令人发指的几条指令,就可以办到了。
比如说,CPU,它根本上其实只会三招:与、或、非。
与就是全为真,则输出真;或是只要一个为真,则输出真;非则是输入真它就输出假、输入假就输出真——所谓的真假,一般写作1、0,在计算机内部就是高低电平。
别看CPU只会这三板斧;可当它们巧妙的组合起来后(构造成计数器、指令寄存器等等等等再组合成CPU),就达到了图灵完备的要求,产生了质变。
具体是怎么做的,这就不是三言两语能说清楚的了。还是仔细看看自己的数字电路这本书吧。
——数字电路研究的,就是如何用与或非这三板斧,来实现各种高级运算甚至CPU指令集这么复杂的事物
——而CPU指令集呢,则形成了另外一个强大得多的图灵机,这就是机器码(和汇编指令几乎一一对应);然后呢,诸如c/c++、java等高级语言,就是利用CPU指令集形成的、另一个更加强大的图灵机(编译器/解释器负责两种图灵机之间的翻译工作)。
——而程序员们研究的,就是如何用编程语言这样一个强大的图灵机,去实现office、photoshop、wow甚至人工智能这样复杂的事物。
——这也是一个层层模拟的过程。
————————————————————————————
总之,开关的通断是基础;而各种神奇的功能是如何用这么简单的东西组合出来的呢,那就必须理解“程序”原理(也就是图灵机原理)了。
【孙立伟的回答(0票)】:
谢邀。可惜我不是搞单片机开发的。虽然我也接触过一点点单片机编程,但是对于单片机如何工作的还搞得不是很清楚。看过一些单片机原理的书,大致有一个模糊的理解。单片机实际上是一个小型的计算机系统,依然遵循冯诺依曼的体系结构。
至于单片机如何将代码转换成01信号,我猜测应该看看逻辑电路的书。
【知乎用户的回答(0票)】:
题主问的很模糊,前面有人从高级语言的角度回答了,我就说下最底层的硬件代码吧,要明确一点就是高级语言最后都得通过编译器编程硬件机器码才可以直接控制硬件。上面随风的回答中控制电压的结论其实是从模电的角度解释了问题,我这个答案算是从数电的角度说下吧。这二者是不矛盾的,因为所有的数电理论最后也是通过模电来起作用的。
--------------------------------------------
硬件编程语言verilog和VHDL就是专门来控制硬件的。如果你接触过RTL coding。这种程序里面通篇都是用code控制硬件,我想了下大概可以先介绍两种。
1控制信号
简单说就是你先把硬件什么的都搭好,即data path,然后编写代码通过control unit控制data flow。CPU不管是最原始的single cycle,multi cycle CPU还是现在的多核多线程,都就是这么发展出来的。比如硬件电路中很常见的选择器multiplexer,拿一个2to1的来说,你编写他的控制信号是是0,他就给你接第一条线,这样就是一种通路,你编写他的控制信号是是0就开通了另一条录。而这个控制的信号0和1又可以通过一定的逻辑来生成。
下图是一个最基础的single cycle CPU
其中橙色的部分就是control signal,是编程者可以控制的部分,你可以看到这些橙色的线都接到了不同的MUX(即multiplexer即选择器)的控制端。举个栗子比如最上面的RegDst信号,如果你的程序里面有一句:其中橙色的部分就是control signal,是编程者可以控制的部分,你可以看到这些橙色的线都接到了不同的MUX(即multiplexer即选择器)的控制端。举个栗子比如最上面的RegDst信号,如果你的程序里面有一句:
RegDst=1;
那么你会顺着线看到Instruction[15~11](指令的11到15位)被送到了寄存器集的WriteRegister端。
2赋值操作:
比如上面的栗子,指令的11到15位在某些指令里是指的数据往register file里的某个写入的地址,要把数据存到这个地址里还得用上这么一句:
reg_file[寄存器地址]<=Mem[数据在内存内的地址];
-----------------
全部总结的工作不是我这种喳喳能完成了,就先写两种好了,话说我们从来没这么给分类过,因为额,没什么用。盗了professor一张slide哈哈~
【刘小斌的回答(0票)】:
对于一条代码 a=b+c而言,编译器会把它弄成mov ax,b; add ax,c;mov a,ax这么几条指令;
而masm会把这几条指令弄成0101010的机器指令;假如mov的码是001,add的码是010
那么这三条指令就等价于001*****,010*****,001*****,当CPU读到第一条指令时,就知道,哦,001开头的是mov指令,那么它就会把b的值放到寄存器ax中,这个中间是通过逻辑电路实现的,同理,add指令会通过alu计算值放到ax中,从而完成了这次计算。具体可以找本组成原理看看
【知乎用户的回答(0票)】:
我们从下往上看:
【假面师爷的回答(0票)】:
应该从晶振开始解释。晶振产生有序的高低电平,从而开始驱动CPU、内存等开始工作。CPU以及内存都是有很多引脚的,当CPU需要和内存交互数据时,就会将固定的管脚置为相应序列的电平。至于模数转换,数字电子电路应该会有相应的说明。
【XieYipeng的回答(0票)】:
绝大部分答案都没看补充说明。
0和1本身就是电脉冲进来的,还是电脉冲出去。
键盘的0和1是电路通断,鼠标是光电转换,硬盘里是磁头读取的电脉冲,光盘就还是光电信号转换。
无非就是这么回事,大体上理解了传感器就理解抽象信号和电信号的关系了,扯那么多电路有什么用。
【本杰明的回答(0票)】:
因为代码本来就是高低不同的电平,在这个意义上说就可以说代码就是硬件的表现。
制作芯片的时候,内部大部分是由大量MOS管构成的(几十亿个)。这个可以由光刻或者化学沉积做到
像上面的MOS管,G是高电平(有电压),这样D和S就导通,可以进一步控制其他电路。这样一大堆MOS管就可以做成译码器/加法器/乘法器等不同的电路。像上面的MOS管,G是高电平(有电压),这样D和S就导通,可以进一步控制其他电路。这样一大堆MOS管就可以做成译码器/加法器/乘法器等不同的电路。
编程的时候,通常我们用C++或者JAVA编程,又专门的编译器,把所有代码统一处理成机器语言,就是类似ADD R1 R3那些汇编指令,存在机器内部存储器(ROM)里。(举个例子,存的时候可能是000110101就代表ADD,000000001代表,000000003代表R3,不同的芯片存储风格不一样)。存在ROM里的意思,就是ROM里面有一系列MOS管开关(见上图),可以随时读出,并且可以掉电保存的,高电平就一直是高电平,低电平一直低电平,除非有改写的操作。
代码执行的时候,就把指令(ADD R1 R3)通过取码器,译码器的MOS管读出来(也就是那电平接出来),然后把输出的MOS管电平变化记录下来,再存到ROM里或者参与到下一次指令处理的输入端。
你说的代码控制硬件,应该就是代码控制输入输出口(IO吧)。如果该指令是控制外部接口的指令,那这个指令就会指挥各种MOS管的高低高低,最终连接到控制外围芯片引脚的MOS管(当然这个MOS管电流会更大),这样用电压表一量外围引脚就会显示出高电平或者低电平了。外围引脚再接个LED灯,你就可以看到LED灯亮/熄了。
实际的情况是,代码一直都在控制硬件,每运行一条代码,里面的微小MOS管都已经通断通断了几千次了。芯片里面有好几十亿个MOS管呢
联系客服