0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

聊聊流水灯的写法

单片机技术宅 ? 来源:单片机技术宅 ? 作者:单片机技术宅 ? 2021-03-02 15:52 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

流水灯,学单片机时,编程第一课的内容,多少小伙伴的单片机之路都是从流水灯开始的。那有没有想过,我们能用几种方式来写流水灯,各有什么优缺点呢?今天小代就来聊聊流水灯的写法。

硬件介绍:小代采用自己画的STC15开发板,8位LED接P0口,阳极驱动,共阴连接方式,就这么多。

(实际测试时用的数码管模拟,昨天刚接了线,懒得再次重新接线,直接用数码管来代替LED,原理都一样,能验证就好)

1.初学者入门法

直接上代码看后再说

#include"STC15.h"#defineu8unsignedchar#defineu16unsignedintvoid delay_ms(u16x);//ms延时函数void main(){u8led=0x01;u8i=0;P0M1=0x00;//STC15单片机把IO设为推挽输出P0M0=0xff;P2M1=0x00;P2M0=0xff;P2=0xff;//数码管位选驱动,硬件介绍上已经说明原因while(1){//①初学者常见delay延时方式流水灯led=0x01;for(i=0;i<8;i++){????????????P0=led;????????????delay_ms(1000);????????????led=led<<1;????????}?????}??????//while(1)?结束}//main结束 //************************************//功能:ms延时函数?//参数:x--延时的时间长短,x=1000约为1s 24M晶振//作者:小代//微信关注:单片机技术宅//************************************void delay_ms(u16?x){????u16?i,j,k;????for(k=0;k

一看代码37行,太多了,仔细一看,注释和空行占据了一大半,这样一想就开心多了。这个代码没有更多需要解释的,采用最常见的,初学者最喜欢的方式,delay延时方式实现,下面聊优缺点。

优点:简单粗暴好理解,能看懂文字(字母)的都知道

缺点:代码执行效率太低,太低,太低

程序流程图如下图所示,CPU更多的时间是花在“等待1s”上,效率太低,单纯的这样演示流水灯,那这个程序没有任何问题,当在这个程序中再加入其它的程序,必然会出问题,第一流水灯会被执行慢了,第二,新加入的功能反应会很慢,特别是一些实时性有要求的代码。加到这里就会有问题了。为了解决这些问题,我们引出了第二种方式的流水灯。

2.记录主程序执行次数方式

还是先上代码再聊

#include "STC15.h"

#define u8 unsigned char

#define u16 unsigned int

//************************************

//功能:主函数入口 main

//参数:无

//作者:小代

//微信关注:单片机技术宅

//************************************

voidmain(){

u8 led=0x01;

u16main_cnt=0;

P0M1=0x00; //STC15单片机把IO设为推挽输出

P0M0=0xff;

P2M1=0x00;

P2M0=0xff;

P2=0xff; //数码管位选驱动,硬件介绍上已经说明原因

while(1){

//②主程序循环次数实现延时方式流水灯

main_cnt++; //主程序每运行一次,main_cnt将会被加1

//通过if语句实现内部代码块的运行速率降低

//只有主程序循环60000此后,if语句内的代码块才被执行一次

//如若需要更低的执行速率,可以采用两层变量嵌套计数

P0=led;

if(main_cnt>60000){

main_cnt=0; //次数记录清零,为下一次记录准备

if(led==0x80){

led=0x01;

}

else{

led=led<<1;

}

}

} //while(1) 结束

}

//main结束

还是40+行代码,还是注释+空行占据了一半左右。以上代码最大的特点就是没有之前执行效率很低的delay函数,也算是升级了吧。没了delay延时,那如何实现等待的呢?小代慢慢聊。

在while(1)循环里的第21行,只要主程序每运行一次,21行就会对变量main_cnt加1,这个变量定义为16位无符号类型,最大可以到65535,在此,小代记录60000此后就去点亮下一个流水灯的LED,显示效果比方法1的略快,以上注释也说了,如果单一变量记录次数没法满足需要的等待时间,可以采用两个变量嵌套记录的方式。

通过这种方式点亮LED灯,真正的点灯程序段只有在主程序运行60000后才会被运行到一次。仔细看主程序里面,其实就只有一条语句,那就是对main_cnt做加1处理,完了每次都去判断一下main_cnt有没有到60000了,到了后才去处理LED点灯。下面聊聊优缺点。

优点:程序简单,效率高

缺点:点灯的速度会随着主程序内循环语句的增多而降低。

也就是说如果主程序里增加了其他的运行语句,那这里控制点灯的记录次数值就不再是60000,需要减小,或者说60000得到的效果就会让流水灯变慢。程序流程图如下图

