打印
[匠人手记]

使用74HC595和74LS138动态扫描LED

[复制链接]
8084|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sjg_mcu|  楼主 | 2009-9-25 22:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//=============================================================================
//74HC595与74LS138联合使用显示技术(可用于项目,proteus仿真通过,硬件没测)
//本程序为原创.
//功能,节约CPU的IO口,使原来需要16个IO口的8个LED8,现在只需要6个IO口
//P10-P12驱动74HC138输出扫描字(数组法),P13_P15驱动74HC595使用输出段码
//-----------------------------------------------------------------------------
//显示错乱分析:595是在上升沿触发,输出段码.如果先输出扫描字,
//因595有锁存功能,LED上显示就是上一次段码,时间等于串口传送的时间(这个时间较长)
//等传送完毕,595锁存,LED显示本次段码.在一个很短时间出现本次段码和上次段码交叉显示
//视觉效果就是显示错乱.
//解决方法:先把段码传送好,再把扫描字放好,然后打开段码开关,即595门控位置1产生上升沿
//这样段码与扫描字不同步的时间就很短,视觉上就不会产生错乱感.
//程序员:舒杰刚 2009年9月17日
//=============================================================================
#include "reg51.h"     //文件包含命令
#include "intrins.h"    //包含_nop_()
#define uchar unsigned char   //定义一下方便输入
#define uint unsigned int   //定义一下方便输入
//-----------------------------------------------------------------------------
void senddata(uchar senddat);
//-----------------------------------------------------------------------------
sbit DAT=P1^3;        //定义串行数据输入端
sbit CLK=P1^4;        //定义时钟端
sbit CNT=P1^5;        //定义门控位
//-----------------------------------------------------------------------------
uchar code disp_dm[]={      //定义段码共阴
  0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
//定义扫描字
uchar code disp_smz[]={0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff};
//-----------------------------------------------------------------------------
uchar dispbuf[8]={1,2,3,4,5,6,7,8};   //显示缓存
//=============================================================================
//数据传送指令(本程序核心函数)
//=============================================================================
void senddata(uchar senddat)
{ uchar i;
for(i=0;i<8;i++)
{ if((senddat&0x01)==0){DAT=0;}
  else{DAT=1;}
  _nop_();CLK=0;      //595是上升沿触发方式
  _nop_();CLK=1;      //时钟产生一个上升沿
  senddat=senddat>>1;
}
}
//=============================================================================
//定时器0中断程序
//=============================================================================
void t0() interrupt 1
{
uchar tmp,c;
static uchar disp_count;
TH0=0x06;TL0=0x06;  //定时器赋初值
//动态扫描显示,传送段码----------------------------------------------------
CNT=0;         //关闭存储寄存器输入
c=dispbuf[disp_count];     //取出待显示字符
senddata(disp_dm[c]);     //送出字形码数据
//显示扫描字---------------------------------------------------------------
tmp=disp_smz[disp_count];    //根据当前的计数值取位值
P1=P1|0x07;        //P1或00000111B相或,将低3位置1
P1=P1&tmp;        //低三位输出扫描字
CNT=1;         //开启存储器的输入
//-------------------------------------------------------------------------
disp_count++;
if(disp_count>7){disp_count=0;}
}
//=============================================================================
//主函数
//=============================================================================
void main(void)
{
TMOD=0x02;    //定时器工作方式2
TH0=0x06;TL0=0x06;  //定时器赋初值
TR0=1;ET0=1;EA=1;  //R0开始运行,开T0中断,总中断
dispbuf[4]=4;dispbuf[6]=1;  //测试用
while(1)
{;}
}

led8_595_138.rar

16.31 KB

评分
参与人数 1威望 +6 收起 理由
程序匠人 + 6

相关帖子

沙发
sjg_mcu|  楼主 | 2009-9-25 22:52 | 只看该作者
附件文件为proteus格式文件,本例主要是解决单片机IO口不够

使用特权

评论回复
板凳
爱学小生| | 2009-10-14 17:56 | 只看该作者
弱弱的问一句_nop_()和uchar dispbuf[8]={1,2,3,4,5,6,7,8};   //显示缓存
是干嘛的  在很多程序里都能看到

使用特权

评论回复
地板
longcai1988| | 2009-10-15 14:51 | 只看该作者
LZ以后上传的时候能不能把HEX文件也一块上传,这样弄起来比较方便。谢了。

使用特权

评论回复
5
蓝色的云| | 2009-10-19 21:02 | 只看该作者
本帖最后由 蓝色的云 于 2009-10-19 21:06 编辑

4# 爱学小生

_nop_()     
空操作,什么也不干,可用于延时一个指令周期,与汇编的NOP指令相同 定义在头文件intrins.h中 所以用的时候有写 include "intrins.h"  

uchar dispbuf[8]={1,2,3,4,5,6,7,8};   //显示缓存
显示缓存,可把要显示的数据先更新在这个数组中,再通过这个数组的数找对应的段码显示
通常每一位对应着一个数码管,比如要显示87654321,那么就先把uchar dispbuf[8更新为uchar dispbuf[8]={8,7,6,5,4,3,2,1};,以楼主的段码则可通过Px=disp_smz[dispbuf[ i ] ]显示

使用特权

评论回复
6
Beyond411| | 2009-11-3 08:25 | 只看该作者
谢谢分享

使用特权

评论回复
7
holle| | 2009-11-24 14:31 | 只看该作者
呵呵

使用特权

评论回复
8
aceice| | 2009-12-7 16:37 | 只看该作者
呵呵,显示缓存那个,其实是编程模块化必然的结果。
更新缓存的函数和显示函数肯定不在一起。

使用特权

评论回复
9
yixuanyuxiao| | 2009-12-27 00:57 | 只看该作者
谢谢楼主,小弟正在做这个的毕设,看看能否优化自己的程序,多谢!

使用特权

评论回复
10
catzl7| | 2010-1-27 12:38 | 只看该作者
不错......

使用特权

评论回复
11
zhlw820905| | 2010-1-27 15:59 | 只看该作者
顶贴,折腾了好久的东西,学习了

使用特权

评论回复
12
paopaosha| | 2010-2-1 16:20 | 只看该作者
谢谢分享,,,学习了

使用特权

评论回复
13
paopaosha| | 2010-2-1 16:27 | 只看该作者
您好,请问,如果我用595通过单片机控制20个LED,让LED流水状态流动,,如果用扫描的方式 怎么扫描啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

150

帖子

1

粉丝