历史上的今天

今天是:2024年11月12日(星期二)

2021年11月12日 | 51单片机实现两片联级74HC595依次点亮且每次只能点亮一个

发布者:大泉人家 来源: eefocus关键字:51单片机  74HC595  逐个亮灯 手机看文章 扫描二维码
随时随地手机看文章

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

二、编写程序


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

----@Project:LED-74HC595

----@File:main.c

----@Edit:ZHQ

----@Version:V1.0

----@CreationTime:20200526

----@ModifiedTime:20200526

----@Description:第9个至第16个LED灯,依次逐个亮灯并且每次只能亮一个灯。第1至第8个LED灯一直灭。

----单片机:AT89C52

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

#include "reg52.h"

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

#define FOSC 11059200L

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

 

#define const_time_level_09_16  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_09_16 = 0; /*第9个至第16个LED跑马灯的步骤变量*/

unsigned int  uiTimeCnt_09_16 = 0; /*第9个至第16个LED跑马灯的统计定时中断次数的延时计数器*/

 

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_09_16(void)

{

switch(ucLedStep_09_16)

{

case 0:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED16 = 0;

ucLED9 = 1;

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

ucLedStep_09_16 = 1;

}

break;

case 1:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED9 = 0;

ucLED10 = 1;

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

ucLedStep_09_16 = 2;

}

break;

case 2:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED10 = 0;

ucLED11 = 1;

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

ucLedStep_09_16 = 3;

}

break;

case 3:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED11 = 0;

ucLED12 = 1;

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

ucLedStep_09_16 = 4;

}

break;

case 4:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED12 = 0;

ucLED13 = 1;

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

ucLedStep_09_16 = 5;

}

break;

case 5:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED13 = 0;

ucLED14 = 1;

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

ucLedStep_09_16 = 6;

}

break;

case 6:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED14 = 0;

ucLED15 = 1;

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

ucLedStep_09_16 = 7;

}

break;

case 7:

if(uiTimeCnt_09_16 >= const_time_level_09_16)

{

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

ucLED15 = 0;

ucLED16 = 1;

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

ucLedStep_09_16 = 0;

}

break;

}

}

/**

* @brief  定时器0中断函数

* @param  无

* @retval 无

**/

void ISR_T0(void)interrupt 1

{

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

  TR0 = 0; /*关中断*/

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

{

uiTimeCnt_09_16 ++;

}

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_09_16();

/*LED更新函数*/

LED_Update(); 

}

}

 

三、仿真实现



关键字:51单片机  74HC595  逐个亮灯 引用地址:51单片机实现两片联级74HC595依次点亮且每次只能点亮一个

上一篇:51单片机实现两片联级74HC595多任务并行处理两路跑马灯
下一篇:51单片机实现两片联级74HC595依次点亮LED后依次熄灭

推荐阅读

专注于提供海量库存的电子元器件分销商贸泽电子 (Mouser Electronics) 即日起开始供应超低功耗的Bosch BMA400三轴加速度计。BMA400加速度计可在出色性能与低功耗之间取得绝佳平衡,耗电量只有同类加速度传感器的十分之一,还赢得了2018年消费电子展 (CES) 大奖。BMA400加速度计适合需要不间断电池供电的设备,是物联网 (IoT) 和可穿戴应用的理想之...
11 月 12 日讯,汽车行业的电子化步伐正在加速,恩智浦也加快了中国本土车企合作脚步。 近期,恩智浦宣布新一代智能驾舱在启辰 T90 上实现首次量产,而此前,恩智浦已相继宣布了与长安汽车、吉利汽车和北汽集团的战略合作。 作为全球第一大汽车市场,中国对以汽车半导体为核心业务的恩智浦意义重大,而随着中国对汽车电动化和自动驾驶发展的重视,恩...
据集微网了解,11月12日,深圳市利和兴股份有限公司(简称“利和兴”)创业板IPO成功过会。据悉,利和兴自设立以来专注于自动化、智能化设备的研发、生产和销售,致力于成为新一代信息和通信技术领域(5G)领先的智能制造解决方案提供商。目前,公司作为设备供应商,主要服务于信息和通信技术等领域客户,实现高端装备制造与新一代信息技术等新产业的深度...
根据外媒 techpowerup 报道,韩国企业 SK 海力士于 11 月 11 日获得了 ISO 26262: 2018 FSM 汽车半导体芯片安全认证。这一认证由全球汽车功能安全认证机构 TUV Nord 颁布,两家公司举办了证书颁布仪式。ISO 26262 标准由国际标准组织于 2011 年制定,目的是保证相关产品能满足汽车工况,以防汽车电子、电气系统发生故障引发事故。本次...

史海拾趣

问答坊 | AI 解惑

HT1380串行时钟芯片

HT1380串行时钟芯片一般来说,HT系列的芯片在串行口的应用一直以来就是很好的在单片机 这个领域,串行时钟一直占着很重要的位置…

查看全部问答∨

Introduction to NI VeriStand

Introduction to NI VeriStand…

查看全部问答∨

奇怪了,请大家看下做标记的那几行代码

请大家看下下面打问号几行代码,抛开其功能不说,真的是奇怪了,我都看了又看,头都大了,就是不知道为什么,请朋友们指点下 #include<reg52.h>                     &nbs ...…

查看全部问答∨

evc托盘编程

使用evc4.0编写一个系统托盘,就是我的程序起来之后,不显示对话框,自动出现一个图标到右下角,通过双机图标,可以弹出对话框。 右键单击右下角图标,可以弹出一个菜单。 不知道如何实现这些功能,请兄弟姐妹们帮个忙!…

查看全部问答∨

请高手帮忙~~~在EVC下的2个函数没定义.

error C2065: \'GetRunningObjectTable\' : undeclared identifier error C2065: \'CreateItemMoniker\' : undeclared identifier 我用的是EVC 4.0+SP4…

查看全部问答∨

si4010有没有人用过,求探讨

si4010有没有人用过,求探讨,开发软件,调试软件,烧录工具等等…

查看全部问答∨

STM32的驱动库好用吗?效率高吗?优化的吗?准备上STM32

    N多年没买过开发板了,也没用过仿真器了。都是用软件编译调试好,直接ISP,然后通过串口命令开启调试信息的输出。    昨天买了块STM32F103全功能型开发板,他们的办事效率真低(深圳到广州通常当 ...…

查看全部问答∨

求IAR Embedded Workbench for MCS-51 完整版

各位高手,小弟求IAR Embedded Workbench for MCS-51完整版,有哪位高人有,能否分享一下。我的邮箱jinghongchen@126.com…

查看全部问答∨

猎头招聘

世界500强招聘压力传感器SAE,如有兴趣可发简历至:aerie.song@seek-jobs.com.cn 要求:至少五年以上相关工作经验,英文流利。…

查看全部问答∨

批评英蓓特,一个细节反映出的不认真

还是说说今天参加安富利的“ARM研讨会”,参观展台时,逛到了英蓓特(EMBEST)那里。大家可能知道,这家公司就是专门围绕ARM生存的,有很多ARM开发板。我在看到英蓓特展台的易拉宝时,楞了一下,原来上面罗列的产品线时,赫然有“Luminary系列”。 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved