蓝桥杯LED发光二极管

文章介绍了如何使用STM8微控制器控制LED灯,包括共阳极LED的连接方式、锁存器的使用以及编程技巧。通过示例代码展示了如何点亮特定LED、使用全局变量进行控制以及实现流水灯效果。还提到了利用共用体和结构体进行字节和位赋值的方法。
摘要由CSDN通过智能技术生成

电路介绍

与蜂鸣器、继电器电路原理一模一样,只是使用的锁存器(U6)和选通锁存器的管脚(Y4C)不一样。

蓝桥杯板上一个使用的8个LED组成灯组,并且是共阳极连接的,也就是所有LED的阳极全部连接在一起接上电源VCC,所以要想让LED点亮,就需要给它输入低电平,也就是相应管教置0就点亮,置1就熄灭。

与蜂鸣器继电器一样,首先P0相应的管脚置0,再将Y4C置1,选通U6锁存器(P2=0x80),人后将Y4C置0,关闭锁存器,就可以对相应的LED进行点亮。

点亮指定的LED

虽然板子上的LED是L1~L8这样子排列的,但是在给P0赋值时是从高位开始的(P7~P0),所以在进行写代码进行进制转换时,要按照L8~L1这样来思考。考试的时候是可以直接用计算器来进行进制转换之类的计算的,但是考试一般使用的是win7系统,所以建议大家下载一个win7计算器来使用,以便于适应考试时的电脑。

/*
上电默认关闭继电器、蜂鸣器,并点亮指定的LED灯
1.点亮L1 L3 L7 L8四个LED,其余熄灭
2.点亮L1 L3 L5 L7四个LED,其余熄灭
*/


#include "STC15F2K60S2.h"
#include "intrins.h"

unsigned char buzzer_ctrl;        //定义全局变量buzzer_ctrl来控制蜂鸣器
unsigned char relay_ctrl;        //定义全局relay_ctrl变量来控制继电器

