流水灯实验
程序设计思路
流水灯是经典实验。要点亮发光二极管,要把P0端口和P2.3端口设置成推挽输出,然后
- 将P2.3设成“1”,这表示使能发光二极管
- 对P0端口赋值,就可以点亮对应的led灯了
而对于流水灯,基本思路就是点亮一个led灯,等待一段时间,然后熄灭它,同时点亮下一个led灯,然后如此循环下去,就可以看到流水效果如下
1 | 00000001 |
关键代码说明
相关定义以及头文件
1 | /* 这个是我们的单片机的端口的定义 */ |
本程序主要是三个函数组成
对二级管初始化
void Init();
这个函数主要是发光二极管的初始化设置:
只要将P0口和P2.3工作模式设置为推挽输出,同时将P2.3置“1”,使能发光二极管电路。(这里的置“1”是P2的bit3置为1)
其中P0、P2这两个端口的设置通过对对应的寄存器赋值来设置实现。
看看上面两个表,其中第一列,也就是通道1为0(八个位都是0),通道0为1(特定位为1),表示处于推挽模式。STC15F2K60S2数据手册4.1章节(322页)有详细的介绍,下面简单介绍进一步如何配置。
上面是STC-B的部分电路原理图。由于处于推挽输出模式,要求通道0为1,通道1为0。通道1为0,就把通道一八个位全部设置成低电平。但是通道0为1就要对特定位进行赋1。对于P0端口,我们可以在电路图中看到是红色框框,它对应了八个发光二极管的正极端,所以要让8个发光二极管统统发光,就要全部设置使能。所以对于P0的通道0,进行赋1,就要把八个位全部设置成1。另一方面,对于P2端口。我们看到上面对于这个实验的led灯,只有一个LED负极开漏端有一个LED_SEL选择信号,表示选择哪一个LED发光。可以看到蓝色框框,只是P2.3,也就是端口P2的0通道的第三个位赋1就好。
因此我们得到如下初始化代码:
1 | void Init() { |
延时函数
void delay_ms(uint n);
函数delay_ms
的功能是延时n毫秒,但时间不一定特别准确。单片机工作在同一的时钟脉冲控制下。这个脉冲式单片机控制器的时钟电路产生的。时钟电路由振荡器和分频器构成,振荡器产生基本振荡信号,然后分频,得到相应时钟。(这玩意了解一下就好了)
关于单片机中周期的说明:
振荡周期: 晶体振荡器的周期。
状态周期: 振荡信号经二分频后形成的时钟脉冲信号,用S表示。一个状态周期的两个振荡周期作为两个节拍分别称为节拍P1和节拍P2。P1有效时,通常完成算术逻辑操作;P2有效时,一般进行内部寄存器之间的传输。
机器周期: 完成一个基本操作所需的时间称为机器周期。一个机器周期包含6个状态周期,用S1、S2、….、S6表示;共12个节拍,依次可表示为S1P1、S1P2、S2P1、S2P2、……、S6P1、S6P2。
指令周期:CPU执行一条指令所需要的时间。CPU执行指令是在时钟脉冲控制下一步一步进行的,由于指令的功能和长短各不相同,因此,指令执行所需的时间也不一样。一个指令周期通常含有1~4个机器周期。
上图是MCS-51单片机各种周期的相互关系。
因此,根据指令执行的时间,可计算出1ms可以相应执行多少条指令,函数中可通过循环执行空指令来达到延时1ms的效果。此外延时函数也可以在STC-ISP中通过“软件延时计算器”功能自动生成指定延时时间的延时函数代码,如下:
直接用ISP串口助手生成延时200ms对应的代码即可
1 | void Delay200ms() //@11.0592MHz |
主函数
void main();
首先要调用函数Init()对电路进行初始化,再循环地对P0口进行赋值,点亮流水灯。
每一次流水灯对应点亮的位向左移动一位,具体就如“程序设计思路”的演示图所示。
1 | void main() |
下载程序
在学习资料里面下载相关工具。主要是keil uvision 4。
新建工程uprojx,然后编译生成hex文件,烧入程序,运行。
如果编译没有生成
.hex
文件可以进行如下设置
成功效果如下