第18节:把74HC595驱动程序翻译成类似单片机IO口直接驱动的方

发布者:Serendipity99最新更新时间:2016-03-14 来源: eefocus关键字:74HC595  驱动程序  单片机  IO口  直接驱动 手机看文章 扫描二维码
随时随地手机看文章
开场白:

上一节讲了74HC595的驱动程序。为了更加方便操作74HC595输出的每个IO状态,这节讲如何把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式。要教会大家两个知识点:

第一点:如何灵活运用与和非的运算符来实现位的操作。

第二点:如何灵活运用一个更新变量来实现静态刷新输出或者静态刷新显示的功能。

具体内容,请看源代码讲解。

 

(1)硬件平台:基于朱兆祺51单片机学习板。

 

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

 

(3)源代码讲解如下:

#include "REG52.H"

 

#define const_time_level 200  

 

void initial_myself();    

void initial_peripheral();

void delay_short(unsigned int uiDelayShort); 

void delay_long(unsigned int uiDelaylong);

void led_flicker();

void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);

void led_update();  //LED更新函数

void T0_time();  //定时中断函数

 

 

sbit hc595_sh_dr=P2^3;    

sbit hc595_st_dr=P2^4;  

sbit hc595_ds_dr=P2^5;  

 

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

unsigned char ucLed_dr2=0;

unsigned char ucLed_dr3=0;

unsigned char ucLed_dr4=0;

unsigned char ucLed_dr5=0;

unsigned char ucLed_dr6=0;

unsigned char ucLed_dr7=0;

unsigned char ucLed_dr8=0;

unsigned char ucLed_dr9=0;

unsigned char ucLed_dr10=0;

unsigned char ucLed_dr11=0;

unsigned char ucLed_dr12=0;

unsigned char ucLed_dr13=0;

unsigned char ucLed_dr14=0;

unsigned char ucLed_dr15=0;

unsigned char ucLed_dr16=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输出状态的中间变量

 

void main() 

  {

   initial_myself();  

   delay_long(100);   

   initial_peripheral(); 

   while(1)   

   {

      led_flicker();   

          led_update();  //LED更新函数

   }

 

}

 

 

/* 注释一:

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

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

*/

void led_update()  //LED更新函数

{

 

   if(ucLed_update==1)

   {

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

 

       if(ucLed_dr1==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x01;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfe;

           }

 

       if(ucLed_dr2==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x02;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfd;

           }

 

       if(ucLed_dr3==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x04;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfb;

           }

 

       if(ucLed_dr4==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x08;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xf7;

           }

 

 

       if(ucLed_dr5==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x10;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xef;

           }

 

 

       if(ucLed_dr6==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x20;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xdf;

           }

 

 

       if(ucLed_dr7==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x40;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xbf;

           }

 

 

       if(ucLed_dr8==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x80;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0x7f;

           }

 

       if(ucLed_dr9==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x01;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfe;

           }

 

       if(ucLed_dr10==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x02;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfd;

           }

 

       if(ucLed_dr11==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x04;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfb;

           }

 

       if(ucLed_dr12==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x08;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xf7;

           }

 

 

       if(ucLed_dr13==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x10;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xef;

           }

 

 

       if(ucLed_dr14==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x20;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xdf;

           }

 

 

       if(ucLed_dr15==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x40;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xbf;

           }

 

 

       if(ucLed_dr16==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x80;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0x7f;

           }

 

       hc595_drive(ucLedStatus16_09,ucLedStatus08_01);  //74HC595底层驱动函数

 

   }

}

 

void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)

{

   unsigned char i;

   unsigned char ucTempData;

   hc595_sh_dr=0;

   hc595_st_dr=0;

 

   ucTempData=ucLedStatusTemp16_09;  //先送高8位

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

   { 

         if(ucTempData>=0x80)hc595_ds_dr=1;

         else hc595_ds_dr=0;

 

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

         delay_short(15); 

         hc595_sh_dr=1;

         delay_short(15); 

 

         ucTempData=ucTempData<<1;

   }

 

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

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

   { 

         if(ucTempData>=0x80)hc595_ds_dr=1;

         else hc595_ds_dr=0;

 

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

         delay_short(15); 

         hc595_sh_dr=1;

         delay_short(15); 

 

         ucTempData=ucTempData<<1;

   }

 

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

   delay_short(15); 

   hc595_st_dr=1;

   delay_short(15); 

 

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

   hc595_st_dr=0;

   hc595_ds_dr=0;

 

}

 

 

void led_flicker() ////第三区 LED闪烁应用程序

