51单片机实现两片联级74HC595驱动16个LED灯

最新更新时间:2022-02-19来源: eefocus关键字:51单片机  74HC595  LED灯 手机看文章 扫描二维码
随时随地手机看文章

一、使用proteus绘制简单的电路图,用于后续仿真

二、编写程序


/********************************************************************************************************************

----@Project:LED-74HC595

----@File:main.c

----@Edit:ZHQ

----@Version:V1.0

----@CreationTime:20200524

----@ModifiedTime:20200524

----@Description:两片联级的74HC595驱动的16个LED灯交叉闪烁。比如,先是第1,3,5,7,9,11,13,15八个灯亮,其它的灯都灭。然后再反过来,原来亮的就灭,原来灭的就亮。交替闪烁。

----单片机:AT89C52

********************************************************************************************************************/

#include "reg52.h"

/*——————宏定义——————*/

#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   /*1ms timer calculation method in 12Tmode*/

 

#define const_time_level  400   

 

 

/*——————变量函数定义及声明——————*/

/*定义74HC595*/

sbit Hc595_Sh = P2^3;

sbit Hc595_St = P2^4;

sbit Hc595_Ds = P2^5;

 

unsigned char ucLED1 = 0;   /*代表16个灯的亮灭状态,0代表灭,1代表亮*/

unsigned char ucLED2 = 0;

unsigned char ucLED3 = 0;

unsigned char ucLED4 = 0;

unsigned char ucLED5 = 0;

unsigned char ucLED6 = 0;

unsigned char ucLED7 = 0;

unsigned char ucLED8 = 0;

unsigned char ucLED9 = 0;

unsigned char ucLED10 = 0;

unsigned char ucLED11 = 0;

unsigned char ucLED12 = 0;

unsigned char ucLED13 = 0;

unsigned char ucLED14 = 0;

unsigned char ucLED15 = 0;

unsigned char ucLED16 = 0;

 

 

unsigned char ucLed_update = 0;  /*刷新变量。每次更改LED灯的状态都要更新一次。*/

 

unsigned char ucLedStep = 0; /*步骤变量*/

unsigned int  uiTimeCnt = 0; /*统计定时中断次数的延时计数器*/

 

unsigned char ucLedStatus16_09 = 0;   /*代表底层74HC595输出状态的中间变量*/

unsigned char ucLedStatus08_01 = 0;   /*代表底层74HC595输出状态的中间变量*/

 

/**

* @brief  定时器0初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_T0(void)

{

TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

}

/**

* @brief  外围初始化函数

* @param  无

* @retval 初始化外围

**/

void Init_Peripheral(void)

{

ET0 = 1;/*允许定时中断*/

TR0 = 1;/*启动定时中断*/

EA = 1;/*开总中断*/

 

}

 

/**

* @brief  初始化函数

* @param  无

* @retval 初始化单片机

**/

voidInit(void)

