51单片机学习笔记(郭天祥版)(4)——练习、动态扫描、练习、数码管消影

  1.  让P1.0输出方波,周期为1s,那么就是高电平500ms,低电平500ms,这样P1.0的发光二极管就闪烁了,频率是周期的倒数,1s的倒数还是1,假设12MHz,其实电路板是11.0592MHz,只是为了计算方便。
  2. 让P1口的八个二极管流水灯,1秒钟10次。
  3. 第一个300ms输出频率为1KHz的方波,第二个300ms输出10KHz的方波,以此类推。(改变频率可以使其唱歌,这里是有源蜂鸣器,效果不好,无源的声音很清脆)
  4. 例题就是。

接下里一个练习,流水灯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了,所以以后永远不会变化了。

解决方法:

  1. 将n==40改为>=40,这里就不给代码了。
  2. 将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也是有值的。

接下来说一下消影的方法

  1. 我们可以在开启位选以前先让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 }

     

  2. 我们可以改变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 }

     


作业

 

posted @ 2019-03-30 23:03  裂缘冰释  阅读(1304)  评论(0编辑  收藏  举报