{

  switch(ucLedStep)

  {

     case 0:

           if(uiTimeCnt>=const_time_level) //时间到

           {

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

 

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

               ucLed_dr2=0;

               ucLed_dr3=1;

               ucLed_dr4=0;

               ucLed_dr5=1;

               ucLed_dr6=0;

               ucLed_dr7=1;

               ucLed_dr8=0;

               ucLed_dr9=1;

               ucLed_dr10=0;

               ucLed_dr11=1;

               ucLed_dr12=0;

               ucLed_dr13=1;

               ucLed_dr14=0;

               ucLed_dr15=1;

               ucLed_dr16=0;

 

               ucLed_update=1;  //更新显示

               ucLedStep=1; //切换到下一个步骤

           }

           break;

     case 1:

           if(uiTimeCnt>=const_time_level) //时间到

           {

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

 

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

               ucLed_dr2=1;

               ucLed_dr3=0;

               ucLed_dr4=1;

               ucLed_dr5=0;

               ucLed_dr6=1;

               ucLed_dr7=0;

               ucLed_dr8=1;

               ucLed_dr9=0;

               ucLed_dr10=1;

               ucLed_dr11=0;

               ucLed_dr12=1;

               ucLed_dr13=0;

               ucLed_dr14=1;

               ucLed_dr15=0;

               ucLed_dr16=1;

 

               ucLed_update=1;  //更新显示

               ucLedStep=0; //返回到上一个步骤

           }

           break;

  

   }

 

}

 

 

void T0_time() interrupt 1

{

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

  TR0=0; //关中断

 

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

  {

      uiTimeCnt++;  //累加定时中断的次数,

  }

 

  TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f

  TL0=0x2f;

  TR0=1;  //开中断

}

 

void delay_short(unsigned int uiDelayShort) 

{

   unsigned int i;  

   for(i=0;i

   {

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

   }

}

 

void delay_long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i

   {

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

          {

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

          }

   }

}

 

 

void initial_myself()  //第一区 初始化单片机

{

 

  TMOD=0x01;  //设置定时器0为工作方式1

 

 

  TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f

  TL0=0x2f;

 

 

}

 

void initial_peripheral() //第二区 初始化外围

{

  EA=1;     //开总中断

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

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

 

}

总结陈词:

这节讲了把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式,接下来,我们该如何来运用这种驱动方式实现跑马灯的程序?欲知详情,请听下回分解-----依次逐个点亮LED之后,再依次逐个熄灭LED的跑马灯程序。

关键字:74HC595  驱动程序  单片机  IO口  直接驱动 引用地址:第18节:把74HC595驱动程序翻译成类似单片机IO口直接驱动的方

上一篇:第17节:两片联级74HC595驱动16个LED灯的基本驱动程序
下一篇:第19节:依次逐个点亮后逐个熄灭LED的跑马灯程序

推荐阅读最新更新时间:2024-03-16 14:47

