Chinaunix首页 | 论坛 | 博客
  • 博客访问: 262669
  • 博文数量: 42
  • 博客积分: 2415
  • 博客等级: 大尉
  • 技术积分: 590
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-13 14:14
文章分类

全部博文(42)

文章存档

2018年(1)

2017年(8)

2015年(3)

2012年(4)

2011年(11)

2010年(1)

2009年(5)

2008年(9)

我的朋友

分类: 嵌入式

2012-01-27 23:47:16

研究的第一个程序是流水灯。
这是代码

点击(此处)折叠或打开

  1. #include<reg52.h> //包含单片机寄存器的头文件

  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. /* 函数申明 -----------------------------------------------*/
  5. void delay(uint z);

  6. /*
  7. ********************************************************************************
  8. ** 函数名称 : main(void)
  9. ** 函数功能 : 主函数
  10. ********************************************************************************
  11. */
  12. void main()
  13. {
  14.     uchar num,dat1,dat2;
  15.     delay(500);
  16.     P0=0;
  17.     while(1)
  18.     {
  19.         dat1=0xfe;
  20.         dat2=0x7f;
  21.         for(num=0;num<7;num++)
  22.         {
  23.             P1=dat1;     //初始化赋值
  24.             dat1=dat1<<1; //右移一位
  25.             delay(500); //延时    
  26.         }
  27.         for(num=0;num<7;num++)
  28.         {
  29.             P1=dat2;     //初始化赋值
  30.             dat2=dat2>>1; //右移一位
  31.             delay(500); //延时    
  32.         }
  33.     }
  34. }

  35. /*
  36. ********************************************************************************
  37. ** 函数名称 : delay(uint z)
  38. ** 函数功能 : 延时函数
  39. ********************************************************************************
  40. */
  41. void delay(uint z)
  42. {
  43.     uchar j;
  44.     for(z;z>0;z--)
  45.         for(j=200;j>0;j--);
  46. }

开始研究程序.(应该不会有版权问题吧...)

  1. #include<reg52.h> //包含单片机寄存器的头文件
这个头文件的里边定义了一些寄存器变量,跟reg51.h至少在P0,P1的定义上是一样的,其余的定义将来再研究.

接下来是两个宏定义:
  1. #define uchar unsigned char
  2. #define uint unsigned int
这两个宏定义可以改用typedef:
  1. typedef    unsigned char uchar;
  2. typedef    unsigned int uint;
实际上对于这种情况我更习惯于使用typedef而不是宏.

两者在句法上的差异一目了然,在语义上也完全不同.
宏本质上是文本或者说符号替换.
而typedef则是定义了一个新的数据类型.可以参考这里以助理解.

点击(此处)折叠或打开

  1. /* 函数申明 -----------------------------------------------*/
  2. void delay(uint z);
  3. /*
顾名思义这是一个延迟函数的申明,这个函数的定义放到了main函数的下面,大多数情况下我也是这样处理函数的申明和定义的,这个没什么好特别讨论的,毕竟,原教旨主义者什么的最讨厌了。
函数的定义如下:

点击(此处)折叠或打开

  1. /*
  2. ********************************************************************************
  3. ** 函数名称 : delay(uint z)
  4. ** 函数功能 : 延时函数
  5. ********************************************************************************
  6. */
  7. void delay(uint z)
  8. {
  9.     uchar j;
  10.     for(z;z>0;z--)
  11.         for(j=200;j>0;j--);
  12. }
显然,这个延时函数是通过一个空循环来实现的。这里边出现了个数字200,所以到底延迟了多久就不要纠结了,总之通过让cpu空转实现了延迟,当然,如果可能的话,将来可以尝试用时钟中断来实现一个延迟函数。
接下来是主函数:

点击(此处)折叠或打开

  1. void main()
  2. {
  3.     uchar num,dat1,dat2;
  4.     delay(500);
  5.     P0=0;
  6.     while(1)
  7.     {
  8.         dat1=0xfe;
  9.         dat2=0x7f;
  10.         for(num=0;num<7;num++)
  11.         {
  12.             P1=dat1;     //初始化赋值
  13.             dat1=dat1<<1; //右移一位
  14.             delay(500); //延时    
  15.         }
  16.         for(num=0;num<7;num++)
  17.         {
  18.             P1=dat2;     //初始化赋值
  19.             dat2=dat2>>1; //右移一位
  20.             delay(500); //延时    
  21.         }
  22.     }
  23. }
首先定义了三个uchar也就是unsigned char类型的变量,这里主要的是考虑变量的长度,也就是说这3个变量的长度都分别是1个字节,而不是说这三个变量将要存放的是字符。
然后是调用延迟函数:

点击(此处)折叠或打开

  1. delay(500);
如前所述,具体延迟了多少时间不知,当然根据芯片主频是可以推算出来的,不过这个并不重要,把这句注释掉也不影响下面程序的执行以及执行结果的正确性。

点击(此处)折叠或打开

  1. P0=0;
这一句实际上是为了避免开发板上的其他电路受到影响而加上的。具体怎么回事留到将来研究电路图的时候再说。


点击(此处)折叠或打开

  1. while(1)
  2.     {
  3.         dat1=0xfe;
  4.         dat2=0x7f;
  5.         for(num=0;num<7;num++)
  6.         {
  7.             P1=dat1; //初始化赋值
  8.             dat1=dat1<<1; //右移一位
  9.             delay(500); //延时
  10.         }
  11.         for(num=0;num<7;num++)
  12.         {
  13.             P1=dat2; //初始化赋值
  14.             dat2=dat2>>1; //右移一位
  15.             delay(500); //延时
  16.         }
  17.     }
这是程序的主体部分,一个while死循环里边有两个for循环,这两个for循环分别迭代8次,因为程序控制的led正好是8个,并且这两个for循环分别控制了这8个led点亮的两种顺序。


点击(此处)折叠或打开

  1. dat1=0xfe;
  2. dat2=0x7f;
0xfe也就是11111110,0x7f也就是01111111,这是用来控制p1的电平的。
看第一个for循环

点击(此处)折叠或打开

  1. for(num=0;num<7;num++)
  2.         {
  3.             P1=dat1; //初始化赋值
  4.             dat1=dat1<<1; //右移一位
  5.             delay(500); //延时
  6.         }
P1=dat1;
表示给P1各引脚上的初始电平,除了P1.0是低电平,其余各脚均为高电平。
dat1=dat1<<1;
当然,这里注释写错了,应该是左移一位。左移的结果是各脚依次变为低电平。
执行的结果就是当引脚为低电平时对应的led亮。
第二个循环是类似的,就不多说了。
这个程序就是演示通过控制引脚的电平来控制led的亮灭,而控制引脚电平则是通过给P1这个变量赋值来实现的,所以通过不同的值,可以控制led亮灭的顺序。
比方说,把while循环改成这样:

点击(此处)折叠或打开

    while(1)
    {
        dat1=0xff;
        dat2=0xff;
        for(num=0;num<7;num++)
        {
            P1=dat1^dat2;
                  //初始化赋值
            dat1=dat1<<1; //左移一位
            dat2=dat2>>1; //右移一位
            delay(500);   //延时    
        }
     }

那么执行结果会如何呢?
并且实际上如果dat1或者dat2定义为char而不是unsigned char,结果也有可能会不一样的,就不多说了。







阅读(1174) | 评论(0) | 转发(0) |
0

上一篇:单片机之路-2

下一篇:swift笔记-Functions

给主人留下些什么吧!~~