为什么要学单片机?

2013年09月17日 10:59    发布者:edu118gct
一、单片机与传统电子技术的区别
   
当今社会,应用单片机的产品已经渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的足迹。现在,这种单片机的使用领域已十分广泛,如智能仪表、实时工控、通讯设备、导航系统、家用电器等,这些都离不开单片机。因此,单片机的学习、开发与应用将造就一批计算机应用与智能化控制的工程师和科学家。科技越发达,智能化的东西就越多。学习单片机是社会发展的必然需求,也是电子爱好者和工程师的必修课。
   
早期的大部分电子仪器和设备,不是成本太高就是电路复杂,工程师要维护它要花很多精力和时间,想要更改它的功能更加困难。而单片机强大的功能应付这些将会使您得心应手,当然前提是您必需要去了解和学习它。
   
从事单片机技术的研发工程师都属于高职位、高薪水岗位。据调查,截止2006年,我国的单片机从业人员250万人。随着社会的发展,单片机的从业人员将更为抢手。据不完全统计,到2010年,我国单片机设计从业人员将达400万人之多。培养单片机应用人才,特别是具有最新现代单片机技术和实践经验的工程师具有着重要的现实意义。

二、什么是单片机?单片机有什么用?
   
如果说单片机和我们用的电脑的在本质上没有什么区别,你一定感到惊讶(一个芯片)...这并不奇怪。而事实就是这样理解的:单片机是一个简单却又是完整的计算机系统,麻雀虽小,五脏俱全,它被集成到一个芯片上。它内部也用和电脑功能类似的模块,比如CPU,内存,并行总线,还有和硬盘作用相同的存储器件,不同的是它的这些部件性能都相对我们的家用电脑弱很多,不过价钱也是低的,一般不超过10元即可......但用它来做一些控制电器一类不是太复杂的工作足够了。我们现在用的全自动滚筒洗衣机,排烟罩VCD等等的家电里面都可以看到它的身影!......它主要是作为控制部分的核心部件。
   
单片机是靠程序的,并且可以修改。通过不同的程序实现不同的功能,尤其是特殊的独特的一些功能,这是别的器件需要费很大力气才能做到的,有些则是花大力气也很难做到的。一个不是很复杂的功能要是用美国50年代开发的74系列,或者60年代的CD4000系列这些纯硬件来搞定的话,电路一定是一块大PCB 板!但是如果要是用美国70年代成功投放市场的系列单片机,结果就会有天壤之别!只因为单片机的通过你编写的程序可以实现高智能,高效率,以及高可靠性!
   
随着超大规模集成电路的出现及其发展,将计算机的CPU、RAM、ROM、定时/计数器和多种I/O资源接口集成到一片芯片上,形成了芯片级的计算机。最早期的含义为单片微型计算机,又称微控制器(Microcontroller),英文缩写为“MCU”。
   
准确地说单片机不叫IC,单片机不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。概括的讲:一块单片机芯片就成了一台微型计算机。它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。同时,学习使用单片机是了解计算机原理与结构的最佳选择。

可以说,二十世纪跨越了三个“电”的时代,即电气时代、电子时代和现已进入的电脑时代。不过,这种电脑,通常是指个人计算机,简称PC机。它由主机、键盘、显示器等组成(如图1所示)。还有一类计算机,大多数人却不怎么熟悉。这种计算机就是把智能赋予各种机械的单片机(亦称微控制器)。顾名思义,这种计算机的最小系统只用了一片集成电路,即可进行简单运算和控制。因为它体积小,通常都藏在被控机械的“肚子”里。它在整个装置中,起着有如人类头脑的作用,它出了毛病,整个装置就瘫痪了。各种产品一旦用上了单片机,就能起到使产品升级换代的功效,常在产品名称前冠以形容词——“智能型”,如智能型洗衣机等。现在有些工厂的技术人员或其它业余电子开发者搞出来的某些产品,不是电路太复杂,就是功能太简单且极易被仿制。究其原因,可能就卡在产品未使用单片机或其它可编程逻辑器件。

三、单片机的主要特点
优异的性能价格比
高集成度,高可靠性,体积小
低电压,低功耗
控制功能强大
丰富灵活的软件编程
应用领域广泛,可涉及所有电子领域

四、学习单片机的条件  
   
目前单片机很多,学哪一个?8051、PIC、MS430、AVR还是其他型号?其实学哪一个都可以,单片机虽然型号不同,但是芯片内部的资源种类都差不多,而且这些资源的使用方法也大同小异,可以说学会一种,其他种将融会贯通。究竟学哪一种,主要看具备的条件。
   
8051系列是老型号,是全球大名鼎鼎的CPU制作商美国INTEL公司奠定基础而推向全球的,这种单片机目前虽不是功能最强大的,但却是用得最广泛而且但教学书最多、资料最多、软件开放和硬件支持都很成熟的MCU芯片,各大单片机网站都有相关学习和例程资料。Atmel公司将其发扬光大,推出了FLASH型AT89的产品系列,现在流行的是AT89S51,52。很多人就是从这款单片机起家的。因此,本站推荐从51单片机入门。
   
学习单片机还得拥有以下基本的硬件和软件:
个人PC(就是电脑)
单片机及常用外围元件
编程器或下载线
实验板和仿真器
万用表和工具(烙铁等)
一本或几本入门好书

学习单片机很难吗?说不难是骗人的,说很难也是不负责任的,有难的地方,也有简单的地方。总之,学单片机最主要的就是不断地动手实践!内部结构不懂不要怕,指令记不住不要怕,当你有了实物一步一步的实践,很快的,内部结构就会在你脑海中清晰,指令也会一条一条的记住,理解理论知识也就清晰了,并且也会使用了。

网友评论

fdjlz78 2013年10月12日
:)
edu118gct 2013年10月13日
:)不错,学习了
DynamicCore 2013年11月18日
    有人已经给你回答了为什么要学习单片机。我现在要给你谁说的是现代单片机设计制作的发展变化。
    现在我们设计制造单片机可以用现场可编程阵列器件FPGA来作。只要学习好硬件编程语言Verilog HDL或VHDL就可以达到目的,而不用去买那些现成的CPU芯片,也不用去购买什么编程器。过去设计单片机,一般要使用市场上出售的CPU芯片,例如80c51等,有时还要配上一些别人制造好的设备。现在你可以将所有的设备都集中在一个芯片中,自己设计运算器、存储器、寄存器、控制器、模数转换器、看门狗等一系列器件,按照自己的想法放到一个方寸不到的芯片中,使之成为一个名副其实的单片机。这种设计单片机的好处是用什么设计什么,不会让多余的东西干扰你的作品,需要简单就简单,需要复杂就复杂。是不是很有意思?
   这样设计的单片机,非常能够培养你掌握单片机全部的能力,发挥你的创造精神,使你成为一个对单片机无所不知,无所不晓的计算机设计人才。国内搞单片机的人最缺乏的是对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 o;

output oqw,oda;
output opc,omar,osp;
output ojp;
output  ozf; /*oiro,lda,oadd,oout,osdal,osdah,ostr,osub,
ojmp,ojz,ojn,ocall,oret,*/

reg   dwren,swren;
wire q_w,q_data;
    reg   ir;
reg   b,a,da,oo,ddata;
reg   pc,pc_back,mar,sp,q_s;
reg   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)
    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==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)
    5'b00001: begin  //lda  <= 1;
        mar<=q_w;
        jp <= 3;
       end
    5'b00010: begin  //add  <= 1;
        mar<=q_w;
        jp <= 3;
       end
    5'b00011:   begin  //out  <= 1;
        mar<=q_w;
        jp <= 3;
       end
     
    5'b00100:   begin  //sdal <= 1;
        da <= {{8{q_w}},q_w};        //扩充16位有符号数
        sdal<= 0;
        pc <= pc+1;
        jp<= 0;
       end
     
    5'b00101:   begin  //sdah  <= 1;
        da <= {q_w,da};
        sdah <= 0;
        pc <= pc+1;
        jp<= 0;
       end
     
    5'b00110:   begin  //str  <= 1;
        mar<=q_w;
        ddata <= da;
        jp <= 3;
       end
    5'b00111:   begin  //sub  <= 1;
        mar<=q_w;
        jp <= 3;
       end
   
    5'b01000:   begin  //jmp  <= 1;
        pc <= q_w;
        jmp <=0;
        jp <= 0;
       end
    5'b01001:   begin  //jz   <= 1;
        if (jz) pc <= q_w;
        else   pc <= pc+1;
        jz <=0;
        jp <= 0;
       end
   
    5'b01010:   begin  //jn   <= 1;
        if (jn) pc <= q_w;
        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;
        jp <= 3;
       end
    5'b01110: begin  //divi  <= 1;
        mar<=q_w;
        jp <= 3;
       end
    5'b11111: jp<=0;
    default:    jp <= 0;
    endcase
   end
  3: begin
    case (q_w)
    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;
         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)
    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)
    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计算机开发板上下载运行。

JZS 2013年12月03日
edu118gct 2013年12月06日
:):):)