原文链接:delay()延时实现LED灯的闪烁。

文章目录

  • 原文
  • 读后感
  • 自我练习

原文

第二节:delay()延时实现LED灯的闪烁。

开场白:
上一节鸿哥列出了初学者七大误区,到底什么才是初学者关注的核心?那就是裸机奔跑的程序结构。一个好的程序结构,本身就是一个微型的多任务操作系统。鸿哥教给大家的就是如何编写这个简单的操作系统。在main函数循环中用switch语句实现多任务并行处理的任务切换,再外加一个定时器中断,这两者的结合就是鸿哥多年来所有实战项目的核心。鸿哥的程序结构看似简单,实际上就是那么简单。大家不用着急,本篇连载文章现在才正式开始,这一节我要教会大家两个知识点:
第一点:鸿哥首次提出的“三区一线”理论。此理论把程序代码分成三个区,一个延时分割线。
第二点:delay()延时的用途。

(1)硬件平台:基于朱兆祺51单片机学习板。

(2)实现功能:让一个LED闪烁。

(3)源代码讲解如下:

#include "REG52.H"void initial_myself();
void initial_peripheral();void delay_short(unsigned int uiDelayshort);
void delay_long(unsigned int uiDelaylong);
void led_flicker();/* 注释一:
* 吴坚鸿个人的命名风格:凡是输出后缀都是_dr,凡是输入后缀都是_sr。
* dr代表drive驱动,sr代表sensor感应器
*/
sbit led_dr=P3^5;  void main()  //学习要点:深刻理解鸿哥首次提出的三区一线理论{/* 注释二:
* initial_myself()函数属于鸿哥三区一线理论的第一区,
* 专门用来初始化单片机自己的寄存器以及个别外围要求响应速度快的输出设备,
* 防止刚上电之后,由于输出IO口电平状态不确定而导致外围设备误动作,
* 比如继电器的误动作等等。
*/initial_myself();/* 注释三:
* 此处的delay_long()延时函数属于第一区与第二区的分割线,
* 延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定。
* 比如液晶模块,AT24C02存储芯片,DS1302时钟芯片,
* 这类芯片有个特点,一般都是跟单片机进行串口或并口通讯的,
* 并且不要求上电立即处理的。
*/delay_long(100);/* 注释四:
* initial_peripheral()函数属于鸿哥三区一线理论的第二区,
* 专门用来初始化不要求上电立即处理的外围芯片和模块.
* 比如液晶模块,AT24C02存储芯片,DS1302时钟芯片。
* 本程序基于朱兆祺51单片机学习板。
*/initial_peripheral();/* 注释五:
* while(1){}主函数循环区属于鸿哥三区一线理论的第三区,
* 专门用来编写被循环扫描到的非中断应用程序
*/while(1){led_flicker();   //LED闪烁应用程序}}void led_flicker() //LED闪烁应用程序
{led_dr=1;  //LED亮delay_short(50000);  //延时50000个空指令的时间/* 注释六:
* delay_long(100)延时50000个空指令的时间,因为内嵌了一个500次的for循环
*/led_dr=0;  //LED灭delay_long(100);    //延时50000个空指令的时间
}/* 注释七:
* delay_short(unsigned int uiDelayShort)是小延时函数,
* 专门用在时序驱动的小延时,一般uiDelayShort的数值取10左右,
* 最大一般也不超过100.本例为了解释此函数的特点,取值范围超过100。
* 此函数的特点是时间的细分度高,延时时间不宜过长。uiDelayShort数值
* 的大小就代表里面执行了多少条空指令的时间。数值越大,延时越长。
* 时间精度不要刻意去计算,感觉差不多就行。
*/
void delay_short(unsigned int uiDelayShort)
{unsigned int i;  for(i=0;i<uiDelayShort;i++){;   //一个分号相当于执行一条空语句}
}/* 注释八:
* delay_long(unsigned int uiDelayLong)是大延时函数,
* 专门用在上电初始化的大延时,
* 此函数的特点是能实现比较长时间的延时,细分度取决于内嵌for循环的次数,
* uiDelayLong的数值的大小就代表里面执行了多少次500条空指令的时间。
* 数值越大,延时越长。时间精度不要刻意去计算,感觉差不多就行。
*/
void delay_long(unsigned int uiDelayLong)
{unsigned int i;unsigned int j;for(i=0;i<uiDelayLong;i++){for(j=0;j<500;j++)  //内嵌循环的空指令数量{; //一个分号相当于执行一条空语句}}
}void initial_myself()  //初始化单片机
{led_dr=0;  //LED灭
}
void initial_peripheral() //初始化外围
{;   //本例为空
}

总结陈词:
鸿哥首次提出的“三区一线”理论概况了各种项目程序的基本分区。我后续的程序就按此分区编写。
Delay()函数的长延时适用在上电初始化。
Delay()函数的短延时适用在驱动时序的脉冲延时,此时的时间不能太长,本例中暂时没有列出这方面的例子,在后面的章节中会提到。
在本例源代码中,在led_flicker()闪烁应用程序里用到的两个延时delay,它们的延时时间都太长了,在实战项目中肯定不能用这种延时,因为消耗的时间太长了,其它任务根本没有机会执行。那怎么办呢?我们应该如何改善?欲知详情,请听下回分解-----累计主循环次数使LED灯闪烁。【帖子原文】

读后感

吴老师在这篇文章提到了他的编程风格,说到编程风格,我不禁开始头疼,那么多种,那么多种说法,到底那个才是好的,后来仔细想了想,既然大家各执一词,我何不另辟蹊径,按照自己的想法,随便编造一种(当然,这要求有一定的看他人代码经验),不过还是要按常理出牌。比如函数名,有人喜欢驼峰式的,如LedOn();或者全小写,但用下划线分开,如led_on();我一直以来的风格是首字母大写、带下划线,如Led_On()。变量(普通、全局、函数参数等)我的风格总是不固定,不过大多情况下是全小写,多单词就用下划线分隔,如led_flag,但是看完吴老师的文章,我打算以后在写单片机程序时换种风格:如果类型为u32(unsigned int)时,就以u32开头,如u32_i,u32_led_flag,如果类型时u16(unsinged short),就以u16开头,如u16_cnt,u8的话,就u8_data;其他常规类型,float,double这些就不加类型前缀了;指针的话,就无论类型,都以p开头,如p_dev_addr;结构体、枚举这类自创类型,就以st或e开头,如st_tmp、e_tmp。宏定义的常量,我觉得用全大写比较合适,比如LED_OFF,这也是普遍风格。

回到吴老师的文章内容,他提到了他定义的三区一线理论,第一区:initial_myself(),用来初始化单片机寄存器和外围高速设备,继电器初始电平、LED默认状态、蜂鸣器默认电平等,先初始化它们是为了防止刚上电之后,由于输出IO口电平状态不确定而导致外围设备误动作;第二区:initial_peripheral(),用来初始化不要求上电立即处理的外围芯片和模块,液晶模块,AT24C02存储芯片,DS1302时钟芯片,这些都是通过串口或并口和单片机通信的外设;第三区:while(1){}主函数循环区属于第三区,专门用来编写被循环扫描到的非中断应用程序。一线:delay_long()延时函数属于第一区与第二区的分割线,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定。这个框架还是不错的,我看一些人写的代码和这个差不多,但是很少看到第一区和第二区的延时分割线。

自我练习

参照吴老师代码自己再写一遍,加深印象。
代码:

#include "REG52.h"/******************************************************************************* 重定义*****************************************************************************/
typedef unsigned int u16;     //51单片机int长度为2Bytes
typedef unsigned char u8;/******************************************************************************* 函数声明*****************************************************************************/
void System_Init(); //系统初始化——第一区
void User_Init();   //用户初始化——第二区void Delay_Short(u16 u16_delay_short);  //短延时
void Delay_Long(u16 u16_delay_long);    //长延时void Led_Fliker();  //LED闪烁/******************************************************************************* 全局变量*****************************************************************************/sbit led_out = P3^5;   //LED输出IO/******************************************************************************* @ 函数名  : main* @ 功  能  : 主函数* @ 参  数  : 无* @ 返回值  : 无*****************************************************************************/
int main()
{System_Init();    //系统及高速外设初始化——第一区Delay_Long(100);  //延时0.3-2秒——第一区与第二区分隔线User_Init();      //用户模块初始化/低速外设——第二区while(1)          //while循环——第三区{Led_Fliker();  //LED闪烁程序}}/******************************************************************************* @ 函数名  : Led_Fliker* @ 功  能  : LED闪烁程序* @ 参  数  : 无* @ 返回值  : 无*****************************************************************************/
void Led_Fliker()
{led_out = 1;        //LED亮Delay_Short(50000); //延时50000个空指令的时间led_out = 0;        //LED灭Delay_Long(100);    //延时50000个空指令的时间,函数内嵌500次for循环
}/******************************************************************************* @ 函数名  : Delay_Short* @ 功  能  : 短延时* @ 参  数  : u16_delay_short  延时参数* @ 返回值  : 无*****************************************************************************/
void Delay_Short(u16 u16_delay_short)
{u16 u16_i = 0;for(u16_i = 0; u16_i < u16_delay_short; u16_i ++){;      //空语句}
}/******************************************************************************* @ 函数名  : Delay_Long* @ 功  能  : 长延时* @ 参  数  : u16_delay_long  延时参数* @ 返回值  : 无*****************************************************************************/
void Delay_Long(u16 u16_delay_long)
{u16 u16_i = 0;u16 u16_j = 0;for(u16_i = 0; u16_i < u16_delay_long; u16_i ++){for(u16_j = 0; u16_j < 500; u16_j ++){;      //空语句} }
}/******************************************************************************* @ 函数名  : System_Init* @ 功  能  : 系统外设初始化* @ 参  数  : 无* @ 返回值  : 无*****************************************************************************/
void System_Init()
{led_out = 0;    //LED灭
}/******************************************************************************* @ 函数名  : User_Init* @ 功  能  : 用户低速外设初始化* @ 参  数  : 无* @ 返回值  : 无*****************************************************************************/
void User_Init()
{;    //无
}

Proteus仿真:

使用Keil调试,Delay_Long(100)耗时大约0.15s。

跟着吴坚鸿学单片机——第2天:delay()延时实现LED灯的闪烁相关推荐

  1. 跟着吴坚鸿学单片机——第1天:吴坚鸿谈初学单片机的误区

    原文链接:第一节:吴坚鸿谈初学单片机的误区. 文章目录 原文 读后感 原文 第一节:吴坚鸿谈初学单片机的误区. (1)很难记住繁杂的寄存器?寄存器不用死记硬背,鸿哥我行走江湖多年,连一个寄存器都记不住 ...

  2. 跟着吴坚鸿学单片机——第16天:矩阵键盘的组合按键触发

    原文链接:第十六节:矩阵键盘的组合按键触发. 文章目录 原文 读后感 自我练习 原文 第十六节:矩阵键盘的组合按键触发. 开场白: 上一节讲了矩阵键盘单个触发的压缩代码编程.这节讲矩阵键盘的组合按键触 ...

  3. Holtek合泰单片机 《四》 从TM定时器中断到led灯1s闪烁

    跳过中断直接讲TM中断是不是有些超前了? 由于最近参加了一个项目,真是忙的不要不要的,没办法,只有抽了点放假的时间来更新下自己的博文,希望对正在学习HT单片机的同学有帮助. 重庆合泰初赛是5月15日, ...

  4. 51单片机手把手教学(二)—— 点亮 LED 灯(GPIO 操作)

    本文章 来自原创专栏<51单片机手把手教学>,讲解如何使用 Keil uVision 构建 51单片机 程序,发布文章并 会持续为已发布文章添加新内容! 每篇文章都经过了精打细磨! ↓↓↓ ...

  5. AVR单片机期末自选2 4x4薄膜开关控制led灯

    AVR单片机期末自选2 4x4薄膜开关控制led灯 具体内容 :AVR单片机 ATmega16 PD接跑马灯 PB接软膜 功能 按1第一个亮 再按就灭 按2第二个亮 再按就灭 -- 按8第八个亮 再按 ...

  6. c51单片机led奇数偶数亮_单片机LED灯花式闪烁电路图及程序

    单片机LED灯花式闪烁电路图及程序 在点亮LED灯的程序中我们知道开发板上的LED灯是接到高电平的,如果单片机引脚输出电平,LED导通发亮.如果单片机引脚输出高电平,LED截止熄灭.知道这个原理后我们 ...

  7. 使用51单片机点亮我们的第一个LED灯

    说实在的我们对于点亮一个LED灯,并不难,但是还是那句话外行看热闹,内行看门道,我们对于专业性来说肯定不会太难,但是非专业的刚刚转入我们这个行业的估计是有一些难,并且,这个虽然并不是一个新专业,但是我 ...

  8. stm32单片机屏幕一直闪_stm32实现LED灯的闪烁

    stm32单片机设计比较复杂,所以,对于外设的控制就相对于51单片机来说,就复杂很多.那么如何用stm32单片机点亮LED呢?通过一下几个步骤,就可以实现LED的闪烁.这里使用的stm32型号是stm ...

  9. C51单片机-2只LED灯循环闪烁

    keil uVision4界面: #include<reg51.h> //包含8051单片机寄存器定义的头文件sbit D1=P0^0; //定义P0口sbit D2=P0^1;void ...

最新文章

  1. 加密工具类 - CryptoUtils.java
  2. dos命令配置jdk环境
  3. php基础教程 第七步数组补充及循环基础
  4. 比char还小的变量
  5. unity矩阵运算,数学计算
  6. 用python演绎神奇的生命游戏,在游戏中学习numpy和matplotlib动画
  7. PICKIT3脱机烧写指导书
  8. 360云盘账号停止服务器,360云盘服务器终止为什么
  9. rstudio 连接mysql_RStudio 操作MySQL数据库
  10. 网址在QQ微信被拦截怎么办?怎么样才能让被微信屏蔽的网址正常访问
  11. 副总和副总裁的区别_总经理与副总经理的巨大区别
  12. [vscode] markdown_index 可以为你的markdown标题添加序号的插件
  13. 混凝土抗压弹性模量自动计算表_2011混凝土弹性模量试验.doc
  14. originos系统和鸿蒙系统哪个好用,originos系统适配机型_originos系统更新名单
  15. JavaMail IMAPFolder.getMessageByUID 获取QQ和腾讯企业邮箱新邮件的问题
  16. 用迭代法求某数a的平方根
  17. php new object delete,php – S3 DeleteObject – DeleteMarker始终返回空
  18. 002稀疏数组和队列[超大章]
  19. 泛型类、泛型方法的使用与理解
  20. Python 实现动态解析阿里云DNS记录

热门文章

  1. 计算机基础在线阅读高职,高职计算机基础教案一
  2. 基于PHP的学生食堂管理系统
  3. 电子计算机机房设计规范
  4. linux挂载U盘汉字乱码问题
  5. |蚂蚁金服漆远首谈刚完成的AI重大突破及紧缺人才,呼吁国内多点技术性强的大会,少点网红
  6. 论文全免费下载网站SCI-Hub新网址
  7. 【好书荐读】《世界因你不同——李开复自传》
  8. 高清媒体播放机产品分析()
  9. 基于javaee地铁人事管理系统的设计与实现
  10. 6.24:K60电源管理V5_最简版本蓄水池