东芝面向超低功率MCU开发隧穿场效应晶体管
东京—东芝公司(TOKYO:6502)今天宣布面向超低功率微控制器(MCU)开发采用新工作原理的隧穿场效应晶体管(TFET)。该工作原理已经被应用到使用CMOS平台兼容工艺的两种不同的TFET开发中。通过将每种TFET应用到一些电路块中,可实现大幅降低MCU的功耗。 9月9日和10日,东芝在日本筑波举办的2014年固态元件与材料(SSDM)国际会议上的三场展览中展示了其TFET。其中的两次展览是建立在与日本产业技术综合研究所(AIST)合作研究团队绿色纳米电子中心(GNC)的联合研究的基础上。 无线设备和移动设备的需求快速增长,正拉动着大规模集成电路(LSI)超低功耗的需求增长。在这种形势下,我们急切需要创新设备,
[模拟电子]
单片机机械臂PWM波联合控制多路舵机按规律动作程序
简单的机械臂控制系统设计: 没有机械臂的具体结构图,电机处仅代表机械臂关节处的运动情况。 通过控制电机的运动来控制机械臂的具体动作。 将货物从一个固定位置搬运到另一个固定位置,重复此操作。其中用一个压力传感器作为机械臂的启动开关,当压力传感器检测到有货物存在于货架上时机械臂开始执行动作,将货物夹起搬运到另一个位置。当货物被搬运到另一个位置的时候数码显示屏幕记录下搬运的个数,当搬运完毕后如果传感器再次检测到货架上有货物,机械臂即再一次执行刚才的动作,将货物搬运到另一个位置,同时显示屏显示的数字加一,记录下搬运的货物数量。 机械臂主要结构,各连接处用电机代替 机械臂末端示意图 五个舵机:Kpower公司的舵机,分别为:两
[单片机]
<font color='red'>单片机</font>机械臂PWM波联合控制多路舵机按规律动作程序
51单片机的LED与数码管的驱动
1、编写C51代码,实现流水灯字变花型: /*********************************************************** * 实验功能 : LED实现流水灯花型控制 *************************************************************/ # include reg51.h void delay(unsigned int z) { unsigned int x,y; for(x=z;x 0;x--) for(y=100;y 0;y--); } timer0() interrupt 1 { st
[单片机]
平凡单片机教学 第十九讲 定时/计数器实验2
前面我们做了定时器的实验,现在来看一看计数实验,在工作中计数通常会有两种要求:第一、将计数的值显示出来,第二、计数值到一定程度即中断报警。第一种如各种计数器、里程表,第二种如前面例中讲到的生产线上的计数。先看第一种吧。我们的硬件中是这样连线的:324构成的振荡器连到定时/计数器1的外部引脚T1上面,我们就利用这个来做一个计数实验,要将计数的值显示出来,当然最好用数码管了,可我们还没讲到这一部份,为了避免把问题复杂化,我们用P1口的8个LED来显示计到的数据。 程序如下: ORG 0000H AJMP START ORG 30H START: MOV SP,#5FH MOV TMOD,#01000000
[单片机]
基于51单片机的医用血压测量仪设计案例
一、主要功能 本项目使用Proteus8.12仿真51单片机控制器,使用OLED12864液晶模块、PCF8591 AD模块、按键、电机等。 主要功能: 系统运行后,OLED显示开机显示界面。可通过K1键开始测量血压,气泵阀开启,一段时间后停止,开始测量高压和低压,并将测量值显示在OLED,并且显示当前血压状态。 主要功能如下: (1)OLED显示血压; (2)血压高压测量你; (3)血压低压测量; (4)血压状态显示。 二、硬件资源 51单片机核心模块、OLED12864液晶模块、按键、电机模块、PCF8591 AD模块。 三、软件设计 /* //定义结构体 _sys_ctrl sys_ctrl; //系统参数设置 vo
[单片机]
基于51<font color='red'>单片机</font>的医用血压测量仪设计案例
micro2440 按键驱动程序
my_buttons.c文件: #include linux/fs.h #include linux/poll.h #include linux/irq.h #include linux/interrupt.h #include mach/regs-gpio.h #include mach/hardware.h #include linux/miscdevice.h #define DEVICE_NAME mybuttons struct button_irq_desc { int irq; int pin; int pin_setting; int number; char *na
[单片机]
在节电设计中掉电状态MCU的复位唤醒速度
引言 在MCU的节电措施中,除了降低工作频率与工作电压以外,剩下的就是如何选择MCU的节电模式了。由于节电的机理是设法停掉片内一部分电路的工作,因此节电效果最好的是片内电路全停的掉电方式。以MCS51系列的AT89C2051为例,其休闲方式(CPU冻结,但振荡器、中断、定时器与串行口等仍继续运行)的耗电约为850uA,而掉电方式(片内所有电路均停止工作,仅保持I/O端口引脚状态和片内RAM内容不变)的耗电仅为1uA不到。显然,对于那些正常运行中存在等待状态的MCU应用项目来说,应当尽可能地选择这种掉电方式来作节电设计。但由于掉电状态下MCU片内的时钟和中断系统均不工作,所以无法以片外中断方式唤醒片内的CPU,而只能以复位方
[单片机]
在节电设计中掉电状态<font color='red'>MCU</font>的复位唤醒速度
Microchip扩展中档8位PIC®单片机系列
全球领先的整合单片机、模拟器件和闪存专利解决方案的供应商——Microchip Technology Inc.(美国微芯科技公司)宣布,推出其增强型中档内核8位PIC®单片机(MCU)系列的最新产品——外设丰富、低引脚数的PIC12F(LF)1840和PIC16F(LF)1847。全新器件分别配备7 KB和14 KB片上闪存,高达1 K的RAM,是8和18引脚封装产品中存储容量最高的PIC® MCU。“LF”型号采用超低功耗(XLP)技术,工作电流小于40 µA/MHz,休眠电流低至20 nA。凭借丰富的外设和功能——包括mTouch™容性触摸传感和多种通信外设,这些通用MCU非常适合于家电(如咖啡壶、搅拌机和洗碗机)、消费类
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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