精华内容
下载资源
问答
  • 51单片机入门

    2013-06-15 20:52:45
    51单片机入门C语言入门教程
  • 51单片机入门教程(2)——实现流水灯

    万次阅读 多人点赞 2018-11-03 13:06:52
    51单片机入门教程(2)——实现流水灯一、搭建流水灯电路二、流水灯程序2.1 延时程序2.2 延时函数2.3 按字节寻址2.4 逻辑移位2.5 条件判断 一、搭建流水灯电路 在Proteus中搭建流水灯电路如图 二、流水灯程序 我们...

    一、搭建流水灯电路

    在Proteus中搭建流水灯电路如图
    在这里插入图片描述

    二、流水灯程序

    我们可以把流水灯看作依次点亮若干个灯。
    程序如下:

    #include <reg52.h>
    sbit led1 = P2^0;
    sbit led2 = P2^1;
    sbit led3 = P2^2;
    sbit led4 = P2^3;
    sbit led5 = P2^4;
    sbit led6 = P2^5;
    sbit led7 = P2^6;
    sbit led8 = P2^7;
    
    void main()
    {
        //点亮第一个灯
        led1 = 1;
        led2 = 0;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        //点亮第二个灯
        led1 = 0;
        led2 = 1;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;    
        //点亮剩余的灯
        //省略……
        while(1);
    }
    

    编译并下载程序到仿真中,观察现象发现只有第二个灯是亮的???
    什么鬼???

    2.1 延时程序

    单片机的执行指令速度非常快,一个晶振是12MHz的单片机执行一条指令的速度是微秒级的,所以点亮第一个灯的时间太短了,以至于我们根本没有察觉。
    因此我们需要一个延时的语句。
    实现延时的方法就是循环执行很多次空指令。程序如下:

    //延时一秒的程序
    int i,j;
    for(i = 0;i < 110; ++i)
    {
      for(j = 0; j < 1000; ++j)
      {
        ;//什么也不做
      }
    }
    
    

    然后我们就可以把流水灯的程序改成这样的:

    #include <reg52.h>
    sbit led1 = P2^0;
    sbit led2 = P2^1;
    sbit led3 = P2^2;
    sbit led4 = P2^3;
    sbit led5 = P2^4;
    sbit led6 = P2^5;
    sbit led7 = P2^6;
    sbit led8 = P2^7;
    
    void main()
    {
        int i,j;
       //点亮第一个灯
        led1 = 1;
        led2 = 0;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        //延时1秒 
    	for(i = 0;i < 110; ++i)
    	{
    	  for(j = 0; j < 1000; ++j)
    	  {
    	    ;//什么也不做
    	  }
    	}
        //点亮第二个灯
        led1 = 0;
        led2 = 1;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;    
        //点亮剩余的灯
        //省略……
        while(1);
    }
    

    编译并下载程序到仿真中,观察现象发现首先第一个灯亮,过了一会儿第二个灯亮。

    2.2 延时函数

    我们剩下的任务就是依次点亮每个灯,但是每次点亮一个灯就需要写一段延时程序,很麻烦!
    为了程序的可读性(toulan),可以把延时程序写成一个子函数,随时供我们使用。
    C语言中子函数的定义方式如下

    返回值类型 函数名 (参数1,参数2,……)
    {
      函数体;
    }
    

    这样我们就可以把延时函数写成这样:

    void delay1s()
    {
      int i,j;
      for(i = 0; i<110;++i)
      {
        for(j = 0; j<1000;++j)
        {
          //什么也不做
        }
      }
    }
    

    几点说明:

    • void:因为该延时函数不需要返回值,所以写为void
    • delay1s:该函数的函数名,命名需要符合C语言的标识符命名规则。
    • (): 不需要传入参数,所以括号中为空
      至此我们可以把流水灯程序写为以下形式:
    #include <reg52.h>
    
    sbit led1 = P2^0;
    sbit led2 = P2^1;
    sbit led3 = P2^2;
    sbit led4 = P2^3;
    sbit led5 = P2^4;
    sbit led6 = P2^5;
    sbit led7 = P2^6;
    sbit led8 = P2^7;
    
    //延时1s
    void delay1s()
    {	 
        int i ,j;
       	for(i = 0;i<110; ++i){
    	  for(j = 0;j<1000;++j){
    	    ;
    	  }
    	}
    }
    
    void main()
    {
        //点亮第一个灯
        led1 = 1;
        led2 = 0;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
    
    	//延时1s
    	delay1s();
    
        //点亮第二个灯
        led1 = 0;
        led2 = 1;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;    
        //点亮剩余的灯
        //省略……
        while(1);
    }
    

    2.3 按字节寻址

    我们可以看到,上面的代码十分冗长,每次点亮一个灯需要8条语句,那么如何简化?
    比如把
    led1 = 1;led2 = 0; led3 = 0; led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0;
    这8条语句替代为P2 = 0000 0001???
    答案是可以的。代码如下

    unsigned char a = 0x01;  //0x01是0000 0001的16进制形式
    P2 = a;//相当于led1 = 1;led2 = 0; led3 = 0;  led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0;
    

    至此,我们可以把流水的代码优化为如下形式:

    #include <reg52.h>
    
    //延时1s
    void delay1s()
    {	 
        int i ,j;
       	for(i = 0;i<110; ++i){
    	  for(j = 0;j<1000;++j){
    	    ;
    	  }
    	}
    }
    
    void main()
    {
    	unsigned char a1 = 0x01 ;    // 0000 0001
    	unsigned char a2 = 0x02;    // 0000 0010
        //点亮第一个灯
    	P2 = a1;
    
    	//延时1s
    	delay1s();
    
        //点亮第二个灯
    	P2 = a2;    
        //点亮剩余的灯
        //省略……
        while(1);
    }
    

    2.4 逻辑移位

    依次点亮8个灯,每点亮一个灯都需要一句赋值语句还是很麻烦 。
    所以可以使用逻辑移位语句,每次赋值后,将数值左移一位。
    C语言逻辑左移代码如下:

    unsigned char a = 0x01;  //a = 0000 0001
    unsigned char b = a<<1;  // b = 0000 0010
    usingned char c = a<<3;   //c = 0000 1000
    

    至此,我们可以把流水灯的代码优化如下:

    #include <reg52.h>
    //延时1s
    void delay1s()
    {	 
        int i ,j;
       	for(i = 0;i<110; ++i){
    	  for(j = 0;j<1000;++j){
    	    ;
    	  }
    	}
    }
    
    void main()
    {
        //初始化
    	unsigned char a = 0x01;
        while(1)
    	{
    	  //循环点亮流水灯
    	  P2 = a;   
    	  a = a<<1;
    	  delay1s();
    	}
    }
    

    编译并下载程序到仿真中,观察现象发现8个灯依次亮过之后不再亮了。

    2.5 条件判断

    因为在移位操作中,当变量a的值为1000 0000时,再次执行左移操作,a 中的1就溢出了,因此a的值变为0000 0000,此时我们需要加一个判断,使a再次恢复为0000 0001
    C语言中,if条件判断使用方式如下

    if(判断条件)
    {
      //语句
    }
    

    当判断条件为真时,执行{ }中的语句。
    至此,流水灯代码可改成如下形式:

    #include <reg52.h>
    
    //延时1s
    void delay1s()
    {	 
        int i ,j;
       	for(i = 0;i<110; ++i){
    	  for(j = 0;j<1000;++j){
    	    ;
    	  }
    	}
    }
    
    void main()
    {
    	unsigned char a = 0x01;
        while(1)
    	{
    	  if(a == 0x00)   //如果高位溢出
    	  {
    	    a = 0x01;      //则恢复
    	  }
    	  //循环点亮led灯
    	  P2 = a;
    	  a = a<<1;
    	  delay1s();
    	}
    }
    
    展开全文
  • C51单片机入门教程

    2018-06-06 20:43:07
    C51单片机入门教程,介绍了51单片机的基本眼里及C语言开发流程
  • 51单片机——51单片机入门基础知识

    万次阅读 多人点赞 2018-07-20 19:38:07
    MSC-51单片机指以8051为核心的单片机,由美国的Intel公司在1980年推出,80C51是MCS-51系列中的一个典型品种;其它厂商以8051为基核开发出的CMOS工艺单片机产品统称为80C51系列。 单片机:在一片集成电路芯片上集成...

    第一部分。单片机简介

    MSC-51单片机指以8051为核心的单片机,由美国的Intel公司在1980年推出,80C51是MCS-51系列中的一个典型品种;其它厂商以8051为基核开发出的CMOS工艺单片机产品统称为80C51系列。

    单片机:在一片集成电路芯片上集成微处理器(CPU)、存储器(ROM和RAM)、I/O接口电路,从而构成了单芯片微型计算机,即单片机(single chip Microcomputer)也叫微控制器(MCU)。

    CPU( Central Processing Unit ):由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器;

    RAM( Random-Access Memory ):用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据;

    ROM (Read-Only Memory):用以存放程序、一些原始数据和表格;

    I/O(input/output)口:四个8位并行I/O口,既可用作输入,也可用作输出;

    T/C (timer/counter):两个定时/记数器,既可以工作在定时模式,也可以工作在记数模式;

     数字电路中只有两种电平:高和低

    单片机为TTL电平: +5V       0V

    RS232电平:计算机的串口    -12V     +12V

    所以计算机与单片机之间通讯时需要加电平转换芯片max232等其他芯片

    数字电路的点评特性据定了他只能用二级制:

    二进制逻辑运算,与或非和异或

    数据类型:

    因为51单片机是8位的,所以他的数据类型一般用unsigned char 

    第二部分。引脚简介

    1.  电源引脚:Vcc (40脚):电源端,接+5V电源。

    Vss(Gnd) (20脚):接地端,接+5V电源地端

    2. 外接晶体引脚:XTAL1和XTAL2

    89C51内部有一个振荡器和时钟产生电路。

    XTAL1(19脚):   片内振荡电路反相放大器输入

    XTAL2(18脚):片内振荡电路反相放大器输出 当采用内部时钟时,片外连接石 英晶体和微调电容,产生原始 的振荡脉冲信号。

    采用外部时钟时, XTAL1输入 外部时钟脉冲信号, XTAL2悬空.

    3. 控制信号引脚:RST、ALE、PSEN、EA

    RST (9脚) : 复位信号输入端,高电平有效。

              保持两个机器周期高电平时,完成复位操作。

    ALE/PROG (30脚) :

    地址锁存允许输出端/编程脉冲输入端

    正常时,连续输出振荡器频率的1/6正脉冲信号。

    访问片外存储器时:

    作为锁存P0口低8位地址的控制信号。

    对8751片内 ROM编程写入时:作为编程脉冲输入端。

    PSEN (29脚): 外部程序存储器读选通输出信号

    访问片外ROM时,输出负脉冲作为读ROM选通.

    常连接到片外ROM芯片的输出允许端(OE)作外部ROM的读选通信号。

    EA/Vpp (31脚):

    外部程序存储器地址使能输入/编程电压输入端.   平常,接“1”时,CPU访问片内4KB的ROM,当地址超4KB时,自动转向片外ROM中的程序。当接“0”时,CPU只访问片外ROM。 第2功能Vpp              对8051编程时,编程电压输入端。

    4. 输入/输出端口引脚 P0、P1、P2、P3

    4个8位的并行输入/输出端口,共32个引脚。作为通用输入/输出端口

    通用输入/输出端口

         准双向口:  作输入时要先对锁存器写“1”。默认启动初始化为高电平

    P0端口(P0.0—P0.7,第39—32脚):

          漏极开路的准双向口, 内部没有上拉电阻,为搞阻状态,不能正常输出高低电平,做I/O时需要接上拉电阻(10K)

    P1端口(P1.0—P1.7,第1—8脚):

          内部带上拉电阻的准双向口,在做输入时要先1

    P2端口(P2.0—P2.7,第21—28脚):

          内部带上拉电阻的准双向口,与P1相似

    P3端口(P3.0—P3.7,第10—17脚):

          内部带上拉电阻的准双向口,做I/O时与P1相似,另外有第二功能

    P3口的第二功能

     

    展开全文
  • 51单片机入门教程

    2011-11-20 11:42:22
    51单片机入门教程,51单片机入门教程51单片机入门教程,51单片机入门教程
  • 51单片机入门详细教程 郭天祥完整单片机入门教程 使使用者一周能 入门
  • 51单片机入门资料.pdf

    2021-03-20 21:40:55
    51单片机入门资料.pdf
  • 51单片机入门学习

    2018-03-10 16:44:46
    51单片机入门学习,简单的流水灯,数码管,计时器,中断
  • 51单片机入门.7z

    2019-09-19 21:05:45
    很棒的51单片机入门,适合学习嵌入式的新生。包含《51单片机C语言入门教程详细解说》,《51单片机经典入门教程》。
  • 51单片机入门资料包含硬件 C语言 和51单片机项目程序适合敢接触单片机的同学
  • 51单片机入门级别常用函数,主要包括I/O口、定时器、计数器、中断、通信等。
  • 51单片机入门教程的ppt.pptx
  • STC51单片机入门_C语言

    2018-09-10 09:28:07
    STC51单片机入门_C语言,单片机应用系统与开发技术教学课件,
  • 51单片机入门流水灯程序,keil软件工程,带hex文件,可以直接烧录,不用位操作,简单直白了解51单片机工作
  • 30章C51单片机入门

    2014-12-09 22:40:39
    30章C51单片机入门教材,30章C51单片机入门教材。
  • 51单片机入门led闪烁程序 这一节简单讲下proteus仿真软件的使用,关键在于需要的元器件的代号,比如电阻是resistor,电容是capacitor等等,不过不用刻意去记,用得多了自然就记住了,碰到新的元器件就网上查找。...
  • 51单片机入门教程(易懂版)pdf,51单片机入门教程(易懂版)
  • 51单片机入门的C语音例程,有IO口的各种输入输出操作,各种样式的LED点亮、数码管的使用、各种中断和定时器的操作、电机和蜂鸣器的使用
  • 51单片机入门教程(易懂版) .
  • 51单片机入门教程(1)——点亮一个LED灯

    万次阅读 多人点赞 2018-10-27 10:00:25
    51单片机入门教程(1)——点亮一个LED灯 先放这里,下午再写

    51单片机入门教程(1)——点亮一个LED灯

    一、什么是单片机

    单片机(Microcontrollers)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。
    以上是百度百科上的词条,随便看看就行了,下面说一下我对单片机的理解:
    我们都知道,我们的电脑是由CPU、内存、磁盘、IO设备等组成的,而单片机简而言之,就是一个微型电脑,它在一块芯片上包含了CPU,硬盘(flash)和内存条(ram)以及基本输入输出设备(io口)。
    51单片机

    二、怎么学习单片机

    void 学习单片机()
    {
      while(1){
        动手写单片机程序;
        调试程序;
        发现程序中的语法与逻辑错误;
        改正程序中的错误;
      }
    }
    

    三、点亮一个LED灯

    说了这么多,现在步入正题。

    3.1 在Proteus上搭建LED灯的电路

    首先打开Proteus软件,界面如图
    Proteus
    左侧的一栏是各种类型的组建,其中我们主要需要用到的有组件选项(component mode)终端选项(Terminals mode)
    组件选项包括了我们用到的芯片,元件和其它的一些东西。
    终端选项包括了VCCGND等一些组件。
    在这里插入图片描述
    首先在组件选项中点击“P”按钮,找到我们需要的89c51芯片,并放入到主面板里。
    在这里插入图片描述
    同理
    在组件选项中输入LED-YELLOW找到led灯放入主面板
    在终端选项中选择POWER放入到主面板。
    在这里插入图片描述
    然后就要连接电路。power为电路提供电源输入,即电路的正极,所以将power的线连接到led灯的正极,然后我们把led灯的另一端接到单片机的P2^0引脚上。
    之后我们就可以在程序中给P2^0引脚一个低电平(即电路的负极)使其构成一个回路,就可以达到点亮led灯的目的。
    在这里插入图片描述

    3.2 在keil中创建工程

    3.2.1新建一个工程

    打开keil,在菜单栏中找到工程(project),点击第一个,然后选择工程保存路径并点击保存。
    在这里插入图片描述

    然后选择单片机型号,找到Atmel点击左边的小加号,选择at89c51(或at89c52),点击确定。
    j在这里插入图片描述

    接下来的窗口是提示我们“是否把启动代码添加到工程中”,我们选择确定。
    在这里插入图片描述
    这样我们的工程就创建好了。
    在这里插入图片描述
    随后我们需要给工程创建源码文件。
    点击“文件”->“新建”,使用组合键ctrl+s保存文件,命名为main.c(可以随便命名,但是后面要加上 .c),点击保存。
    在这里插入图片描述
    右击源组,点击添加文件到源组。
    在这里插入图片描述
    在这里插入图片描述
    点击这里的魔术棒,选择output,选中create hex file
    在这里插入图片描述
    在这里插入图片描述

    至此就可以编写代码了。
    在文件中输入以下代码:

    #include <reg52.h>
    sbit led = P2^0;
    void main(){
    	while(1){
    		led = 0;
    	}
    }
    

    说一下这几句代码是什么意思。

    • 第一行是包含头文件,头文件里面定义了单片机寄存器的一些定义。初学者不理解也没有关系。
    • 第二行是声明了P2^0端口,相当于给这个端口起了一个名字。
    • 第三行是main函数,代码从这里开始执行。
    • 第四行是一个while死循环,程序会一直执行while循环里面的内容。
    • 第五行是给名字为led的端口(即P2^0端口)一个低电平(1代表高电平,0代表低电平),使led灯的两端构成回路。

    然后编译程序,点击左上角的编译按钮。可以看到"0 error , 0 warning"的提示。
    在这里插入图片描述

    3.3 将程序导入到单片机中运行

    我们已经搭建好了电路,写好了程序,生成了hex文件,之后需要在电路上运行我们的程序。
    打开3.1中创建的仿真电路,双击单片机,找到3.2生成的hex文件,点击打开。
    在这里插入图片描述

    左下角的一排控制按钮意思分别是运行 单步 暂停 结束,我们点击运行就可以看到led灯被点亮。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 89c51单片机入门

    2008-03-18 17:52:09
    89c51单片机入门
  • 51单片机入门教程(5)——定时器中断

    万次阅读 多人点赞 2018-11-25 22:53:58
    51单片机入门教程(5)——定时器中断一、中断的概念二、定时器中断2.1 软件延时的不足2.2 中断寄存器2.2.1 中断允许控制寄存器 IE2.2.2 定时器工作方式寄存器 TMOD2.2.3 定时器控制寄存器 TCON2.2.4 定时器初值...


    写在开头:中断是包括单片机在内的所有微处理器很重要的功能之一,初学单片机必须这一部分的知识。

    一、中断的概念

    先看百度百科是怎么定义中断的:

    中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
    —— 百度百科

    那么怎么理解中断?看下面的例子。

    关于中断
    小A正在学习。这时,他的朋友小B叫他一块儿吃鸡,小A停止学习,转去玩吃鸡游戏。玩了几局后,关掉游戏,继续学习。
    关于中断优先级
    小A正在学习。这时,他的朋友小B叫他一块儿吃鸡,小A停止学习,转去玩吃鸡游戏,(吃鸡过程中,小A女朋友打来电话,于是挂机游戏,去接电话,接完电话,继续游戏。)玩了几局后,关掉游戏,继续学习。

    • 几个重要概念:

    中断:小A学习被小B打断的过程就称为中断
    中断源:小B被称为中断源
    中断服务程序:小A执行的玩游戏操作称为中断服务程序
    中断优先级:小A女朋友的电话比游戏优先级

    在89c52单片机中,有3类中断源:

    1、外部中断:当外部中断引脚信号产生跳变(低电平→高电平)时引起中断。
    2、定时器/计数器中断:当计数器计满溢出时引起跳变。
    3、串口中断:串行端口完成一帧数据的发送/接受时引起(如蓝牙传输)。

    其优先级如下表:

    中断源 优先级 中断服务号
    INT0 – 外部中断0 最高 0
    T0 – 定时器/计数器0中断 第2 1
    INT1 – 外部中断1 第3 2
    T1 – 定时器/计数器1中断 第4 3
    串口中断 第5 4
    T2 – 定时器/计数器2中断 最低 5

    下面以定时器中断为例,讨论中断的编程方法。

    二、定时器中断

    2.1 软件延时的不足

    根据现有的知识,如果要在程序中等待一端时间,想到的操作应该是通过执行若干次空指令,达到延时的效果。
    如下:

    //延时xms
    void delayms(uint xms){
      uint i,j;
      for(i = 0; i < xms; ++i)
        for(j = 0; j < 110; ++j)
        ;
    }
    

    但是,假设要实现以下功能:

    1、8位数码管动态扫描显示。
    2、LED灯每隔1s闪烁一次。

    电路如下:
    在这里插入图片描述
    考虑程序怎么写……

    //代码不完整,仅为举例说明
    void main(){
      P2 = 0x01;       //数码管从最低位开始扫描
      while(1){
        //功能1:执行数码管动态扫描
        //P2控制显示哪一个数码管,P0控制数码管显示什么内容
        P2 = P2<<1;      //扫描更高一位的数码管
        P0 = xxxx;       //输出段码
        delayms(5);      //延时5ms后显示下一位数码管
      
        //功能2:执行LED灯闪烁
        led = ~led;     //LED灯状态取反
        delayms(1000);  //延时1000ms
      }
    }
    

    功能1和功能2单独写都没有问题。
    但是如果组合在一起,写在一个while循环中,就会有问题了:
    一个while循环中有两个延时函数,因此执行一次while循环,共延时了1005ms。这并不是我们所希望的结果。我们希望led闪烁的延时不影响数码管动态扫描的延时。

    2.2 中断寄存器

    要使用硬件定时,主要涉及到寄存器的操作。51单片机里的关于中断的寄存器如下:

    IE – 中断允许控制寄存器
    IP – 中断优先级控制寄存器
    TMOD – 定时器工作方式寄存器
    TCON – 定时器控制寄存器
    SCON – 串口控制寄存器
    THx/TLx – 定时器初值寄存器

    在定时器中断中,需要设置的有TMOD、THx/TLx、TCON、IE。
    下面只介绍使用定时器中断所需要设置的寄存器,其余寄存器可自行查阅资料。

    2.2.1 中断允许控制寄存器 IE

    该寄存器的主要功能是控制中断的开启与关闭,共7个有效位,包含一个全局中断控制位和6个中断源的控制位。
    中断允许控制寄存器 IE各位的定义如下表:

    序号 D7 D6 D5 D4 D3 D2 D1 D0
    符号 EA ET2 ES ET1 EX1 ET0 EX0

    说明:
    EA 全局中断允许位,当此位是1时中断可用。(重要)
    ET2 定时器/计数器2中断允许位
    ES 串口中断允许位
    ET1 定时器/计数器1中断允许位
    EX1 外部中断1允许位
    ET0 定时器/计数器0中断允许位 (重要)
    EX0 外部中断0允许位
    要使用定时器中断,需要将IE寄存器中的EA位设置为1,以及需要将ETx(x = 0,1,2)设置为1。

    2.2.2 定时器工作方式寄存器 TMOD

    该寄存器的主要功能是设置定时器/计数器中断的工作方式。如设置位定时器模式、定时器模式的计数位的位数。以下是详细介绍:
    定时器工作方式寄存器 TMOD各位的定义如下表:

    序号 D7 D6 D5 D4 D3 D2 D1 D0
    符号 GATE C/TˉC/\bar{T} M1 M0 GATE C/TˉC/\bar{T} M1 M0

    说明:
    GATE 定时器/计数器的开关控制选项。常将该位置0,即定时器/计数器的开关控制仅由TCON寄存器中的TRx(x = 0,1)控制。(见2.2.3的TRx)
    C/T 定时器模式和计数器模式选择位,将该位置0则为定时器模式。
    M1M0 设置定时器/计数器工作方式,常将该两位设置为0 1,其定义如下表:

    M1 M0 工作方式
    0 0 模式0,13位计数
    0 1 模式1,16位计数,常用此模式
    1 0 模式2,8位初值自动重装
    1 1 模式3,仅适用于T0,分为两个8位计数器,T1停止计数

    2.2.3 定时器控制寄存器 TCON

    该寄存器用于控制中断,如控制定时器的启动,停止、判断定时器的溢出和中断情况。
    定时器控制寄存器 TCON各位的定义如下表:

    序号 D7 D6 D5 D4 D3 D2 D1 D0
    符号 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0

    说明:
    TF1 定时器1溢出标志位
    TR1 定时器1运行控制位,将该位置1时启动定时器1
    TF0 定时器0溢出标志位
    TR0 定时器0运行控制位,将该位置1时启动定时器0 (重要)
    IE1 外部中断1请求标志
    IT1 外部中断1触发方式选择位
    IE0 外部中断0请求标志
    IT0 外部中断0触发方式选择位

    2.2.4 定时器初值寄存器 THx/TLx

    以定时器T0为例,其的工作原理是,每当晶振产生一次脉冲,就将该寄存器TL0加一,当TL0加满溢出后,将TL0清空,TH0加一,TH0计满后产生定时中断。即TH0与TL0组成了一个16位的计数器,这个计数器可以从0x0000(0)加到0xffff(65535)。
    以12Mhz的晶振、定时10ms为例:
    51单片机为12分频单片机,因此执行一条指令的时间是12×(1/12M) s,即计数器每1us加一。
    若定时10ms,则共需要加10000次。
    因此将TH0、TL0设置从(65536-10000)= 55536开始计数。55536 的16进制为0xD8F0。因此将TH0设置为0xD8,TL0 设置为0xF0

    2.3 定时器中断程序写法

    首先要初始化定时器,即将命令写入以上的寄存器。 假设使用定时器T0
    首先设置定时器工作模式TMOD:GATE设置为0;C/T位设置为0使其工作在定时器模式下;M1M0设置为01,使用16位计数。
    因此第一句代码是

    TMOD = 0x01;   // 0000 0001
    

    然后设置定时器时长THx/TLx:

    TH0 = 0xD8;
    TL0 = 0xF0;
    

    设置定时器允许寄存器IE,打开中断总开关和T0中断开关

    EA = 1;
    ET0 = 1;
    

    最后设置定时器控制寄存器TCON,使定时器开始计数

    TR0 = 1;
    

    因此,完整的定时器初始化代码如下

    void initT0(){
      TMOD = 0x01;   // 0000 0001.
      TH0 = 0xD8;    //65536-10000
      TL0 = 0xF0;    //55536
      EA = 1;
      ET0 = 1;
      TR0 = 1;
    }
    

    当定时器计数触发中断时,单片机会调用中断服务程序。中断服务程序的格式如下:

    void 函数名() interrupt 中断号 using 工作组
    {
      //所要执行内容
    }
    

    说明:
    中断服务函数要写在主函数后面,且不需要声明 。
    中断服务函数无返回值,所以用void
    函数名可以随便起
    interrupt后的中断号由下表的重点服务号确定
    using 工作组可省略不写

    中断源 优先级 中断服务号
    INT0 – 外部中断0 最高 0
    T0 – 定时器/计数器0中断 第2 1
    INT1 – 外部中断1 第3 2
    T1 – 定时器/计数器1中断 第4 3
    串口中断 第5 4
    T2 – 定时器/计数器2中断 最低 5

    因此T0中断服务程序如下:

    void t0Intr() interrupt 0
    {
      //因为执行到此时,计数器已经清零,所以要重新赋值
      TH0 = 0xD8;    //65536-10000
      TL0 = 0xF0;    //55536
      
      //下面写需要执行的操作
    }
    

    根据以上内容,可设计一个简单定时器电路如下:
    在这里插入图片描述
    其中:

    D1灯由定时器控制,每秒闪一次
    D2 - D8由软件延时实现流水灯效果,周期为100ms

    代码如下

    #include <reg51.h>
    #include <intrins.h>
    //num为计数器,每10ms将num加一,当num为100时为1s
    unsigned char num;
    sbit led = P1^0;
    //函数声明
    void delay100ms();  //软件延时100ms
    void initT0();      //初始化定时器T0
    
    void main()
    {
      unsigned char k ;
      //初始化num值
      num = 0;
      //初始化定时器
      initT0();
      //初始化led灯
      led = 0;
      //初始化流水灯
      P0 = 0xfe;
      k = 0xfe;
      while(1)
      {
        //每100ms流水灯移位一次
        k = _crol_(k, 1);
        P0 = k;
        delay100ms();
      }
    }
    //t0定时器中断服务程序
    //每隔10ms进入一次该程序
    void t0Intr() interrupt 1
    {
      TH0 = 0xD8;
      TL0 = 0xF0;
      
      num++;   //该变量加至100说明为1s
      if(num == 100)
      {
        num = 0;
        led = ~led;   //翻转led灯状态
      }
    }
    void delay100ms()
    {
      unsigned char a,b,c;
      for(c=19;c>0;c--)
        for(b=20;b>0;b--)
          for(a=130;a>0;a--);
    }
    
    void initT0()
    {
      TMOD = 0x01;
      TH0 = 0xD8;
      TL0 = 0xF0;
      EA = 1;
      ET0 = 1;
      TR0 = 1;
    }
    
    
    展开全文
  • 51单片机入门教程30课

    2015-06-12 16:32:27
    51单片机入门教程30课,每一课均有详细的pdf格式单片机教程,以及与教程相对应的C语言程序,十分详细。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,314
精华内容 925
关键字:

51单片机入门