• 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 }

    作业

  • 相关阅读:
    Python之推导式笔记
    利用ShardingSphere-JDBC实现分库分表--配置中心的实现
    利用ShardingSphere-JDBC实现分库分表
    MGR安装记录
    学习RadonDB源码(三)
    学习RadonDB源码(二)
    学习RadonDB源码(一)
    Spring Cloud学习笔记--Spring Boot初次搭建
    一次单核CPU占用过高问题的处理
    MySQL AutoCommit带来的问题
  • 原文地址:https://www.cnblogs.com/IceHowe/p/10629667.html
Copyright © 2020-2023  润新知