郭天祥 10天搞定单片机 (3)数码管+中断
2024-06-02 10:52:11
好久没有更新了,前两个月在复习备考,9月底刚刚考过,希望能有好结果吧~
这一讲接着讲流水灯,涉及到段选和位选,以及介绍了中断的知识。
先介绍一下使用的单片机的主控引脚:
- 总线型引脚定义:
- RST/Vpd: RST是复位端,高电平持续24个振荡周期,就可以复位,指针就回到最开始的语句。Vpd给RAM提供备用电源
- 同一个口的不同值由寄存器里的值控制
- P3.0/RXD: RXD 串行输入口
- P3.1/TXD:TXD串行输出口
- P3.2,INT0一横,P3.3 INT1一横,外部中断0和外部中断1
- T0/T1: 计时器0和计时器1
- P3.6 WR一横:外部寄存器的写选通
- P3.7 RD一横:外部寄存器的读选通
- XTAL2,XTAL1:外部晶振的输入端
- 晶振
- Vss: 接地
- PDEN一横:一般不用
- ALE/PROG一横:第二功能,输出1/6晶振频率的方波
- EA一横:内部存储器选择控制端
- P0口没有上拉电阻,P1 P2 P3内部有上拉电阻
- 特殊功能寄存器
- 数码管如何显示字符
- 看是共阴极还是共阳极
- 要显示什么数字,要先确定那几个笔画需要显示,再确定管脚
- 段选和位选
WE1就是位选,其他是段选。因为第几个数码管和每个数码管上的每个笔画都是由P0口控制的,所以要由位选段选来控制什么时候控制选数码管还是选数码管上的笔画。
来编程让第一个数码管显示1:
#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;void main()
{wela=1; //启动位选P0=0xfe; // 第一个启动,WE1=0,其他为1wela=0; //WELA=0, 低电平,锁存上一次的输出结果dula=1; //启动段选P0=0x06; //数字1, b, c两段是亮的,即编号4和6管脚导通dula=0;
}
这是静态控制。
利用人眼的残留效应和数码管的余晖可以实现动态显示。
下面这段让6个数码管同时亮,并且同时按1,2,3……循环变化:
#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
#define uint unsigned int
#define uchar unsigned char
void delay(uint);
uchar num;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
void main()
{ wela=1;P0=0xc0;wela=0;while(1){for(num=0;num<16;num++){dula=1;P0=table[num];dula=0;delay(5);}}
}void delay(uint z)
{uint x,y;for (x=z; x>0; x--){ for (y=5000;y>0;y--){}}
}
中断
- 中断的概念:CPU在处理某时间A时,发生了另外一件事B请求CPU处理(中断发生);CPU暂时中断当前工作,去处理B(中断响应或者中断服务);当处理完B后,CPU再回到原先A被中断的地方继续处理A(中断返回);这个过程被称为中断。
- 中断可以嵌套;
- 中断的地方被称为断点,引起CPU中断的根源被称为中断源
- 80C51有5个中断源,2个优先级,可以实现二级中断嵌套
- 中断允许寄存器IE是一个特殊功能寄存器,之前学的都是I/O口的寄存器。
位序号 |
位符号 |
含义 |
D7 |
EA |
全局中断允许位 |
D6 |
-- |
-- |
D5 |
ET2 |
定时器/计数器2中断允许位 |
D4 |
ES |
串行口中断允许位 |
D3 |
ET1 |
定时器/计数器1中断允许位 |
D2 |
EX1 |
外部中断1 中断允许位 |
D1 |
ET0 |
定时器/计数器0中断允许位 |
D0 |
EX0 |
外部中断0 中断允许位 |
都是置1打开中断。复位后IE全部清0。
- 中断优先级寄存器IP:有一个默认的中断优先级顺序,等下再说。
位序号 |
位符号 |
含义 |
D7 |
/ |
|
D6 |
/ |
|
D5 |
/ |
|
D4 |
PS |
串口优先 |
D3 |
PT1 |
定时器/计数器1优先 |
D2 |
PX1 |
外部中断1优先 |
D1 |
PT0 |
定时器/计数器0优先 |
D0 |
PX0 |
外部中断0优先 |
- 默认的中断优先顺序:外部中断0>定时器/计数器0>外部中断1>定时器/计数器1>串行口>定时器/计数器2
- 外部中是由端口低电平或者下降沿引起;计数器/定时器是计时器计满回零引起;串行是串行端口完成一帧字符的发送或者接受引起
- 中断函数的定义:
void exter0() interrupt 0 //无返回值,函数名是exter0, interrupt是必须要有的,0是中断序号
{
d1=0;
}
- 中断函数不需要声明
- 外部中断0的例子:
#include<reg52.h> sbit dula=P2^6; sbit wela=P2^7; sbit d1=P1^0; #define uint unsigned int #define uchar unsigned char void delay(uint); uchar num; uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71}; void main() { EA=1;EX0=1;wela=1;P0=0xc0;wela=0;while(1){for(num=0;num<16;num++){d1=1;dula=1;P0=table[num];dula=0;delay(5);}} }void delay(uint z) {uint x,y;for (x=z; x>0; x--){ for (y=5000;y>0;y--){}} } void exter0() interrupt 0 {d1=0; }
定义了中断函数后,将外部中断0的端口,P2.3接地,就可以触发中断。
- 定时器:每个机器周期+1,加满后回零,中断
- 实现定时功能,除了利用单片机内部的计数器/定时器外,还有下面三种方法:软件定时(不占用硬件资源,但是占CPU资源),时基电路定时(外接必要的元器件,定时值和定时范围不可编程),可编程芯片定时
- 每个定时器是两个8位的寄存器,共16位
- 还有两个与计时器相关的寄存器,TMOD和TCON
- TMOD高四位用于控制T1,低四位用于控制T0