{

Init_T0();

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i   {

      for(j=0;j<500;j++)  /*内嵌循环的空指令数量*/

          {

             ; /*一个分号相当于执行一条空语句*/

          }

   }

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Short(unsigned int uiDelayShort)

{

   unsigned int i;

   for(i=0;i   {

; /*一个分号相当于执行一条空语句*/

   }

}

 

/**

* @brief  595驱动函数

* @param  无

* @retval * 两个联级74HC595的工作过程:

* 每个74HC595内部都有一个8位的寄存器,两个联级起来就有两个寄存器。ST引脚就相当于一个刷新

* 信号引脚,当ST引脚产生一个上升沿信号时,就会把寄存器的数值输出到74HC595的输出引脚并且锁存起来,

* DS是数据引脚,SH是把新数据送入寄存器的时钟信号。也就是说,SH引脚负责把数据送入到寄存器里,ST引脚

* 负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。

**/

void HC595_Drive(unsigned char ucLedStatusTemp16_09, unsigned char ucLedStatusTemp08_01)

{

unsigned char i;

unsigned char ucTempData;

Hc595_Sh = 0;

Hc595_St = 0;

ucTempData = ucLedStatusTemp16_09;/*先送高8位*/

for(i = 0; i < 8; i ++)

{

if(ucTempData >= 0x80)

{

Hc595_Ds = 1;

}

else

{

Hc595_Ds = 0;

}

Hc595_Sh = 0;/*SH引脚的上升沿把数据送入寄存器*/

Delay_Short(15); 

Hc595_Sh = 1;

Delay_Short(15);

ucTempData = ucTempData <<1;

}

ucTempData = ucLedStatusTemp08_01;/*再先送低8位*/

for(i = 0; i < 8; i ++)

{

if(ucTempData >= 0x80)

{

Hc595_Ds = 1;

}

else

{

Hc595_Ds = 0;

}

Hc595_Sh = 0;/*SH引脚的上升沿把数据送入寄存器*/

Delay_Short(15); 

Hc595_Sh = 1;

Delay_Short(15);

ucTempData = ucTempData <<1;

}

Hc595_St = 0;/*ST引脚把两个寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来*/

Delay_Short(15);

Hc595_St = 1;

Delay_Short(15);

Hc595_Sh = 0;/*拉低,抗干扰就增强*/

Hc595_St = 0;

Hc595_Ds = 0;

}

/**

* @brief  LED更新函数

* @param  无

* @retval 

* 把74HC595驱动程序翻译成类似单片机IO口直接驱动方式的过程。

* 每次更新LED输出,记得都要把ucLed_update置1表示更新。

**/

void LED_Update()

{

if(ucLed_update == 1)

{

ucLed_update = 0;/*及时清零,让它产生只更新一次的效果,避免一直更新。*/

if(ucLED1 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x01;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xfe;

}

if(ucLED2 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x02;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xfd;

}

if(ucLED3 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x04;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xfb;

}

if(ucLED4 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x08;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xf7;

}

if(ucLED5 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x10;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xef;

}

if(ucLED6 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x20;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xdf;

}

if(ucLED7 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x40;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0xbf;

}

if(ucLED8 == 1)

{

ucLedStatus08_01 = ucLedStatus08_01 | 0x80;

}

else

{

ucLedStatus08_01 = ucLedStatus08_01 & 0x7f;

}

if(ucLED9 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x01;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xfe;

}

if(ucLED10 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x02;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xfd;

}

if(ucLED11 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x04;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xfb;

}

if(ucLED12 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x08;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xf7;

}

if(ucLED13 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x10;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xef;

}

if(ucLED14 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x20;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xdf;

}

if(ucLED15 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x40;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0xbf;

}

if(ucLED16 == 1)

{

ucLedStatus16_09 = ucLedStatus16_09 | 0x80;

}

else

{

ucLedStatus16_09 = ucLedStatus16_09 & 0x7f;

}

HC595_Drive(ucLedStatus16_09, ucLedStatus08_01);

}

}

/**

* @brief  LED闪烁函数

* @param  无

* @retval 无

**/

void LED_Flicker(void)

{

switch(ucLedStep)

{

case 0:

if(uiTimeCnt >= const_time_level)

{

uiTimeCnt = 0;/*时间计数器清零*/

ucLED1 = 1;/*每个变量都代表一个LED灯的状态*/

ucLED2 = 0;

ucLED3 = 1;

ucLED4 = 0;

ucLED5 = 1;

ucLED6 = 0;

ucLED7 = 1;

ucLED8 = 0;

ucLED9 = 1;

ucLED10 = 0;

ucLED11 = 1;

ucLED12 = 0;

ucLED13 = 1;

ucLED14 = 0;

ucLED15 = 1;

ucLED16 = 0;

ucLed_update = 1;  /*更新显示*/

ucLedStep = 1;

}

break;

case 1:

if(uiTimeCnt >= const_time_level)

{

uiTimeCnt = 0;/*时间计数器清零*/

ucLED1 = 0;/*每个变量都代表一个LED灯的状态*/

ucLED2 = 1;

ucLED3 = 0;

ucLED4 = 1;

ucLED5 = 0;

ucLED6 = 1;

ucLED7 = 0;

ucLED8 = 1;

ucLED9 = 0;

ucLED10 = 1;

ucLED11 = 0;

ucLED12 = 1;

ucLED13 = 0;

ucLED14 = 1;

ucLED15 = 0;

ucLED16 = 1;

ucLed_update = 1;  /*更新显示*/

ucLedStep = 0;

}

break;

}

}

/**

* @brief  定时器0中断函数

* @param  无

* @retval 无

**/

void ISR_T0(void)interrupt 1

{

TF0 = 0;  /*清除中断标志*/

  TR0 = 0; /*关中断*/

if(uiTimeCnt < 0xffff)/*设定这个条件,防止uiTimeCnt超范围。*/

{

uiTimeCnt ++;

}

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

  TR0 = 1; /*开中断*/

}

 

/*——————主函数——————*/

/**

* @brief  主函数

* @param  无

* @retval 实现LED灯闪烁

**/

void main()

{

/*单片机初始化*/

Init();

/*延时,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定*/

Delay_Long(100);

/*单片机外围初始化*/

Init_Peripheral();

while(1)

{

/*按键服务函数*/

LED_Flicker();

/*LED更新函数*/

LED_Update(); 

}

}

 

三、仿真实现


关键字:51单片机  74HC595  LED灯 编辑:什么鱼 引用地址:51单片机实现两片联级74HC595驱动16个LED灯

上一篇:51单片机实现两片联级74HC595依次点亮LED后依次熄灭
下一篇:51单片机实现矩阵键盘的组合按键触发

推荐阅读

用AT89C51单片机显示倒计时程序
;可设定时间的倒计时定时器,可选择5/15/20/30/35/45/50分钟倒计时;倒计时时间由四位拨码开关的2/3/4位来控制,;第2位表示5分钟,第3位表示15分钟,第4位表示30分钟,;通过不同的组合可以产生5/15/20/30/35/45/50分钟倒计时;P1.0口的外接的发光二极管为状态LED,定时未开始时LED常亮,定时过程中LED闪烁;K1为开始按钮,K2为停止按钮适用STM8S/STM8L/STM8A N76E003 脱机编程器/烧录器/下载器/SP_00【包邮】m.tb.cn/h.UlXVKiOa_bit equ 20h ;数码管个位数存放内存位置b_bit equ 21h ;数码管十位数存放内存位置temp eq
发表于 2023-01-13
51单片机数码管静态显示和动态显示原理及实验 夜猫子
数码管多位数码管,即是两个或两个以上单个数码管并列集中在一起形成一体的数码管。当多位一体时,它们内部的公共端是独立的,而负责显示什么数字的段线全部是连接在一起的,独立的公共端可以控制多位一体中的哪一位数码管点亮,而连接在一起的段线可以控制这个能点亮数码管亮什么数字,通常我们把公共端叫做“位选线”,连接在一起的段线叫做“段选线”有了这两个线后,通过单片机及外部驱动电路就可以控制任意的数码管显示。一般一位数码管有10个引脚,二位数码管也是10个引脚,四位数码管是12个引脚。为了更方便区分段选和位选,请看下原理图:如图为两个4位一体的数码管,可以看到与8个com相连的是两个数码管的位选,位选与引脚相连,所以位选控制那个灯亮。段选可以看到a
发表于 2023-01-12
<font color='red'>51单片机</font>数码管静态显示和动态显示原理及实验 夜猫子
51单片机独立按键和矩阵按键实现
独立按键实验按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。我们开发板上使用的按键及内部简易图如下图所示管脚与管脚之间(注意是距离)距离长的是导通状态,短的是接通状态。通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号如下图所示:如图所示,按键闭合式不会立刻稳定的接通,断开时也不会一下子断开,会伴随一些抖动。抖动的时间长短有按键特性决定,一般为5Ms到10ms.按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖。消抖消抖可分为硬件消抖和软件消抖。为了使电路更加简单,通常采用软件消抖。一般来说一个简单的按键消抖就是先读取按键的状态, 如果得到按键按下
发表于 2023-01-12
51单片机8*8点阵原理及实现
LED点阵(8*8)LED 点阵是由发光二极管排列组成的显示器件,在我们日常生活的电器中随处可见,被广泛应用于汽车报站器,广告屏等。通常应用较多的是 8* 8 点阵,然后使用多个 8 * 8 点阵可组成不同分辨率的 LED点阵显示屏,比如 16* 16 点阵可以使用 4 个 8* 8 点阵构成。因此理解了 8* 8LED点阵的工作原理,其他分辨率的 LED 点阵显示屏都是一样的。这里以 8* 8LED 点阵来做介绍。发光原理8* 8 点阵共由 64 个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置 1 电平(行所接的是二极管的阳极,所以为高电平),某一列置 0 电平(列所接的是二极管的阴极极,所以为低
发表于 2023-01-12
51单片机中断基本概念
问题引入在了解基本概念之前,先看三个问题:1.你想使用的中断是哪个?2.你所希望的触发条件是什么?3.你希望在中断之后做什么?可以边看边思考,文章最后给出答案中断概念为什么引入中断?中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。中断系统特点:①分时操作。CPU 可以分时为多个 I/O 设备服务,提高了计算机的利用率;②实时响应。CPU 能够及时处理应用系统的随机事件,系统的实时性大大增强;③可靠性高。CPU 具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高中断过程对于单片机来讲,中断是指CPU在处理某一时间A时,发生了另一事件B请求CPU立
发表于 2023-01-12
51单片机外部中断点亮LED
外部中断软件设计原理中断发生的三个条件①中断源有中断请求;②此中断源的中断允许位为 1;③CPU 开中断(即 EA=1)。比如我们配置外部中断 0,对应的配置程序如下:EA=1;//打开总中断开关EX0=1;//开外部中断 0IT0=0/1;//设置外部中断的触发方式(下降沿触发)如果要配置的是外部中断 1,只需将 EX0 改为 EX1,IT0 改为 IT1在编写程序时通常我们会将外部中断的配置放到一个自定义函数内便于管理维护。如下伪代码所示:void Int0Init(){//设置 INT0IT0=1;//边沿触发方式(下降沿)EX0=1;//打开 INT0 的中断允许。EA=1;//打开总中断}/*当触发中断后即会进入中断服务函
发表于 2023-01-12

推荐帖子

mini2440的按键控制LED小程序~~~
看到坛子里很多人拿到板子后不知道第一步该如何做, 在网上看到一个朋友的博客,感觉还不错,对于购买板子的朋友应该有所帮助,所以呈现出来: 来源:http://adreaman.com/0524arm-mini2440-led-key-non-os.html mini2440是当前最经济的arm9开发板了,目前就是500多元一块,麻雀虽小,重要的那几个部件也还算齐全,用它来做计算机系统底层的学习工具很合适。而且关于s3c2410/2440系列的教程资料和经验文章在网上很多,大家遇到问题时多
fish001 嵌入式系统
MOS管 DS脚的峰值电压测试以哪个为标准
MOS管的DS脚的峰值电压测试以哪个为标准呢 \0\0\0eeworldpostqqMOS管DS脚的峰值电压测试以哪个为标准
桂花蒸 电源技术
PNG双缓冲问题,为什么我的图片不能显示呢??
intwidth=dstRc.right-dstRc.left, heigth=dstRc.top-dstRc.bottom; HDCmemDC=CreateCompatibleDC(hdc);//关联两个DC HBITMAPhBitmap=CreateCompatibleBitmap(hdc,width,heigth);//在缓冲中建立BITMAP
kakashi2010 嵌入式系统
当CMOS遇上TTL
本帖最后由fish001于2018-6-2617:51编辑 当COMS遇上TTL,现阶段只有纠结,因为对两者之间的联系?区别?都没有理性的认识,为此今日在此做一小小比较。 TTL:Transistor—TransistorLogic.标准的TTL电路输入高电平最小为2V,输出高电平为2.4V,典型值为3.4V;输入低电平最高为0.8V,输出低电平最高0.4V,典型值为0.2V.TTL电路电源供电只允许在5V+/-10%范围内,且扇出数为10个以下的TTL门电路。
fish001 模拟与混合信号
【国产FPGA 正点原子DFPGL22G开发板】二、千兆以太网测评【硬件设计篇】
本帖最后由yyliu于2023-1-618:36编辑 声明:针对本帖中可能出现的侵权行为,请及时联系本人修改或删除。未经本人允许,请勿转载。若本帖存在错误或不足之处,烦请指正,本人会及时修改。 0.说明 第二期将对千兆以太网模块进行测评,由于本人从事硬件设计工作,第二期打算出两篇测评:硬件设计篇和程序设计篇。硬件设计篇主要介绍DFPGL22G开发板千兆以太网模块的硬件方案,以及一些硬件设计细节;程序设计篇主要介绍千兆以太网通信的程序框图和代码实现,有条件的话还会做一些
yyliu 国产芯片交流
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved