一、單片機與傳統電子技術的區別 當今社會,應用單片機的產品已經滲透到我們生活的各個領域,幾乎很難找到哪個領域沒有單片機的足跡。現在,這種單片機的使用領域已十分廣泛,如智能儀表、實時工控、通訊設備、導航系統、家用電器等,這些都離不開單片機。因此,單片機的學習、開發與應用將造就一批計算機應用與智能化控制的工程師和科學家?萍荚桨l達,智能化的東西就越多。學習單片機是社會發展的必然需求,也是電子愛好者和工程師的必修課。 早期的大部分電子儀器和設備,不是成本太高就是電路復雜,工程師要維護它要花很多精力和時間,想要更改它的功能更加困難。而單片機強大的功能應付這些將會使您得心應手,當然前提是您必需要去了解和學習它。 從事單片機技術的研發工程師都屬于高職位、高薪水崗位。據調查,截止2006年,我國的單片機從業人員250萬人。隨著社會的發展,單片機的從業人員將更為搶手。據不完全統計,到2010年,我國單片機設計從業人員將達400萬人之多。培養單片機應用人才,特別是具有最新現代單片機技術和實踐經驗的工程師具有著重要的現實意義。 二、什么是單片機?單片機有什么用? 如果說單片機和我們用的電腦的在本質上沒有什么區別,你一定感到驚訝(一個芯片)...這并不奇怪。而事實就是這樣理解的:單片機是一個簡單卻又是完整的計算機系統,麻雀雖小,五臟俱全,它被集成到一個芯片上。它內部也用和電腦功能類似的模塊,比如CPU,內存,并行總線,還有和硬盤作用相同的存儲器件,不同的是它的這些部件性能都相對我們的家用電腦弱很多,不過價錢也是低的,一般不超過10元即可......但用它來做一些控制電器一類不是太復雜的工作足夠了。我們現在用的全自動滾筒洗衣機,排煙罩VCD等等的家電里面都可以看到它的身影!......它主要是作為控制部分的核心部件。 單片機是靠程序的,并且可以修改。通過不同的程序實現不同的功能,尤其是特殊的獨特的一些功能,這是別的器件需要費很大力氣才能做到的,有些則是花大力氣也很難做到的。一個不是很復雜的功能要是用美國50年代開發的74系列,或者60年代的CD4000系列這些純硬件來搞定的話,電路一定是一塊大PCB 板!但是如果要是用美國70年代成功投放市場的系列單片機,結果就會有天壤之別!只因為單片機的通過你編寫的程序可以實現高智能,高效率,以及高可靠性! 隨著超大規模集成電路的出現及其發展,將計算機的CPU、RAM、ROM、定時/計數器和多種I/O資源接口集成到一片芯片上,形成了芯片級的計算機。最早期的含義為單片微型計算機,又稱微控制器(Microcontroller),英文縮寫為“MCU”。 準確地說單片機不叫IC,單片機不是完成某一個邏輯功能的芯片,而是把一個計算機系統集成到一個芯片上。概括的講:一塊單片機芯片就成了一臺微型計算機。它的體積小、質量輕、價格便宜、為學習、應用和開發提供了便利條件。同時,學習使用單片機是了解計算機原理與結構的最佳選擇。 可以說,二十世紀跨越了三個“電”的時代,即電氣時代、電子時代和現已進入的電腦時代。不過,這種電腦,通常是指個人計算機,簡稱PC機。它由主機、鍵盤、顯示器等組成(如圖1所示)。還有一類計算機,大多數人卻不怎么熟悉。這種計算機就是把智能賦予各種機械的單片機(亦稱微控制器)。顧名思義,這種計算機的最小系統只用了一片集成電路,即可進行簡單運算和控制。因為它體積小,通常都藏在被控機械的“肚子”里。它在整個裝置中,起著有如人類頭腦的作用,它出了毛病,整個裝置就癱瘓了。各種產品一旦用上了單片機,就能起到使產品升級換代的功效,常在產品名稱前冠以形容詞——“智能型”,如智能型洗衣機等,F在有些工廠的技術人員或其它業余電子開發者搞出來的某些產品,不是電路太復雜,就是功能太簡單且極易被仿制。究其原因,可能就卡在產品未使用單片機或其它可編程邏輯器件。 三、單片機的主要特點 優異的性能價格比 高集成度,高可靠性,體積小 低電壓,低功耗 控制功能強大 豐富靈活的軟件編程 應用領域廣泛,可涉及所有電子領域 四、學習單片機的條件 目前單片機很多,學哪一個?8051、PIC、MS430、AVR還是其他型號?其實學哪一個都可以,單片機雖然型號不同,但是芯片內部的資源種類都差不多,而且這些資源的使用方法也大同小異,可以說學會一種,其他種將融會貫通。究竟學哪一種,主要看具備的條件。 8051系列是老型號,是全球大名鼎鼎的CPU制作商美國INTEL公司奠定基礎而推向全球的,這種單片機目前雖不是功能最強大的,但卻是用得最廣泛而且但教學書最多、資料最多、軟件開放和硬件支持都很成熟的MCU芯片,各大單片機網站都有相關學習和例程資料。Atmel公司將其發揚光大,推出了FLASH型AT89的產品系列,現在流行的是AT89S51,52。很多人就是從這款單片機起家的。因此,本站推薦從51單片機入門。 學習單片機還得擁有以下基本的硬件和軟件: 個人PC(就是電腦) 單片機及常用外圍元件 編程器或下載線 實驗板和仿真器 萬用表和工具(烙鐵等) 一本或幾本入門好書 學習單片機很難嗎?說不難是騙人的,說很難也是不負責任的,有難的地方,也有簡單的地方?傊,學單片機最主要的就是不斷地動手實踐!內部結構不懂不要怕,指令記不住不要怕,當你有了實物一步一步的實踐,很快的,內部結構就會在你腦海中清晰,指令也會一條一條的記住,理解理論知識也就清晰了,并且也會使用了。 |
![]() |
![]() |
有人已經給你回答了為什么要學習單片機。我現在要給你誰說的是現代單片機設計制作的發展變化。 現在我們設計制造單片機可以用現場可編程陣列器件FPGA來作。只要學習好硬件編程語言Verilog HDL或VHDL就可以達到目的,而不用去買那些現成的CPU芯片,也不用去購買什么編程器。過去設計單片機,一般要使用市場上出售的CPU芯片,例如80c51等,有時還要配上一些別人制造好的設備,F在你可以將所有的設備都集中在一個芯片中,自己設計運算器、存儲器、寄存器、控制器、模數轉換器、看門狗等一系列器件,按照自己的想法放到一個方寸不到的芯片中,使之成為一個名副其實的單片機。這種設計單片機的好處是用什么設計什么,不會讓多余的東西干擾你的作品,需要簡單就簡單,需要復雜就復雜。是不是很有意思? 這樣設計的單片機,非常能夠培養你掌握單片機全部的能力,發揮你的創造精神,使你成為一個對單片機無所不知,無所不曉的計算機設計人才。國內搞單片機的人最缺乏的是對CPU 的設計,大多數都在使用市場上購買的CPU,按照廠家的要求作中下游的進一步開發。實際上,這種方法不僅效率不高,而且也影響我們對單片機的創新。因而突破CPU設計的門檻,掌握cpu設計技術,我們就會對單片機的理解和設計都會有更高層次的發展。下面給你一個簡單的CPU設計程序,希望你能引導你盡快進入單片機完整設計的大門。 //基本輸入時鐘clock //復位控制:reset_n,低電位有效 //基本輸出:o //程序存儲器iram,16位,高5位是類指令代碼,用imem16_1.mif初始化 //數據存儲器dram,16位,不用數據文件初始化 //用lpm存儲器地址數據信號要穩定1拍,才可以讀寫數據 //指令格式:高5位指令代碼,11位地址碼,16位立即數(分高低8位) module jdcpu ( clock, reset_n, o, //調試輸出(可以不要): opc, omar, ojp, oqw, /* olda, oadd, oout, osdal, osdah, ostr, osub, ojmp, ojz, ojn, ocall, oret, oir, */ oda, ozf,osp ); input clock; input reset_n; output [15:0] o; output [15:0] oqw,oda; output [10:0] opc,omar,osp; output [2:0] ojp; output ozf; /*oiro,lda,oadd,oout,osdal,osdah,ostr,osub, ojmp,ojz,ojn,ocall,oret,*/ reg dwren,swren; wire [15:0] q_w,q_data; reg [15:0] ir; reg [15:0] b,a,da,oo,ddata; reg [10:0] pc,pc_back,mar,sp,q_s; reg [2:0] jp; //節拍 //指令: reg lda, //取數:從數據單元取數到da add, //加:da與數據單元相加,結果放入da out, //輸出:將數據單元內容輸出到輸出寄存器 sdal, //低8位立即數:將8位立即數擴充為16位送da sdah, //高8位立即數:將8位立即數作為高8位,與原da低8位連接成16位放在da中 str, //da送數據存儲單元: sub, //減:da與數據單元相減,結果放入da jmp, //跳轉 jz, //da為0跳轉 jn, //da為負跳轉 call, //調用子程序 ret, //返回 mult, // divi, // stp; //停止 //仿真信號輸出: assign o = oo; assign opc = pc; assign osp = sp; assign omar = mar; assign ojp = jp; assign oqw = q_w; assign olda=lda; assign oadd=add; assign osub=sub; assign oout=out; assign ojmp=jmp; assign ostr=str; assign osdal=sdal; assign osdah=sdah; assign ocall=call; assign oret=ret; assign ojz=jz; assign ojn=jn; assign oda=da; assign oir=ir; assign ozf=~|da; //指令存儲器: lpm_rom iram(.address(pc),.inclock(clock),.q(q_w)); //程序存儲器 defparam iram.lpm_width = 16; defparam iram.lpm_widthad = 11; defparam iram.lpm_outdata = "UNREGISTERED"; defparam iram.lpm_indata = "REGISTERED"; defparam iram.lpm_address_control = "REGISTERED"; defparam iram.lpm_file = "liti3.mif"; //初始化文件,放置程序 //數據存儲器: lpm_ram_dq dram(.data(ddata),.address(mar),.we(dwren),.inclock(clock),.q(q_data)); //數據存儲器 defparam dram.lpm_width = 16; defparam dram.lpm_widthad = 10; defparam dram.lpm_outdata = "UNREGISTERED"; defparam dram.lpm_indata = "REGISTERED"; defparam dram.lpm_address_control = "REGISTERED"; lpm_ram_dq sram(.data(pc_back),.address(sp),.we(swren),.inclock(clock),.q(q_s)); //堆棧 defparam sram.lpm_width = 11; defparam sram.lpm_widthad = 10; defparam sram.lpm_outdata = "UNREGISTERED"; defparam sram.lpm_indata = "REGISTERED"; defparam sram.lpm_address_control = "REGISTERED"; always @(posedge clock or negedge reset_n) begin if (!reset_n) begin pc <= 0; sp <= 0; lda <= 0; add <= 0; out <= 0; sdal <= 0; sdah <= 0; str <= 0; sub <= 0; jmp <= 0; jz <= 0; jn <= 0; call <= 0; ret <= 0; mult <= 0; divi <= 0; jp <= 0; end else begin // 節拍jp指出的狀態: case (jp) 0: begin jp <= 1; end 1: begin case (q_w[15:11]) 5'b00001: lda <= 1; //lda:00001 5'b00010: add <= 1; //add:00010 5'b00011: out <= 1; //out:00011 5'b00100: sdal <= 1; //低8位,擴充有符號16位 5'b00101: sdah <= 1; //高8位,與前面低8位輸入合成16位 5'b00110: str <= 1; //da送數據單元 5'b00111: sub <= 1; 5'b01000: jmp <= 1; 5'b01001: if (da==0) jz <= 1; 5'b01010: if (da[15]==1) jn <= 1; 5'b01011: call <= 1; 5'b01100: ret <= 1; 5'b01101: mult <= 1; 5'b01110: divi <= 1; 5'b11111: stp <= 1; default: jp <= 0; endcase jp <= 2; end 2: begin case (q_w[15:11]) 5'b00001: begin //lda <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b00010: begin //add <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b00011: begin //out <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b00100: begin //sdal <= 1; da <= {{8{q_w[7]}},q_w[7:0]}; //擴充16位有符號數 sdal<= 0; pc <= pc+1; jp<= 0; end 5'b00101: begin //sdah <= 1; da[15:0] <= {q_w[7:0],da[7:0]}; sdah <= 0; pc <= pc+1; jp<= 0; end 5'b00110: begin //str <= 1; mar<=q_w[10:0]; ddata <= da; jp <= 3; end 5'b00111: begin //sub <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b01000: begin //jmp <= 1; pc <= q_w[10:0]; jmp <=0; jp <= 0; end 5'b01001: begin //jz <= 1; if (jz) pc <= q_w[10:0]; else pc <= pc+1; jz <=0; jp <= 0; end 5'b01010: begin //jn <= 1; if (jn) pc <= q_w[10:0]; else pc <= pc+1; jn<=0; jp <= 0; end 5'b01011: begin //call <= 1; pc_back <= pc+1; jp <= 3; end 5'b01100: begin //ret <= 1; jp <= 3; end 5'b01101: begin //mult <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b01110: begin //divi <= 1; mar<=q_w[10:0]; jp <= 3; end 5'b11111: jp<=0; default: jp <= 0; endcase end 3: begin case (q_w[15:11]) 5'b00001: begin //lda <= 1; jp <= 4; end 5'b00010: begin //add <= 1; jp <= 4; end 5'b00011: begin //out <= 1; jp <= 4; end 5'b00110: begin //str <= 1; dwren <= 1; jp <= 4; end 5'b00111: begin //sub <= 1; jp <= 4; end 5'b01011: begin //call <= 1; pc <= q_w[10:0]; swren <= 1; jp <= 4; end 5'b01100: begin //ret <= 1; sp <= sp-1; jp <= 4; end 5'b01101: begin //mult <= 1; jp <= 4; end 5'b01110: begin //divi <= 1; jp <= 4; end default: jp <= 0; endcase end 4: begin case (q_w[15:11]) 5'b00001: begin //lda <= 1; da<=q_data; pc <= pc+1; jp <= 0; lda<= 0; end 5'b00010: begin //add <= 1; b<=q_data; a<=da; jp <= 5; end 5'b00011: begin //out <= 1; oo <= q_data; pc <= pc+1; jp <= 0; out<= 0; end 5'b00110: begin //str <= 1; jp <= 5; end 5'b00111: begin //sub <= 1; b<=q_data; a<=da; jp <= 5; end 5'b01011: begin //call <= 1; sp <= sp+1; jp <= 5; end 5'b01100: begin //ret <= 1; jp <= 5; end 5'b01101: begin //mult <= 1; b<=q_data; a<=da; jp <= 5; end 5'b01110: begin //divi <= 1; b<=q_data; a<=da; jp <= 5; end default: jp <= 0; endcase end 5: begin case (q_w[15:11]) 5'b00010: begin //add <= 1; da<=a+b; pc <= pc+1; add <=0; jp <= 0; end 5'b00110: begin //str <= 1; dwren <= 0; pc <= pc+1; str <=0; jp <= 0; end 5'b00111: begin //sub <= 1; da<=a-b; pc <= pc+1; sub<=0; jp <= 0; end 5'b01011: begin //call <= 1; swren <= 0; call<=0; jp<=0; end 5'b01100: begin //ret <= 1; pc <= q_s; ret<=0; jp <= 0; end 5'b01101: begin //mult <= 1; da <=a*b; pc <= pc+1; mult <=0; jp <= 0; end 5'b01110: begin //divi <= 1; da <=a/b; pc <= pc+1; divi <=0; jp <= 0; end default: jp <= 0; endcase end endcase end end endmodule ////// 仿真實例: 求64*8且輸出循環次數 //////// // // 匯編 編譯 // sdal 1 2001 // str one 3001 // sub one 3801 // str result 3002 // str n 3005 // sdal 64 2040 // str x 3003 // sdal 8 2008 // str y 3004 //loop: lda y 0804 // jz exit 4812 // sub one 3801 // str y 3004 // lda result 0802 // add x 1003 // str result 3002 // call loopno 5814 // jmp loop 4009 //exit: out result 1802 // stp ffff //loopno: lda n 0805 // add one 1001 // str n 3005 // out n 1805 // ret 6000 // // 將編譯的16進制數寫入imem16_1.mif // /////// 16進制結果輸出:0200 ////////////////// // ////驗證CPU的實例3: 求8!且輸出結果。 // // 匯編 編譯 // sdal 1 2001 // str one 3001 // str result 3002 // sdal 8 2008 // str x 3003 //loop: lda x 0803 // jz exit 480D // mult result 6802 // str result 3002 // lda x 0803 // sub one 3801 // str x 3003 // jmp loop 4005 //exit: out result 1802 // stp ffff //將編譯的16進制數寫入imem16_2013.mif /////// 如果下載到開發板檢查運行情況,各輸出之間要加延時子程序。 // //畢業設計:擴充設計一個功能完備的計算機,并在PMC110計算機開發板上下載運行。 |
頂 |
![]() ![]() ![]() |