LabVIEW编程实例:趣味流水灯程序设计
很多小伙伴在学单片机的时候,不管是用汇编也好,还是用C语言也好,都写过各种各样的流水灯小程序,当一排LED灯按你的设计循环亮起的时候,是不是非常有成就感呢?
那么我们思考下,在LabVIEW平台上,是否也可以编程实现一个纯软件版的流水灯演示小程序呢?答案是肯定的,下面看看怎么做吧。
示例说明
先看下完成后的软件界面运行图,如下所示:
这个流水灯小程序共包括了8个小灯,其主要功能包括:
可设置每个小灯初始的亮灭状态;可设置流水灯的移动方向;可设置流水灯每次向左或向右移动的位数;可设置流水灯移动的速度;可控制流水灯的开始/暂停状态。在LabVIEW中编程实现这么多功能是不是很难啊?其实还是比较简单的,下面看看怎么实现吧。
文末最后有动态图演示哦,不要错过。
代码实现
代码实现主要关键点:
主要程序结构:使用while循环结构+事件结构+移位寄存器,在事件结构的超时事件中完成流水灯状态的显示,在移位寄存器中存储上次流水灯状态对应的数值;主要功能函数:布尔数组(流水灯数组的值)与数值(需要移位的值)之间的转换函数,循环移位函数;为简化程序代码的设计,将前面板上所有的流水灯控件放到一个U8类型的一维数组控件中。其中,超时事件代码框图如下图所示:
这是这个程序功能实现的主要代码,在超时事件中,通过移位寄存器中读取上次流水灯状态对应的数值,然后根据前面板上的控件设置决定流水灯是否移动、左移或右移及移动的位数,其关键函数是循环移位函数,该函数参数接口意义如下,通过给定y值的正负号控件其左移或右移:
当在前面板上改变流水灯初始值状态时,需重新给移位寄存器赋初值,其代码如下:
在前面板上点击退出程序按钮时,在事件结构的值改变事件中退出程序的运行,代码如下:
至此,程序的主要代码实现就完成了。
总结
可能大家会想,如果一开始让你在LabVIEW中实现一个这么花哨的多种控制功能的流水灯小程序,你可能会觉得这太难了,甚至无从下手,实际上,通过上面的实现代码可看出程序也并不是太难,关键是要熟悉如事件结构、移位寄存器、循环移位及布尔数组与数值之间的转换等几个小知识点,把任务分解清楚,花不了几分钟也就可以做出来了。
好了,大家照着这个例子做一遍吧,如果还做不出来的话,大家可以加关注并私信回复:LabVIEW065 ,可获取该文章对应的LabVIEW原程序下载。
最后再看下这个小例子的动态运行效果图吧:
本文由编码那些事原创,请关注+转发+收藏+点赞,带你一起长知识!
基于51的流水灯程序
大家好,通过前面几节的介绍相信大家对单片机的开发流程操作和软件的编写有了大致的了解和认识,下面这节的主要内容是以51单片机和keil开发环境为平台真正的去开发一个小的项目,以最简单的LED流水灯为例。
LED流水灯的开发在51单片机中再常见不过了,主要是让大家掌握IO的操作是单片机控制最基本的要求。根据开发流程,我们先查看选型的单片机的资源和控制寄存器,然后在软件上实现控制。
在这里芯片我们采用STC15W404AS作为开发的硬件平台,在这里我们用该单片机的P1引脚来驱动LED实现流水灯的功能。
如图是LED连接的硬件电路,可以看到8颗LED是阳极通过限流电阻共同连接到VCC上的,也就是说当LED的阴极有高电平的时候LED灯是灭的,相反当LED的阴极是低电平的时候LED就会亮起来,并且由于限流电阻为510欧姆,电源VCC电压是5V,红光LED的电压在1.9V左右,因此LED在亮起来的时候大概有6mA的电流。有了上面的参数我们可以有目的的去看单片机的手册了。
从手册中可以看到,P1口可以设置成I/O(输入输出)模式,输入模式以及输出模式,并且每种模式的下能够承受的电流大小也不相同,在这里根据我们的电路连接方式可以看到我们需要的是输入的模式,并且输入的电流最大在3mA左右,因此根据说手册上的说明,我们将P1口设置成准双向口就可以,当然如果想用单片机端口来作为LED电流源驱动的话那就设置成推挽输出就可以。因此我们将P1端口的控制寄存器P1M1和P1M0相应的位(对应端口)设置成0即可,也就是P1M1=0x00;P1M0=0x00;
将P1的控制位设置好后,我们就可以通过P1的直接赋值来控制LED的亮和灭了,其对应关系是:P1=~0x01,第一颗亮;~0x02第二颗亮……由此,我们可以有很多种方法来实现流水的功能。
1.数组的方法
由前面的结果类推我们可以制作一个表{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}这样我们只要选择这个表格中的一位数然后取反赋值给P1就能控制相应的灯的亮灭,因此我们把这个表格做成一个数组然后进行循环来实现LED的流水功能。其程序如下:
#include<stc15.h>
unsigned char code LED[]={0x01,0x02,0x04,0x08,0x10,0x20};
void delay()
{
unsigned int i;
for(i=0;i<500;i++);
}
void IO_Config()
{
P1M0=0x00;//设置P1端口的类型
P1M1=0x00;//可以根据不同的电路来修改
}
void main()
{
unsigned char j;
IO_Config();
while(1)
{
for(j=0;j<=5;j++)
{
P1=~LED[j];
delay();
}
}
}
复制代码
由于我们选择的这款芯片P1引脚只有6个(P1.0~P1.5)所以我们只设置了6个值,对于8个的也使用只需要将数组拓展到8位即可,编译后可以通过下载到单片机调试即可,下图为测试的结果:
2.移位的方法
在C语言中我们有个<<(右移)和>>(左移)功能,这也在单片机中常用到,值得注意的是,当数据移动后会用0来填补,这点要非常注意,因此上面的程序可以简化为下面的结构:
#include<stc15.h>
//unsigned char code LED[]={0x01,0x02,0x04,0x08,0x10,0x20};
void delay()
{
unsigned int i;
for(i=0;i<500;i++);
}
void IO_Config()
{
P1M0=0x00;//设置P1端口的类型
P1M1=0x00;//可以根据不同的电路来修改
}
void main()
{
unsigned char j,temp;
IO_Config();
while(1)
{
temp=0xfe;
for(j=0;j<=5;j++)
{
//P1=~LED[j];
P1=temp;
temp=(temp<<1)|0x01;//左移以后要用1来补齐
delay();
}
}
}
复制代码
同样将改程序编译后生成HEX文件烧写到单片机内然后就可以调试了,生成的波形如下:
3.循环移位法
从上面可以看到用C语言的移位的方法移动后都自动会用0来填补,这样我们必须在后面通过或的方法来补齐原来的数据,我们知道在汇编语言中有RR和RL(rotate right和rotateleft)的移位方法,这种以为的好处是从移动过程中数据是圆形的移位,这样不需要填补就可以,但是这个以为的方法只是对ACC进行移位的。那么我们要实现这个函数怎么办呢,第一种方法就是在C语言中嵌入汇编通过# pragma asm和# pragma endasm来实现嵌入汇编,格式如下:
……
#pragma asm
RL A
……
#pragma end asm
……
当然在这里这不是我们要讲的重点,我们要说的是第二种方法,那么我们是不是能够编写一个和RL,RR功能一样的函数呢?其实完全没有必要,这些函数都在intrins头文件中,根据前面几章介绍的知识,我们只需要在文件中加入这个头文件就可以用了,那么这个函数是怎么个形式呢?我们就看看这个函数吧。
externvoid _nop_ (void);
externbit _testbit_ (bit);
externunsigned char _cror_ (unsigned char,unsigned char);
externunsigned int _iror_ (unsigned int, unsigned char);
externunsigned long _lror_ (unsigned long,unsigned char);
externunsigned char _crol_ (unsigned char,unsigned char);
externunsigned int _irol_ (unsigned int, unsigned char);
externunsigned long _lrol_ (unsigned long,unsigned char);
externunsigned char _chkfloat_(float);
externvoid _push_ (unsigned char _sfr);
externvoid _pop_ (unsigned char _sfr);
以上界函数是在intrins头文件中的函数,这些函数的源码keil封装了起来,只能看到函数的接口,其具体用法在我的附件中有说明,在这里我们需要的就是_crol_字符循环左移的指令,这个函数有两个入口参数分别是要移动的数据和移动的位数着这里我们移动的数据是0xfe,移动的位数为j(和所在的位有关)位,因此我们可以将上面的程序改写:
#include<stc15.h>
#include<intrins.h>
//unsigned char code LED[]={0x01,0x02,0x04,0x08,0x10,0x20};
void delay()
{
unsigned int i;
for(i=0;i<500;i++);
}
void IO_Config()
{
P1M0=0x00;//设置P1端口的类型
P1M1=0x00;//可以根据不同的电路来修改
}
void main()
{
unsigned char j;
IO_Config();
while(1)
{
for(j=0;j<=5;j++)
{
//P1=~LED[j];//第一种方法
//P1=temp; //第二种方法
//temp=(temp<<1)|0x01;//左移以后要用1来补齐
P1=_crol_(0xfe,j);//第三种方法
delay();
}
}
}
复制代码
测试的结果如下:
可以看到其时序和前面的都一样。
最后总结一下,在这个小设计的开发过程中我们主要根据前面的开发流程加深了对单片机的开发,首先设计硬件电路根据硬件电路来将参数提取出来,再根据所选单片机手册来选择相应的功能,最后根据要求来编写程序,再编程过程中善于利用已经编写好的源码来是实现自己的功能,如果现成的源码不能满足自己的要求就根据自己的需求来编写相应的程序。
相关问答
单片机 用 汇编 语言编写一个。用十个按钮分别控制十个灯。比如:按下按钮K1 LED1灯亮。按下"?检测是否有按键按下,相应的指示灯点亮,并熄灭其它的指示灯。至于10S锁住其他按钮,如果程序不做其它的事情,最简单的方法就是点亮指示灯后延时10S,再回到主函...
8051 单片机 用 汇编程序 让八个LED灯每隔一秒亮一个,轮流亮(加说明啊,谢谢了)?设个定时器。然后一个端口,赋值1(高电平亮),如果低电平就赋值11111110b然后每隔一秒给它做个移位。不就完了。设个定时器。然后一个端口,赋值1(高电平亮),...
单片机 初学者问题 汇编 语言编制一个循环闪烁的?;八个LED接在P1,低电平发光。ORG0000HMOVA,#7FH;A=01111111,有一个低电平LOP1:MOVR2,#10LOP2:MOVP1,A;输出一个低...
求51 单片机汇编 语言,要求P1口LED灯闪烁,并且P2口接1个数码管自动计数并且P3.2按键计数,求答案啊?ORG0000HLJMPMAINORG0003HLJMPEX0INTORG0030HMAIN:MOVSP,#5FHSETBIT0SETBEX0SETBEAMOV...
单片机 怎么实现一个开关控制八个灯按一下亮一个按八下八个灯都亮 汇编 语言 程序 ?一个开关控制八个灯;按一下亮一个;按八下八个灯都亮;按键接在P1.0;八个灯在P0,低电平灯亮KEYEQUP1.0ORG0000HMOVA,#11111111BWAIT:MOV......
单片机 , 程序 ORG 0000H LJMP MAIN?ORG是汇编器的伪指令,是告知编译器下一条语句的存放地址(偏移值)。ORG0800H即告知编译器下一条语句(MAIN:MOVR0,#20H)的存放地址是0800H。ORG语句的作...
单片机 C51的 汇编语言 编程pragma只是用于之间潜入asm代码,不是变了相的混合编程技术,它不能直接调用其他文件(注意是文件)中的函数。真正意义上的多模块编程,每个模块之间都...
湖南软件职业学院开发过什么有名的软件? - 红网问答新浪Sina,包括iask.sina.com也是软件。还有小部分软件是个人开发的,有些人是兴趣,做个软件给大家使用,也的有是为了盈利,你可以上一些程序员经常上...
单片机 是89c51采用定时器T0的方式1的定时中断方式初始状态...[最佳回答]是要汇编呀,早不说,做了C的.
单片机 定时器应用实验用80C51内部定时器1,按方式1工作,即作...[最佳回答]完全一样的题目呀,真幸运,看我的吧(我的是8052的,没关系的):汇编程序:S1EQU30HS2EQU31HORG0000HAJMPMAIN&nb...完全一...