先說代碼:
我們是用電腦的鍵盤來輸入的指令,每一個指令都對應一個ASCII碼,而這里的ASCII碼就是有序的電壓的高低(或電流的有無,下面只提電壓的高低),即我們輸入的是電壓的高低,你所看到代碼是這些電壓的高低控制顯示器所顯示的圖像,其實電腦也不知道它是什么,只知道這樣顯示。
結論:代碼其實就是存儲在存儲器(內存、硬盤或者閃存等等)中有序的電壓的高低。
再說編譯:
編譯是一個有序的電壓的高低向另一種有序的電壓高低的一種轉換過程,下面以52單片機為例,我們編譯是從表示ASCII碼的那種有序電壓高低轉換為52單片機能夠識別的另一種規定好的有序電壓高低,即表示HEX文件的電壓高低。
結論:編譯出的結果還是電腦中存儲的有序電壓高低。
程序燒錄到單片機:
接下倆就是燒錄,理解了上面兩點就很容易理解下面的內容,燒錄就是電腦中的有序電壓高低通過數據線傳輸到單片機中的ROM中。
接下來ROM就可以釋放其中的電壓來控制外圍的電路。
總結:從代碼的編輯到最后對電路的控制都是電壓在起作用,只是為了方面我們而給我們展現的形式不一樣而已,而其本質都是電壓,這樣也就不存在轉換。
理解這句話:世界上沒有軟件,軟件只是對硬件的一種反映,就像意識是對世界的一種反映是一樣的!
相信這樣就很容易理解了。
單片機中的0與1:
只要你提到0/1,提到軟件,這個問題就沒法理解...因為軟件【包括0/1】和硬件始終存在一道無法跨越的鴻溝;
你說你在單片機中寫0,請問你是如何寫0的?在鍵盤上敲個0?實際還是電平【和我們理解的數字沒關系】,那個0只是你在電腦顯示器上電平的呈現形式,那個所謂的0【實質是電平】可以傳輸到單片機中的ROM中,電平控制電平沒什么疑問吧,這樣就輸出低電平了...
翻開數字電路相關教材,最前面幾頁。
一般它都會告訴你,三極管/場效應管類似繼電器(一種通過線圈產生磁場、然后用磁場控制物理開關的通斷與否的設備);在它一個管腳上輸入/切斷電壓信號,另一個管腳就會出現高/低電平。
PS:繼電器是一種利用電磁鐵控制的開關;當向電磁鐵通電時就產生磁場,而這個磁場就會吸合或者分離開關,從而實現“以微弱電流控制另一條電路的通斷”這個功能。
其中,平常觸點接觸使得被控制電路導通、給控制它的電磁鐵通電后就使得開關斷開的那種繼電器,就等效于非門。三極管拿來當開關使用時,和這種繼電器效果幾乎一樣。
以上,就是數字電路的基礎。
指令
你敲入的任何東西,最終就是通過類似的東西/機制儲存的;所謂“指令”,其實就是“某個命令碼“(一般叫機器碼),這個”命令碼”會改變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的三板斧
圖靈的貢獻就是,他證明了,如果一臺機器,可以接受一系列的輸入、并按輸入指示完成運算;那么,當這臺機器可支持的操作滿足“圖靈完備”的要求時,它就可以模擬任何其它數學/邏輯運算!
這實在是太關鍵了。要知道,人類早就想利用機械裝置代替一些腦力工作了。比如說,算盤,按照口訣機械的一陣擺弄,答案就出來了;還有老外的各種機械計算器,比如手搖計算機到炮兵用的彈道計算機、再到德軍的機械加/解密機等等,這種嘗試可以說是數不勝數。
但,再怎么的,這些東西也只能解決特定的問題。想做能解決全部問題的通用機?天哪,那得有多復雜。
而圖靈,就在這時候,為人類指出了一條通向機械智能的可行道路……
——一臺只會做加法的機器,只要能想辦法讓它實現“連續做指定次數加法”,那它就可以模擬一臺乘法機(模擬二進制乘法會更容易一些)。而能夠模擬任何數學/邏輯運算的機器,并不比加法機復雜太多。
換句話說,要搞出一臺“無所不能”的計算機器,并不需要窮盡一切可能,而是只要支持程序輸入、再支持少的令人發指的幾條指令,就可以辦到了。
比如說,CPU,它根本上其實只會三招:與、或、非。
與就是全為真,則輸出真;或是只要一個為真,則輸出真;非則是輸入真它就輸出假、輸入假就輸出真——所謂的真假,一般寫作1、0,在計算機內部就是高低電平。
別看CPU只會這三板斧;可當它們巧妙的組合起來后(構造成計數器、指令寄存器等等等等再組合成CPU),就達到了圖靈完備的要求,產生了質變——比如,前面提到過的加法器,就是“如何用這類基本邏輯模擬多位二進制數的加法”的一個實例。
更具體是怎么做的,這就不是三言兩語能說清楚的了。還是仔細看看自己的數字電路這本書吧。
——數字電路研究的,就是如何用與或非這三板斧,來實現各種高級運算甚至CPU指令集這么復雜的事物(甚至是直接實現某些算法,如加密、視頻編碼等等)
——而CPU指令集呢,則形成了另外一個強大得多的圖靈機(體現在能夠支持更多比原始的與或非更”高階“的操作上):這就是機器碼(和匯編指令幾乎一一對應)
——然后呢,諸如c/c++、java等高級語言,就是利用CPU指令集形成的、另一個更加強大的圖靈機(編譯器/解釋器負責兩種圖靈機之間的翻譯工作)。
——而程序員們研究的,就是如何用編程語言這樣一個強大的圖靈機,去實現office、photoshop、wow甚至人工智能這樣復雜的事物。
這是一個層層模擬的過程。
————————————————————————————
總之,開關的通斷是基礎;而各種神奇的功能是如何用這么簡單的東西組合出來的呢,那就必須理解“程序”原理(也就是圖靈機原理)了。
如果說,計算機是一個人,那么,軟件就是他掌握的知識。這個知識使得他不僅能掰著手指頭數數(相當于硬件直接提供的基礎功能),甚至還可以去洞悉宇宙的奧秘(相當于利用軟件“模擬”出來的、無窮無盡的擴展功能)。
————————————————————————————————
具體一些,人是怎樣開車的呢?
首先,他要知道車的控制原理(知識/軟件);然后,基于這些知識,大腦向他的四肢肌肉發出神經沖動,驅使他完成轉方向盤、掛擋、踩離合器/油門等種種動作,最終達到開車這個目的。
軟件控制硬件的原理
前面說過,程序本身就是高低電平的組合;它通過在CPU上執行來模擬各種決策過程;同時,計算機就是一堆開關;那么,通過指令向某些地址寫出數據(訪問特定地址是通過各種尋址機制/指令完成的,歸根結底也可以說是通過開關切換,改變了電路拓撲),就等于開啟/關閉了對應地址上的某個開關;這個開關可以是類似CPU內部那樣的一組三極管,也可以是通向另外一個繼電器的信號線——這個信號就促使繼電器閉合,于是電機導通……
就好象人開汽車一樣,神經發出的微不足道的電脈沖經過肌肉放大,影響了涉及數百甚至數千馬力的能量洪流的發動機/變速箱的運轉,然后汽車就開走了。
計算機也一樣:它通過向控制特定地址上的開關輸出0/1(高低電平),就可以通過事先準備的物理設施驅動諸如航模電機、舵機等等機構,這就完成了航模控制。
完整的控制回路甚至可以是:
航模上的傳感器采集飛行姿態、地形、位置等等數據(最終轉換成高低電平構成的信號)----信號通過某些端口送到CPU-----CPU執行程序,程序讀取傳感器發來的信號,決定下一步的行動-----經過程序的智能判斷后,通過控制特定地址上的開關(前面提過,向這個地址發一組高低電平構成的數據就行了),驅動諸如航模電機、舵機等等機構,完成航模控制。
這,就是所謂的“機器人”(當然,只是最簡化的機器人原理而已)。
我們就用代碼展示一下怎么會顯示低電平
以51單片機舉例
我把題主的意思先用51單片機C語言寫出來,可以在keil中運行的
好了,題主說在單片機控制里,寫0就會輸出低電平,是這樣的。
題主說的輸出低電平就是在其中的一個引腳上輸出低電平
我想看不懂代碼的人也能夠看到代碼第七行里,p1.0這個變量被賦予了0值
那么咱們深入的看一下給他賦0值單片機內部發生了什么變化
首先給大家展示一下單片機一個引腳內部到底是什么東東,如下圖。
左邊的大家就不用看了,右邊給大家解釋一下,最右邊的就是引腳了
雖然引腳是一個,但是大家可以看到
右邊是有兩個裝置的,上邊的裝置是用來保持內部輸出到引腳的電平不會被外部的信號所干擾。下邊的裝置會把從外部收集來的信號臨時存儲起來,這里存的不是0就是1。怎么判斷?大于某一電壓就是1,小于某一電壓就是0。這兩個裝置互不干擾。
第七行的代碼就是將某一引腳輸出低電平并用上邊的保持元件將其維持到低電平。
那么,就有人想問了,為什么寫成這樣單片機就會認識呢?還會奇怪為什么單片機認識的語言和程序員認識的語言一樣呢?
這里就牽扯到了計算機組成原理了。我就簡單的介紹一下:
首先,我寫的這段代碼會在一個軟件里運行,這個軟件會編譯我的代碼形成枯燥難懂但是70年代時會被人認為高大上的匯編語言,類似下圖這樣的(除綠色字部分,解釋用的):
這還不夠,形成這樣的語言會讓計算機中的低等編譯器認識,低等編譯器會將代碼翻譯成如下圖所示的東東,如下圖。
注意,這是16進制的數,具體怎么轉化為二進制我就不詳細展開了。為什么要編譯成圖3的語言再編譯呢?說白了我感覺就是跟水廠一樣,水廠把我制作的水放到一個通用的大水管里然后通到不同單片機的家里,單片機按照自己家的情況把水引到廚房等地。(就是這樣吧 - -)
那么,我們就可以讓單片機或者叫做計算機來執行這段代碼了。
對不起,現在才進入到計算機組成原理(對不起計組老師)
現如今,大家所用到的計算機都是馮諾依曼型計算機。
什么是馮諾依曼型計算機?書上解釋說:
采取存儲程序的方式讓控制器從存儲器中讀取二進制并解釋然后讓運算器去計算數值。
我來再解釋一下,首先讓我們了解運算器是什么東東,如下圖。
最下面的就是運算器,運算器能夠進行加減乘除邏輯運算,控制器會從存儲器中讀取數據放到上圖運算器上邊的框框里,一個框框放一個數據。
怎么放?
看到左右的兩條道道了嗎?數據會在控制器的控制下被放到這些框框里,當然控制器會控制最下面的運算器做出各種運算然后放回到上邊的框框里
那么數據是怎么回去的呢?
廢話,當然是怎么來就怎么滾了,通過左右兩條道道啊親
讓我們來解釋一下最開始樓主說的輸出低電平,上邊的框框有一些是不能隨便放數據的,這些框框用來引出引腳,即有些框框里的數據連接著引腳啊親
講到這里,我想我已經比較清楚的解釋了0是怎么控制低電平的了。
如果哪些地方沒講明白,大家可以交流一下,我會再詳細講講我理解的一些內容。
首先看一下“低電平”是怎么形成的。
可以知道,引腳輸出的電平來自右下方那一對互補輸出級。
所以當PMOS關斷,NMOS導通,那么I/O口輸出低電平。
這個“控制信號”來自單片機的輸出寄存器(output control)。
那么這個信號的根源是怎么來的呢?
以STM32控制器為例
?
我們看到I/O的部分鏈接在APB(peripheral bus 外圍總線)上。
看來這個信號就是來自這個總線。
不難知道,所有數據的調度都來自STM32的核心--Cortex-M3.
我們就可以從微處理器如何執行指令的角度去看。
實際上,每一段程序都被保存在ROM里,這個ROM里保存的就是我們軟件傳達下來所賦予的“信息”,微處理器通過總線在ROM里提取所需要的指令,然后再一定的時鐘調配下,最后執行指令的。
而指令的實質居然是
沒有錯,mem[]里表述的是地址,而右邊的二進制碼“16‘hd000”就是本質的0和1的組合,是能夠被機器識別的,故稱機器碼。
我這里注釋的是他們分別代表的含義亦即匯編語言。
具體起來,這段"機器碼"的不同位置的01排序代表不同的含義
當然,這個含義是約定俗成的,就是指令集嘛!
這樣我們知道了,其實在儲存器里保存的01序列,我們通過機器識別即取指令,可以了解到不同含義,進而執行不同的操作。
那么這個儲存器的01序列怎么來的呢?
一般就儲存原理來說,每一個ROM都是一個個小房間,而房間的排列組合就是信息,他們是有序的。是通過一定模式或者條件下“燒寫進去”的。即使沒有外部觸發,依舊能保持原有電位。
EEPROM存儲原理
EEPROM基本存儲單元電路的工作原理如下圖所示。與EPROM相似,它是在EPROM基本單元電路的浮空柵的上面再生成一個浮空柵,前者稱為第一級浮空柵,后者稱為第二級浮空柵。可給第二級浮空柵引出一個電極,使第二級浮空柵極接某一電壓VG。若VG為正電壓,第一浮空柵極與漏極之間產生隧道效應,使電子注入第一浮空柵極,即編程寫入。若使VG為負電壓,強使第一級浮空柵極的電子散失,即擦除。擦除后可重新寫入。
隧道效應:量子力學則認為,即使粒子能量小于閾值能量,很多粒子沖向勢壘,一部分粒子反彈,還會有一些粒子能過去,好象有一個隧道,稱作“量子隧道(quantum tunneling)”。
那這個有序的信息就是"0"和“1”的組合。
這個序列如何燒寫進單片機,當然是有外圍電路啦,具體就是通過一定的時序打開單片機的儲存通路,然后把信息燒寫進去。
如何燒寫呢?
JTAG(Joint Test Action Group;聯合測試工作組)是一種國際標準測試協議(IEEE 1149.1兼容),主要用于芯片內部測試。現在多數的高級器件都支持JTAG協議,如DSP、FPGA器件等。標準的JTAG接口是4線:TMS、TCK、TDI、TDO,分別為模式選擇、時鐘、數據輸入和數據輸出線。
?
然后那些高高低低的01信息就這樣在時序里被輸出、被接收。
接下來我們說軟件。
我們寫的軟件都是高級語言,離機器很遠,但是很容易被人的邏輯所理解,聰明的我們由一些翻譯官完成更繁雜的工作:
這些翻譯官就是編譯器,比如KEIL,就是把C語言翻譯成匯編語言,再通過匯編器,把匯編語言變成機器碼,然后把機器碼燒寫進單片機的ROM,單片機上電之后,運行程序,讀取指令也就是那些信息,然后執行,控制IO口的寄存器,最后使IO口接地,哈哈,低電平就這樣完成了。
我們寫的軟件經過這幾個步驟 高級語言-->匯編語言--->機器語言。機器語言是二進制的,每一種指令操作都有對應的二進制編碼,比如我們執行 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就使管腳輸出低電平。
總結一下:
你的程序編寫完后通過編譯器將變成一堆二進制的機器編碼----->單片機對這些編碼進行譯碼,知道你要對哪一個寄存器進行什么樣的操作----->對應的寄存器被寫入正確的值,如果是IO管腳的話將根據時鐘將寄存器的值輸出到外部IO管腳。所以實際上單片機也就是一堆數字電路的組合,只不過我們人為的規定什么樣的編碼要進行什么樣的操作而已。
cpu內部就是一堆門電路,門電路導通和閉合對應著輸出為1或者0;
那怎么讓它導通呢?用電壓讓它導通,你可以認為這個電壓是一個能量,用能量驅動這個道理很通俗了吧;
那你可能又要說了,那電壓導通那它輸出是一個具體的電壓啊它也不是1呀,這個就是數電和模電之間的聯系和區別了:我們之所以制造數字電路,是要通過數字電路得到一種邏輯實現,而模電才是想得到一個電壓輸出,這就是模電和數電的天壤之別。那什么又是邏輯實現?簡單的說其實也就是數學實現,所謂編程就是把我們的需求變成數學問題,用編程語言編輯出來,給到cpu,讓它計算并驅動終端,最終把我們的邏輯顯示出來。
至于數模之間的聯系,它們之間的聯系就是器件都是靠電壓驅動,那你又要問了,那么電壓為什么可以驅動半導體器件?well,這個你要去看電磁場+半導體物理,可能還得看一點量子力學,我也都沒看呢Orz;
說到這總結一下:我們制造數字電路,就是想得到一個能讓我們自由表達邏輯,并能讓我們眼睜睜看見我們的邏輯實現了的一個工具,至于這個工具是數字電路,還是量子路,還是光路,只要你低功耗性能好,是啥都無所謂,最好是真空才好呢,對人類來說,空氣都智能了才好呢。
接下來就要說說cpu架構+指令集。
我們常常聽說,一種cpu架構對應著一種指令集,那這是為什么呢?
我們說所謂數字系統,其實很簡單,你給我輸入,我就給你輸出;你想要什么樣的輸出,那你就要分析分析你要給到我什么樣的輸入我才能輸出你想要看到的輸出,編程也就是這個過程;可是問題來了,你隨隨便便給我什么輸入我都hold住嗎?很明顯是hold不住的,這個例子,我就不舉了。。。。
給這段下個結論就是:所謂指令集,其實就是給cpu這個數字系統一套驅動編碼
說到這其實大的框架就差不多了,剩下的比較重要的部分就是布爾代數和數學之間的聯系,數學和實際需求之間的聯系,然后就是顯示這一部分,慢慢來吧
從高級語言網下到晶體管開關都有直接的映射關系,于是代碼就這樣控制硬件了。
詳細說一下,高級語言可以通過編譯器轉換成匯編語言。匯編語言就是硬件的指令,可以直接轉換成0101010101。而這些010101就是電路中的低電平和高電平。這些電平控制開關的打開關斷,于是各種組合就產生了復雜的邏輯電路。
?
審核編輯:黃飛
?
評論
查看更多