单片机之基础编程 流水灯(二)

我们在知道STC-B板的焊接一系列过程之后,我们现在就将使用一系列的代码及原理来使用我们的板子,我们就最先来接触最简单的流水灯案例吧


流水灯案例

我们可以先来看
实验板图片
在这里插入图片描述

实验现象

其步骤为:

  1. 下载对应的流水灯.hex文件,驱动我们的应用程序
    在这里插入图片描述
    界面如下:
    在这里插入图片描述

  2. 我们用特定的线连接其接口与电脑
    在这里插入图片描述
    可看到串口号变为USB接口(若没有改变,自己查找自己对应的USB接口,否则检查线与板子是否插稳)

  3. 打开程序文件(即选择我们刚下载好的hex文件)
    在这里插入图片描述

  4. 选择下载/编程
    在这里插入图片描述
    出现如下界面
    在这里插入图片描述

  5. 按下板子上的RST键(可观察到操作成功提示)
    在这里插入图片描述

  6. 可同时观察到板子上的LED灯开始从右往左依次亮起

后面的一系列工程都是如此来观察实验现象的
知道了实验现象,激起了我们的兴趣之后,我们来了解一下其原理

实验原理

这一部分,我们不仅要了解部分接口,同时也要知道代码的含义及其编写,改进

相关电路及工作原理图

芯片引脚对应图
(这幅图对于我们理解代码以及明白交互式有非常重要的作用)
在这里插入图片描述
数码管与发光二极管硬件电路图
在这里插入图片描述

由实验现象可以知道,是从L7-L0依次闪烁的,而观察其电路图(上面第二幅图)P0 的八个接口对应了8个发光二极管L0-L7的阳极,而他们拥有共同的阴极,且通过反相器,其端口为P2.3,且信号为LED_SEL

发光二极管具有单向导通性,(即阳极为高,阴极为0才会导通发光,然而有个反相器,故LED_SEL(P2.3)应为高电平)
之后我们可以设置其P0的8个端口来设置哪个灯亮

既然这样
我们好好了解一下P0口的设置及工作原理吧!

STC系列芯片有5组8位输入口,分别为P0到P5,其中P5口仅P5.0~P5.5用于输入输出。
STC芯片的所有I/O口都可以配置为四种工作模式之一:

  • 准双向口/弱上拉
  • 推挽/强上拉
  • 输入/高阻
  • 开漏模式

STC15系列单片机上电复位后为准双向口/弱上拉工作模式

注意:
每个I/O口的工作模式由2个控制寄存器中的相应位控制(PnM0和PnM1,n=0、1、2、3、4、5)。也就是说P0口的具体工作模式由P0M0和P0M1控制。
可参看下表

P0M1[1: 0]该寄存器地址为93HP0M0[1: 0]该寄存器地址为94HI/O口模式
00准双向口,灌电流可达20mA,拉电流为270微安,由于制造误差,实际为270-150
01推挽输出(可达20mA,要加限流电阻)
10仅为输入(高阻)
11开漏,内部上拉电阻断开,其模式即可读外部状态,也可对外输出(高或低电平),e.g.要正确读取外部状态或需要对外输出高电平,需外加上拉电阻,否则读不到外部状态,也对外不输出高电平

具体模式说明:

  1. 准双向口
    真正的双向口指的是具有输入和输出两种模式的端口,在不同模式之间需要进行转换;如果从输入改为输出,需要对某些控制寄存器进行设定,才能完成
    51系列单片机的I/O口线在输入和输出之间没有明确的模式区别。相应端口在同样模式下,既可以作为输入,又可以作为输出。P3口除外,因为它需要连接外设
    51单片机的I/O口如果要读必须先写1才可以,因此称为“准”双向口
    需要大电流高电平输出能力的场合和高速场合不能使用该模式

  2. 推挽电路输入输出(push-pull)模式
    推挽电路的输出端好像有两个“臂”(两组放大元件),一个“臂”的电流增加时,另一个“臂”的电流则减小,二者的状态轮流转换。对负载而言,好象是一个“臂”在推,一个“臂”在拉,共同完成电流输出任务
    该电路模式的主要作用是增强驱动能力,为外部设备提供大电流,可以直接输出高电平电压

  3. 输入/高阻模式
    仅用于输入

  4. 开漏电路
    I/O口的开漏就是没有连接上拉电阻

故对于流水灯
需要将P0的8个引脚和P2.3都设置为推挽输出

案例代码

下面解析其代码(我们后面将详细涉及其代码的编写)
一个UV文件都涉及三个基础文件,但其放置的对应子文件夹不同,我们现在只解析.c版本的代码(因为我学的是C++)