void Delay1000ms()                /* 延时1s@12.000MHz,用STC-ISP软件生成 */
{
    unsigned char i, j, k;

    _nop_();
    _nop_();
    i = 46;
    j = 153;
    k = 245;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

void Divice_Ctrl(unsigned char p2data,unsigned char p0data)    //继电器、蜂鸣器控制函数
{
    P0=p0data;
    P2=p2data;
    P2=0;
}

void System_Init()      //系统初始化函数,将继电器、蜂鸣器关闭
{
    buzzer_ctrl=0;
    relay_ctrl=0;
    Divice_Ctrl(0xa0,((buzzer_ctrl<<6)|(relay_ctrl<<4)));
}
  

void main()
{    
    System_Init();
    Divice_Ctrl(0x80,0x3a);    //0x3a就是0011 1010的16进制
    Delay1000ms();
    Divice_Ctrl(0x80,0xaa);    //0xaa就是1010 1010的16进制
    Delay1000ms();
}

变量位操作LED

上面的代码是整个P0口进行赋值来点亮LED,用变量位来进行点亮LED,就可以单独操作一个P

0的位,且不影响其他的位。也就是控制单个LED且不影响其他LED的控制。

/**数组进行变量位控制**/
/*点亮L1 L3 L7 L8四个LED*/
#include "STC15F2K60S2.h"
#include "intrins.h"


unsigned char led_ctrl[9];

void Divice_Ctrl(unsigned char p2data,unsigned char p0data)    //继电器、蜂鸣器控制函数
{
    P0=p0data;
    P2=p2data;
    P2=0;
}


void System_Init()      //系统初始化函数,将继电器、蜂鸣器关闭
{
    Divice_Ctrl(0xa0,0);
}


void main()
{
    System_Init();
    led_ctrl[1]=1;
    led_ctrl[3]=1;
    led_ctrl[7]=1;
    led_ctrl[8]=1;
    Divice_Ctrl(0x80,~(led_ctrl[1] | led_ctrl[3]<<2 | led_ctrl[7]<<6 | led_ctrl[8]<<7));
    while(1)
    {
        
    }
}

以上代码与前面的继电器、蜂鸣器十分形似,都采用全局变量来进行相应控制,并且该代码使用了取反运算符(~),这样就可以记忆成相应管脚置1点亮LED,可以更好的与继电器、蜂鸣器一起进行记忆。

以上代码采用了数组中相应的元素进行赋值,并移位的操作来控制LED,当需要单独控制某一个LED时,就可以直接对数组中的元素进行操作,此方法使用起来方便,不需要进行进制转换,并且容易记,所以相较于上面的对整个P0口进行赋值操作的方法,更推荐该种方法。

  • 注:为什么不使用sbit来定义管脚,直接进行位控制,而是要用变量的方式来进行控制

使用sbit对单独的位进行操作时,如果前面有对蜂鸣器、继电器操作后留下的数据,在打开锁 存器进行LED控制时,前面遗留下的数据,可能会对LED的控制产生影响。所以为了避免这种 情况,在进行控制时,要对整个P0口一起控制。

流水灯

/*流水灯*/
/*L1~L8从左往右依次点亮,间隔为1s*/
/*L8~L1从右往左依次点亮,间隔为1s*/
/*L2 L4 L6 L8从左往右依次点亮,间隔为1s*/
#include "STC15F2K60S2.h"
#include "intrins.h"


unsigned char led_ctrl[9];

void Divice_Ctrl(unsigned char p2data,unsigned char p0data)    //继电器、蜂鸣器控制函数
{
    P0=p0data;
    P2=p2data;
    P2=0;
}

void Delay1000ms()                /* 延时1s@12.000MHz,用STC-ISP软件生成 */
{
    unsigned char i, j, k;

    _nop_();
    _nop_();
    i = 46;
    j = 153;
    k = 245;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

void System_Init()      //系统初始化函数,将继电器、蜂鸣器关闭
{
    Divice_Ctrl(0xa0,0);
}


void led_flash_L1_L8()
{
    static unsigned char led_shift=0;
    Divice_Ctrl(0x80,~(0x01 << led_shift));
    led_shift++;
    if(led_shift==8)
        led_shift=0;
}

void led_flash_L8_L1()
{
    static unsigned char led_shift=0;
    Divice_Ctrl(0x80,~(0x80 >> led_shift));
    led_shift++;
    if(led_shift==8)
        led_shift=0;
}
    
void led_flash_L2_L4_L6_L8()
{
    static unsigned char led_shift=0;
    Divice_Ctrl(0x80,~(0x02 << led_shift));
    led_shift=led_shift+2;
    if(led_shift==8)
        led_shift=0;
}
   
void main()
{
    Divice_Ctrl(0xa0,0);
    while(1){
        //led_flash_L1_L8();
        //led_flash_L8_L1();
        led_flash_L2_L4_L6_L8();
        Delay1000ms();
    }
}

以上代码需要注意的是,控制移位操作的变量需要定义为static静态变量,不然在while循环中,每次执行该函数,都会将led_shift赋值为0,灯也就不会进行流水点亮,会只点亮一个灯。当然如果不像上面一样进行函数封装,直接在while循环中实现流水灯代码,也就不需要定义为静态变量了。

利用共用体实现字节赋值和位赋值

这种方式可以既能字节赋值也能位赋值,需要用到结构体、共用体、位域等知识。

/*************************************************
File name:      【LED】利用共用体实现字节赋值和位赋值
Description: 
             1. 定义一个叫bits的结构体数据类型! 用bits b;  变量b就是结构体变量!
             2. 定义一个叫HexTobin的共用体数据类型! 用 HexToBin led_ctrl;  变量led_ctrl就是个共用体变量!
             3. 对led_ctrl.hex赋值一个字节的数据,对应的led_ctrl.b.b0 到 led_ctrl.b.b7会对应变化!
             4. 对led_ctrl.b.b0进行位赋值,对应led_ctrl.hex也会对应变化!
Attention:
             1.  熟悉typedef用法,结构体struct用法,共用体union用法!
             
Copyright (c) 电子设计工坊 dianshe.taobao.com
All rights reserved
*************************************************/
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "Delay.h"
#include "Device.h"

/* 用typedef定义一个叫bits的结构体“数据类型”, 从而可以用 bits b; 定义b为结构体的“变量”*/
typedef struct
{
    unsigned char b0 : 1;
    unsigned char b1 : 1;
    unsigned char b2 : 1;
    unsigned char b3 : 1;
    unsigned char b4 : 1;
    unsigned char b5 : 1;
    unsigned char b6 : 1;
    unsigned char b7 : 1;
}bits;

/* 用typedef定义一个叫HexToBin的共用体“数据类型”, 从而可以用 HexToBin led_ctrl; 定义led_ctrl为共用体的“变量”*/
typedef union
{
    unsigned char hex;        
    bits b;
}HexToBin;

HexToBin led_ctrl,buzzer_ctrl;

/**
  * @brief  系统初始化函数:关闭继电器、蜂鸣器
  * @param  None
  * @retval None
  * @author dianshe.taobao.com
  */
void vSystem_Init(void)
{
    vDevice_Ctrl(0xa0,0);         /* 关闭蜂鸣器、继电器*/
}

void main(void)
{
    vSystem_Init();
    led_ctrl.hex = 0x55;                  /* 对led_ctrl进行“字节赋值”,希望L2 L4 L6 L8点亮 */
    vDevice_Ctrl(0x80,led_ctrl.hex);      /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成点亮L2 L4 L6 L8操作 */
    
    buzzer_ctrl.b.b4 = 1;                  /* 对buzzer_crtl进行“位赋值”,希望吸合继电器 */
    vDevice_Ctrl(0xa0,buzzer_ctrl.hex);    /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成吸合继电器操作 */
    while(1)
    {
        led_ctrl.b.b1 = 1;                    /* led_ctrl进行“位赋值”,希望熄灭L2 */
        vDevice_Ctrl(0x80,led_ctrl.hex);    /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成熄灭L2操作 */
        
        buzzer_ctrl.b.b4 = 1;                    /* 对buzzer_crtl进行“位赋值”,希望吸合继电器 */
        vDevice_Ctrl(0xa0,buzzer_ctrl.hex);        /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成吸合继电器操作 */        
        vDelay_Ms(200);                            /* 仅作练习用,在while(1)不要使用大于20ms的延时!会造成CPU资源浪费!学完定时器,即可把长时间Delay给优化掉! */
        
        led_ctrl.b.b1 = 0;                        /* led_ctrl进行“位赋值”,希望点亮L2 */
        vDevice_Ctrl(0x80,led_ctrl.hex);        /* 选通Y4C锁存器,并在P0口输出一个字节数据,完成点亮L2操作 */
        
        buzzer_ctrl.b.b4 = 0;                    /* 对buzzer_crtl进行“位赋值”,希望关闭继电器 */
        vDevice_Ctrl(0xa0,buzzer_ctrl.hex);        /* 选通Y5C锁存器,并在P0口输出一个字节数据,完成关闭继电器操作 */
        vDelay_Ms(200);
    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值