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

/**原理图以及各74HC595的IO口功能见上一例****/

#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 ucLedStatusTemp08_01);
void led_updata(); //LED更新函数 
void T0_time(); //定时中断函数

sbit hc595_sh_dr=P3^6;  //上升沿时,数据寄存器数据移位
sbit hc595_st_dr=P3^5;  //上升沿时移位寄存器的数据进入数据寄存器,下降沿时数据不变。当移位结束后,会产生一个正脉冲,用于更新显示数据。
sbit hc595_ds_dr=P3^4;  //串行数据输入端,级联的话接上一级的Q7。

unsigned char ucLed_dr1=1;  //8个灯,1代表灭,0代表亮
unsigned char ucLed_dr2=1;
unsigned char ucLed_dr3=1;
unsigned char ucLed_dr4=1;
unsigned char ucLed_dr5=1;
unsigned char ucLed_dr6=1;
unsigned char ucLed_dr7=1;
unsigned char ucLed_dr8=1;

unsigned char ucLed_updata=0; //刷新变量。每次更改LED灯的状态都要更新一次
unsigned char ucLedStep=0; //步骤变量
unsigned int uiTimeCnt=0; //统计定时中断次数的延时计数器

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

void main()
{
 initial_myself();
 delay_long(100);
 initial_peripheral();
 while(1)
 {
  led_flicker();
  led_updata(); //LED更新函数
 }
}

/*把74HC595驱动程序翻译成类似单片机IO口直接驱动方式的过程。每次更新LED输出,记得都要把ucLed_uodata置1表示更新*/
void led_updata() //LED更新函数
{
 if(ucLed_updata==1)
 {
  ucLed_updata=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;
  
  
  hc595_drive(ucLedStatus08_01); //74HC595底层驱动函数
 }
}

void hc595_drive(unsigned char ucLedStatusTemp08_01)
{
 unsigned char i;
 unsigned char ucTempData;
 hc595_sh_dr=0;
 hc595_st_dr=0;
 
 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;
 delay_short(15);
 hc595_st_dr=1;  //ST引脚负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。
 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_updata=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_updata=1; //更新显示
    ucLedStep=0; //返回到上一步骤
   }
   break;
 }
}

void T0_time() interrupt 1
{
 TF0=0; //清除中断标志
 TR0=0; //关中断

if(uiTimeCnt<0xffff) //设定这个条件,防止uiTimeCnt超范围
 {
  uiTimeCnt++; //累加定时中断的次数
 }
 
 TH0=0xf8;
 TL0=0x2f;
 TR0=1;  //开中断
}

void delay_short(unsigned int uiDelayShort)
{
 unsigned int i;
 for(i=0;i<uiDelayShort;i++)
  ;
}

void delay_long(unsigned int uiDelayLong)
{
 unsigned int i;
 unsigned int j;
 for(i=0;i<uiDelayLong;i++)
  for(j=0;j<500;j++)
   ;
}

void initial_myself()  //第一区  初始化单片机
{
 TMOD=0x01;
 TH0=0xf8;
 TL0=0x2f;
}

void initial_peripheral()
{
 EA=1;
 ET0=1;
 TR0=1; 
}

原文地址:https://www.cnblogs.com/TheFly/p/12009981.html

时间: 2024-10-31 19:35:46

把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式的相关文章

单片机IO口标准双向,推挽,高阻,开漏模式 ,LED感应亮灭实验【原创!】

单片机IO口标准双向,推挽,高阻,开漏模式 ,LED感应亮灭实验  十一长假在家快烂了,没事儿做,DIY技术搞起来!  [关于12C增强型单片机I/O口的工作类型实验研究] 文中动画视频效果下载: STC单片机头文件[51CTO-->单片机-->LED感应亮灭实验] 下载链接 链接:http://pan.baidu.com/s/1pJKK4w7   密码:a0re  1.用强推模式,点亮一个LED  /* 工程创建MCU选取,Atmel 89C55 单片机:STC12C4052AD 晶振:无要

STM32系列单片机IO口模式设置

STM32单片机的每组IO口都有4个32位配置寄存器用于配置GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR和GPIOx_PUPDR,2个32位数据寄存器用于配置输入和输出寄存器GPIOx_IDR和GPIOx_ODR,1个32位置位复位寄存器GPIOx_BSRR,1个32位锁定寄存器GPIOx_LCKR和2个32位复用功能选择寄存器GPIOx_AFRH和GPIOx_AFRL. GPIO的输出状态可以配置为推挽或开漏加上上拉或下拉.输出数据既可以来自输出数据寄存器,

