基于单片机的流水灯电路设计

描述

前面一课掌握了嵌入式程序源代码级调试,为复杂单片机实验程序的调试做好了准备工作。本次实验完成流水灯电路模型设计和编程,在实验过程中,学习流水灯电路设计、编写延迟函数、循环移位宏定义。

流水灯电路设计

本次实验设计要求通过单片机P0口实现流水灯控制电路,P0口8个端口外接8个LED,每个LED串联一个200欧姆的限流电阻,8个限流电阻的公共端接5V直流电源。电路设计如下图所示:

流水灯

8个LED正极端通过串联电阻接5V直流电源,负极端接P0端口,只要给P0端口一个低电平,就可以点亮LED,若需要熄灭LED,需要给P0端口一个高电平,要实现LED流水灯功能,只要将8个LED依次点亮、熄灭即可。

编写时间延迟函数

流水灯电路要求LED依次点亮,每个LED要持续亮一段时间后熄灭。用程序来控制LED的点亮和熄灭,只需要将与LED连接的端口写入低电平或高电平即可,代码如下:

#include
void main()
{
       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次循环。

// 时间延迟函数
void delay(unsigned int millisecond)
{
       unsigned int i,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。

流水灯算法实现代码如下:

void main()
{
    unsigned char value=0xfe,a,b;
       unsigned char count = 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
#define ROTATE_LEFT(x) ((x) < < 1) | ((x) > > 7 )
void delay(unsigned int millisecond)
{
       unsigned int i,j;
       for(i=millisecond;i >0;i--)
              for(j=120;j >0;j--);
}
void main()
{
    unsigned char value=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口循环输出高电平和低电平。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分