大家好!今天是学习51单片机的第十一天,今天学习中断与定时。学习笔记如下:
1.中断介绍
中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一,是我们学习单片机必须要掌握的。
中断的出现代表我们可以完成许多事情,排列一些程序发生的顺序。
那我们来看一下,中断的理论图。
当然中断也是有优先级的,比如在同一个地方,满足了两个中断的条件,所以我们会选择优先级高的,我们一般采用默认的优先级,当然我们也可以自己设置。
2.定时器介绍
单片机的定时器可以理解成一个杯子,假如一个杯子装满需要花费十秒的时间,但是我只需要5秒钟的定时,那么我们就可以先给已经有杯水的杯子加水加满,那么我们就实现5秒钟的定时。假如我们需要20秒的定时,那我们可以准备两个空杯子。这是不是很像一款游戏。(先这样了解一下)
CPU 时序的有关知识:
(1)振荡周期
(2)状态周期:一个状态周期=两个振荡周期
(3)机器周期:一个机械周期=六个状态周期
(4)指令周期:一个指令周期=1~4个振荡周期
例如:外接晶振为 12MHz 时,51 单片机相关周期的具体值为: 振荡周期=1/12us; 状态周期=1/6us; 机器周期=1us; 指令周期=1~4us;
中断与定时器需要涉及到三个寄存器
中断允许控制寄存器(IE寄存器):
1.EA为CPU的总中断,EA=1,开放;EA=0,关闭所有中断。
2.ES为串行口中断允许位,这个讲串口通信的时候会用到。
3.ET0与ET1与定时器有关,ET0为定时器/计数器T0的溢出允许位,ET1位为定时器/计数器T0的溢出允许位。后面均已ET0举例,ET0=1允许T0中断。
4.EX1/EX0为外部中断有关,EX0=1,允许外部中断0中断。
见下图的IE寄存器:
中断请求标志寄存器(TCON寄存器)
1.前四位TF1/TR1/TF0/TR0是与定时器/计数器有关的,后四位IE1/IT1/IE0/IT0与外部中断有关。
2.先介绍外部中断:IT0为外部中断0的触发方式控制位,IT0=0,低电平触发:IT0=1.下降沿触发。如图上面的为低电平触发持续触发,下面的下降沿触发瞬时触发。通常我们使用下降沿触发。
IE0为外部中断0的请求标志位,由单片机内部自动配置,无触发时,IE0=0,当有触发时,IE0=1,由单片机自动发出请求。
IT1/IE1也是同理,只是设置外部中断1的
3.TF1为定时器/计数器T1溢出标志位,当T1被允许计数的时候,从初值开始加1计数
中断优先级寄存器(IP寄存器)
因为我们通常使用的是默认优先级,所以我们先介绍默认优先级:
IP寄存器
PS为串行口中断优先级控制位。PS=1,串行口中断为高优先级中断:PS=0,串行口中断为低优先级中断。PT1为定时器/计数器T1中断优先级控制位,PT0为定时器/计数器T0的中断优先级控制位,PX1为外部中断1中断优先级控制位,PX0为外部中断0中断优先级控制位,控制同上PS一样。
今天先这样!
贴一段代码,有兴趣的可以看一下
#include "reg51.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入
#define LEDDZ_COL_PORT P0 //点阵列控制端口
u8 code tuxing_col[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
u8 code tuxing_row[32][8]={
{0x80,0x42,0x24,0x18,0x18,0x24,0x42,0x80},
{0x42,0x24,0x18,0x18,0x24,0x42,0x80,0x00},
{0x24,0x18,0x18,0x24,0x42,0x80,0x00,0x00},
{0x18,0x18,0x24,0x42,0x80,0x00,0x00,0x82},
{0x18,0x24,0x42,0x80,0x00,0x00,0x82,0xFE},
{0x24,0x42,0x80,0x00,0x00,0x82,0xFE,0xFE},
{0x42,0x80,0x00,0x00,0x82,0xFE,0xFE,0x82},
{0x80,0x00,0x00,0x82,0xFE,0xFE,0x82,0x00},
{0x00,0x00,0x82,0xFE,0xFE,0x82,0x00,0x00},
{0x00,0x82,0xFE,0xFE,0x82,0x00,0x00,0x1C},
{0x82,0xFE,0xFE,0x82,0x00,0x00,0x1C,0x22},
{0xFE,0xFE,0x82,0x00,0x00,0x1C,0x22,0x42},
{0xFE,0x82,0x00,0x00,0x1C,0x22,0x42,0x84},
{0x82,0x00,0x00,0x1C,0x22,0x42,0x84,0x84},
{0x00,0x00,0x1C,0x22,0x42,0x84,0x84,0x42},
{0x00,0x1C,0x22,0x42,0x84,0x84,0x42,0x22},
{0x1C,0x22,0x42,0x84,0x84,0x42,0x22,0x1C},
{0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C},
{0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C},
{0x22,0x42,0x84,0x84,0x42,0x22,0x1C,0x00},
{0x42,0x84,0x84,0x42,0x22,0x1C,0x00,0x00},
{0x84,0x84,0x42,0x22,0x1C,0x00,0x00,0x7E},
{0x84,0x42,0x22,0x1C,0x00,0x00,0x7E,0xFE},
{0x42,0x22,0x1C,0x00,0x00,0x7E,0xFE,0xC0},
{0x22,0x1C,0x00,0x00,0x7E,0xFE,0xC0,0xC0},
{0x1C,0x00,0x00,0x7E,0xFE,0xC0,0xC0,0xFE},
{0x00,0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E},
{0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E,0x00},
{0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E,0x00},
{0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E,0x00},
{0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E,0x00},
{0x00,0x7E,0xFE,0xC0,0xC0,0xFE,0x7E,0x00},
} ;
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void hc595_write_data(u8 dat)
{
u8 i=0;
for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中
{
SER=dat>>7;//优先传输一个字节中的高位
dat<<=1;//将低位移动到高位
SRCLK=0;
delay_10us(1);
SRCLK=1;
delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中
}
RCLK=0;
delay_10us(1);
RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
void main()
{
u8 i=0,j=0,k;
while(1)
{
for(j=0;j<32;j++)
{
for(k=0;k<10;k++)
{
for(i=0;i<8;i++)//循环8次扫描8行、列
{
hc595_write_data(tuxing_row[j][i]);//传送行选数据
LEDDZ_COL_PORT=tuxing_col[i];//传送列选数据
// hc595_write_data(tuxing_row[j][i]);//传送行选数据
delay_10us(100);//延时一段时间,等待显示稳定
hc595_write_data(0x00);//消影
}
}
}
}
}