51单片机学习【每天必学】
单片机里的周期
在单片机里面, 我们会接触到一些基本的周期知识点。主要的周期有时钟周期, 机器周期, 指令周期, 这三个周期他们的各自含义是什么?
时钟周期
时钟周期,就是一个没有分频或者倍频的晶振的震荡周期。如果晶振的输出分频或者倍频, 那么这个单片机的时钟周期就是分频或者倍频的震荡周期。 即 时钟周期=晶振的震荡周期. 一般晶振上会标准Hz为单位的值,这里我们需要注意的是, 这里是频率的意思。 也就是时钟周期等于震荡频率的倒数。
比如一个11.088MHz的晶振, 那么时钟周期就是1/11.088M
, 这个就是最小时间单位 1/11.088(us)
机器周期
在单片机中, 常把一条指令的执行过程划分为若干个阶段,每一个阶段完成一项工作。 这每一项工作称为一个基本操作。 完成每一个基本操作的所需要的的时间,我们称为机器周期。
比如, 在89c51系列单片机中, 一般执行一条指令的每一个阶段分为12个时钟周期,那么这个 机器周期= 时钟周期 * 12。即 机器周期=1/11.088 * 12
指令周期
CPU每取出一条指令并执行这条指令,所需要的的时间,我们称之为指令周期。
由于每一条指令的操作功能不同, 因此他们的指令周期也是不一样的。有的指令只需要一个机器周期时间, 有的需要两个机器周期时间。这里我们分为将这两个指令称为单周期指令和双周期指令。
LED
LED总共有8个, 主要由P1
排针的分别对应脚来控制。这里我们需要理解到的是引脚的初始值, 及对引脚的控制(其实就是复制)。当前单片机的LED的每一个脚初始值为1(高电平不亮),设置为0(低电平)时,LED亮起。
sbit LED_0 = P1^0; //获取引脚的指针地址。
LED_0 = 0; //灯亮
通过引脚高低平的控制, 可以使LED灯开与关的控制。 我们可以制作更多的特效。比如间隔关闭开启, 比如流水灯等。 下面我们实现这两个效果。在实现这两个效果前,我们需要编写一个延迟的功能函数(这里我们还没有学到定时器)。
延迟函数
延迟函数, 我们利用指令周期的时间来, 大概的编写一个延迟功能。
void delay(int us) {
int i;
for(i = 0; i < us * 1000 + 82; i++);
}
void delay_s(int s) {
delay(s * 1000);
}
第一个delay
为微秒单位, 第二个函数 delay_s
已秒为单位。
间隔LED开于关(呼吸灯, 心跳灯)
我当前开发板是用P1排针来控制的, 这里我们只控制P1第一个脚P1^0. P1其实就是一个数字, 代表了寄存器的地址,可以直接进行数据修改。
sbit LED_0 = P1^0;
void led_heart() {
while(1) {
LED_0 = 0;
delay_s(1);
LED_0 = 1;
delay_s(1);
}
}
代码中时1秒作为时间间隔。
流水灯
流水灯是控制8个LED灯, 来回的亮。 所以我们这里就直接控制P1全部的排针, 那我们直接使用P1来控制其值。P1代表了一个8位的值, 所以我们直接控制八个0,1: 11111111b
(这里代表一个二进制数).
思路: 0 代表灯亮,比如第一个灯亮, P1的值就是11111110
, 第二个灯亮,P1的值为11111101
, 依次类推。我们可以得出一个结果: 就是每换一个灯亮, 其值都是在减去一个2的次方。那这里我们需要一个次方函数来辅助完成流水灯。
次方函数如下:
static int pow(int x) {
int s = 1;
if(x == 0) return 1;
while(x > 0) {
s *= 2;
x--;
}
return s;
}
流水灯功能:
void flow_water() {
char i = 0;
char d = 0;
while(1) {
P1 = 0xFF - pow(i);
d ? i--: i++;
if(i == 7) d = 1;
if(i == 0) d = 0;
delay_s(1);
}
}
定时器
todo
TCON
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
标志 | TF1 | TR1 | TF0 | TR0 | ... | ... | ... | ... |
说明 | T1溢出标志 | T1是否启动 | T0溢出标志 | T0是否启动 | .. | .. | .. | .. |
- 4-5位 T0定时器控制位
- 6-7位 T1定时器控制位
- TF0/TF1 定时器溢出的标识, 1代表溢出, 0代表未溢出
- TR0/TR1 定时器开关标识, 1代表启动, 0代表不启动
TMOD
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
标志 | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
- 0-3位 T0定时器的控制位
- 4-7位 T1定时器的控制位
- GATE 门控位。 0 时,TR0/TR0为1时,定时器可以启动;1 时,TR0/TR1为1, 同时外部中断引脚为高电平时,定时器才能启动
- C/T 定时模式位。 0 代表定时模式; 1 代表计数模式。
- M1,M0 00 代表13位定时器;01代表16位定时;10代表8位自动重装;11代表T0分为独立的两个8位定时,T1无效。
中断
中断顾名思义就是打断的意思。中断出现的背景在于一个高速设备和一个低速设备外设连接,沟通时, 效率极低。 低速设备会无端的占用CPU的时间。导致无法进行多任务并行处理。这时候, 就需要中断 来介入。
中断优点:
- 分时操作
- 实时响应
- 可靠性高
中断设计环节:
- 中断源
- 中断请求
- 开放中断
- 保护现场
- 中断服务
- 恢复中断
- 中断返回
中断控制
在80C52单片机中有6个中断源,2个优先级,可以实现中断嵌套。80C51单片机是5个中断源,2个优先级。
中断启用控制: IE寄存器
IE寄存器是控制中断是否启用的开关。
IE寄存器位说明
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
标志 | IE7(EA) | IE6 | IE5 | IE4(ES) | IE3(ET1) | IE2(EX1) | IE1(ET0) | IE0(EX0) |
- EX0 外部中断0允许位
- ET0 定时器T0中断位
- EX1 外部中断1允许位
- ET1 定时器T1终端位
- ES 串口中断位
- EA 中断总开关
中断优先级控制: IP寄存器
中断优先级分为低优先级和高优先级, 全部默认为低优先级。 我们可以通过IP来控制各个中断源的优先级是属于低优先级,还是属于高优先级。 优先级高的, 请求响应优先。优先级高的, 在同一级优先级的中断中, 他们的优先顺序由硬件的设计决定。在80C51中,优先级为: 外部中断0 > T0 > 外部中断1 > T1 > 串口
。
中断优先级原则
- CPU同时接收到几个中断请求时, 首先响应优先级别最高的中断请求。
- 正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。
- 正在进行的低优先级中断服务,能被高优先级中断请求所中断。
为了实现上述的3条原则, 中断内部设有2
个用户不能寻址的优先级状态触发器. 其中一个置为1, 表示正在响应高优先级的中断,他将阻断后来所有的中断请求; 另外一个置为1, 表示正在响应低优先级中断, 他将阻断后来所有的低优先级中断请求。
IP寄存器位说明
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
标志 | PT2 | PS | PT1 | PX1 | PT0 | PX0 |
- PX0 外部中断0优先级
- PT0 定时器0中断优先级
- PX1 外部中断1优先级
- PT1 定时器1中断优先级
- PS 串口中断优先级
- PT2 定时器2优先级
PWM
todo
.......................