注:此单片机型号为 STC15F2K60S2.

原理

如图,发光二极管L1—L8 共阳接法,VCC为电源正极,高电平。
已知发光二极管正向导通反向截至,要使得二极管发光,就要让Q1—Q8为低电平。可控管脚为P00—P07,所以要输入P00—P07为低电平。为了让P0能够影响到Q1—Q8,就要使得锁存器 M74HC573M1R 导通,即要让管脚LE为高电平。又管脚LE与Y4C连接,所以Y4C也为高电平。


又Y4C连接了一个或非门,或非门的输入端为Y4和WR。因为WR已用跳线帽与GND连接在了一起,GND为接地,所以WR为0(低电平)。
根据或非门逻辑表格:

Y4         WR       Y4C
0          0         1
0          1         0
1          0         0
1          1         0

所以,当Y4C为0时,Y4为1;当Y4C为1时,Y4为0.
所以,要使得Y4C为高电平,Y4就要为低电平,即Y4为0.

又Y4是由 74HC138 位译码器的输入端A、B、C来控制,以 C、B、A 为逻辑顺序,CBA组成二进制数,来选中Y0—Y7,被选中者即为低电平。

所以,要使得 Y4 为低电平,CBA 要为 100.

另外,由于 P0 口是复用的,意味着也要控制别的器件,所以如果一直让 LE 为高,那么就在控制别的器件的时候就会影响到 LED,所以在锁存器导通后,应该截止保存住它的状态。

整理逻辑

点亮LED:
Q1—Q8为低电平 —> P00-P07为低电平 -> 导通锁存器,LE为高电平 ->
Y4C为高电平 -> 或非门,Y4为低电平 -> 译码器,CBA组合为100 ->
锁存状态,断开锁存器,LE为低电平,Y4C为低电平 ->
或非门,Y4为高电平 -> 译码器,CBA组合为000.(不为100即可)同理,熄灭LED:
Q1—Q8为高电平 —> P00-P07为高电平 -> 导通锁存器,LE为高电平 ->
Y4C为高电平 -> 或非门,Y4为低电平 -> 译码器,CBA组合为100 ->
锁存状态,断开锁存器,LE为低电平,Y4C为低电平 ->
或非门,Y4为高电平 -> 译码器,CBA组合为000.(不为100即可)

代码

官方代码

来源:蓝桥杯官方资料。

#include "reg52.h"
// #include "absacc.h"
// 关闭外设
void Cls_Peripheral(void)
{ // IO模式(J13-2和J13-3相连)P0 = 0xFF;P2 = P2 & 0x1F | 0x80;            // P27~P25清零,再定位Y4CP2 &= 0x1F;                      // P27~P25清零P0 = 0;P2 = P2 & 0x1F | 0xA0;         // P27~P25清零,再定位Y5CP2 &= 0x1F;                      // P27~P25清零
//XBYTE[0x8000] = 0xFF;                // MM模式(J13-2和J13-1相连)
//XBYTE[0xA000] = 0;
}
// LED显示
void Led_Disp(unsigned char ucLed)
{ // IO模式(J13-2和J13-3相连)P0 = ~ucLed;                      //unsigned charP2 = P2 & 0x1F | 0x80;         // P27~P25清零,再定位Y4CP2 &= 0x1F;                      // P27~P25清零
//XBYTE[0x8000] = ~ucLed;          // MM模式(J13-2和J13-1相连)
}
// 延时函数(最小约1ms@12MHz)
void Delay(unsigned int num)
{unsigned int i;while(num--)for(i=0; i<628; i++);
}
// 主函数
void main(void)
{unsigned char i, j;Cls_Peripheral();while(1){ // 4个亮度等级for(i=0; i<4; i++)for(j=0; j<100; j++){Led_Disp(0xff);Delay(i+1);Led_Disp(0);Delay(4-i);}}
}

第一段:关闭外设
因为C51单片机默认P口为高电平,所以LED和蜂鸣器等等在程序运行前就会工作。具体原理看这个@我的头绝不是面团捏的 —— 蓝桥杯单片机比赛系列 1 初探关闭外设。
代码就直接放这了:

// 关闭外设
void Cls_Peripheral(void)
{ // IO模式(J13-2和J13-3相连)P0 = 0xFF;P2 = P2 & 0x1F | 0x80;            // P27~P25清零,再定位Y4CP2 &= 0x1F;                      // P27~P25清零P0 = 0;P2 = P2 & 0x1F | 0xA0;         // P27~P25清零,再定位Y5CP2 &= 0x1F;                      // P27~P25清零
//XBYTE[0x8000] = 0xFF;                // MM模式(J13-2和J13-1相连)
//XBYTE[0xA000] = 0;
}

(注:这个IO模式还是不懂诶,懂了我再填上,先放个参考博客——liu_endong——51 单片机 ——IO 口工作模式及配置)

第二段:LED 显示

// LED显示
void Led_Disp(unsigned char ucLed)
{ // IO模式(J13-2和J13-3相连)P0 = ~ucLed;                      //unsigned charP2 = P2 & 0x1F | 0x80;         // P27~P25清零,再定位Y4CP2 &= 0x1F;                      // P27~P25清零
//XBYTE[0x8000] = ~ucLed;          // MM模式(J13-2和J13-1相连)
}

先设置 P0 口,选择要点亮的灯的编码 ucled ,再选中 Y4 导通锁存器,在 LED 点亮后再锁存。

第三段:延时函数

// 延时函数(最小约1ms@12MHz)
void Delay(unsigned int num)
{unsigned int i;while(num--)for(i=0; i<628; i++);
}

这个就不用说了吧,应该都懂。

第四段:主函数

void main(void)
{unsigned char i, j; //设置无符号char型参数  i,j.Cls_Peripheral();   //关闭外设while(1)            //循环{ // 4个亮度等级for(i=0; i<4; i++)for(j=0; j<100; j++){Led_Disp(0xff);//1111 1111,全灭Delay(i+1);    //设置延迟时间Led_Disp(0);   //0000 0000  全亮Delay(4-i);    //}}
}

呼吸灯其实就是以不同的亮度点亮led灯,关键就在于如何以不同的亮度来点亮led灯,也就是改变led灯的亮度。简单的方法就是在肉眼观察不到的时间范围内,改变 led 点亮时间的占比,从而形成不同亮度的视觉效果。

// 4个亮度等级
for(i=0; i<4; i++)for(j=0; j<100; j++){Led_Disp(0xff);//1111 1111,全灭Delay(i+1);    //设置延迟时间Led_Disp(0);   //0000 0000  全亮Delay(4-i);    //}

两个循环,第一个循环和Delay函数一起用来设置亮与灭的时间,从而设置灯的亮度等级。第二个循环则设置每一个亮度等级的运行时间。
第二个循环内的内容,是将亮与灭的时间分为四份,按照不同搭配组合调节灯的亮度。

我的代码

led.c

/****************************************************************************
* Copyright (C), 2022,Moqim
* 文件名: led.c
* 内容简述:LED初始化、LED控制函数
*
* 文件历史:
* 版本号      日期       作者     说明
*   01a    2022-04-24   Moqim   创建该文件
*
* All rights reserved
*/#include "led.h"/****************************************************************************
* 函数名: LED_Init()
* 功 能: 关闭全部的LED灯
* 输 入: 无
* 输 出: 无
*/
void LED_Init(void)
{   P0 = 0Xff;            //拉高所有PO端口P2 = P2 & 0x1f | 0x80;// P27~P25清零,再定位Y4C  关闭ledP2 &= 0x1f;           // P27~P25清零,锁存
}/****************************************************************************
* 函数名: LED_Ctrl()
* 功 能: 关闭全部的LED灯
* 输 入: 无
* 输 出: 无
*/
void LED_Ctrl(unsigned char ucLed)//uc 表示 "unsigned char" 类型
{P0 = ~ucLed;          //ucled取反 0000 0001 -> 1111 1110P2 = P2 & 0x1f | 0x80;// P27~P25清零,再定位Y4CP2 &= 0x1f;           // P27~P25清零,锁存
}

led.h

//为了防止头文件被重复引用,应当用 ifndef/define/endif结构产生预处理块#ifndef __LED_H
#define __LED_H#include "stc15f2k60s2.h"void LED_Init(void);
void LED_Ctrl(unsigned char ucLed);#endif /*__LED_H*/

main.c

/****************************************************************************
* Copyright (C), 2022,Moqim
* 文件名: main.c
* 内容简述:实现十个等级的呼吸灯与向右移动的LED流水灯
*
* 文件历史:
* 版本号      日期       作者     说明
*   01a    2022-04-24   Moqim   创建该文件
*
* All rights reserved
*///头文件调用区
#include "stc15f2k60s2.h"
#include "led.h"//变量定义区//函数声明区
void LED_NotifyLight(void);
void LED_Runningwater(void);
void Delay_ms(unsigned int num);//Main Body
int main(void)
{LED_Init();while (1){LED_NotifyLight();LED_Runningwater();}}/****************************************************************************
* 函数名: LED_NotifyLight()
* 功 能: 实现10个等级的呼吸灯
* 输 入: 无
* 输 出: 无
* 说 明:像油画调色一样,不同比例的亮与暗的搭配,可以实现LED的不同亮度
*/
void LED_NotifyLight(void)
{int i, j;for(i=0; i<10; i++)//划分等级,将LED的亮度划分为十份for(j=0; j<100; j++)//为保证肉眼能够观察,将每个时段的时间扩大一百倍{//熄灭时间 + 点亮时间 = 10(按比例理解也是一样的)LED_Ctrl(0xff);Delay_ms(i+1);//设定LED熄灭的时间LED_Ctrl(0);Delay_ms(10-i);//设定LED点亮的时间}
}/****************************************************************************
* 函数名: LED_Runningwater()
* 功 能: 实现向右移动的LED流水灯
* 输 入: 无
* 输 出: 无
* 说 明:注意蓝桥杯板子上LED灯的排序,是低位在前,~0x01在第一个,~0x02在第二个,~0x04在......
*/
void LED_Runningwater(void)
{int i = 0;//变量定义放在外面,或者紧挨着函数开头的括号for (i = 0;i<8;i++)//右移8次 (包括移动0位){LED_Ctrl(0x01 << i);//取反后为:1111 1110 -> 1111 1101 ->1111 1011 ->......Delay_ms(500);}
}/****************************************************************************
* 函数名: Delay_ms()
* 功 能: 延时
* 输 入: unsigned int num:延时num毫秒
* 输 出: 无
*/
void Delay_ms(unsigned int num)//软件延时不精确,凑合用吧
{int i,j;for(i = 0;i<num;i++){for(j = 0;j<625;j++);}
}

老师的代码(流水灯)

int i;
while(1){for(i=0;i<8;i++){P0 = ~(1<<i);//从右往左//从左往右   P0 = ~(0x80>>i);P2 = P2 & 0x1F | 0x80;P2& = 0x1F;}}

注:

流水灯连续左移右移可能会导致有一个灯闪烁两次,为了解决这个问题,可以使得左移 1-7,右移也 1-7,直接交叉点亮。

蓝桥杯——单片机学习(3——点亮LED灯)相关推荐

  1. 蓝桥杯嵌入式第一篇 点亮LED灯开启成功之路

    文章目录 前言 一.准备工作 1.拿到开发板第一步看原理图 2.下载STM32cubeMX 二.开始点灯 1.查看LED原理图 2.cubeMX配置 3.代码实现 总结 前言 从这篇文章开始将为大家带 ...

  2. 【蓝桥杯—单片机学习笔记(四)】共阳数码管的动态显示

    一.要求 在CT107D单片机训练综合平台上,实现数码管的动态显示,在8位数码管中,前面4位显示年份"2022",接着是2个分隔符"--",最后两位是月份,从1 ...

  3. 蓝桥杯单片机学习11——PCF8591A/DD/A转换芯片

    上期我们学习了DS1302实时时钟的基本使用,现在我们来学习PCF8591A/D&D/A转换芯片的相关内容 蓝桥杯单片机学习11--PCF8591A/D&D/A转换芯片 PCF8591 ...

  4. 蓝桥杯单片机学习13——NE555方波发生器频率测量

    NE555 简介 引脚图 原理图 真值表 工作原理 频率测量原理 定时器测量频率方法 代码实现 总结(一堆废话) 简介 NE555是一种高度稳定的控制器,内部用三个阻值为5KΩ的电阻分压,因此叫做55 ...

  5. 蓝桥杯单片机学习12——AT24C02EEPROM存储芯片

    上期我们学习了PCF8591A/D&D/A转换芯片的相关内容,这么我们来介绍以下AT24C02 AT24C02 简介 命名格式 引脚描述 原理图 IIC通信原理 读写地址 存储地址 基本控制方 ...

  6. 蓝桥杯单片机学习日记3-矩阵键盘的使用,线反转法,三步消抖,按键长按与短按

    此片文章用于记录蓝桥杯单片机的学习 篮球杯单片机上的矩阵按键原理图如下: 使用矩阵键盘时,要将跳线帽J5跳至KBD模式. 值得注意的是,若开发板上的单片机使用的为STC15,那么以上原理图适用.如果单 ...

  7. 【蓝桥杯-单片机学习笔记(六)】矩阵键盘控制数码管显示0~F

    一.要求 在CT107D单片机训练平台上,首先将J5处的跳线帽接到1~2引脚,使按键S4~S19组成4*4的矩阵键盘.在扫描按键的过程中,发现有按键触发信号后,待按键松开后,数码管显示相应的数字.按键 ...

  8. 【STM32学习笔记-点亮LED灯】

    STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...

  9. 单片机C语言-1-点亮LED灯

    单片机C语言-1-点亮LED灯 #include "stm32f10x.h" //引入头文件//高低电平 //低电平 GND 0V //高电平 VCC 单片机的VCC供电电压//I ...

  10. 蓝桥杯单片机学习日记1-LED 蜂鸣器 继电器 数码管的简单驱动

    此片文章用于记录蓝桥杯单片机的学习. LED 蜂鸣器 继电器 数码管 这些都是比赛时常用的外设,如下原理图:  LED部分:  蜂鸣器和继电器部分(图中还有步进电机部分):  数码管部分: 可见,上述 ...

最新文章

  1. centos7安装sql-server2017
  2. xbox acc驱动win7_Xbox老大:希望第一方工作室能推出更多单机游戏_电竞
  3. JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
  4. 开源文件服务器file-service介绍
  5. 探究make_shared效率
  6. 点这里,关注计算机视觉技术最前沿~
  7. vs2017环境下编译log4cpp-1.1.3
  8. SEO小白学习与实践(一):seo学习缘起、目标
  9. 适合计算机社团活动的游戏,适合大学社团活动“游戏”有哪些?
  10. 小区门口的健身房,就是韭菜收割厂
  11. visio常用快捷键_Visio2019常用形状对象的快捷键及常用操作技巧举例(一)
  12. 不积跬步无以至千里 不积小流无以成江海
  13. 记一次gitlab添加用户收不到邮件的解决办法
  14. C#事件中sender的小用法(转载)
  15. Google-indexing api使用
  16. Julia Computing获得 2400 万美元融资,前 Snowflake CEO 加入董事会
  17. 荒野今天维护服务器吗,荒野行动1月29日为什么无法登录原因 今天停服更新维护吗?...
  18. 未分配利润与利润表不一致_资产负债表中的未分配利润和利润表中的净利润肯定是一致的吗?...
  19. Qt编写的开源帖子集合(懒人专用)
  20. js【详解】arr.splice() 数组拼接

热门文章

  1. 华为手机真机测试问题 The application could not be installed: INSTALL_FALLED_INTERNAL_ERROR
  2. 任务服务器未响应,win10任务管理器没有响应的解决方法
  3. 罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了。之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原因
  4. Xilinx SDSoc 加载opencv库
  5. Git 笔记 - git rebase
  6. 【攻防世界7-12题】题解和解题心得
  7. 第九弹:计算机编程入门,免费学习资源,2020.07.05更新
  8. 以太网没有有效IP配置的解决方法
  9. 超详细的《使用腾讯云移动直播开发连麦》
  10. everedit选择_文本编辑器软件EverEdit怎么样?EverEdit相关功能介绍