到这里,程序执行效率问题我们已经解决了,在这程序基础上加入其它代码后,各个功能还是能运行起来,但是还是有问题,流水灯的速度会改变,为解决这个问题,小代引出了第三种方法。

3.定时器实现

说到定时器,首先还得知道中断的原理,但是,中断和定时器,学单片机连这两个知识点都没学会,那怎好意思说你学过单片机。也就是说中断和定时器就像单片机驱动IO口一样的普通,一样的简单,不要想的多复杂。还是先上代码再聊。

#include "STC15.h"

#define u8 unsigned char

#define u16 unsigned int

voiddelay_ms(u16 x); //ms延时函数

voidTimer0Init(void); //2毫秒@24.000MHz

u16 timer0_cnt=0;

bit timer0_1s_flag=0;

//************************************

//功能:主函数入口 main

//参数:无

//作者:小代

//微信关注:单片机技术宅

//************************************

voidmain(){

u8 led=0x01;

u16main_cnt=0;

P0M1=0x00; //STC15单片机把IO设为推挽输出

P0M0=0xff;

P2M1=0x00;

P2M0=0xff;

P2=0xff; //数码管位选驱动

Timer0Init(); //定时器初始化

while(1){

//③通过定时器中断控制流水灯效果

//主程序里只做LED的驱动

//如果任务少,判断标志位置位都可以放到定时器中断里

//这里统一放到了主循环里

P0=led;

if(timer0_1s_flag==1){

timer0_1s_flag=0; //清除标志位

if(led==0x80){ //是否移动了8次

led=0x01;

}

else{

led=led<<1;

}

}

}//while(1) 结束

}

//main结束

//************************************

//功能:定时器初始化函数

//参数:无

//作者:小代

//微信关注:单片机技术宅

//************************************

voidTimer0Init(void) //2毫秒@24.000MHz

{

AUXR|=0x80; //定时器时钟1T模式

TMOD&=0xF0; //设置定时器模式

TL0=0x80; //设置定时初值

TH0=0x44; //设置定时初值

TF0=0; //清除TF0标志

TR0=1; //定时器0开始计时

ET0=1; //开中断

EA=1;

}

//************************************

//功能:Timer0中断函数 2ms中断一次

//参数:无

//作者:小代

//微信关注:单片机技术宅

//************************************

voidtimer0_int (void) interrupt 1 {

TF0=0;

timer0_cnt++;

if(timer0_cnt==500){

timer0_1s_flag=1;

timer0_cnt=0;

}

}

看到这,一看代码量暴增,一下子就是原来的两倍,其实更多的也还是注释,代码量是有所增加,因为用到了定时器和中断,需要对定时器进行初始化,完了还需要一个中断函数。在这个程序,定时T0每2ms中断一次,进入中断后,中断处理函数直接对timer0_cnt变量加1记录,当记录500次后,说明1s时间到,此时置位1s时间标志位timer0_1s_flag=1。在主程序,只做点灯和判断1s时间到来没有,当1s时间到来后,主程序就去处理LED的移位操作。

优点:效率极高,实时性好,时间稳定

缺点:非要说,那就是用到了定时器和中断,初学者会觉得难

通过这种方式实现流水灯,还可以在主程序中加入其它的代码,并不会影响到流水灯的运行。其实这只是一个最简单的模型,在复杂项目中同样可以用这模型,比如,1s点亮一个LED灯,1ms刷新一次数码管,10ms读取一次按键,500ms读取一次ADC的值等等。这样很多的功能都可以采用这样的模型来实现,并且各个功能之间是互不干扰的。

到此,今天的内容聊完了,其实第三种方式就是“状态机”或者“分时处理”等等一些比较高级的名称就是这么一回事。下次再听到这些高大上的名称时,一定要知道,这并不是什么高深的东西。更重要的是在以后的复杂项目中要会用这样的方式去处理各个功能之间的切换。

责任编辑:lq

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

    关注

    6068

    文章

    45037

    浏览量

    652429
  • 流水灯
    +关注

    关注

    21

    文章

    433

    浏览量

    60622
  • 代码
    +关注

    关注

    30

    文章

    4906

    浏览量

    71030

原文标题:你有几种方法写流水灯

