单片机C语言第二篇之进阶”Hello LED”


无意中发现另一种实现LED亮灭的方法

注意

本篇文章的功能实现基于 STC89C52RC 芯片,八颗LED灯接于P2口,使用Keil4原版编译环境,借鉴时注意不要一昧照搬。

前言

在上一篇《单片机C语言第一篇之”Hello LED”》中,实现LED灯亮灭的方法是直接用进制转换的8421法计算对应I/O口的LED亮灭的十六进制数,而这个程序用的是另一种方法,我之前也没有学过。

正文

该程序代码如下:

#include "reg52.h"  //这里的头文件写法与#include<reg52.h>相同

//IO引脚定义:
sbit LED9 = P2^0;    //管脚定义 类似于起名字
                    //用led 来代替P2.0

void main(void) 
{
    LED9=0;     //P2.0引脚输出0,因LED是共阳接法,因此是输出0来吸收电流点亮LED灯
    while(1)
    {
    }   //主程序循环,即程序要停止在这里
}

代码注意事项

  • sbit是用来定义管脚名字的,除了程序里的LED,数码管的管脚、蜂鸣器的管脚都可以定义
  • 我们所说的P2.0口在程序中不能写作P2.0,而应该是P2^0
  • 如果LED是共阴极接法,则LED = 0为高电位,LED = 1为低点位,这个根据单片机PCB板的设计不同而不同
    while(1)
    {
    }   //主程序循环,即程序要停止在这里
        //这个程序要不要这个while,不是很清楚,因为我试过不放这个while
        //程序也是正常运作,不会跑飞

总结

这个程序很简单,甚至没有延迟函数让LED闪烁,但是他实现了用sbit定义所需使用的组件的管脚来实现对组件的控制,是非常方便的,起码不用算十六进制数,个人觉得是十分不错的改进。

进阶再进阶

让它闪烁

还是上面那个程序,把之前的延迟函数加进去,让LED灯闪烁。

实现代码如下:

#include <reg52.h>

sbit led9 = P2^0;               //管脚定义

void delay(unsigned int time)   //延时子函数,定义延时参数time。time的大小决定延时时间长短
{
    while(time--);              //减1循环,减到0退出
}       

void main(void) 
{
    while(1)            // 主程序循环     
    {
        led9=1;             // LED灯灭
        delay(30000);   // 延时,改变参数则改变变化时间
        led9=0;         // LED灯亮
        delay(30000);   // 延时
    }
}

是不是很简单?但是这只是让一个灯亮。我的PCB板上可是有8颗LED灯呢,如何让他全部闪烁?

多个LED灯闪烁

我已经教了两种方法,一种是直接用8421法算出对应的十六进制数,另一种是先给LED管脚定义然后进行位操作。那么就来看看实现4颗LED灯闪烁的代码哪种更易读、易理解

8421法

#include <reg52.h>

void delay(unsigned int t)
{
    while(t--);
}

void main()
{

    while(1)
    {
        P2=0xa6;
        delay(30000);
        P2=0xFF;
        delay(30000);
    }
}

管脚定义法

我对这个方法的设想,是定义sbit数组,在循环中进行初始化,并进行位控制,结果并不能。在网上查找资料后也是不能。原因可能是以下几种,我自己也不懂

  • Keil C51编译器不支持
  • sbit特殊寄存属于直接寻址,而数组、调用数组时简介寻址
  • sbit用来定义特殊寄存器中可以寻位的位,占1位,不能定义指针,也不能定义数组(我觉得是这种)

总结

用sbit定义管脚的方法是昨天才看到的,觉得十分新奇,于是想用sbit同时控制多个LED灯闪烁,但是很明显失败了。即使每一个LED管脚都单独定义,按照程序执行的顺序,也不能同时闪烁,所以只能用十六进制方法实现,写了几十行代码都没法用,唉。这也是比课堂上更快地自学C51单片机的乐趣和痛苦吧。