- 让P1.0输出方波,周期为1s,那么就是高电平500ms,低电平500ms,这样P1.0的发光二极管就闪烁了,频率是周期的倒数,1s的倒数还是1,假设12MHz,其实电路板是11.0592MHz,只是为了计算方便。
- 让P1口的八个二极管流水灯,1秒钟10次。
- 第一个300ms输出频率为1KHz的方波,第二个300ms输出10KHz的方波,以此类推。(改变频率可以使其唱歌,这里是有源蜂鸣器,效果不好,无源的声音很清脆)
- 例题就是。
接下里一个练习,流水灯1s间隔(延时函数),数码管2s间隔显示0~F(定时器),用延时函数和定时器,把前面的复习一遍
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9
10 sbit WEI=P2^7;
11 sbit DUAN=P2^6;
12
13 void Delay1ms();
14 void delay(int n);
15
16 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
17 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
18 //[]括号内可以不写,编译时会自动数元素数然后分配内存
19
20 uchar num=0,n=0;
21 void main()
22 {
23 TMOD=0x01;//设置定时器0为工作方式1
24 TH0=(65536-50000)/256;
25 TL0=(65536-50000)%256;
26 EA=1;//开总中断
27 ET0=1;//开启定时器中断
28 TR0=1;//开启定时器
29
30 WEI=1;
31 P0=0x00;
32 WEI=0;
33
34 DUAN=1;
35 P0=Table[num];
36 DUAN=0;
37 P1=0xfe;
38 while(1)
39 {
40 P1=_crol_(P1,1);
41 delay(1000);
42 if(n==40)
43 {
44 n=0;
45 num++;
46 if(num==16)
47 {
48 num=0;
49 }
50 DUAN=1;
51 P0=Table[num];
52 DUAN=0;
53 }
54 }
55 }
56
57 void timer0() interrupt 1 //有的会写 interrupt 1 using 0~3, 暂时不需要知道,好麻烦......
58
59 {
60 TH0=(65536-50000)/256;
61 TL0=(65536-50000)%256;
62 n++;
63 }
64
65 void delay(int n)
66 {
67 while(n--)
68 {
69 Delay1ms();
70 }
71 }
72 void Delay1ms() //@12.000MHz
73 {
74 unsigned char i, j;
75
76 i = 2;
77 j = 239;
78 do
79 {
80 while (--j);
81 } while (--i);
82 }
你会发现这样写,是有问题的,开始还能好,过一会数码管就不会变了,单独运行流水灯和数码管的程序都可以正常运行。
原因:
两个delay的时间n就达到了40,但是其它语句的运行也是需要时间的,若P1=_crol还有if两个语句分别需要20ms(当然肯定没这么久,而且只有if成功时才占用的时间比较长),那么从头开始执行到if结束时,n=20,并且定时器已经计时到了40ms,然后再次循环,执行完P1=,那么就是n=21,执行完delay,n=41,开始if判断时,需要的是n==40,这样才能数码管变化,但是这时已经n=41了,所以以后永远不会变化了。
解决方法:
- 将n==40改为>=40,这里就不给代码了。
- 将if判断放在中断函数里,当然这样还是有误差的,就像上面说的,P1=也是用时间的,但是太小太小了,所以误差不大。
1 #include<reg51.h> 2 #include<intrins.h> 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 void Delay1ms(); 8 void delay(int n); 9 10 sbit WEI=P2^7; 11 sbit DUAN=P2^6; 12 13 void Delay1ms(); 14 void delay(int n); 15 16 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; 17 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示 18 //[]括号内可以不写,编译时会自动数元素数然后分配内存 19 20 uchar num=0,n=0; 21 void main() 22 { 23 TMOD=0x01;//设置定时器0为工作方式1 24 TH0=(65536-50000)/256; 25 TL0=(65536-50000)%256; 26 EA=1;//开总中断 27 ET0=1;//开启定时器中断 28 TR0=1;//开启定时器 29 30 WEI=1; 31 P0=0x00; 32 WEI=0; 33 34 DUAN=1; 35 P0=Table[num]; 36 DUAN=0; 37 P1=0xfe; 38 while(1) 39 { 40 P1=_crol_(P1,1); 41 delay(1000); 42 // if(n==40) 43 // { 44 // n=0; 45 // num++; 46 // if(num==16) 47 // { 48 // num=0; 49 // } 50 // DUAN=1; 51 // P0=Table[num]; 52 // DUAN=0; 53 // } 54 } 55 } 56 57 void timer0() interrupt 1 //有的会写 interrupt 1 using 0~3, 暂时不需要知道,好麻烦...... 58 59 { 60 TH0=(65536-50000)/256; 61 TL0=(65536-50000)%256; 62 n++; 63 if(n==40) 64 { 65 n=0; 66 num++; 67 if(num==16) 68 { 69 num=0; 70 } 71 DUAN=1; 72 P0=Table[num]; 73 DUAN=0; 74 } 75 } 76 77 void delay(int n) 78 { 79 while(n--) 80 { 81 Delay1ms(); 82 } 83 } 84 void Delay1ms() //@12.000MHz 85 { 86 unsigned char i, j; 87 88 i = 2; 89 j = 239; 90 do 91 { 92 while (--j); 93 } while (--i); 94 }
接下里再写一个程序,让8个数码管一个一个显示,从1到8,一秒一次,意思是,第一秒第一个数码管亮,显示1,第二秒第二个数码管亮,显示2,以此类推。
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 sbit WEI=P2^7;
8 sbit DUAN=P2^6;
9
10 void Delay1ms();
11 void delay(int n);
12
13 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
14 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
15 uchar code Wei_Table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
16 //位选表,也可以用位循环来做
17 uchar num=0,n=0,wei_num=0;
18 void main()
19 {
20 TMOD=0x01;//设置定时器0为工作方式1
21 TH0=(65536-50000)/256;
22 TL0=(65536-50000)%256;
23 EA=1;//开总中断
24 ET0=1;//开启定时器中断
25 TR0=1;//开启定时器
26
27 while(1)
28 {
29 if(n==20)
30 {
31 n=0;
32 num++;
33 if(num==9)
34 num=1;
35 DUAN=1;
36 P0=Table[num];
37 DUAN=0;
38
39 WEI=1;
40 P0=Wei_Table[wei_num];
41 WEI=0;
42
43 wei_num++;
44 if(wei_num==8)
45 wei_num=0;
46 }
47 }
48 }
49
50 void timer0() interrupt 1
51 {
52 TH0=(65536-50000)/256;
53 TL0=(65536-50000)%256;
54 n++;
55 }
如果我们把上面的时间改一下,改的短一点,比如50ms一次,即n=1,这样就会更快,如果再小,就可以看见有几个灯像是一直亮着,如果再小比如5ms,就可以发现8个灯一直亮着,这就是动态扫描了。(注意尝试了,用锁存器的电路图的话,那么仿真这里是不能出现12345678的,所以从这里开始要用单片机了)
电阻要小这是针对典型电路的,我们这里用了锁存器,每一个大致能输出10mA电流,所以足够亮,还能简化电路。
其实这里不需要用到定时器,所以接下来我们用延时函数,来让数码管显示12,同时不能用数组的形式储存段选值
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9
10 sbit WEI=P2^7;
11 sbit DUAN=P2^6;
12
13 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
14 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
15
16 uchar num=0,shi,ge,temp;
17 void main()
18 {
19 temp=12;
20 shi=temp/10;
21 ge=temp%10;
22 while(1)
23 {
24 DUAN=1;
25 P0=Table[shi];
26 DUAN=0;
27
28 WEI=1;
29 P0=0xfe;
30 WEI=0;
31 delay(5);
32
33 DUAN=1;
34 P0=Table[ge];
35 DUAN=0;
36
37 WEI=1;
38 P0=0xfd;
39 WEI=0;
40 delay(5);
41 }
42 }
43
44 void delay(int n)
45 {
46 while(n--)
47 {
48 Delay1ms();
49 }
50 }
51 void Delay1ms() //@12.000MHz
52 {
53 unsigned char i, j;
54
55 i = 2;
56 j = 239;
57 do
58 {
59 while (--j);
60 } while (--i);
61 }
那么接下来要显示三位数,如352怎么办?
你可能会这样写
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9
10 sbit WEI=P2^7;
11 sbit DUAN=P2^6;
12
13 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
14 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
15
16 uchar num=0,shi,ge,temp,bai;
17 void main()
18 {
19 temp=352;
20 bai=temp/100;
21 shi=temp/10%10;
22 ge=temp%10;
23 while(1)
24 {
25 DUAN=1;
26 P0=Table[bai];
27 DUAN=0;
28
29 WEI=1;
30 P0=0xfe;
31 WEI=0;
32 delay(5);
33
34 DUAN=1;
35 P0=Table[shi];
36 DUAN=0;
37
38 WEI=1;
39 P0=0xfd;
40 WEI=0;
41 delay(5);
42
43 DUAN=1;
44 P0=Table[ge];
45 DUAN=0;
46
47 WEI=1;
48 P0=0xfb;
49 WEI=0;
50 delay(5);
51 }
52 }
53
54 void delay(int n)
55 {
56 while(n--)
57 {
58 Delay1ms();
59 }
60 }
61 void Delay1ms() //@12.000MHz
62 {
63 unsigned char i, j;
64
65 i = 2;
66 j = 239;
67 do
68 {
69 while (--j);
70 } while (--i);
71 }
咦,为什么是96呢???!
发现没有,temp是unsigned char类型的,char类型的变量是1个字节,8位的,那么最大是2的8次方,即256,那么超过了这个数就会取超过的部分(352-256=96),如果是600,超出了两个256,同样是再取超过的,即88。
如果是小于256的三位数就是对的,如152。想要显示352,只要换成int就好了。
然后我们可以把显示内容写成函数,这样就成了一个模板了。
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9 void display(uchar bai,uchar shi,uchar ge);
10 sbit WEI=P2^7;
11 sbit DUAN=P2^6;
12
13 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
14 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
15
16 uchar num=0,shi,ge,temp,bai;
17 void main()
18 {
19 temp=152;
20 bai=temp/100;
21 shi=temp/10%10;
22 ge=temp%10;
23 while(1)
24 {
25 display(bai,shi,ge);
26 }
27 }
28
29 void display(uchar bai,uchar shi,uchar ge)
30 {
31 DUAN=1;
32 P0=Table[bai];
33 DUAN=0;
34
35 WEI=1;
36 P0=0xfe;
37 WEI=0;
38 delay(5);
39
40 DUAN=1;
41 P0=Table[shi];
42 DUAN=0;
43
44 WEI=1;
45 P0=0xfd;
46 WEI=0;
47 delay(5);
48
49 DUAN=1;
50 P0=Table[ge];
51 DUAN=0;
52
53 WEI=1;
54 P0=0xfb;
55 WEI=0;
56 delay(5);
57 }
58 void delay(int n)
59 {
60 while(n--)
61 {
62 Delay1ms();
63 }
64 }
65 void Delay1ms() //@12.000MHz
66 {
67 unsigned char i, j;
68
69 i = 2;
70 j = 239;
71 do
72 {
73 while (--j);
74 } while (--i);
75 }
写一个程序,显示计时,这次规范点。
1 #include<reg51.h>
2 #include<intrins.h>
3
4 #define uchar unsigned char
5 #define uint unsigned int
6
7 void Delay1ms();
8 void delay(int n);
9 void display(uchar bai,uchar shi,uchar ge);
10 void init();
11 sbit WEI=P2^7;
12 sbit DUAN=P2^6;
13
14 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
15 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示
16
17 uchar num=0,shi,ge,temp=0,bai,a=0;
18 void main()
19 {
20 init();
21 bai=temp/100;
22 shi=temp/10%10;
23 ge=temp%10;
24 while(1)
25 {
26 if(a==20)
27 {
28 a=0;
29 temp++;
30 if(temp==101)
31 {
32 temp=0;
33 }
34 bai=temp/100;
35 shi=temp/10%10;
36 ge=temp%10;
37 }
38 display(bai,shi,ge);
39 }
40 }
41
42 void display(uchar bai,uchar shi,uchar ge)
43 {
44 DUAN=1;
45 P0=Table[bai];
46 DUAN=0;
47
48 WEI=1;
49 P0=0xfe;
50 WEI=0;
51 delay(5);
52
53 DUAN=1;
54 P0=Table[shi];
55 DUAN=0;
56
57 WEI=1;
58 P0=0xfd;
59 WEI=0;
60 delay(5);
61
62 DUAN=1;
63 P0=Table[ge];
64 DUAN=0;
65
66 WEI=1;
67 P0=0xfb;
68 WEI=0;
69 delay(5);
70 }
71 void init()
72 {
73 TH0=(65536-50000)/256;
74 TL0=(65536-50000)%256;
75 EA=1;
76 ET0=1;
77 TR0=1;
78 }
79 void delay(int n)
80 {
81 while(n--)
82 {
83 Delay1ms();
84 }
85 }
86 void Delay1ms() //@12.000MHz
87 {
88 unsigned char i, j;
89
90 i = 2;
91 j = 239;
92 do
93 {
94 while (--j);
95 } while (--i);
96 }
97 void timer0() interrupt 1
98 {
99 TMOD=0x01;
100 TH0=(65536-50000)/256;
101 TL0=(65536-50000)%256;
102 a++;
103 }
会发现出了前三个数码管以外,后面的数码管显示的很浅。之所以这样,是因为段选关闭,开启位选以前,P0也是有值的。
接下来说一下消影的方法
- 我们可以在开启位选以前先让P0=0xff,关闭所有数码管
1 #include<reg51.h> 2 #include<intrins.h> 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 void Delay1ms(); 8 void delay(int n); 9 void display(uchar bai,uchar shi,uchar ge); 10 void init(); 11 sbit WEI=P2^7; 12 sbit DUAN=P2^6; 13 14 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; 15 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示 16 17 uchar num=0,shi,ge,temp=0,bai,a=0; 18 void main() 19 { 20 init(); 21 bai=temp/100; 22 shi=temp/10%10; 23 ge=temp%10; 24 while(1) 25 { 26 if(a==20) 27 { 28 a=0; 29 temp++; 30 if(temp==101) 31 { 32 temp=0; 33 } 34 bai=temp/100; 35 shi=temp/10%10; 36 ge=temp%10; 37 } 38 display(bai,shi,ge); 39 } 40 } 41 42 void display(uchar bai,uchar shi,uchar ge) 43 { 44 DUAN=1; 45 P0=Table[bai]; 46 DUAN=0; 47 48 P0=0xff; 49 WEI=1; 50 P0=0xfe; 51 WEI=0; 52 delay(5); 53 54 DUAN=1; 55 P0=Table[shi]; 56 DUAN=0; 57 58 P0=0xff; 59 WEI=1; 60 P0=0xfd; 61 WEI=0; 62 delay(5); 63 64 DUAN=1; 65 P0=Table[ge]; 66 DUAN=0; 67 68 P0=0xff; 69 WEI=1; 70 P0=0xfb; 71 WEI=0; 72 delay(5); 73 } 74 void init() 75 { 76 TH0=(65536-50000)/256; 77 TL0=(65536-50000)%256; 78 EA=1; 79 ET0=1; 80 TR0=1; 81 } 82 void delay(int n) 83 { 84 while(n--) 85 { 86 Delay1ms(); 87 } 88 } 89 void Delay1ms() //@12.000MHz 90 { 91 unsigned char i, j; 92 93 i = 2; 94 j = 239; 95 do 96 { 97 while (--j); 98 } while (--i); 99 } 100 void timer0() interrupt 1 101 { 102 TMOD=0x01; 103 TH0=(65536-50000)/256; 104 TL0=(65536-50000)%256; 105 a++; 106 }
- 我们可以改变P0赋值的顺序,可以先赋值,再开启段选和位选
1 #include<reg51.h> 2 #include<intrins.h> 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 void Delay1ms(); 8 void delay(int n); 9 void display(uchar bai,uchar shi,uchar ge); 10 void init(); 11 sbit WEI=P2^7; 12 sbit DUAN=P2^6; 13 14 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; 15 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 无显示 16 17 uchar num=0,shi,ge,temp=0,bai,a=0; 18 void main() 19 { 20 init(); 21 bai=temp/100; 22 shi=temp/10%10; 23 ge=temp%10; 24 while(1) 25 { 26 if(a==20) 27 { 28 a=0; 29 temp++; 30 if(temp==101) 31 { 32 temp=0; 33 } 34 bai=temp/100; 35 shi=temp/10%10; 36 ge=temp%10; 37 } 38 display(bai,shi,ge); 39 } 40 } 41 42 void display(uchar bai,uchar shi,uchar ge) 43 { 44 P0=Table[bai]; 45 DUAN=1; 46 DUAN=0; 47 48 P0=0xfe; 49 WEI=1; 50 WEI=0; 51 delay(5); 52 53 P0=Table[shi]; 54 DUAN=1; 55 DUAN=0; 56 57 P0=0xfd; 58 WEI=1; 59 WEI=0; 60 delay(5); 61 62 P0=Table[ge]; 63 DUAN=1; 64 DUAN=0; 65 66 P0=0xfb; 67 WEI=1; 68 WEI=0; 69 delay(5); 70 } 71 void init() 72 { 73 TH0=(65536-50000)/256; 74 TL0=(65536-50000)%256; 75 EA=1; 76 ET0=1; 77 TR0=1; 78 } 79 void delay(int n) 80 { 81 while(n--) 82 { 83 Delay1ms(); 84 } 85 } 86 void Delay1ms() //@12.000MHz 87 { 88 unsigned char i, j; 89 90 i = 2; 91 j = 239; 92 do 93 { 94 while (--j); 95 } while (--i); 96 } 97 void timer0() interrupt 1 98 { 99 TMOD=0x01; 100 TH0=(65536-50000)/256; 101 TL0=(65536-50000)%256; 102 a++; 103 }
作业
评论(0)
您还未登录,请登录后发表或查看评论