文章出处:【微信号:chuxue_MCU,微信公众号:单片机技术宅】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    寻开发伙伴 一起搞细胞电阻仪,有兴趣的朋友来聊聊

    寻开发伙伴 一起搞细胞电阻仪,有兴趣的朋友来聊聊
    发表于 07-10 15:51

    【沁恒CH585开发板免费试用体验】GPIO 流水灯

    开发环境: IDE:MounRiver Studio MCU:CH585 1 GPIO工作原理 熟悉单片机的朋友都知道,学习的第一个例程就是流水灯,要想实现流水灯,首先必须了解GPIO的工作原理
    发表于 07-04 22:55

    水灯具好不好?水下灯具气密性检测仪测过才知道

    在现代照明领域,防水灯具的应用越来越广泛,无论是户外景观照明,还是水下特殊环境照明,都离不开防水灯具的支持。然而,防水灯具的气密性直接关系到其防水性能、使用寿命和安全性,水下灯具气密性检测仪则成为
    的头像 发表于 06-14 15:09 ?157次阅读
    防<b class='flag-5'>水灯</b>具好不好?水下灯具气密性检测仪测过才知道

    远程io模块在汽车流水线的应用

    在汽车制造领域,生产流水线的高效、稳定运行是保障产品质量与生产效率的关键。随着工业 4.0 和智能制造理念的深入,汽车生产企业对流水线自动化控制提出了更高要求,不仅要实现设备间的精准协同作业,还需
    的头像 发表于 06-11 15:26 ?286次阅读

    【RA-Eco-RA4M2开发板评测】点灯实现6种LED花式流水灯操作

    很高兴收到瑞萨电子提供的RA4M2开发板,这次帖子就专门用来说说专业点灯操作,实现各种花式的流水灯,可以十分方便地控制LED的各种状态,甚至多个LED组合控制,如跑马灯等。 打开原理图,可以看到3个
    发表于 04-28 21:28

    【RA-Eco-RA4M2开发板评测】使用串口通信实现花样流水灯操作

    串口使用USB串口吧,节省USB口线!!!!! 使用串口通信实现花样流水灯操作,本次测评通过使用串口助手发送数据来控制RA4M2的流水灯操作,总共有9中模式: (1)发送0,3个LED全灭 (2
    发表于 04-27 21:33

    【RA-Eco-RA4M2开发板评测】2 初识GPIO流水灯

    工作原理 熟悉单片机的朋友都知道,学习的第一个例程就是流水灯,要想实现流水灯,首先必须了解GPIO的工作原理。GPIO的基本结构如下图所示。 Figure ? GPIO的基本结构 和其他
    发表于 04-25 23:06

    #中国香河英茂科工#STC32G12K128#屠龙刀三.2 流水灯例程

    流水灯
    丙丁先生
    发布于 :2025年01月19日 14:19:35

    【正点原子STM32H7R3开发套件试用体验】流水灯

    【正点原子STM32H7R3开发套件试用体验】流水灯 本文介绍了使用 STM32CubeMX 辅助配置 GPIO 及晶振参数,实现流水灯的方法。 工程创建 1.打开 STM32CubeMX 软件
    发表于 12-28 18:51

    低成本单片机方案——触摸流水灯开关控制

    方案触摸流水灯控制方案Thedevelopmentofascheme随着物联网技术的不断发展和智能家居的普及,触摸流水灯控制方案作为一种新型的智能照明控制方式,逐渐成为市场的新宠。PART.1方案
    的头像 发表于 12-26 16:37 ?884次阅读
    低成本单片机方案——触摸<b class='flag-5'>流水灯</b>开关控制

    【RA-Eco-RA4E2-64PIN-V1.0开发板试用】MDK+点灯+流水灯

    ” 文件,在 hal_entry 函数里面编写我们的代码。 直接运行,灯会常亮 流水灯实验,延迟200ms
    发表于 12-15 15:59

    SMT流水线布局优化技巧

    在电子制造领域,SMT(表面贴装技术)流水线的布局优化对于提高生产效率、降低成本和提升产品质量至关重要。一个合理的流水线布局可以减少物料搬运时间,提高设备利用率,减少人为错误,并且提高整体的生产
    的头像 发表于 11-14 09:11 ?1190次阅读

    聊聊std::move函数和std::forward函数

    今天我们聊聊Modern cpp的两个非常重要的概念移动语义和转发引用。
    的头像 发表于 11-05 16:58 ?1133次阅读

    基于51单片机的跑马灯/流水灯系统

    具体实现功能(1)9种LED流水灯模式通过按键进行切换,数码管显示流水灯模式。(2)通过加减按键可以切换每种LED流水灯的速度。仿真演示视频:设计介绍51单片机简介51单片是一种低功耗、高性能
    的头像 发表于 10-22 14:12 ?750次阅读
    基于51单片机的跑马灯/<b class='flag-5'>流水灯</b>系统

    行云流水线 满足你对工作流编排的一切幻想~skr

    流水线模型 众所周知,DevOps流水线(DevOps pipeline)的本质是实现自动化工作流程,用于支持软件开发、测试和部署的连续集成、交付和部署(CI/CD)实践。它是DevOps方法论
    的头像 发表于 08-05 13:42 ?573次阅读