设计思路
为点亮发光二极管

  1. 首先需要把P0口和P2.3设置为推挽输出,然后将P2.3置“1”,使能发光二极管电路(设置端口初始值
  2. 再对P0口赋值,即可点亮对应的led灯。
  3. 要实现“流水灯”的效果,则可以点亮一个led灯,等待一定时间,将其熄灭,同时点亮下一个led灯,然后如此一直循环下去,即能看到“流水灯”的效果。

即需要三大函数(初始化设置端口,延时,主函数的永真循环
可参照P0的工作模式表,编写这部分代码

  • 初始化
void Init(){

	P0M1=0x00;
	P0M0=0xff;
	//p0口设置为推挽输出,16进制
	//改写为2进制,就表示M1中8位全为0,M0中8位全为1
	//即我们需要的P0口的八位均为推挽输出

	P2M1=0x00;
	P2M0=0x08;
	//P2.3口也需设置推挽输出,
	//其余默认为准双向口
	//即P2的第4位设定为1即表示为16进制08

	led_sel=1;	
	//即p2.3端口一直为高电平,保证发光二极管会亮
}
  • 延时函数
    在正式了解之前,我们需要了解单片机的周期,即与实时时钟的频率关系,这样我们才能换算出我们期望的延时是多少

故我们先来了解单片机是如何控制延时的

单片机工作时,是在统一的时钟脉冲控制下有序进行的。
这个脉冲是由单片机控制器中的时钟电路产生的。
时钟电路由振荡器和分频器组成,
振荡器产生基本的振荡信号,然后进行分频,得到相应的时钟。振荡电路通常有内部振荡和外部振荡两种方式。
STC15F2K60S2单片机内部集成高精度R/C时钟,工作时钟可以使用内部振荡器或者外部晶体振荡器(简称晶振)产生的时钟。外部振荡信号通过内部时钟电路,经过分频,得到相应的时钟信号。

该图为外部震荡模式工作原理图
在这里插入图片描述

我们下面了解一些基本的概念

  • 振荡周期:
    晶体振荡器的周期。

  • 状态周期:
    振荡信号经二分频后形成的时钟脉冲信号,用S表示。
    一个状态周期的两个振荡周期作为两个节拍分别称为节拍P1和节拍P2。
    P1有效时,通常完成算术逻辑操作;
    P2有效时,一般进行内部寄存器之间的传输。

  • 机器周期:
    完成一个基本操作所需的时间称为机器周期。
    一个机器周期包含6个状态周期,用S1、S2、….、S6表示;共12个节拍,依次可表示为S1P1、S1P2、S2P1、S2P2、……、S6P1、S6P2。

  • 指令周期:
    CPU执行一条指令所需要的时间。
    CPU执行指令是在时钟脉冲控制下一步一步进行的,由于指令的功能和长短各不相同,因此,指令执行所需的时间也不一样。
    一个指令周期通常含有1~4个机器周期。

在这里插入图片描述
该图可以更直观的帮助大家了解上述关系

举个例子

若MCS-51单片机外接晶振为12MHz时,则单片机的四个周期的具体值为:

振荡周期=1/12MHz=1/12μs=0.0833μs

时钟周期=1/6μs=0.167μs

机器周期=1μs

指令周期=1~4μs

单片机晶体振荡器M的频率可以在4MHz~48MHz之间选择,典型值是11.0592MHz(因为使用这个频率的晶振可以准确地得到9600bits/s和19200bits/s的波特率)

后面11.0592MHz这个数值我们将频繁遇到

既然我们已经知道指令周期等数值,那如果我们期望延迟200ms,那是不是要通过计算才能确定我们代码实际需要执行多少次的空指令呢
代码如下:

void Delay200ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	//_nop_();
	//_nop_();
	i = 9;
	j = 104;
	k = 139;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

不了解的人可能不能明白为啥200ms是这样的,也更不理解这是计算出来的结果

故我们还是用高端一点的方式来实现延迟吧!
在这里插入图片描述
还是我们的这个窗口,但是我们很明显的看到我们选择的已经不是原来的菜单栏了,而是我们的软件延时计算器(往右查找即能找到)
已经确定其系统频率为我们熟悉的数字
然后就是我们自己设定的延迟时间了
点击生成自己熟悉的代码,再复制粘贴到自己的源代码中
一切就大功告成了!

  • 主函数部分
void main()
{
	Init();
	//调用初始化函数部分
	
	led=0x01;
	//设置最低位为高电平
	
	while(1) //永真循环
	{
		P0=led;  //设置L0灯亮	
		delay_ms(200);  //调用延时函数
		if(led==0x80)  //如果最高位亮,设置最低位为高电平
			led=0x01;
		else
			led=led<<1;   //否则左移一位
	}
	
}

看到这我们就恍然大悟啦,整个程序实现并不困难,那我们后面就慢慢接触难一点的代码原理,并尝试写出来吧!

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值