关于单片机中断模块的心得体会

2019-04-15 15:26发布

单片机中断的理解。 1.首先52单片机里6个中断源(比51多一个T2),具体如下图1.1所示。
图1.1  52单片机6个中断源       在这里我们需要注意的是,定时系统是单片机硬件的组成部分,52单片机引脚如图1.2所示。   由图1.2可以看出功能复用的引脚,比如T2/P1.0、T0/P3.4等。 为什么我们在单片机定时中断程序中看不到响应中断函数的子函数呢?这正是它的巧妙之处! 定时系统与CPU和晶振通过某种关系连接,于是当CPU一旦设置定时功能,定时器便在晶振作用下自动开始计时。通过加1计数器计时,当计数器计满后,便开始产生中断。   
图1.2  52单片机引脚图 2.在使用中断时,必须使用的两个寄存器:IE和IP。其中IE(interrupt enable,中断允许寄存器)、IP(interrupt priority,中断优先级寄存器)。IE的字节地址为A8H,IP的字节地址是B8H,对于我们在单片机C语言编程,用不到,字节地址用于汇编语言中。图2.1和图2.2分别是IE和IP寄存器的各位定义。
图2.1  IP各位
图2.2  IE各位 具体各位怎么设置,查看书就好。 3.定时器的两个寄存器。TMOD和TCON。即为Time mode和time control
图3.1  TCON各位
图3.2 TMOD各位
图3.3  定时器/计数器的四种工作方式      在这里有一个问题就是设置TH0和TL0的初值。 4.在这里我主要分析下串口通信实现上位机和下位机之间是如何通讯的(采用方式1来实现编程)。          通讯分并行和串行两种方式,单片机系统信息的交换多采用串行通信方式。 单片机的串行口设定为4种.波特率定义为每秒传输的二进制代码的位数,它表示的是单片机或计算机在串口通讯时的速率,即:1波特=1位/秒(单位bps)。 下面来分析在波特率为9600bps,系统晶振频率为11.0592MHZ,方式1下来TH1和TL1中装入的数值。 设所求的数位X,则定时器每计256-X个数溢出一次。 每计一个数的时间为一个机器周期,一个机器周期为12个时钟周期,于是可知计一个数的时间为12/11.0592MHZ(s), 定时器溢出一次的时间为[256-X]*12/11.0592MHZ(s)。T1的溢出率就是它的倒数。因此代入方式1波特率的公式可求得波特率为 (2SMOD/32)*(T1溢出率),代入9600可得,X=253,转化为十六进制为0xFD。           另一细小问题。若这里采用12MHZ的晶振,则计算出T1的初值不是一个整数,这样通信将会产生累计误差。 在单片机串行口的描述中有个SBUF寄存器。SBUF----串行数据缓冲寄存器。SBUF是两个独立的串行数据缓冲器(一个是receive,一个是transmit),两个SBUF公用同一块地址99H。接收数据时,写a=SBUF;发送数据时,写SBUF=a。为什么是这样呢?让我们看图4.1
  图4.1  SBUF数据的接收与发送      接下来让我们了解下串行口控制寄存器SCON(serial control)。图4.2是串行口控制寄存器,图4.3是串行口工作方式。
图4.2  串行口控制寄存器
图4.3  串行口工作方式 在这里我们选用的是方式1,即SM0=0,SM1=1。图4.2中,在方式1中,我们需要注意REN(允许串行接收位)、TI(发送中断标志位)、RI(接收中断标志位),其中TI和RI是硬件置1,软件清零。方式1是10位数据的异步通讯,1位起始位,8位数据位,1位停止位。由图1.2我们可以看出TXD(P3.1)为数据发送引脚,RXD(P3.0)为数据接收引脚。波特率由定时器的溢出率决定(T1定时器每溢出一次的时间的倒数,即为溢出率) 下面程序是有串口输入数据,控制LED灯。 #include  #define uchar unsigned char  #define uint unsigned int  unsigned char flag,a,i;    void init()// 寄存器初始化  {      TMOD=0X20;//T1定时器工作方式2(8为初值自动重装)       TH1=0Xfd;//波特率为9600bps下,装初值       TL1=0Xfd;       TR1=1 ;  //启动定时器1       REN=1 ; //允许串口接收       SM0=0;  //串口工作方式1(10位异步收发)       SM1=1;       EA=1; //全局中断       ES=1; //串口中断  }     void main()  {      init();       while (1)//在这框架下进行       {              if(flag==1)//当标志位flag为1时,说明程序已经执行过串口中断              {                     ES=0;//必须将ES清零,否则陷入死循环                     flag=0;   //清零                     SBUF=a;//向串口发送数据                     while(!TI);     //判断是否发送完,发送完,会由硬件将TI置1                     TI=0; //手动清零取消中断申请                     ES=1;  //打开串口中断              }       } }    void ser()   interrupt4    //串口中断服务程序  {      RI=0;/*  进入这里,则说明已产生中断(收到或发送数据);开始没有发 送任何数据,那程序必定是收到数据,此时RI由硬件置1,所以必须将RI清零*/       P1=SBUF;//接收数据       a=SBUF;//重新将SBUF赋给a       flag=1;   //flag置1 }    PS:我是新手,学习单片机有2个月时间。 自己画原理图、PCB,送出去做板子、焊板子调试。 感觉对单片机编程调试时,一定要把各个相关寄存器搞清楚,因为编程无非就是在操作相关寄存器。