一、点亮LED和流水灯设计
点亮LED和流水灯设计
参考书籍:51单片机C语言教程
视频链接:参考视频
单片机型号:巫妖王51单片机V2版
单片机概述
什么是单片机?
Micro Controller Unit简称MCU,即单片微型计算机,简称单片机。
用专业语言讲,单片机就是在一块硅片上集成了微处理器、存储器及各种输入/输出接口的芯片,这样一块芯片就具有了计算机的属性,因此称为单片微型机,也叫单片机。
通俗点来说,单片机就是一块集成芯片,但这块集成芯片具有一些特殊的功能,而功能的实现要靠我们使用者自己来编程完成。我们编程的目的就是控制这个芯片的各个引脚在不同时间输出不同的电平,进而控制单片机各个引脚相连接的外围电路的电气状态。
单片机能作什么
单片机属于控制类数字芯片,目前其应用领域非常广泛。
单片机如何学习
理论和实践需要相辅相成。
点亮LED
- LED介绍
- 电阻阻值看法
- 电平
- LED点亮的原理
LED原理图:
LED点亮代码如下:
#include <REGX52.H>
void main()
{P2=0xFE; //对P2口的8个I/O口同时操作,0x代表后面的数据是以十六进制表示的,十六进制的FE //表示的是 1111 1110 //原理图上表示 P20对应的LED为D2,故D2亮,其余不亮while(1) //用于程序的死循环{ }
}//书上的另外一种写法:9
/*
#include <REGX52.H>sbit led1=P2^0; //声明单片机P2口的第一位(最低位),将单片机P2口的最低位定义为led1
void()
{led1=0; //点亮第一个发光二极管,对P2口的最低位清0,由于没有操作其他位,所以其他位均保持原来的状态不变
}
*/
头文件:reg51.h和reg52.h是定义51单片机或52单片机特殊功能寄存器和位寄存器的。
main()函数
格式:void main()
特点:无返回值,无参数。
无返回值,表示该函数执行之后不返回任何值,上面的main前面的void表示“空”,即不返回值的意思。
无参数表示该函数不带任何参数,即main后面的括号中没有任何参数,我们只写“()”就可以,也可以在括号里写上void,表示“空”的意思,如void main(void)
任何一个单片程序有且仅有一个main函数,它是整个程序开始执行的入口。
电平特性:
单片机是一种数字集成芯片,数字电路中只有两种电平:高电平和低电平。常用的逻辑电平有TTL、CMOS、LVTTL、ECL、PECL、GTL等。其中TTL和CMOS的逻辑电平可分为四类:5V系列(5V TTL和5V CMOS)、3.3V系列、2.5V系列和1.8V系列。
常见的51单片机通常使用TTL电平信号,+5V等价逻辑1,0V等价逻辑0。
while()语句
格式:
while(表达式) {内部语句(内部可空) }
特点:先判断表达式,后执行内部语句。
原则:若表达式不是0,即为真,那么执行语句,否则跳出while语句,执行后面的语句。
需要注意三点:
- 在C语言中我们一般把“0”认为是假,“非0”认为是真,也就是说只要不是0就为真,所以1、2、3等都为真
- 内部语句可为空,就是说while后面的大括号里可以什么也不写,如
while(1);
,注意:;
一定不可少,否则while()会把跟在它后面第一个分号前的语句认为是它的内部语句。 - 表达式可以是一个常数,也可以是一个运算或带一个返回值的函数
有了上述的介绍,就可以知道,我们往往会在单片机后加上
while(1);
这样的一条让程序停止的语句。因为该语句表达式值为1,内部语句为空,执行前先判断表达式的值,因为为真,所以什么也不执行,然后再判断表达式,仍然为真,又不执行,所以程序会一直执行这条语句,换而言之,单片机在点亮LED后将一直重复执行这条语句。
LED闪烁
由while语句生成延时函数
由while语句构成的延时子函数可通过stc-isp进行生成:
主函数代码如下:
#include <REGX52.H>
#include <INTRINS.H> //空语句需要用到的头文件void Delay500ms() //@12.000MHz 子函数
{unsigned char i, j, k;_nop_(); //空语句i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);
}
void main()
{while(1) //做大循环 {P2=0xfe;// 1111 1110 P2.0亮 也就是D2亮Delay500ms(); //调用子函数,延时半秒P2=0xdd;// 1101 1101 P2.1亮 P2.5亮 也就是D3和D7亮Delay500ms();}
}//知识点
/*
void main()
main()函数
无返回值,无参数
*/
由for语句写出的简单延时语句
for语句
格式:
for(表达式1;表达式2;表达式3) {语句(内部可为空) }
执行过程:
第一步,求解表达式1
第二步,求解表达式2,若其值为真(非0即为真),则执行for语句中的内容,然后执行第3步;否则结束for语句,直接跳出,不再执行第3步
第三步,求解表达式3
第四步,跳到第二步重复执行。
实例:
unsigned char i; for(i=2,i>0,i--); /* 首先定义一个无符号字符型变量i,然后执行for语句 -表达式1,i=2:给i赋一个初值2 -表达式2。i>0:判断i大于0是真是假 -表达式3。i--:i自减1 *///for嵌套 unsigned char i,j; for(i=2,i>0,i--)for(j=2,j>0,j--);
显然程序在执行上述语句的时候是需要时间的,i的初值较小,所以执行的步数就少,当我们给i赋一个较大的值,它执行所花的时间也就越长,通过这个原理,我们就可以利用for语句来作为一个简单的延时语句。
需要注意的是,由于i是无符号字符型变量,它的最大值为255,所以不能通过赋给i一个尽可能大的值来写一个延时较大的语句。
这就是为什么每次给变量赋值时都要首先考虑变量类型,然后根据变量类型赋一个合理的值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xuEEqghd-1666776958774)(https://louis-typora.oss-cn-nanjing.aliyuncs.com/img_for_typora/20221026154601.png)]
LED流水灯
带参数和不带参数函数的写法
- 不带参数函数的写法及调用
在C语言代码中,如果有一些语句不止一次用到,而且语句内容都相同,我们就可以把这样一些语句写成不带参数的子函数,当主函数需要用到这些语句时,只需要调用子函数即可。我们先观察一下由stc-isp
生成的延时函数:
//由stc-isp的软件延时计算器生成的延时函数
void Delay1ms() //@12.000MHz
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}
//课本中延时函数的写法采用for语句
void表示这个函数执行之后不返回任何数据,即它是一个无返回值的函数
Delay1ms是函数名,名字可以随便取,但是注意不要与C语言中的关键词相同,函数命名规则一般写成方便记忆或读懂的名字,也就是一看到函数名就知道函数实现的内容是什么。
显然通过这个函数名我们知道这个函数是一个延时1ms的函数,函数名后面紧跟括号(),这个括号内没有任何数据或符号(即C语言中的“参数”),因此这个函数是一个无参数的函数。
写法:子函数可以写在主函数的前面或者后面,一定不能写在主函数里面。
子函数写在主函数后面
当子函数写在主函数后面,必须在主函数之前声明子函数。
声明方法:
将返回值特性、函数名及后面的小括号完全复制。若是无参函数,则括号内为空;若是有参函数,需要在括号内依次写上参数类型,只写参数类型,无需写参数,参数类型之间用逗号隔开,最后在小括号后面必须加上分号。
如无参函数声明:
void delay1ms();
如有参函数声明:
void delay1ms(unsigned int);
子函数写在主函数之前
当子函数写在主函数之前可以不用声明子函数,这是因为写函数体的同时就已经相当于声明了函数本身。通俗的来说,声明子函数的目的是为了编译器在编译主程序的时候,当它遇到一个子函数的时候知道有这样一个子函数的存在,并且知道它的类型和带参情况等信息,以方便为这个子函数分配必要的存储空间。
- 带参数函数的写法及调用
先看一段延时子函数代码:
#include <REGX52.H>void Delay1ms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}
//我们注意到子函数内部“unsigned char i, j;”语句,介绍一下变量定义的方式
unsigned int xms
:函数所带的一个参数,xms是unsigned int类型变量,又叫这个函数的形参,在调用此函数时,我们用一个具体真实的数据代替此形参,这个真实数据称为实参,形参在被实参代替后,在子函数内部所有和形参名相同的变量将都被实参代替。声明:
void delay1ms(unsigned int)
调用方法:
调用一个延时300ms的函数:
void delay1ms(300)
调用一个延时500ms的函数:
void delay1ms(500)
变量定义:
以上面子函数内部
“unsigned char i, j;”
语句为例,i, j两个变量的定义放到了子函数里,而没有写在主函数的最外面。在主函数外面定义的变量叫全局变量,像这种定义在子函数内部的变量叫局部变量,这里的i, j就是局部变量。局部变量只在当前函数中有效,程序一旦执行完当前子函数,在它内部定义的所有变量都将自动销毁,当下次再用到该子函数时,编译器重新为其分配内存空间。
每个全局变量都占据着单片机内固定的RAM,由于单片机内部RAM空间有限,所以我们要从一开始写程序时就要坚持能节省的RAM空间就要节省,能用局部变量就不用全局变量的原则。
移位操作
实现流水灯的办法有很多,可以用逻辑运算来实现,也可以用C51自带的函数来实现。
移位:
- 左移:
a=a<<1
- 右移:
a=a>>1
库函数:
- 循环左移函数:
_crol_
- 循环右移函数:
_cror_
#include <intrins.h> unsigned char_crol_(unsigned char c,unsigned char b)//字符C循环左移b位 //return value: 返回的是C循环左移之后的值
函数描述:以循环左移函数为例,
_crol_
这个函数的意思是将字符C循环左移b位,由于这是C51库自带的内部函数,在使用这个函数之前,需要在文件中包含它所在的头文件。- 左移:
流水灯的实现
流水灯的代码如下:
#include <REGX52.H>
#include <intrins.h>unsigned char aa;//定义一个变量,用来给P2口赋值void Delay1ms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{aa=0xFE;while(1) //大循环{P2=aa; //先点亮第一个发光管Delay1ms(500); //延时aa=_crol_(aa,1); //将aa的值左移一位后再赋给aa}
}
一、点亮LED和流水灯设计相关推荐
- 点灯合集(点亮LED、流水灯、8x8点阵、点阵拓展)——附程序
点灯合集 一.点亮LED 简介: LED闪烁: Proteus仿真图: 视频展示: 代码: 二.流水灯 Proteus仿真图: 代码: 代码一: 代码二(优化): 三.行列扫描原理 四.8x8点阵 简 ...
- FPGA零基础学习:LED流水灯设计
FPGA零基础学习:LED流水灯设计 本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的"傻瓜式"讲解,让电子.信息.通信类专 ...
- LED流水灯设计-ISE操作工具
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的"傻瓜式"讲解,让电子.信息.通信类专业学生.初入职场小白及打算进阶提升的职 ...
- 基于51单片机的51单片机的LED彩灯霓虹灯控制器(心形流水灯)设计
基于51单片机的51单片机的LED彩灯霓虹灯控制器(心形流水灯)设计 必看!!视频讲解 基于51单片机的LED彩灯霓虹灯心形流水灯设计 这里写目录标题 1 开发环境 2 功能说明介绍 3 仿真图 4 ...
- Keil软件使用及流水灯设计
Keil软件使用及流水灯设计 在点亮流水灯的同时,我们要对移位操作进行了解 左移 在C51中操作符"<<",每执行一次左移指令,会将最高位移入单片机寄存器的CY位(CY ...
- 基于51单片机的汇编程序:拨码开关控制八位LED实现流水灯
基于51单片机的汇编程序:拨码开关控制八位LED实现流水灯 2022-03-08,51单片机学习笔记 功能 打开K1循环左移,打开K2循环右移,打开K3两侧到中心来回点亮,打开K4单双数位置交替点亮. ...
- 基于51单片机的汇编/C程序:拨码开关控制八位LED实现流水灯
基于51单片机的汇编程序:拨码开关控制八位LED实现流水灯 2022-03-08,51单片机学习笔记 功能 打开K1循环左移,打开K2循环右移,打开K3两侧到中心来回点亮,打开K4单双数位置交替点亮. ...
- 基于51单片机的花样流水灯设计(源码+仿真+设计报告)
资料编号:113 采用51单片机的IO控制多个LED灯,实现多种模式的流水风,全套资料齐全:具体功能请看下方演示视频 113-基于51单片机的花样流水灯设计(源码+仿真+设计报告) 单片机最小系统介绍 ...
- 基于verilog流水灯设计
使用verilog语言实现流水灯设计并进行仿真波形验证如下: 下面是在vivado下仿真截图: 流水灯顶层模块包括分频器和状态机组成 顶层模块如下: module ledwater( input cl ...
最新文章
- c#操作mysql数据库
- 一、【用django2.0来开发】 环境部署和初始化项目
- .NET CORE 怎么样从控制台中读取输入流
- 微信小程序启动、更新机制
- anaconda安装python3.7、jupyter_Anaconda3 Python 3 和 2 in Jupyter Notebook共存方法
- Linux2个文件一起打包,Linux文件压缩和打包(二)
- 基于Debian的Linux发行版安装深度音乐及其插件,支持ubunut16
- 高等数学学习指导_学习A-Level应该如何选课?
- PART 1.3 风控利率那些事儿(名义利率 实际利率 还款方式 以及 计算逻辑汇总)
- h5 字体加粗_css 加粗字体
- jxl 实现导出excel添加水印
- SQLite Expert查看SQLite数据库文件没有数据的问题
- 计算机技术对高分子的意义,计算机技术在高分子材料工程中的应用.docx
- 数据库系统---数据挖掘
- V4L2驱动的移植与应用(三)
- Eclipse搭建第一个Spring boot项目
- 《五月集训》第十四天——栈
- 2021面试题——微信小程序面试题
- Linux - 可视化菜单界面设计
- 视频教程-游戏网络编程必备知识-Unity3D
热门文章
- 本证方程的本征值 与 特征方程的特征值 的 区别 辨析
- 一个神经网络有多少个神经元?
- Excel与hive、hbase的交互[转自 AIMP平台wiki]
- 计算机网络在铁路信号中的应用,计算机网络在铁路信号中的应用.doc
- 格创校园跑腿小程序源码
- maxcms支持mysql吗_马克斯maxCMS整合M3U8播放器插件+教程
- 排序算法之冒泡排序及鸡尾酒排序
- 专科出身,苦学Android,最终圆梦阿里,2021最新Android框架体系架构面试题
- hook Android 权限请求, 插入权限目的dialog显示
- Processing Java Annotations Using Reflection