0x06 LED矩阵
74HC595
教程:https://www.bilibili.com/video/av25104575?from=search&seid=1047628661288106627
工作原理
D0到D7从下到上
P0到P7从右往左
代码示例
0x07 驱动直流电机
驱动原理
本例中使用的是UNL2003芯片
可以看到和非门类似,输入低电平就为高电平,输入高电平就为低电平
吧直流电机一端接在5V电源上(高电平),另外一端接四个管脚的其中一个
要控制直流电机,要使直流电机两端电平不同,一端已经接了高电平(5V),所以因为UNL2003类似非门,输入高电平时才是低电平,所以UNL2003芯片的输入应该也为高电平
代码
让直流电机运行一小会
注意最后一定要加while(1);
单片机默认会循环的执行程序,所以不加的话可能就会一直运行或者运行一会停止又马上运行
#include <reg51.h>
#include "intrins.h"
sbit moto = P1^0;
typedef unsigned char u8;
typedef unsigned int u16;
void delay(u16 t){
while(t--);
}
void main(){
moto = 0; //?????
delay(5000);
//??????
moto = 1;
delay(50000);
moto = 0;// ?????
while(1){}
}
注意:
默认直流电机为开启状态,如果打开电源后电机总是处在运行状态没有停止与代码不相符,一定要检查是否控制错了管脚,本例中控制的是P01
0x07 中断
1. 中断的概念
中断即指单品机停止当前所作的工作A,转向工作B,稍后在来完成工作A
引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现中断功能的部件称为中断系统。
2. 中断的类型
STC89C5X 系列单片机提供了 8 个中断请求源,它们分别是:外部中断 O(INTO)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定时器 0 中断、定时器 1 中断、定时器 2 中断、串口(UART)中断
注意:51 系列单片 机一定有基本的 5 个中断,但不全有 8 个中断,需要查看芯片手册,通常我们 使用的都是基本的 5 个中断:INT0、INT1、定时器 0/1,串口中断
中断号会体现在代码中!
3. 单片机中断系统
89C51/52的中断系统有5个中断源 ,2个优先级,可实现二级中断嵌套 。
从上到下优先级递增
4. 中断的条件
1.1 中断允许控制
CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的。
- EX0(IE.0),外部中断0允许位;
- ET0(IE.1),定时/计数器T0中断允许位;
- EX1(IE.2),外部中断0允许位;
- ET1(IE.3),定时/计数器T1中断允许位;
- ES(IE.4),串行口中断允许位;
- EA (IE.7), CPU中断允许(总允许)位。如果置0不能发生中断
1.2 中断请求标志
- IT0(TCON.0),外部中断0触发方式控制位。
- 当IT0=0时,为电平触发方式。
- 当IT0=1时,为边沿触发方式(下降沿有效)。
- IE0(TCON.1),外部中断0中断请求标志位。
- IT1(TCON.2),外部中断1触发方式控制位。
- IE1(TCON.3),外部中断1中断请求标志位。
- TF0(TCON.5),定时/计数器T0溢出中断请求标志位。
- TF1(TCON.7),定时/计数器T1溢出中断请求标志位。
1.3 中断响应条件
- 中断源有中断请求.如当IT0 = 1时发生了下降沿
- 此中断源的中断允许位为1,如外部中断0, EX0 =1
- CPU开中断(即EA=1)。
以上三条同时满足时,CPU才有可能响应中断。
4. 使用中断,程序员需要做什么?
- 你想使用的中断是哪个?选择相应的中断号;
- 你所希望的触发条件是什么?
- 你希望在中断之后干什么?
中断服务函数:
void int0 () interrupt 0 using 1
{
do anything that you want
}
using 1可以省略不用
0x08 定时器/计数器中断
51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之 为定时器/计数器。
1. 四个周期
- 振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡 周期)
- 状态周期:2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周 期或时钟周期
- 机器周期:1 个机器周期含 6 个状态周期,12 个振荡周期。
- 指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位
,51 单片机相关周期的具体值为:
振荡周期=1/12us; 状态周期=1/6us;
机器周期=1us; 指令周期=1~4us;
2. 定时器工作原理
STC89C5X 单片机内有两个可编程的定时/计数器 T0、T1 和一个特殊功能定 时器 T2。定时/计数器的实质是加 1 计数器(16 位),由高 8 位和低 8 位两 个寄存器 THx 和 TLx 组成。它随着计数器的输入脉冲进行自加 1,也就是每来一 个脉冲,计数器就自动加 1,当加到计数器为全 1 时,再输入一个脉冲就使计数 器回零,且计数器的溢出使相应的中断标志位置 1,向 CPU 发出中断请求(定时 /计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到; 如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数 初值才是加 1 计数器的计数值。
注意:
①定时器/计数器和单片机的 CPU 是相互独立的。定时器/计数器工作的过程 是自动完成的,不需要 CPU 的参与。
②51 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信 号对寄存器中的数据加 1。
2.1 51 单片机定时/计数器结构
T0对应 P3.4管脚
T1对应P3.5 管脚
51单片机定时/计数器的工作由两个特殊功能寄存器控制.
- TMOD: 确定工作方式
- TCON: 控制定时器/计数器的启动,停止与设置溢出标志
2.2 工作方式寄存器TMOD
工作方式寄存器 TMOD 用于设置定时/计数器的工作方式,低四位用于 T0,高 四位用于 T1。其格式如下:
GATE 是门控位, GATE=0 时,用于控制定时器的启动是否受外部中断源信号 的影响。只要用软件使 TCON 中的 TR0 或 TR1 为 1,就可以启动定时/计数器工作; GATA=1 时,要用软件使 TR0 或 TR1 为 1,同时外部中断引脚 INT0/1 也为高电平 时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了 INT0/1 引脚 为高电平这一条件
C/T :定时/计数模式选择位。C/T =0 为定时模式;C/T =1 为计数模式。 M1M0:工作方式设置位。工作方式详见下节
例如要使用定时器0,那么就设置TMOD |= 0x01(使用或运算是为了不使之前TMOD的值收到干扰)
即
- GATE = 0 ,此时将TCON中的TR0设置为1即可工作
- C/T = 0定时模式
- M1M0 = 01 为模式1
2.3 控制寄存器TCON
TCON 的低 4 位用于控制外部中断,已在前面介绍。TCON 的高 4 位用于控制定 时/计数器的启动和中断申请。其格式如下:
TF1(TCON.7):T1 溢出中断请求标志位。T1 计数溢出时由硬件自动置 TF1 为 1。CPU 响应中断后 TF1 由硬件自动清 0。T1 工作时,CPU 可随时查询 TF1 的 状态。所以,TF1 可用作查询测试的标志。TF1 也可以用软件置 1 或清 0,同硬 件置 1 或清 0 的效果一样。 TR1(TCON.6):T1 运行控制位。TR1 置 1 时,T1 开始工作;TR1 置 0 时, T1 停止工作。TR1 由软件置 1 或清 0。所以,用软件可控制定时/计数器的启动 与停止。 TF0(TCON.5):T0 溢出中断请求标志位,其功能与 TF1 类同。 TR0(TCON.4):T0 运行控制位,其功能与 TR1 类同。
如果要使用定时器0,需要将TR1 置为1,才能打开控制,当溢出时TF0 为1,清零将TF0置零即可
3. 定时器工作方式
定时/计数器有四种工作方式。
3.1 方式0
方式 0 为 13 位计数,由 TL0 的低 5 位(高 3 位未用)和 TH0 的 8 位组成。 TL0 的低 5 位溢出时向 TH0 进位,TH0 溢出时,置位 TCON 中的 TF0 标志,向 CPU 发出中断请求。其结构图如下所示:
3.2 方式1
方式 1 的计数位数是 16 位,由 TL0 作为低 8 位,TH0 作为高 8 位,组成了 16 位加 1 计数器。其结构图如下所示:
3.3 方式2
方式 2 为自动重装初值的 8 位计数方式。工作方式 2 特别适合于用作较 精确的脉冲信号发生器。其结构图如下所示:
4. 定时器配置
在使用定时器时,应该如何配置使其工作?其步骤如下(各步骤顺序可任 意):①对 TMOD 赋值,以确定 T0 和 T1 的工作方式,如果使用定时器 0 即对 T0 配 置,如果使用定时器 1 即对 T1 配置。 ②根据所要定时的时间计算初值,并将其写入 TH0、TL0 或 TH1、TL1。 ③如果使用中断,则对 EA 赋值,开放定时器中断。 ④使 TR0 或 TR1 置位,启动定时/计数器定时或计数。 上述中有一个定时/计数器初值的计算,下面我们来看下如何计算定时/计数 器初值。
5. 计算初值
定时器本质上其实就是计数器,只不过是根据机器周期把计数的次数转化成了时间而已
可以自己计算,也可以使用软件计算
自己计算的方法如下
定时器初值计算方法
前面我们介绍过机器周期的概念,它是 CPU 完成一个基本操作所需要的时间。 其计算公式是:机器周期=1/单片机的时钟频率。51 单片机内部时钟频率是外部 时钟的 12 分频,也就是说当外部晶振的频率输入到单片机里面的时候要进行 12 分频。比如说你用的是 12MHZ 晶振,那么单片机内部的时钟频率就是 12/12MHZ, 当你使用 12MHZ 的外部晶振的时候,机器周期=1/1M=1us。如果我们想定时 1ms 172
的初值是多少呢?1ms/1us=1000。也就是要计数 1000 个,初值=65535-1000+1 (因为实际上计数器计数到 66636(2 的 16 次方)才溢出,所以后面要加 1) =64536=FC18H,所以初值即为 THx=0XFC,TLx=0X18。
如果要计算太多的时间,可以以一个比较小的时间为基本单位:如1ms,
6. 实验代码
控制小灯间隔1s闪烁
别忘了在main函数中调用Timer0Init()函数!!!
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit led = P2^0;
void Timer0init(){
// ???????????TMOD????????????,????M0M1,????|????
TMOD |= 0x01; //???????0????1,??TMOD?????λ????,????λ??????????
//???1ms ????????1us ???????? 1ms/1us = 1000 c????65536-1000 = FC18H
//??????????μ???????????м???
//???ó??
TH0 = 0xFC;
TL0 = 0x18;
//?????1????ж???λ ET0
ET0 = 1;
// ???ж?
EA = 1;
//???п???λ,??1???????
TR0 = 1;
}
void main(){
Timer0init();
while(1)
{
}
}
//?????0???ж???1,?????1???ж???3
void Timer0() interrupt 1{
static u16 i = 0;
TH0 = 0xFC;
TL0 = 0x18;
i++;
//??i????1s
if(i==1000){
i = 0;
led = ~led;
}
}