研究的第一个程序是流水灯。
这是代码
- #include<reg52.h> //包含单片机寄存器的头文件
- #define uchar unsigned char
- #define uint unsigned int
- /* 函数申明 -----------------------------------------------*/
- void delay(uint z);
- /*
- ********************************************************************************
- ** 函数名称 : main(void)
- ** 函数功能 : 主函数
- ********************************************************************************
- */
- void main()
- {
- uchar num,dat1,dat2;
- delay(500);
- P0=0;
- while(1)
- {
- dat1=0xfe;
- dat2=0x7f;
- for(num=0;num<7;num++)
- {
- P1=dat1; //初始化赋值
- dat1=dat1<<1; //右移一位
- delay(500); //延时
- }
- for(num=0;num<7;num++)
- {
- P1=dat2; //初始化赋值
- dat2=dat2>>1; //右移一位
- delay(500); //延时
- }
- }
- }
- /*
- ********************************************************************************
- ** 函数名称 : delay(uint z)
- ** 函数功能 : 延时函数
- ********************************************************************************
- */
- void delay(uint z)
- {
- uchar j;
- for(z;z>0;z--)
- for(j=200;j>0;j--);
- }
开始研究程序.(应该不会有版权问题吧...)
- #include<reg52.h> //包含单片机寄存器的头文件
这个头文件的里边定义了一些寄存器变量,跟reg51.h至少在P0,P1的定义上是一样的,其余的定义将来再研究.
接下来是两个宏定义:
- #define uchar unsigned char
-
#define uint unsigned int
这两个宏定义可以改用typedef:
- typedef unsigned char uchar;
- typedef unsigned int uint;
实际上对于这种情况我更习惯于使用typedef而不是宏.
两者在句法上的差异一目了然,在语义上也完全不同.
宏本质上是文本或者说符号替换.
而typedef则是定义了一个新的数据类型.可以参考
这里以助理解.
- /* 函数申明 -----------------------------------------------*/
- void delay(uint z);
- /*
顾名思义这是一个延迟函数的申明,这个函数的定义放到了main函数的下面,大多数情况下我也是这样处理函数的申明和定义的,这个没什么好特别讨论的,毕竟,原教旨主义者什么的最讨厌了。
函数的定义如下:
- /*
- ********************************************************************************
- ** 函数名称 : delay(uint z)
- ** 函数功能 : 延时函数
- ********************************************************************************
- */
- void delay(uint z)
- {
- uchar j;
- for(z;z>0;z--)
- for(j=200;j>0;j--);
- }
显然,这个延时函数是通过一个空循环来实现的。这里边出现了个数字200,所以到底延迟了多久就不要纠结了,总之通过让cpu空转实现了延迟,当然,如果可能的话,将来可以尝试用时钟中断来实现一个延迟函数。
接下来是主函数:
- void main()
- {
- uchar num,dat1,dat2;
- delay(500);
- P0=0;
- while(1)
- {
- dat1=0xfe;
- dat2=0x7f;
- for(num=0;num<7;num++)
- {
- P1=dat1; //初始化赋值
- dat1=dat1<<1; //右移一位
- delay(500); //延时
- }
- for(num=0;num<7;num++)
- {
- P1=dat2; //初始化赋值
- dat2=dat2>>1; //右移一位
- delay(500); //延时
- }
- }
- }
首先定义了三个uchar也就是unsigned char类型的变量,这里主要的是考虑变量的长度,也就是说这3个变量的长度都分别是1个字节,而不是说这三个变量将要存放的是字符。
然后是调用延迟函数:
如前所述,具体延迟了多少时间不知,当然根据芯片主频是可以推算出来的,不过这个并不重要,把这句注释掉也不影响下面程序的执行以及执行结果的正确性。
这一句实际上是为了避免开发板上的其他电路受到影响而加上的。具体怎么回事留到将来研究电路图的时候再说。
- while(1)
- {
- dat1=0xfe;
- dat2=0x7f;
- for(num=0;num<7;num++)
- {
- P1=dat1; //初始化赋值
- dat1=dat1<<1; //右移一位
- delay(500); //延时
- }
- for(num=0;num<7;num++)
- {
- P1=dat2; //初始化赋值
- dat2=dat2>>1; //右移一位
- delay(500); //延时
- }
- }
这是程序的主体部分,一个while死循环里边有两个for循环,这两个for循环分别迭代8次,因为程序控制的led正好是8个,并且这两个for循环分别控制了这8个led点亮的两种顺序。
0xfe也就是11111110,0x7f也就是01111111,这是用来控制p1的电平的。
看第一个for循环
- for(num=0;num<7;num++)
- {
- P1=dat1; //初始化赋值
- dat1=dat1<<1; //右移一位
- delay(500); //延时
- }
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) |