前面一课掌握了嵌入式程序源代码级调试,为复杂单片机实验程序的调试做好了准备工作。本次实验完成流水灯电路模型设计和编程,在实验过程中,学习流水灯电路设计、编写延迟函数、循环移位宏定义。
本次实验设计要求通过单片机P0口实现流水灯控制电路,P0口8个端口外接8个LED,每个LED串联一个200欧姆的限流电阻,8个限流电阻的公共端接5V直流电源。电路设计如下图所示:
8个LED正极端通过串联电阻接5V直流电源,负极端接P0端口,只要给P0端口一个低电平,就可以点亮LED,若需要熄灭LED,需要给P0端口一个高电平,要实现LED流水灯功能,只要将8个LED依次点亮、熄灭即可。
流水灯电路要求LED依次点亮,每个LED要持续亮一段时间后熄灭。用程序来控制LED的点亮和熄灭,只需要将与LED连接的端口写入低电平或高电平即可,代码如下:
#includevoidmain() {P0= 0xFF;P0= 0xFD; }
上述代码第1条语句将P0第0位写入低电平,与第0位连接的lED被点亮,第2条语句将第0位写入高电平,与第0位连接的lED熄灭。两条语句连续执行,每条语句的执行时间非常短,也就十几微秒,LED点亮后很快被熄灭,人们通过眼睛感觉不到LED被点亮。因此需要在第1条语句和第2条语句之间进行时间延迟,延迟一段时间后再执行第2条语句。
如何用软件来模拟延时时间呢?在设计的电路模型中,51单片机的时钟频率是12MHZ,一个时钟周期约0.08微秒,一个机器周期由12个时钟周期构成,一个机器周期约1微秒,51单片机执行一个指令的时间是机器周期的倍数,若使用for循环语句来实现时间延迟,一条基本的for循环语句执行时间大约为8微秒,若延迟500毫秒,大约需要执行500*120次循环。
// 时间延迟函数voiddelay(unsignedintmillisecond){unsignedinti,j;for(i=millisecond;i >0;i--)for(j=120;j >0;j--); }
delay()函数延迟millisecond毫秒,函数使用for嵌套循环,外层for循环用于控制延迟的毫秒数,内层for循环用于控制1毫秒执行的语句次数。
流水灯需要在每个时间间隔内只有一个LED点亮,其余LED均为熄灭状态,流水灯可以通过循环左移实现。循环左移是将操作数的二进制位按1位进行循环左移,移出的位并不会丢失,而是被后续移动的位填充。
P0默认值为0xFE,P0第0位的LED被点亮,其它位熄灭;延迟一段时间后,P0循环左移1位,其值为0xFD,P0第1位LED被点亮,其它位熄灭;延迟一段时间后,P0循环左移1位,其值为0xFB,P0第2位LED被点亮,其它位熄灭;以此类推,P0不断循环左移1位,从而实现了流水灯控制。
C语言并没有提供循环左移或循环右移的运算功能,需要开发者自己编程实现。
循环左移位的具体算法如上图所示:value为操作数,其值为0xFE,先将value左移1位,赋值给变量a,其值为0xFC,然后将value右移7位,赋值给变量b,其值为0X1,最后计算a|b,计算结果为value循环左移1位,并将计算结果赋值为value。
流水灯算法实现代码如下:
voidmain() { unsignedcharvalue=0xfe,a,b; unsignedcharcount=0;while(1) { P0 = value; delay(5000); a = value < <1; b = value > >7; value = a | b;count+=1;if(count>=8) { value =0xfe;count=0; } } }
算法通过while循环实现流水灯控制,在循环内部,变量value赋值给P0,点亮第0位的LED,其它位的LED为熄灭状态,然后调用delay()函数延迟5000毫秒,value循环左移1位,在下轮循环中,点亮第1位的LED,其它位的LED为熄灭状态,以此类推……。
count为计数变量,当流水灯循环点亮一次后,将value重新赋值为0xFE,并将conunt清零。
考虑到循环移位是经常使用的操作,可以将循环左移位操作定义为宏,在代码中直接调用宏就可以了。
循环左移位的宏定义:
#define ROTATE_LEFT(x) ((x) << 1) | ((x) >> 7 )
完整C程序代码如下:
#include#defineROTATE_LEFT(x) ((x)< < 1) | ((x) >> 7 )voiddelay(unsignedintmillisecond){unsignedinti,j;for(i=millisecond;i >0;i--)for(j=120;j >0;j--); }voidmain(){unsignedcharvalue=0xfe,count=0;while(1) { P0 = value;delay(5000); value =ROTATE_LEFT(value); count +=1;if( count >=8) { value =0xfe; count =0; } } }
通过这次实验,掌握了流水灯的电路模型设计和编程,流水灯电路模型比较简单,单片机通过I/O口的8个端口来控制8个LED的点亮和熄灭。流水灯的控制通过编程实现,编程主要涉及到时间延迟函数和循环左移位宏定义,时间延迟函数用于控制间LED点亮和熄灭的隔时间,循环左移位用于控制I/O口循环输出高电平和低电平。
全部0条评论
快来发表一下你的评论吧 !