关于51单片机IO引脚的驱动能力与上拉电阻

单片机的引脚,可以用程序来控制,输出高.低电平,这些可算是单片机的输出电压.但是,程序控制不了单片机的输出电流. 单片机的输出电流,很大程度上是取决于引脚上的外接器件. 单片机输出低电平时,将允许外部器件,向单片机引脚内灌入电流,这个电流,称为“灌电流”,外部电路称为“灌电流负载”:单片机输出高电平时,则允许外部器件,从单片机的引脚,拉出电流,这个电流,称为“拉电流”,外部电路称为“拉电流负载”. 这些电流一般是多少?最大限度是多少? 这就是常见的单片机输出驱动能力的问题. 早期的 51 系列单

单片机 IO口配置模式介绍

1.准双向口 2.双向口 双向口与准双向口的区别主要是:准双向口I/O口操作时做数据输入时需要对其置1,否则若前一位为低电平,后一位输入的电平为高则MOS管拉不起来导致出错.而双向口则不需要做此动作,因为双向口有悬浮态. 准双向口就是做输入用的时候要有向锁存器写1的这个准备动作,所以叫准双向口. 真正的双向口不需要任何预操作可直接读入读出. 1>准双向一般只能用于数字输入输出,输入时为弱上拉状态(约50K上拉),端口只有两种状态:高或低. 2>双向除用于数字输入输出外还可用于模拟输入输出,模拟

51单片机IO口模拟UART串口通信

#include <reg52.h>#include "main.h"#include "smartcard.h"#include "stdio.h" typedef enum { false, true }bool; #if 0sbit PIN_RXD = P1^0; //接收发送同一个引脚定义sbit PIN_TXD = P1^0; //接收发送同一个发送引脚定义sbit PIN_CLK = P3^1; //智能卡时钟引脚定义sb

51单片机:IO口扩展芯片用法(74HC165,74HC595)

IO口扩展芯片,主要是解决单片机IO口太少. 74HC165:数据从并转串 74HC595:数据从串转并 两种芯片,都是通过时序电路,加上移位功能,进行数据传输 74HC165:数据从并转串.以下实例,实现8个独立按键,控制数码管的8段 #include <reg52.h> #include <intrins.h> typedef unsigned char u8; typedef unsigned int u16; void delay( u16 i ){ while( i--

单片机小白学步系列(二十二) IO口:蜂鸣器的使用/三极管的工作原理

2014-11-22更新:感谢Ireland同学的提醒,修改了PNP型三极管驱动电路,蜂鸣器从三极管的发射极改到了集电极,这样效果会更好,电路也更合理.同时增加了备注4. ====================================== 这一篇继续上一篇的内容,我们来做实验四:按键控制有源蜂鸣器,按下按键蜂鸣器响,释放按键不响. 蜂鸣器 实验四之前简单介绍下蜂鸣器.蜂鸣器有两种,无源蜂鸣器和有源蜂鸣器,一般用于发出报警的声音.声音是由震动产生的,大家都见过喇叭,喇叭里面有磁铁和线圈.

单片机小白学步系列(二十三) IO口原理知识补充:双向IO口、互补推挽、高阻态

由于之前考虑不周,本篇在IO口原理知识的基础上,进一步补充一些知识. ================================================= 双向IO口的输出:互补推挽 在51单片机的P0口工作在普通IO口模式下,为准双向IO口.而工作在第二功能状态下时,则为标准的双向IO口.由于双向IO口的输出,要求能输出高低电平,通常会采用互补推挽电路. 在第二功能状态下,51单片机P0口采用的是互补推挽的输出方式.何为互补推挽呢?下面是它的等效电路图. 当P0第二功能作为输出时

单片机小白学步系列(二十) IO口原理

IO口操作是单片机实践中最基本最重要的一个知识,本篇花了比较长的篇幅介绍IO口的原理.也是查阅了不少资料,确保内容正确无误,花了很长时间写的.IO口原理原本需要涉及很多深入的知识,而这里尽最大可能做了简化方便理解.这样对于以后解决各种IO口相关的问题会有很大的帮助. IO口等效模型是本人独创的方法,通过此模型,能有效的降低对IO口内部结构理解的难度.并且经查阅资料确认,这种模型和实际工作原理基本一致. ========================================== 前面说了