矩阵键盘
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
# include "reg51.h"
unsigned int num = 9; unsigned char s[] = {0X3F, 0X06, 0X5B, 0X4F, 0X66, 0X6D, 0X7D, 0X07, 0X7F, 0X6F,0X76, 0X79, 0X38, 0X38, 0X3F,0XFF}; sbit P10=P1^0; sbit P11=P1^1; sbit P12=P1^2; sbit P13=P1^3; sbit P14=P1^4; sbit P15=P1^5; sbit P16=P1^6; sbit P17=P1^7; void Delay(unsigned int n) { unsigned int i, j; for (i=0; i<n; i++) { for (j=0; j<120; j++); } }
void key_scan() { P1 = 0xff; P1=0xFF; P13=0; if(P17==0){Delay(20);while(P17==0);Delay(20);num=1;} if(P16==0){Delay(20);while(P16==0);Delay(20);num=5;} if(P15==0){Delay(20);while(P15==0);Delay(20);num=9;} if(P14==0){Delay(20);while(P14==0);Delay(20);num=13;} P1=0xFF; P12=0; if(P17==0){Delay(20);while(P17==0);Delay(20);num=2;} if(P16==0){Delay(20);while(P16==0);Delay(20);num=6;} if(P15==0){Delay(20);while(P15==0);Delay(20);num=10;} if(P14==0){Delay(20);while(P14==0);Delay(20);num=14;} P1=0xFF; P11=0; if(P17==0){Delay(20);while(P17==0);Delay(20);num=3;} if(P16==0){Delay(20);while(P16==0);Delay(20);num=7;} if(P15==0){Delay(20);while(P15==0);Delay(20);num=11;} if(P14==0){Delay(20);while(P14==0);Delay(20);num=15;} P1=0xFF; P10=0; if(P17==0){Delay(20);while(P17==0);Delay(20);num=4;} if(P16==0){Delay(20);while(P16==0);Delay(20);num=8;} if(P15==0){Delay(20);while(P15==0);Delay(20);num=12;} if(P14==0){Delay(20);while(P14==0);Delay(20);num=16;} }
void display() { P2 = s[num]; }
void main() { while(1) { key_scan(); display(); }
}
|
定时器
工作方式
interrupt0,13位,当 INT0 引脚由高电平变为低电平时触发中断。
- $X=8192-N\frac{12}{fosc}$
- 上次计数为0,要重复计数需要置零
interrupt1,16位,当定时器 0 计数器溢出时触发中断。
- $X=65536-N\frac{12}{fosc}$
- 上次计数值为0,要重复计数需要重置初值
interrupt2,8位自动重置定时/计数器,当 INT1引脚由高电平变为低电平时触发中断。
interrupt3,8位,只有T0才能使用,当定时器 1 计数器溢出时触发中断。
- $X=256-N\frac{12}{fosc}$
- 计数器自动配置初值,不需要用户重置
interrupt4,串口中断,当串口接收完成(RI)或发送完成(TI)时触发中断。
TMOD 寄存器
TMOD 的低 4 位控制定时器 0,高 4 位控制定时器 1,每个定时器都有两个工作模式可以选择
M0表示定时器0,M1表示定时器1
TMOD=0x20表示定时器1设置为2模式
TMOD=0x02表示定时器0设置为2模式
TMOD |
GATE |
C/T |
M1 |
M0 |
工作模式 |
0x00 |
0 |
0 |
0 |
0 |
模式 0:13 位计数器 |
0x01 |
0 |
0 |
0 |
1 |
模式 1:16 位计数器 |
0x02 |
0 |
0 |
1 |
0 |
模式 2:8 位自动重装载计数器 |
0x03 |
0 |
0 |
1 |
1 |
模式 3:16 位自动重装载计数器 |
0x04 |
0 |
1 |
0 |
0 |
模式 4:外部事件计数 |
0x05 |
0 |
1 |
0 |
1 |
模式 5:保留 |
0x06 |
0 |
1 |
1 |
0 |
模式 6:8 位 PWM 波形发生器 |
0x07 |
0 |
1 |
1 |
1 |
模式 7:16 位 PWM 波形发生器 |
TH和TL寄存器
TH0/TL0
表示定时器0的高低八位
TH1/TL1
表示定时器1的高低八位
IT寄存器
IT0
,外部中断寄存器
IT1
,外部中断寄存器
IT0/IT1=0
,低电平触发
IT0/IT1=1
,下降沿触发
中断寄存器
ET0/ET1
,定时器中断使能寄存器,为1中断允许,为0不允许
EA
,总中断使能寄存器,为1中断允许,为0不允许
TR0/TR1
,定时器启动控制寄存器,为1时开始计数,为0时停止计数。
12MHz晶振对应的一个机器周期为1us,需要延时50ms,则从65536-50000开始计数,分为高低八位分别存储计数,当定时器0计数到65536溢出位时,触发timer_isr中断,执行函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
# include "reg51.h" unsigned char s[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; unsigned char count = 0, num = 0;
void inittimer() { TMOD = 0x01; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; ET0 = 1; EA = 1; TR0 = 1; } void display() { P2 = s[num]; if (num == 10) { num = 0; } }
void timer_isr() interrupt 1 { TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; count++; if (count == 20) { num++; count = 0; }
} void main() { inittimer(); while(1) { display(); } }
|
计数器
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
# include "reg51.h" unsigned char s[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; unsigned char num = 0;
void initcounter() { TMOD = 0X06; TH0 = 255; TL0 = 255; ET0 = 1; EA = 1; TR0 = 1; }
void display() { P2 = s[num]; if (num == 10) { num = 0; } }
void counter_isr() interrupt 1 { num++; }
void main() { initcounter(); while(1) { display(); } }
|